Keras深度学习——输入值分布对神经网络模型性能的影响

683 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第11天,点击查看活动详情

输入值分布对模型性能的影响

虽然我们已经能够以较高都准确率识别手写数字,但我们还没有查看 MNIST 数据集中值的分布情况,而输入值的不同分布可以改变训练速度。在本节中,我们将了解如何通过修改输入值以缩短训练时间,更快地训练权重。构建与原始神经网络完全相同的模型架构,但是,将对输入数据集进行一些小的更改:

  • 反转背景色和前景色。本质上,是将背景涂成白色,数字涂成黑色。

我们首先从理论上分析像素值对模型性能的影响。由于黑色像素值为零,当此输入乘以任何权重值时,输出为零。这将导致黑色像素连接到隐藏层的权重值无论如何更改都不会影响损失值。但是,如果有一个白色像素,那么它将对某些隐藏节点值有所贡献,权重需要进行调整。

  1. 加载并缩放输入数据集:
from keras.datasets import mnist
import numpy as np
from keras.models import Sequential
from keras.layers import Dense, Dropout
from keras.utils import np_utils
import matplotlib.pyplot as plt

(x_train, y_train), (x_test, y_test) = mnist.load_data()

num_pixels = x_train.shape[1] * x_train.shape[2]
x_train = x_train.reshape(-1, num_pixels).astype('float32')
x_test = x_test.reshape(-1, num_pixels).astype('float32')
x_train = x_train / 255.
x_test = x_test / 255.

y_train = np_utils.to_categorical(y_train)
y_test = np_utils.to_categorical(y_test)
num_classes = y_test.shape[1]
  1. 查看输入值的分布情况:
x_train.flatten()

前面的代码将所有输入展平到一个形状为 (28×28×x_train.shape[0]=4704000028\times 28 \times x\_train.shape[0]=47040000) 的列表中。绘制所有输入值的分布情况:

plt.hist(x_train.flatten())
plt.title('Histogram of input values')
plt.xlabel('Input values')
plt.ylabel('Frequency of input values')
plt.show()

由于输入图像的背景为黑色,因此大多数输入都是零(黑色像素值)。

数据值分布

  1. 使用以下代码反转颜色,使得背景为白色,数字为黑色。
x_train = 1-x_train
x_test = 1-x_test

绘制图像:

plt.subplot(221)
plt.imshow(x_train[0].reshape(28,28), cmap='gray')
plt.subplot(222)
plt.imshow(x_train[1].reshape(28,28), cmap='gray')
plt.subplot(223)
plt.imshow(x_test[0].reshape(28,28), cmap='gray')
plt.subplot(224)
plt.imshow(x_test[1].reshape(28,28), cmap='gray')
plt.show()

如下所示: 反转后的图片

反转颜色后生成图像的直方图如下所示:

数据值分布

可以看到,现在大多数输入值的值为 1。

  1. 使用与之前完全相同的模型架构:
model = Sequential()
model.add(Dense(1000, input_dim=num_pixels, activation='relu'))
model.add(Dense(num_classes, activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['acc'])

history = model.fit(x_train, y_train,
                    validation_data=(x_test, y_test),
                    epochs=50,
                    batch_size=64,
                    verbose=1)

绘制不同 epoch 的训练和测试的准确率以及损失值:

准确率和损失值的变化

可以看到,模型准确率下降到到 97%,相比之下,在未反转数据集的时(数据集中数据值多数为零),使用相同的 epoch 数、批大小和模型架构,训练得到的模型的准确率约为 98%。而像素值反转(数据集中数据值零较少)的情况下模型的精度为 97%,且训练过程比大多数输入像素为零的情况要慢得多。当大多数像素为零时,模型的训练更加容易,因为它只需要根据像素值大于零的少数像素值进行预测。但是,当大多数像素不为零时,需要微调更多的权重以减小损失值。

相关链接

Keras深度学习——训练原始神经网络

Keras深度学习——缩放输入数据集提升神经网络性能