本文首发于微信公众号:"算法与编程之美",欢迎关注,及时了解更多此系列文章。
1 前言
Tensorflow认证考试内容五项中的第一项是基础/简单模型,第二项是学习数据集模型。小编猜想,这两者都是比较基础的知识,涉及到的知识应该主要包含:全连接神经网络搭建简单模型,数据集的加载,以及根据数据集搭建全连接神经网络模型进行训练(也有可能会涉及到卷积)。
在基础的内容肯定不能浪费太多时间,所以本文向读者们推荐两种能够快速搭建模型的方式,并辅以数据集的加载和简单的卷积层。
这两种方式能帮助快速地搭建模型,但并不意为这两者方式不能搭建复杂的模型,本文将以典型案例手写数字识别为例,来看看如何运用tf.keras.Sequential和Keras Functional API,这两种方式来快速搭建模型。
2 数据加载及预处理
代码语言:javascript复制import tensorflow as tf
from tensorflow.keras import datasets,Sequential,layers,optimizers,models
def data_preprocess(x,y):
#mnist的数据类型是unit8,需要转换为float32,并将像素点的值从0~255更换为-1~1
x=2*tf.cast(x,dtype=tf.float32)/255.-1
#真实值已经采用one_hot编码,直接转换为整型即可
y=tf.cast(y,dtype=tf.int32)
return x,y
#加载mnist手写字体数据集
(x,y),(x_val,y_val)=datasets.mnist.load_data()
#真实值进行one_hot编码
y=tf.one_hot(y,depth=10)
y_val = tf.one_hot(y_val, depth=10)
#维度变换
x=tf.reshape(x,[-1,28,28,1])
x = tf.reshape(x, [-1, 28, 28, 1])
x_val = tf.reshape(x_val, [-1, 28, 28, 1])
#构建训练数据集train_db
train_db=tf.data.Dataset.from_tensor_slices((x,y))
train_db=train_db.map(data_preprocess).shuffle(10000).batch(128)
#构建测试数据集test_db
test_db=tf.data.Dataset.from_tensor_slices((x_val,y_val))
test_db=test_db.map(data_preprocess).batch(128)
3 tf.keras.Sequential容器搭建
tf.keras.Sequential,可视作一个容器,只需要通过add函数往里面填入所需的神经层,便能快速地构建神经网络模型。
代码语言:javascript复制#创建Sequential容器
model=Sequential()
#加入池化层
model.add(layers.MaxPool2D(pool_size=[2, 2], strides=2, padding='same'))
#加入卷积层
model.add(layers.Conv2D(64,kernel_size=[2,2],padding='same',activation=tf.nn.relu))
model.add(layers.MaxPool2D(pool_size=[2,2],strides=2,padding='same'))
model.add(layers.Conv2D(128, kernel_size=[2, 2], padding='same', activation=tf.nn.relu))
model.add(layers.MaxPool2D(pool_size=[2, 2], strides=2, padding='same'))
model.add(layers.Conv2D(256, kernel_size=[2, 2], padding='same', activation=tf.nn.relu))
model.add(layers.MaxPool2D(pool_size=[2, 2], strides=2, padding='same'))
#矩阵打平
model.add(layers.Flatten())
#加入全连接层
model.add(layers.Dense(128, activation=tf.nn.relu))
model.add(layers.Dense(10))
#建立模型,并指明输入的维度及其形状
model.build(input_shape=[None,28,28,1])
也可以选择在创建容器时,就加入所需要的神经层,两种方式并无太大差别。
代码语言:javascript复制model=Sequential([
#池化层,卷积层各三层,最后打平再加上两层全连接
layers.MaxPool2D(pool_size=[2, 2], strides=2, padding='same'),
layers.Conv2D(64,kernel_size=[2,2],padding='same',activation=tf.nn.relu),
layers.MaxPool2D(pool_size=[2,2],strides=2,padding='same'),
layers.Conv2D(128, kernel_size=[2, 2], padding='same', activation=tf.nn.relu),
layers.MaxPool2D(pool_size=[2, 2], strides=2, padding='same'),
layers.Conv2D(256, kernel_size=[2, 2], padding='same', activation=tf.nn.relu),
layers.MaxPool2D(pool_size=[2, 2], strides=2, padding='same'),
layers.Flatten(),
layers.Dense(128, activation=tf.nn.relu),
layers.Dense(10)
])
#建立模型,并指明输入的维度及其形状
model.build(input_shape=[None,28,28,1])
4 Sequential模型训练
本文提到的两种方式,在模型的训练上都可以直接调用model.compile进行模型训练配置和model.fit进行训练。
代码语言:javascript复制#训练模型的必要配置
model.compile( #优化器选择及lr的数值
optimizer=optimizers.Adam(lr=1e-3),
#损失函数选择,均分误差,交叉熵等
loss=tf.losses.CategoricalCrossentropy(from_logits=True), #用于监控训练,并呈现精确度
metrics=['accuracy']
)
#模型训练,从左往右的参数分别是:训练数据集,训练次数,测试数据集,训练多少次便测试一次
model.fit(train_db,epochs=6,validation_data=test_db,validation_freq=2)
tf.keras.Sequential来搭建模型,简单快速。但缺陷也很明显,框架已定,灵活性太低,无法解决多输入/输出的问题,比如验证码识别:假设一张图内有4个数字,在不对图片进行切割等预处理的情况下,无法通过 Sequential来输出4个结果。
5 Keras Functional API
Functional API即保证了搭建模型的简单快捷,也具有很好的灵活性和可扩充性,无论是单输入/输出还是多/输入输出都能实现。
数据预处理和训练部分都与Sequential相同,那就直接来看看如何用Functional API搭建模型吧。
代码语言:javascript复制#定义输入层,并限制其shape
inputs=tf.keras.Input(shape=[28,28,1])
#定义不同神经层,并且每一层的输入都来自于上一层
x=layers.MaxPool2D(pool_size=[2, 2], strides=2, padding='same')(inputs)
x=layers.Conv2D(64,kernel_size=[2,2],padding='same',activation=tf.nn.relu)(x)
x=layers.MaxPool2D(pool_size=[2, 2], strides=2, padding='same')(x)
x=layers.Conv2D(128,kernel_size=[2,2],padding='same',activation=tf.nn.relu)(x)
x=layers.MaxPool2D(pool_size=[2, 2], strides=2, padding='same')(x)
x=layers.Conv2D(256,kernel_size=[2,2],padding='same',activation=tf.nn.relu)(x)
x=layers.MaxPool2D(pool_size=[2, 2], strides=2, padding='same')(x)
x=layers.Flatten()(x)
x=layers.Dense(128, activation=tf.nn.relu)(x)
#定义输出层
output=layers.Dense(10)(x)
#建立模型传入输入和输出层
model=tf.keras.Model(inputs=inputs,outputs=output)
根据以上代码示例,便建立了一个含有卷积和全连接的神经网络。并且每一层都可以独立提出来,也就是说可以查看每一层的输出情况,可以在一些复杂模型中抽取特定层放入自己的代码中,比如抽取VGG19中的某些层放在自己的代码中去实现图像的风格迁移。
6 总结
tf.keras.Sequential和Keras Functional API都可以有助于快速地建立神经网络模型,.Sequential简单易懂,在既定框架下可以最快的搭建些不是很复杂的模型,Functional API同样简单可扩展性高,应用范围更广。
这两种方式来解决认证考试中的前两项内容,相信绰绰有余。
END
主 编 | 王文星
责 编 | 马原涛
where2go 团队