学习tensorflow使用神经网络实现MNIST手写数字分类的过程中遇到了很多问题,这里记录下来并总结
环境:
- windows11下的VM15,Ubuntu20.04,tensor环境,需要的包统一用conda install进行安装
- IDE为pycharm2021,实际自己练习时使用jupyter效果可能会更好
from tensorflow import keras
第一步没什么好说的,tensorflow是一个和pytorch齐名的框架,keras是作为tensorflow的核心接口
感兴趣可以使用单击tensorflow或者pytorch,再使用Ctrl+鼠标左键进行查看
from tensorflow.keras.datasets import mnist
(X_train, y_train),(X_test,y_test) = mnist.load_data()
这样我们得到了训练集、测试集和标记,但是mnist具体是什么样子的我们不清楚
先看一下数据类型,再看shape
print(type(X_train))
print(X_train.shape)
<class 'numpy.ndarray'>
(60000, 28, 28)
这里可以下载mnist数据
http://yann.lecun.com/exdb/mnist/
四个文件都是ubyte文件,无法用软件打开,需要代码进行读取
X_train = X_train.reshape(len(X_train),-1)
X_test = X_test.reshape(len(X_test),-1)
print(X_test.shape)
首先编写一个将数据转换为图片的函数。
[En]
First write a function that converts data into pictures.
import matplotlib.pyplot as plt
def plot_images(imgs):
"""绘制几个样本图片
:param show: 是否显示绘图
:return:
"""
sample_num = min(9, len(imgs))
img_figure = plt.figure(1)
img_figure.set_figwidth(5)
img_figure.set_figheight(5)
for index in range(0, sample_num):
ax = plt.subplot(3, 3, index + 1)
ax.imshow(imgs[index].reshape(28, 28), cmap='gray')
ax.grid(False)
plt.margins(0, 0)
plt.show()
一开始我很困惑,如果你不像我一样基础,但你也想完整地学习它,并耐心地和我一起检查(伟大的上帝绕道)
[En]
I was confused at first, if you are not as basic as I am, but you also want to learn it completely and check it patiently with me (Great God detour)
- 首先我们要知道图片是二维的,是由像素构成的,比如2828个像素,然后我们得到的X_train是3维的,总计60000,所以一开始我们查看X_shape的结果是(60000, 28, 28)这样的数据,也就是我们要想得到图片的话,我们只需要每次都得到2828的数据,至于怎么把这28*28的数据变成图片,matplotlib已经封装好了,感兴趣的话可以深究。
- 然后该函数将允许我们输出九张图片。
[En]
then this function will let us output nine pictures.*
- figure函数同样可以使用Ctrl+鼠标左键查看,这里的1是第一次作图的意思
- 接下来,设置图片的大小,也可以将其设置为您喜欢的大小。
[En]
next, set the size of the picture, or you can set it to your favorite size.*
- 然后从0到9生成9张图,其中subplot有3个参数,分别是行、列、第几张图,这里是3行3列
- 这里imshow就是我们刚刚将的封装好的画图
- grid消除网格线,不妨设置成True试着玩一下
- 最后使用plt.show()全部输出
plot_images(X_train)
这会产生一张包含9个子图像的图片。
[En]
This results in a picture containing nine sub-images.
在之前的鸢尾花数据集处理中,我们用sklearn的逻辑回归进行分类,流程大致如下:
- 数据集获取
- 数据集分类
- 数据集规则化
- 模型训练
- 模型预测
- 交叉验证
本例中有一个类似的过程
[En]
A similar process in this example
首先我们知道了,我们要600002828的数据,要处理的是28*28的数据,那我们可以先取出来看一下
print(X_train[1])
print(len(X_train[1]))
把数据类型修改成float类型的,并且压缩到[-1,1]
X_train = X_train.astype('float32')
X_test = X_test.astype('float32')
X_train = (X_train - 127)/127
X_test = (X_test - 127)/127
nb_classes = 10
from tensorflow.python.keras.utils import np_utils
print(y_train[1])
y_train = np_utils.to_categorical(y_train,nb_classes)
y_test = np_utils.to_categorical(y_test,nb_classes)
print(y_train[1])
这里需要说明的是np_utils包,如果看到其他的导包和我们的不一样也没关系,这个包是因为keras升级之后在env的位置变化不同,怎么导包最简单呢?按pycharm提示的做就好
0
[1. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
现在,我们可以设计我们的神经网络了。
[En]
Now, we can design our neural network.
像之前的虹膜一样,我们可以一路写下来,但也可以写成函数,以后更方便。
[En]
Like the iris before, we can write it down all the way, but we can also write it as a function, which is more convenient later.
在这里,对于keras,有两种类型的模型,一种是序贯模型,一种是函数式模型
序贯模型(Sequential)及一条路走到底,最简单,这次我们用这个
from tensorflow.python.keras import Sequential
from tensorflow.keras.layers import Dense,Activation,Dropout
def create_model():
"""
采用 keras 搭建神经网络模型
:return: 神经网络模型
"""
model = Sequential()
model.add(Dense(512, input_shape=(784,), kernel_initializer='he_normal'))
model.add(Activation('relu'))
model.add(Dense(512, kernel_initializer='he_normal'))
model.add(Activation('relu'))
model.add(Dense(nb_classes))
model.add(Activation('softmax'))
return model
这个函数脉络比较清晰,3组,每组都是Dense+Activation
Dense即每一层的神经元,每一层都可以自己设置神经元的个数,但是最后一层一定要是10,第一层输入要是784
Activation即激活函数
model = create_model()
下一步是训练和测试我们的神经网络。
[En]
The next step is to train and test our neural network.
def fit_and_predict(model, model_path):
"""
训练模型、模型评估、保存模型
:param model: 搭建好的模型
:param model_path:保存模型路径
:return:
"""
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
model.fit(X_train, y_train, epochs=5, batch_size=64, verbose=1, validation_split=0.05)
model.save(model_path)
loss, accuracy = model.evaluate(X_test, y_test)
print('Test loss:', loss)
print("Accuracy:", accuracy)
自定义训练模型、传入神经网络模型和路径(此处也可以不添加路径,下次可直接使用)
[En]
Custom training model, incoming neural network model and path (here you can also add no path, which can be used directly next time)
- 编译,第一个参数是优化方法,第二个参数定义loss,第三个参数是评估方法
- 训练,传入训练集、训练标记、循环次数、batch_size、模型日志
- 保存模型可不保存
最后,我们进行调用
fit_and_predict(model, model_path='./model.h5')
Epoch 1/5
891/891 [==============================] - 12s 13ms/step - loss: 0.4352 - accuracy: 0.8644 - val_loss: 0.1091 - val_accuracy: 0.9703
Epoch 2/5
891/891 [==============================] - 39s 43ms/step - loss: 0.1306 - accuracy: 0.9582 - val_loss: 0.0824 - val_accuracy: 0.9773
Epoch 3/5
891/891 [==============================] - 11s 13ms/step - loss: 0.0956 - accuracy: 0.9694 - val_loss: 0.0767 - val_accuracy: 0.9803
Epoch 4/5
891/891 [==============================] - 8s 8ms/step - loss: 0.0771 - accuracy: 0.9750 - val_loss: 0.0736 - val_accuracy: 0.9827
Epoch 5/5
891/891 [==============================] - 8s 9ms/step - loss: 0.0629 - accuracy: 0.9795 - val_loss: 0.0885 - val_accuracy: 0.9780
313/313 [==============================] - 169s 531ms/step - loss: 0.1071 - accuracy: 0.9685
Test loss: 0.10707166790962219
Accuracy: 0.968500018119812
Original: https://blog.csdn.net/Uncle_Perry/article/details/121172728
Author: Uncle_Perry
Title: 神经网络实现MNIST手写数字分类
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/514230/
转载文章受原作者版权保护。转载请注明原作者出处!