简介
mnist是机器学习领域的经典数据集,其用例学习堪比编程领域的的“hello world”。
它包含60000张训练图像和10000张测试图像,这些图像是手写的数字,目的是要通过机器学习的方法把这些图像分为10类:0——9。
mnist数据集预先加载在keras库中,其中包含有4个Numpy数组。
关于mnist数据加载的问题,请参考本地加载测试mnist数据集——使用keras库。
开始构建神经网络
跟我一起来,按下面的步骤构建网络。
- 加载数据集
from keras.datasets import mnist
path = r"E:\practice\tf2\mnist.npz" # 修改为数据实际路径
(train_images, train_labels), (test_images, test_labels) = tf.keras.datasets.mnist.load_data(path)
数据集由训练图像、训练标签和测试图像、测试标签组成。前者用来训练网络,后者用来对网络的效果进行测试。
数据加载完毕,按下来的工作流程是:
- 将训练数据输入神经网络
- 网络学习将图像和标签关联在一起
- 网络对test_images生成预测,我们最后验证一下,这些预测是否与test_labels中的标签相匹配
- 搭建网络架构
from keras import models
from keras import layers
network = models.Sequential()
network.add(layers.Dense(512, activation = 'relu', input_shape = (28 * 28, )))
network.add(layers.Dense(10, activation = 'softmax'))
其中,神经网络的核心是layer,它是一种数据处理模块,可以看作数据过滤器。层从数据中提取出表示。
本例中使用2个Dense层,它们是全连接的神经层。第二层是一个10路的softmax层,它将返回由10个概率值组成的数组。
- 编译
框架建立好了,下面开始编译,它需要三个参数:
- 损失函数(loss function):网络衡量在训练数据上的性能,即网络如何朝着正确的方向前进。
- 优化器(optimizer): 基于训练数据和损失函数来更新网络的机制。
- 在训练和测试过程中需要监控的指标(metric):本例只关心精度,即正确分类的图像所占的比例。
代码如下:
network.compile(optimizer = 'rmsprop', loss = 'categorical_crossentropy', metrics = ['accuracy'])
- 准备图像数据
在开始训练之前,需要对数据进行预处理,转化为网络要求的形状,并绽放到所有值都在[0,1]区间。
比如,之前训练图像保存在一个uint8类型的数组中,形状为(60000, 28, 28),取值区间为[0, 255],需要转化为float32数组,形状为(60000, 28 * 28),取值范围为0~1。
train_images = train_images.reshape((60000, 28 * 28))
train_images = train_images.astype('float32') / 255
test_images = test_images.reshape((10000, 28 * 28))
test_images = test_images.astype('float32') / 255
- 标签分类
我们还需要对标签进行分类编码:
from keras.utils import to_categorical
train_labels = to_categorical(train_labels)
test_labels = to_categorical(test_labels)
- 训练网络
终于到这一步了。
我们通过调用网络的fit方法来完成:
network.fit(train_images, train_labels, epochs = 5, batch_size = 128)
在训练数据上fit(拟合)模型,这一过程会输出如下内容:
>>> network.fit(train_images, train_labels, epochs = 5, batch_size = 128)
Epoch 1/5
469/469 [==============================] - 4s 8ms/step - loss: 0.2562 - accuracy: 0.9262
Epoch 2/5
469/469 [==============================] - 4s 8ms/step - loss: 0.1030 - accuracy: 0.9697
Epoch 3/5
469/469 [==============================] - 4s 8ms/step - loss: 0.0681 - accuracy: 0.9795
Epoch 4/5
469/469 [==============================] - 4s 8ms/step - loss: 0.0492 - accuracy: 0.9851
Epoch 5/5
469/469 [==============================] - 4s 8ms/step - loss: 0.0370 - accuracy: 0.9887
<tensorflow.python.keras.callbacks.History object at 0x00000238703E47B8>
>>>
其中,loss为网络在训练数据上的损失,accuracy为网络在训练数据上的精度。
可以看到,我们很快就在训练数据上达到了98.8%的精度。
- 测试效果
最后来检查一下模型在测试集上的效果:
test_loss, test_acc = network.evaluate(test_images, test_labels)
print('test_acc: ', test_acc)
输出如下:
>>> test_loss, test_acc = network.evaluate(test_images, test_labels)
313/313 [==============================] - 1s 2ms/step - loss: 0.0717 - accuracy: 0.9787
>>> print('test_acc', test_acc)
test_acc 0.9786999821662903
可见,模型在测试集上的精度为97.8%,比训练集上的效果差了不少。
这种训练精度和测试精度之间的差距,就是过拟合(overfit)造成的。
过拟合是指机器学习模型在新数据上的性能往往比在训练数据上要差。
小结
整个深度学习的过程就是这样,其中有很多概念没有涉及,会在以后的学习中继续总结。
现在在整个代码放在一起:
from keras.datasets import mnist
path = r"E:\practice\tf2\mnist.npz" # 修改为数据实际路径
(train_images, train_labels), (test_images, test_labels) = mnist.load_data(path)
from keras import models
from keras import layers
network = models.Sequential()
network.add(layers.Dense(512, activation = 'relu', input_shape = (28 * 28, )))
network.add(layers.Dense(10, activation = 'softmax'))
network.compile(optimizer = 'rmsprop', loss = 'categorical_crossentropy', metrics = ['accuracy'])
train_images = train_images.reshape((60000, 28 * 28))
train_images = train_images.astype('float32') / 255
test_images = test_images.reshape((10000, 28 * 28))
test_images = test_images.astype('float32') / 255
from keras.utils import to_categorical
train_labels = to_categorical(train_labels)
test_labels = to_categorical(test_labels)
network.fit(train_images, train_labels, epochs = 5, batch_size = 128)
test_loss, test_acc = network.evaluate(test_images, test_labels)
print('test_acc: ', test_acc)
ok,就是这些简单的代码,就完成了神经网络的构建和训练。
参考资料
《python深度学习》