这一篇是使用tensorflow2进行mnist数据集的分类。
MLP分类mnist
import numpy as np import tensorflow as tf import tensorflow.keras as keras import matplotlib.pyplot as plt # load mnist dataset (train_x, train_y), (test_x, test_y) = keras.datasets.mnist.load_data(path='mnist.npz') # show a picture of number # number = train_x[0] # plt.figure() # plt.title('handwritten numberal') # plt.imshow(number) # plt.show() # define parameters of neural network ninput = 784 # input units, 28 * 28 nhidden1 = 256 # hidden units nhidden2 = 128 # hidden units noutput = 10 # output units # construct a three-layers neural network, aka. MLP model = keras.models.Sequential([ keras.layers.Flatten(input_shape=(28, 28)), keras.layers.Dense(nhidden1, activation='relu'), keras.layers.Dense(nhidden2, activation='relu'), keras.layers.Dense(noutput) ]) model.compile(optimizer=keras.optimizers.SGD(0.001), loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True), metrics=['accuracy']) model.fit(train_x, train_y, epochs=10) test_loss, test_acc = model.evaluate(test_x, test_y, verbose=2) print('loss', test_loss, '\naccuracy: ',test_acc)
上面代码使用的是一个多层感知机进行识别mnist数据集。(一般tensorflow数据存储在.keras/datasets文件夹中,直接使用tensorflow的api下载可能比较慢,可以提前下载好数据放入.keras/datasets文件夹中)
输入使用的是keras.layers.Flatten将图片矩阵装换成MLP所要求的数据输入,这个Flatten相当于如下代码功能(tensorflow提供的数据类型是numpy.ndarray):
lens = train_x.shape[0]
train_x.reshape((lens, -1))
然后两个隐藏层使用Dense(全连接)层,激活函数使用relu,最终输出一个10长度的概率分布,然后取出概率最大的作为最终的结果。
CNN分类mnist
CNN,卷积神经网络,一个十分经典的神经网络,这里就不赘述了,主要需要知道的就是:
1. 卷积操作,通过filter进行提取局部特征
2. 池化层,压缩提取的特征大小,也可以成为下采样
3. pad,提取图片边缘的特征
4. 步长
假设输入的图片是\(\)\(W*H*D\)\(\)(长,宽,channel),filter的个数\(\)\(K\)\(\),filter大小为\(\)\(F*F\)\(\),padding为\(\)\(P\)\(\),步长为\(\)\(S\)\(\),就可以得到隐藏层的输入为:\(\)\(W_1 = (W+2P-F)/S + 1\)\(\),\(\)\(H_1 = (H+2P-F)/S + 1\)\(\),\(\)\(D_1 = K\)\(\)
import numpy as np import tensorflow as tf import tensorflow.keras as keras import matplotlib.pyplot as plt # load mnist dataset (train_x, train_y), (test_x, test_y) = keras.datasets.mnist.load_data(path='mnist.npz') # Normalize train_x, test_x = train_x / 255.0, test_x / 255.0 train_x, test_x = train_x[:, :, :, np.newaxis], test_x[:, :, :, np.newaxis] # show a picture of number # number = train_x[0] # plt.figure() # plt.title('handwritten numberal') # plt.imshow(number) # plt.show() model = keras.models.Sequential([ keras.layers.Conv2D(28, (3, 3), strides=1, padding='same', activation='relu', input_shape=(28, 28, 1)), keras.layers.MaxPooling2D((2, 2)), keras.layers.Conv2D(64, (3, 3), activation='relu'), keras.layers.MaxPooling2D((2, 2)), keras.layers.Conv2D(64, (3, 3), activation='relu'), keras.layers.Flatten(), keras.layers.Dense(64, activation='relu'), keras.layers.Dense(10) ]) # model.summary() model.compile(optimizer='SGD', loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True), metrics=['accuracy']) model.fit(train_x, train_y, epochs=10, validation_data=(test_x, test_y)) test_loss, test_acc = model.evaluate(test_x, test_y, verbose=2) print('loss', test_loss, '\naccuracy: ',test_acc)
使用tf.keras.layers.Conv操作要知道Conv1D与Conv2D的区别,简单的说Conv1D只进行纵向的移动提取特征,Conv2D则是横向以及纵向的移动来提取特征。(reference4),所以对数据进行一个升维处理。考虑到mnist数据集一张图片内的值变化较大(0-255),做了一个标准化处理。
整个模型的架构就是,一层卷积一层池化一层卷积一层池化,然后数据是3D的(tf.keras.layers.Conv2D第一个参数就是filter的个数,也即输入到下一层隐藏层的特征深度),则需要将其展开为一维的,经过两个全连接层最后输出。
建立好模型后则可以使用model.summary()来查看构建的模型。然后就可以训练以及预测了。
系列:
Morvan博客-tensorflow2学习(一)
Morvan博客-tensorflow2学习(二)
Morvan博客-tensorflow2学习(三)
tensorflow2学习(四)
reference
1. https://morvanzhou.github.io/tutorials/machine-learning/tensorflow/5-16-transfer-learning/
2. https://tensorflow.google.cn/guide
3. https://tensorflow.google.cn/tutorials/keras/classification
4.conv1d与conv2d区别 https://blog.csdn.net/Elva_23/article/details/83826587
5. CNN中feature map、卷积核、卷积核个数、filter、channel的概念解释,以及CNN 学习过程中卷积核更新的理解