1. 文章
  2. 文章详情

Tensorflow 2.0搭建 CNN(卷积神经网络) -- MNIST数据集

Tensorflow 2.0 用keras搭建一个简单的卷积神经网络,数据集也采用最简单的手写字符MNIST。

首先,MNIST数据集tensorflow自身提供了加载函数

(train_images, train_labels), (test_images, test_labels) = tf.keras.datasets.mnist.load_data()

第一次运行时会自动下载到本地,如网络情况不好或脱机状态则需要事先手动下载并读取。

搭建网络时,需要用到的模型和各个层均采用keras的实现

from tensorflow.keras import models
from tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense, Reshape

然后,我们将卷积层、池化层等顺序放入,就能很轻松的完成一个模型

def Model():
    model = models.Sequential()
    model.add(Reshape((28, 28, 1), input_shape=(28, 28)))
    model.add(Conv2D(32, (3, 3), activation='relu'))
    model.add(MaxPooling2D((2, 2)))
    model.add(Conv2D(64, (3, 3), activation='relu'))
    model.add(MaxPooling2D((2, 2)))
    model.add(Conv2D(64, (3, 3), activation='relu'))
    model.add(Flatten())
    model.add(Dense(64, activation='relu'))
    model.add(Dense(10, activation='softmax'))
    return model

其中,模型仅第一层需要提供input_shape参数,后续的网络每一层的输入输出大小都会自动推算。这里我的第一层为Reshape,因为tensorflow的数据组织形式为(B, H, W, C),依次为图像的批次数量、高度、宽度、通道数,而MNIST数据集为黑白图像,读取时没有通道维度,从而第一层采用Reshape手动添加通道。Flatten层为将多维数据拉平,从而进行后续的Dense全连接操作。

模型搭建完毕后,可以在代码中加入model.summary(),从而在执行时打印各个层的信息,如

Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
reshape (Reshape)            (None, 28, 28, 1)         0         
_________________________________________________________________
conv2d (Conv2D)              (None, 26, 26, 32)        320       
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 13, 13, 32)        0         
_________________________________________________________________
conv2d_1 (Conv2D)            (None, 11, 11, 64)        18496     
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 5, 5, 64)          0         
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 3, 3, 64)          36928     
_________________________________________________________________
flatten (Flatten)            (None, 576)               0         
_________________________________________________________________
dense (Dense)                (None, 64)                36928     
_________________________________________________________________
dense_1 (Dense)              (None, 10)                650       
=================================================================
Total params: 93,322
Trainable params: 93,322
Non-trainable params: 0
_________________________________________________________________

可以看到,每经过一个卷积层特征图的大小会减2,keras默认卷积的padding形式是valid,如果希望经过卷积层特征图的大小不变(实际上绝大多数情况都是如此),可以设置参数padding='same'来控制。

然后,设置模型训练时的优化器、损失函数,这里我们采用adam作为优化器,损失函数为交叉熵。

model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])

更多的内容如学习率、l2正则会在下篇文章介绍。

最后我们就可以开始训练模型了,这里我们让数据的batchsize为128,网络训练5轮,再在测试机上进行测试。

model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
model.fit(train_images,
          train_labels,
          batch_size=128,
          epochs=5)

test_loss, test_acc = model.evaluate(test_images, test_labels)
print(test_acc)

最终训练集准确率约99%,测试集约98.5%。 完整的代码在

https://github.com/Apm5/tensorflow_2.0_tutorial/blob/master/CNN/simple_example.py

额外说明一点,完整代码中最先执行的gpu设置

physical_devices = tf.config.experimental.list_physical_devices('GPU')
tf.config.experimental.set_memory_growth(device=physical_devices[0], enable=True)

是让显存的占用按需增长,否则无论多小的网络都会将一张显卡的显存全部占满。如果是cpu版本或不想用gpu训练,可以注释掉这两行。

发表评论

登录后才能评论

评论列表(0条)