【調參14】如何設置合適的Batch Size提高模型訓練的穩定性



使用梯度下降來訓練神經網絡,其中基於訓練數據集的子集計算用於更新權重的誤差的估計。誤差梯度的估計中使用的訓練數據集中的示例數稱爲批大小,並且是影響學習算法動力學的重要超參數。重要的是要探索模型的動態特性,以確保充分利用模型。

1. batch size 與 梯度下降

使用隨機梯度下降優化算法(Stochastic Gradient Descent,SGD)訓練神經網絡。

這涉及使用模型的當前狀態進行預測,將預測與期望值進行比較,並使用差異作爲誤差梯度的估計。然後,使用此誤差梯度來更新模型權重,並重復該過程。

誤差梯度是(error gradient)統計估計。估計中使用的訓練示例越多,則該估計將越準確,並且網絡權重以改善模型性能的方式調整的可能性就越大。誤差梯度的改進估計值是以必須使用模型做出更多預測爲代價的,然後才能計算估計值,並依次更新權重。使用整個訓練集的優化算法稱爲批處理或確定性梯度方法(batch or deterministic gradient methods),因爲它們會在一個大批次中同時處理所有訓練示例。

或者,使用較少的y樣本會導致誤差梯度的準確度估計較低,而誤差梯度的估計高度依賴於所使用的特定訓練y樣本。這導致噪聲估計,進而導致模型權重的噪聲更新,例如,許多更新的誤差梯度估計可能完全不同。但是,這些嘈雜的更新可能會導致學習速度加快,有時甚至會導致模型更強大。

一次僅使用一個yt樣本的優化算法有時稱爲隨機方法(stochastic methods),有時也稱爲在線方法(online methods)。在線術語一詞通常用於以下情況:樣本是從連續創建的樣本流中提取的,而不是從固定大小的訓練集中進行的。

誤差梯度估計中使用的訓練示例數量是學習算法的超參數,稱爲批大小(batch size),或簡稱爲批(batch)。批大小爲32意味着在更新模型權重之前,將使用訓練數據集中的32個樣本來估計誤差梯度。一個訓練循環(epoch)意味着學習算法已經遍歷了訓練數據集,其中將樣本按照隨機選擇的批處理大小分組。

將批次大小設置爲訓練樣本總數的訓練算法稱爲批次梯度下降(batch gradient descent),而將批次大小設置爲1個訓練樣本的訓練算法稱爲隨機梯度下降(stochastic gradient descent)在線梯度下降(online gradient descent)

介於兩者之間(例如,大於1個樣本且小於訓練數據集中的樣本數量)的批量大小的配置稱爲小批量梯度下降(minibatch gradient descent)

簡而言之,無論批次大小如何,該算法通常稱爲隨機梯度下降。鑑於非常大的數據集通常用於訓練深度學習神經網絡,因此批次大小很少設置爲訓練數據集的大小。

使用較小的批次大小有兩個主要原因:

  • 較小的批處理噪聲很大,提供了正則化效果和較低的泛化誤差。
  • 較小的批次大小可以更輕鬆地將一批訓練數據存儲在內存中(即使用GPU時)。
    第三個原因是批量大小通常設置爲較小的值,例如32個樣本,但在實際應用過程中常常需要調整。一般來說,小批量(例如32)通常效果很好,一般作爲默認值。

【Paper】Revisiting Small Batch Training for Deep Neural Networks(2018):在各種實驗中,對於給定的計算成本,使用小批量可以達到最佳的訓練穩定性和泛化性能。在所有情況下,批次大小m = 32或更小(通常小到m = 2或m = 4)都可獲得最佳結果。

但是,批次大小會影響模型學習的速度和學習過程的穩定性。它是一個重要的超參數,應該很好地理解並調整。


2. 三種梯度下降方法的Keras實現

2.1 Stochastic Gradient Descent

...
model.fit(trainX, trainy, batch_size=1)

2.2 Batch Gradient Descent

...
model.fit(trainX, trainy, batch_size=len(trainX))

2.3 Minibatch Gradient Descent

在keras中,如果不設置batch_size參數,則默認設置爲32。

...
model.fit(trainX, trainy, batch_size=64)

3. 多分類問題

3.1構造數據集

# scatter plot of blobs dataset
from sklearn.datasets import make_blobs
from matplotlib import pyplot
from numpy import where
# generate 2d classification dataset
X, y = make_blobs(n_samples=1000, centers=3, n_features=2, cluster_std=2, random_state=2)
# scatter plot for each class value
for class_value in range(3):
	# select indices of points with the class label
	row_ix = where(y == class_value)
	# scatter plot for points with a different color
	pyplot.scatter(X[row_ix, 0], X[row_ix, 1])
# show plot
pyplot.show()

創建的數據集有三類,整個數據集的散點圖如下圖所示。標準偏差爲2.0意味着這三類不是線性可分離的,從而導致許多歧義點。
在這裏插入圖片描述

3.2 批梯度下降 MLP

該模型有一個包含50個節點的隱藏層,relu激活函數和He隨機權重初始化。最後,輸出層具有3個節點,以便對這三個類別和softmax激活函數進行預測。

