一緒に書く習慣をつけましょう!「ナゲッツデイリーニュープラン・4月アップデートチャレンジ」に参加して9日目です。クリックしてイベントの詳細をご覧ください。
入力データセットのスケーリングの概要
データセットのスケーリングは、ネットワークがトレーニングされる前にデータを前処理するプロセスであり、その過程で、データセット内のデータの範囲を制限して、データが大きな間隔に分散しないようにします。これを実現する1つの方法は、データセット内の各データをデータセット内の最大のデータで除算することです。一般に、入力データセットをスケーリングすると、ニューラルネットワークのパフォーマンスを向上させることができ、一般的に使用されるデータ前処理方法の1つです。
データセットスケーリングの合理的な解釈
このセクションでは、データセットのスケーリングによってニューラルネットワークのパフォーマンスが向上する理由を説明します。入力のスケーリングが出力に与える影響を理解するために、入力データセットがスケーリングされていない場合のモデルのパフォーマンスと、入力データセットがスケーリングされている場合のパフォーマンスを比較します。入力データがスケーリングされていない場合、さまざまな重み値の作用下でのsigmoid
関数次の表に示します。
入力 | ウェイト | バイアス | シグモイド値 |
---|---|---|---|
255 | 0.01 | 0 | 0.93 |
255 | 0.1 | 0 | 1.00 |
255 | 0.2 | 0 | 1.00 |
255 | 0.4 | 0 | 1.00 |
255 | 0.8 | 0 | 1.00 |
255 | 1.6 | 0 | 1.00 |
255 | 3.2 | 0 | 1.00 |
255 | 6.4 | 0 | 1.00 |
上記の表では、重み値が0.01から6.4の間で変化しても、関数を通過したSigmoid
後。この現象を説明するために、最初Sigmoid
に関数の計算方法を思い出します。
output = 1/(1+np.exp(-(w*x + b))
复制代码
ここw
で、は重み、x
は入力、b
はバイアス値です。
sigmoid
出力が変化しない理由はw * x
、の積が大きいため(主にx
大きいため)、sigmoid
値常に曲線sigmoid
の飽和部分sigmoid
(の右上隅または左下隅の値)に収まるためです。曲線は飽和部分と呼ばれます)。一方、さまざまな重み値に小さい入力数を掛けると、結果は次のようになります。
入力 | ウェイト | バイアス | シグモイド値 |
---|---|---|---|
1 | 0.01 | 0 | 0.50 |
1 | 0.1 | 0 | 0.52 |
1 | 0.2 | 0 | 0.55 |
1 | 0.4 | 0 | 0.60 |
1 | 0.8 | 0 | 0.69 |
1 | 1.6 | 0 | 0.83 |
1 | 3.2 | 0 | 0.96 |
1 | 6.4 | 0 | 1.00 |
由于输入值较小,因此上表中的 Sigmoid
输出值会随权重的变化发生改变。
通过此示例,我们了解了缩放输入对数据集的影响,当权重(假设权重不具有较大范围)乘以较小输入值时,使输入数据能够对输出产生足够重要的影响。同样当权重值也很大时,输入值对输出的影响将变得不太重要。因此,我们一般将权重值初始化为更接近零的较小数值。同时,为了获得最佳的权重值,通常设置初始化权重的范围变化不大,比如权重在初始化期间采样介于 -1 和 +1 之间的随机值。
接下来,我们对使用的数据集MNIST进行缩放,并比较使用和不使用数据缩放对性能的影响。
使用缩放后的数据集训练模型
- 导入相关的包和
MNIST
数据集:
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()
复制代码
- 缩放数据集有多种方法。一种方法是将所有数据点转换为 0 到 1 之间的值(通过将每个数据点除以数据集中的最大值,在本例中最大值为 255),展平输入数据集并对其进行缩放,如下所示:
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.
复制代码
另一种流行的数据缩放方法是对数据集进行归一化,以使值转换到 -1 和 +1 之间,方法是用数据平均值减去数据点,然后将得到的结果除以原始数据集的标准差:
- 将训练和测试输入的值缩放至
[0, 1]
后,我们将数据集的标签转换为独热编码格式:
y_train = np_utils.to_categorical(y_train)
y_test = np_utils.to_categorical(y_test)
num_classes = y_test.shape[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'])
复制代码
上述模型与我们在《使用Keras构建神经网络》中构建的模型完全相同,唯一的区别是本节模型将在缩放后的数据集上进行训练。
- 拟合模型,如下所示:
history = model.fit(x_train, y_train,
validation_data=(x_test, y_test),
epochs=50,
batch_size=64,
verbose=1)
复制代码
モデルの精度は約です98.41%
が、データをスケーリングせずにトレーニングされたモデルの精度は97%
約です。さまざまなトレインとテストepoch
のプロットします(グラフをプロットするためのコードは、トレーニングの元のニューラルネットワークメソッドで使用されているものとまったく同じです):
上のグラフからわかるように、トレーニングとテストの損失の変化は、スケーリングされていないデータセットでトレーニングされたモデルと比較して、より緩やかです。ネットワークは損失値をスムーズに減らすことができますが、トレーニングとテストの精度の間に大きなギャップが見られます。これは、トレーニングデータセットに過剰適合がある可能性があることを示しています。過剰適合は、モデルがトレーニングデータに過剰適合しているために発生します。これにより、テストデータセットのパフォーマンスがトレーニングデータセットよりも低下し、一般化のパフォーマンスが低下します。
値を最大値で除算してデータセットをスケーリングする以外に、一般的に使用される他のスケーリング方法は次のとおりです。
- 最小-最大正規化
- 平均正規化
- 標準偏差の正規化