神经网络实现MNIST手写数字分类

学习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/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球