前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >TensorFlow v2.x使用说明[2]-模型构建

TensorFlow v2.x使用说明[2]-模型构建

作者头像
锦小年
发布2019-10-22 14:19:04
4380
发布2019-10-22 14:19:04
举报
文章被收录于专栏:锦小年的博客锦小年的博客

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

本文链接:https://blog.csdn.net/jinxiaonian11/article/details/102153890

更新时间: 2010-10-5 在v2.x版中,有多种构建模型的方式,分别是基于keras的Sequential(序列式),subclass(子类式),functional(函数式)。下面一一介绍。

不管采用哪种方式,深度学习解决方案完成的过程不会变:数据准备 -> 模型构建 -> 损失函数 -> 优化器选择 -> 模型训练 -> 模型验证。

1. 序列式建模

序列式模式很好理解,和平时画出来的深度网络的图一样,一层一层的堆叠起来。例如:

在这里插入图片描述
在这里插入图片描述
代码语言:javascript
复制
# import lib
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers

# 载入数据
mnist = tf.keras.datasets.mnist
(train_imgs, train_labels), (test_imgs, test_labels) = mnist.load_data()
train_imgs, test_imgs = train_imgs / 255.0, test_imgs / 255.0
train_imgs = train_imgs.reshape(60000,28,28,1)
test_imgs = test_imgs.reshape(10000,28,28,1)
# 模型构建
# 构建模型中的网络包含的所有内容,例如卷积层,池化层,BN层,全连接层,dropout。
cnn_model = keras.Sequential()
cnn_model.add(layers.Conv2D(input_shape=(28,28,1),filters=32,kernel_size=(3,3),activation='relu'))
cnn_model.add(layers.BatchNormalization())
cnn_model.add(layers.Conv2D(filters=64,kernel_size=(3,3),activation='relu'))
cnn_model.add(layers.BatchNormalization())
cnn_model.add(layers.MaxPool2D((2,2)))
cnn_model.add(layers.Conv2D(filters=128,kernel_size=(3,3),activation='relu'))
cnn_model.add(layers.BatchNormalization())
cnn_model.add(layers.Conv2D(filters=256,kernel_size=(3,3),activation='relu'))
cnn_model.add(layers.BatchNormalization())
cnn_model.add(layers.MaxPool2D((2,2)))
cnn_model.add(layers.Conv2D(filters=512,kernel_size=(3,3),activation='relu'))
cnn_model.add(layers.BatchNormalization())
cnn_model.add(layers.Flatten())
cnn_model.add(layers.Dense(1000,activation='relu'))
cnn_model.add(layers.Dropout(0.2))
cnn_model.add(layers.Dense(100,activation='relu'))
cnn_model.add(layers.Dropout(0.2))
cnn_model.add(layers.Dense(10,activation='softmax'))
cnn_model.summary()
# 模型编译
# 损失函数,优化器选择,精度度量
cnn_model.compile(optimizer='adam',
                  loss='sparse_categorical_crossentropy',
                  metrics=['accuracy'])

# 模型训练
cnn_model.fit(train_imgs,train_labels,batch_size=256,epochs=10)
# 模型验证
cnn_model.evaluate(test_imgs,test_labels)

通过代码可以发现,整个过程为:建立Sequential()类,再给里面通过model.add()添加各种层。之后编译,训练,验证。

2. 子类式

这种模式适合对TensorFlow比较熟悉的人去编程,相对于v1也方便了很多。

代码语言:javascript
复制
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras.layers import Conv2D, BatchNormalization, MaxPool2D, Flatten, Dense
import numpy as np

# 准备数据
(train_imgs, train_labels), (test_imgs,
                             test_labels) = keras.datasets.mnist.load_data()
train_imgs, test_imgs = train_imgs / 255.0, test_imgs / 255.0

# 增加一个维度,通过numpy方式
# train_imgs = np.expand_dims(train_imgs,axis=-1)
# test_imgs = np.expand_dims(test_imgs,axis=-1)

# 增加一个维度,通过tf方式
# ...代表索引的前面的所有维度
train_imgs = train_imgs[..., tf.newaxis]
test_imgs = test_imgs[..., tf.newaxis]

train_ds = tf.data.Dataset.from_tensor_slices(
    (train_imgs, train_labels)).shuffle(10000).batch(32)
test_ds = tf.data.Dataset.from_tensor_slices((test_imgs, test_labels)).batch(32)
print(type(train_ds))
# 定义模型
class MnistModel(keras.Model):
    def __init__(self):
        super(MnistModel, self).__init__()
        self.conv1 = Conv2D(
            32, (3, 3), activation='relu', input_shape=(28, 28, 1))
        self.bn1 = BatchNormalization()
        self.conv2 = Conv2D(64, (3, 3), activation='relu')
        self.bn2 = BatchNormalization()
        self.maxpool1 = MaxPool2D((2, 2))
        self.conv3 = Conv2D(128, (3, 3), activation='relu')
        self.bn3 = BatchNormalization()

        self.flatten = Flatten()

        self.dense1 = Dense(1000, activation='relu')
        self.dropout1 = keras.layers.Dropout(0.2)
        self.dense2 = Dense(100, activation='relu')
        self.output1 = Dense(10, activation='softmax')

    def call(self, x):
        cnn_block1 = self.bn1(self.conv1(x))
        cnn_block2 = self.maxpool1(self.bn2(self.conv2(cnn_block1)))
        cnn_block3 = self.bn3(self.conv3(cnn_block2))

        dense_block = self.dense2(
            self.dropout1(self.dense1(self.flatten(cnn_block3))))
        return self.output1(dense_block)


# 实例化一个模型
model = MnistModel()

# 定义验证相关的类
train_loss = keras.metrics.Mean()
test_acc = keras.metrics.SparseCategoricalAccuracy()

# 选择优化器
optimizer = keras.optimizers.Adam()

# 定义训练过程
@tf.function
def train_step(x, y):
    with tf.GradientTape() as tape:
        y_ = model(x)
        loss = keras.losses.SparseCategoricalCrossentropy()(y, y_)
        # loss对于所有训练变量求梯度
        gradients = tape.gradient(loss, model.trainable_variables)
        # 梯度下降法更新参数
        optimizer.apply_gradients(zip(gradients, model.trainable_variables))
        train_loss(loss)


#定义测试过程
@tf.function
def test_step(x,y):
    y_ = model(x)
    test_acc(y, y_)


# 训练模型
MAX_STEPS = 5000
# tf.data.Dataset本质是上是一个可迭代对象,用iter()获取它的迭代器,用next则可以获取下个batch的数据。

iter_data = iter(train_ds)
for i in range(MAX_STEPS):
    try:
        img, label = next(iter_data)
        if not (i+1) %100 :
            test_step(img,label)
            print(i, 'test acc:',test_acc.result())
        else:
            train_step(img,label)
            print(i, train_loss.result())
    except:
        pass
for img, label in test_ds:
    test_step(img,label)

print(test_acc.result())

中间用到一个装饰器@tf.function,它的功能就是将该函数中涉及到的动态图转换为静态图。

上述代码还有些细节地方没有想明白,例如BN层和dropout层在训练集和测试集上是不一样的,但是这样似乎也能运行。

3. 函数式

待更新

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-10-05 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 序列式建模
  • 2. 子类式
  • 3. 函数式
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档