深度学习小白一名,记录第一次神经网络的搭建
我会对所有的代码做解释说明,外加上一些自己的理解和看法
有理解错的部分或者是相关问题欢迎在评论区指出
所有参考代码均来自TensorFlow官网
官网基本图像分类由此进
1. 库引入
首先是最基本的库引入:
Tensorflow框架
numpy库
数据图像绘制工具matplotlib.pyplot
# TensorFlow and tf.keras
import tensorflow as tf
from tensorflow import keras
# Helper libraries
import numpy as np
import matplotlib.pyplot as plt
2.FashionMnist数据集的导入
Fashion MNIST数据集中包含10个类别的70,000张衣物的灰度图像,分辨率为28×28像素。另外Fashion Mnist数据集是内置在TensorFlow框架中的,所以直接使用下列语句就可以载入这个数据集:
fashion_mnist = keras.datasets.fashion_mnist
(train_images, train_labels), (test_images, test_labels) = fashion_mnist.load_data()
前面的二元集载入的是训练图像和标签,而后面的二元集载入的是用于测试网络的图像和标签。载入方法是内置的load_data()方法。
这些图像是28x28维的NumPy数组,像素值分布在0到255之间。标签(Label)是一个整数数组,范围从0到9,与图像所代表的衣物类别相对应:
标签 | 标签对应的类 |
---|---|
0 | T-shirt/top |
1 | Trouser |
2 | Pullover |
3 | Dress |
4 | Coat |
5 | Sandal |
6 | Shirt |
7 | Sneaker |
8 | Bag |
9 | Ankle boot |
由于类名并没有在数据集中被标注,所以我们需要一个自己的类来存放这些类名,帮助我们在后面完成相关数据图像的绘制
class_names = ['T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat',
'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot']
之后,我们需要进行像素值(灰度值)的归一化处理:
train_images = train_images / 255.0
test_images = test_images / 255.0
关于为什么要对0-255的灰度值进行归一化处理,我从网上找到的一种解释是:
输入的归一化是为了让某些激活函数的梯度不致于过小,加快收敛
而另一种解释是:
归一化操作是深度学习模型输入数据之前要进行一项很重要的操作。在不同的评价指标中,量纲单位往往不同,变化区间处于不同的数量级,若不进行归一化,会导致某些指标被忽视,从而影响到数据分析的结果。归一化本身就是把你需要的数据经过一定的处理限制在一定的范围内。
我自己对上面这种解释的理解是这样:举个例子,我们要训练一个预测房价的模型。那么最基本的面积和房间数存在较大的数值差异。面积一般是几十到几百的数值,而房间数量一般是只有几个的。那么房间数量在面积这一数值面前,影响力就相对较小。而归一化可以减少这种影响力差异,让面积和房间数量得到相同对待。
3.构建网络模型
3.1构建网络模型
我们使用下面的代码构建模型:
model = keras.Sequential([
keras.layers.Flatten(input_shape=(28, 28)),
keras.layers.Dense(128, activation='relu'),
keras.layers.Dense(10, activation='softmax')
])
(1) Keras.Sequential()是模型Sequential的构造方法
(2) keras.layers.Flatten()是该网络的第一层,用于将28x28的二维图像展开为一维。(变成一列784像素的一维图片)
(3) keras.layers.Dense()是定义网络层的基本方法,这里定义了两个层,第一个层有128个神经元,使用RELU作为激活函数。而第二个层是输出,有10个神经元,使用SOFTMAX函数作为激活函数,对应了上面十个标签类的输出。
关于更多keras.layers.Dense()方法的操作,可以参考官网API(全英),或者是这一篇博客keras.layers.Dense()方法
3.2 参数设置
在对模型进行训练之前,需要额外设置一些参数。这些是在模型的编译步骤中添加的:
损失函数(Loss function):用来衡量训练过程中模型的准确性,模型训练时通过最小化这个函数来”引导“模型朝正确的方向前进;
优化器(Optimizer):是模型根据数据和损失函数进行更新的方式;
度量(Metrics):用于监视训练和测试步骤。下面的例子使用accuracy度量,即被正确分类的图像的比例
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
其中adam优化器是基于梯度下降法的优化器,比较优秀
损失函数是交叉熵损失函数
4.训练模型
训练神经网络模型需要以下步骤:
(1)将训练数据输入模型。在本例中,训练数据存放在train_images和train_tags数组中;
(2)模型通过学习把图像和标签联系起来;
(3)让模型对本例中的测试集test_images数组进行预测。验证预测是否与test_labels数组中的标签匹配。
要开始训练,使用model.fit方法:
model.fit(train_images, train_labels, epochs=10)
关于该方法的所有含义可以参照这一篇博客model.fit()参数解释说明
这个是在我自己本地电脑上跑出来的运行结果
当模型训练时,会输出显示损失(loss)和精度(accuracy)度量指标。该模型的精度约为0.91(或91%)
5.在测试数据集上评估模型的精度
test_loss, test_acc = model.evaluate(test_images, test_labels, verbose=2)
print('\nTest accuracy:', test_acc)
测试结果:
0.88的正确率略低于训练集,但这是正常现象
6.看看预测效果
模型到这里基本就训练完了,我们可以用图像来看一下该模型的表现:
predictions = model.predict(test_images)
def plot_image(i, predictions_array, true_label, img):
predictions_array, true_label, img = predictions_array, true_label[i], img[i]
plt.grid(False)
plt.xticks([])
plt.yticks([])
plt.imshow(img, cmap=plt.cm.binary)
predicted_label = np.argmax(predictions_array)
if predicted_label == true_label:
color = 'blue'
else:
color = 'red'
plt.xlabel("{} {:2.0f}% ({})".format(class_names[predicted_label],
100*np.max(predictions_array),
class_names[true_label]),
color=color)
def plot_value_array(i, predictions_array, true_label):
predictions_array, true_label = predictions_array, true_label[i]
plt.grid(False)
plt.xticks(range(10))
plt.yticks([])
thisplot = plt.bar(range(10), predictions_array, color="#777777")
plt.ylim([0, 1])
predicted_label = np.argmax(predictions_array)
thisplot[predicted_label].set_color('red')
thisplot[true_label].set_color('blue')
num_rows = 5
num_cols = 3
num_images = num_rows*num_cols
plt.figure(figsize=(2*2*num_cols, 2*num_rows))
for i in range(num_images):
plt.subplot(num_rows, 2*num_cols, 2*i+1)
plot_image(i, predictions[i], test_labels, test_images)
plt.subplot(num_rows, 2*num_cols, 2*i+2)
plot_value_array(i, predictions[i], test_labels)
plt.tight_layout()
plt.show()
下图为输出结果:
柱状表示了对该图片分类预测的概率。可以看见有一张图片(红色柱)分类错误了。
7.结语
这是我第一次搭建网络,是跟着教程来的。该网络是一个十分十分基础的图像分类的网络。
其中大部分参考来源于这篇文章:基本图像分类
虽然是一个十分简单的网络,但是毕竟是第一次跑成功,还是有点激动的。
之后的计划是往卷积神经网络的方向深入,最后完成一个图像隐写的模型。如果能够成功,我会把项目公开到GitHub上,供大家一起改进。