# mlp for the blobs problem with batch gradient descent
from sklearn.datasets import make_blobs
from keras.layers import Dense
from keras.models import Sequential
from keras.optimizers import SGD
from keras.utils import to_categorical
from matplotlib import pyplot
# generate 2d classification dataset
X, y = make_blobs(n_samples=1000, centers=3, n_features=2, cluster_std=2, random_state=2)
# one hot encode output variable
y = to_categorical(y)
# split into train and test
n_train = 500
trainX, testX = X[:n_train, :], X[n_train:, :]
trainy, testy = y[:n_train], y[n_train:]
# define model
model = Sequential()
model.add(Dense(50, input_dim=2, activation='relu', kernel_initializer='he_uniform'))
model.add(Dense(3, activation='softmax'))
# compile model
opt = SGD(lr=0.01, momentum=0.9)
model.compile(loss='categorical_crossentropy', optimizer=opt, metrics=['accuracy'])
# fit model
history = model.fit(trainX, trainy, validation_data=(testX, testy), epochs=200, verbose=0, batch_size=len(trainX))
# evaluate the model
_, train_acc = model.evaluate(trainX, trainy, verbose=0)
_, test_acc = model.evaluate(testX, testy, verbose=0)
print('Train: %.3f, Test: %.3f' % (train_acc, test_acc))
# plot training history
pyplot.plot(history.history['accuracy'], label='train')
pyplot.plot(history.history['val_accuracy'], label='test')
pyplot.legend()
pyplot.show()

從繪製的準確率曲線可以看出,訓練和測試集之間的性能相似,分別爲81%和83%。
在這裏插入圖片描述

3.3 隨機梯度下降 MLP

修改訓練代碼爲:

# fit model
history = model.fit(trainX, trainy, validation_data=(testX, testy), epochs=200, verbose=0, batch_size=1)

重新訓練得到:
在這裏插入圖片描述
在這種情況下,我們可以看到訓練和測試集之間的性能相似,準確度約爲60%,但比使用批梯度下降法要差得多(約20個百分點)。至少對於這個問題以及所選擇的模型和模型配置,隨機(在線)梯度下降是不合適的。

該圖顯示了所選配置下訓練過程的不穩定性質。較差的性能和對模型的劇烈更改表明,在每個訓練示例之後用於更新權重的學習速率可能太大,並且較小的學習速率可能會使學習過程更加穩定

修改學習率:

# compile model
opt = SGD(lr=0.001, momentum=0.9)
model.compile(loss='categorical_crossentropy', optimizer=opt, metrics=['accuracy'])

重新訓練
在這裏插入圖片描述

3.4 小批次梯度下降 MLP

# fit model
history = model.fit(trainX, trainy, validation_data=(testX, testy), epochs=200, verbose=0, batch_size=32)

折線圖顯示了隨機和批次梯度下降的動態。具體來說,該模型學習速度快,並且具有嘈雜的更新,但在運行結束時仍具有更大的穩定性,比隨機梯度下降更穩定。

在這裏插入圖片描述

3.5 批大小對模型性能的影響

# mlp for the blobs problem with minibatch gradient descent with varied batch size
from sklearn.datasets import make_blobs
from keras.layers import Dense
from keras.models import Sequential
from keras.optimizers import SGD
from keras.utils import to_categorical
from matplotlib import pyplot

# prepare train and test dataset
def prepare_data():
	# generate 2d classification dataset
	X, y = make_blobs(n_samples=1000, centers=3, n_features=2, cluster_std=2, random_state=2)
	# one hot encode output variable
	y = to_categorical(y)
	# split into train and test
	n_train = 500
	trainX, testX = X[:n_train, :], X[n_train:, :]
	trainy, testy = y[:n_train], y[n_train:]
	return trainX, trainy, testX, testy

# fit a model and plot learning curve
def fit_model(trainX, trainy, testX, testy, n_batch):
	# define model
	model = Sequential()
	model.add(Dense(50, input_dim=2, activation='relu', kernel_initializer='he_uniform'))
	model.add(Dense(3, activation='softmax'))
	# compile model
	opt = SGD(lr=0.01, momentum=0.9)
	model.compile(loss='categorical_crossentropy', optimizer=opt, metrics=['accuracy'])
	# fit model
	history = model.fit(trainX, trainy, validation_data=(testX, testy), epochs=200, verbose=0, batch_size=n_batch)
	# plot learning curves
	pyplot.plot(history.history['accuracy'], label='train')
	pyplot.plot(history.history['val_accuracy'], label='test')
	pyplot.title('batch='+str(n_batch), pad=-40)

# prepare dataset
trainX, trainy, testX, testy = prepare_data()
# create learning curves for different batch sizes
batch_sizes = [4, 8, 16, 32, 64, 128, 256, 450]
for i in range(len(batch_sizes)):
	# determine the plot number
	plot_no = 420 + (i+1)
	pyplot.subplot(plot_no)
	# fit model and plot learning curves for a batch size
	fit_model(trainX, trainy, testX, testy, batch_sizes[i])
# show learning curves
pyplot.show()

運行該示例將創建一個具有八條線圖的圖形,該圖形顯示了使用小批量梯度下降時不同批次大小的模型和測試集的分類精度。
在這裏插入圖片描述
這些圖表明,小批量通常會導致快速學習,但學習過程不穩定,並且分類精度差異較大。較大的批次大小會減慢學習過程,但最終階段會導致收斂到更穩定的模型,例如分類精度的較低差異。


參考:
https://machinelearningmastery.com/how-to-control-the-speed-and-stability-of-training-neural-networks-with-gradient-descent-batch-size/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章