本文知識(shí)點(diǎn):
- 什么是 mini-batch 梯度下降
- mini-batch 梯度下降具體算法
- 為什么需要 mini-batch 梯度下降
- batch, stochastic ,mini batch 梯度下降的比較
- 如何選擇 mini batch 的參數(shù) batch size 呢
- 在 TensorFlow 中應(yīng)用舉例
之前寫(xiě)過(guò)一篇文章:
如何選擇優(yōu)化器 optimizer
里面對(duì) BGD昂利,SGD,MBGD铁坎,Adagrad蜂奸,Adadelta,RMSprop硬萍,Adam 進(jìn)行了比較扩所,
今天對(duì)其中的 mini-batch 梯度下降 作進(jìn)一步詳解。
1. 什么是 mini-batch 梯度下降
先來(lái)快速看一下 BGD朴乖,SGD碌奉,MBGD 的定義,
當(dāng)每次是對(duì)整個(gè)訓(xùn)練集進(jìn)行梯度下降的時(shí)候寒砖,就是 batch 梯度下降赐劣,
當(dāng)每次只對(duì)一個(gè)樣本進(jìn)行梯度下降的時(shí)候,是 stochastic 梯度下降哩都,
當(dāng)每次處理樣本的個(gè)數(shù)在上面二者之間魁兼,就是 mini batch 梯度下降。
我們知道 Batch 梯度下降的做法是漠嵌,在對(duì)訓(xùn)練集執(zhí)行梯度下降算法時(shí)咐汞,必須處理整個(gè)訓(xùn)練集,然后才能進(jìn)行下一步梯度下降儒鹿。
如果在處理完整個(gè)訓(xùn)練集之前化撕,先讓梯度下降法處理一部分?jǐn)?shù)據(jù),那么算法就會(huì)相對(duì)快一些约炎。
也就是把整個(gè)大的訓(xùn)練集劃分為若干個(gè)小的訓(xùn)練集植阴,被稱(chēng)為 mini batch。
例如 500 萬(wàn)的訓(xùn)練集圾浅,劃分為每個(gè)子集中只有 1000 個(gè)樣本掠手,那么一共會(huì)有 5000 個(gè)這樣的子集。同樣的狸捕,對(duì) y 也做相應(yīng)的劃分:
(注:上角標(biāo)用大括號(hào)表示為第幾個(gè)子集喷鸽,小括號(hào)為第幾個(gè)樣本,中括號(hào)為神經(jīng)網(wǎng)絡(luò)的第幾層灸拍。)
這時(shí)候做祝,每一次對(duì)每個(gè)子集進(jìn)行整體梯度下降砾省,也就是對(duì) 1000 個(gè)樣本進(jìn)行整體梯度下降,而不是同時(shí)處理 500萬(wàn) 個(gè) x 和 y混槐。相應(yīng)的這個(gè)循環(huán)要執(zhí)行 5000 次纯蛾,因?yàn)橐还灿?5000 個(gè)這樣的子集。
2. mini-batch 梯度下降具體算法
t 代表第幾個(gè)子集纵隔,從 1 到 5000翻诉,因?yàn)閯澐趾螅还灿?5000 個(gè)子集捌刮,
1. 對(duì)每個(gè)子集碰煌,先進(jìn)行前向計(jì)算,從第一層網(wǎng)絡(luò)到最后一層輸出層
因?yàn)?batch 梯度下降是對(duì)整個(gè)數(shù)據(jù)集進(jìn)行處理绅作,所以不需要角標(biāo)芦圾,而 mini batch 這里需要對(duì) x 加上角標(biāo),代表的是第幾個(gè)子集俄认。
2. 接下來(lái)計(jì)算當(dāng)前子集的損失函數(shù)个少,因?yàn)樽蛹幸还灿?1000 個(gè)樣本,所以這里要除以 1000眯杏。損失函數(shù)也是有上角標(biāo)夜焦,和第幾個(gè)子集相對(duì)應(yīng)。
3. 然后進(jìn)行反向傳播岂贩,計(jì)算損失函數(shù) J 的梯度茫经。
4. 最后更新參數(shù)。
將 5000 個(gè)子集都計(jì)算完時(shí)萎津,就是進(jìn)行了一個(gè) epoch 處理 卸伞,一個(gè) epoch 意思是遍歷整個(gè)數(shù)據(jù)集,即 5000 個(gè)子數(shù)據(jù)集一次锉屈,也就是做了 5000 個(gè)梯度下降荤傲,
如果需要做多次遍歷,就需要對(duì) epoch 進(jìn)行循環(huán)颈渊。當(dāng)數(shù)據(jù)集很大的時(shí)候遂黍,這個(gè)方法是經(jīng)常被使用的。
3. 為什么需要 mini-batch 梯度下降
當(dāng)數(shù)據(jù)集很大時(shí)儡炼,訓(xùn)練算法是非常慢的妓湘,
和 batch 梯度下降相比查蓉,使用 mini batch 梯度下降更新參數(shù)更快乌询,有利于更魯棒地收斂,避免局部最優(yōu)豌研。
和 stochastic 梯度下降相比妹田,使用 mini batch 梯度下降的計(jì)算效率更高唬党,可以幫助快速訓(xùn)練模型。
4. 進(jìn)一步看 batch鬼佣, stochastic 驶拱,mini batch 梯度下降的比較
讓我們來(lái)看一下 cost 函數(shù)隨著訓(xùn)練的變化情況:
在 batch 梯度下降中,單次迭代的成本是會(huì)下降的晶衷,如果在某次迭代中成本增加了蓝纲,那就是有問(wèn)題了。
在 mini batch 梯度下降中晌纫,并不是每一批的成本都是下降的税迷,
因?yàn)槊看蔚际窃谟?xùn)練不同的子集,所以展示在圖像上就是锹漱,整體走勢(shì)是下降的箭养,但是會(huì)有更多的噪音。
噪音的原因是哥牍,如果是比較容易計(jì)算的子集毕泌,需要的成本就會(huì)低一些,遇到難算的子集嗅辣,成本就要高一些撼泛。
我們知道圖中中間那個(gè)點(diǎn)就是想要達(dá)到的最優(yōu)的情況:
藍(lán)色:為 batch 梯度下降,即 mini batch size = m澡谭,
紫色:為 stochastic 梯度下降坎弯,即 mini batch size = 1,
綠色:為 mini batch 梯度下降译暂,即 1 < mini batch size < m抠忘。
- Batch gradient descent ,噪音少一些外永,幅度大一些崎脉。
BGD 的缺點(diǎn)是,每次對(duì)整個(gè)訓(xùn)練集進(jìn)行處理伯顶,那么數(shù)量級(jí)很大的時(shí)候耗費(fèi)時(shí)間就會(huì)比較長(zhǎng)囚灼。
- Stochastic gradient descent ,因?yàn)槊看沃粚?duì)一個(gè)樣本進(jìn)行梯度下降祭衩,所以大部分時(shí)候是向著最小值靠近的灶体,但也有一些是離最小值越來(lái)越遠(yuǎn),因?yàn)槟切颖厩『弥赶蛳喾吹姆较蚱骸K钥雌饋?lái)會(huì)有很多噪音蝎抽,但整體趨勢(shì)是向最小值逼近。
但 SGD 永遠(yuǎn)不會(huì)收斂路克,它只會(huì)在最小值附近不斷的波動(dòng)樟结,不會(huì)到達(dá)也不會(huì)在此停留养交。
SGD 的噪音,可以通過(guò)調(diào)節(jié)學(xué)習(xí)率來(lái)改善瓢宦,但是它有一個(gè)很大的缺點(diǎn)碎连,就是不能通過(guò)進(jìn)行向量化來(lái)進(jìn)行加速,因?yàn)槊看味贾皇菍?duì)一個(gè)樣本進(jìn)行處理驮履。
- Mini Batch gradient descent 的每個(gè)子集的大小正好位于兩種極端情況的中間鱼辙。
那就有兩個(gè)好處,一個(gè)是可以進(jìn)行向量化玫镐。另一個(gè)是不用等待整個(gè)訓(xùn)練集訓(xùn)練完就可以進(jìn)行后續(xù)的工作座每。
MBGD 的成本函數(shù)的變化,不會(huì)一直朝著最小值的方向前進(jìn)摘悴,但和 SGD 相比峭梳,會(huì)更持續(xù)地靠近最小值。
5. 如何選擇 mini batch 的參數(shù) batch size 呢蹂喻?
不難看出 Mini Batch gradient descent 的 batch 大小葱椭,也是一個(gè)影響著算法效率的參數(shù)。
如果訓(xùn)練集較小口四,一般 小于2000 的孵运,就直接使用 Batch gradient descent 。
一般 Mini Batch gradient descent 的大小在 64 到 512 之間蔓彩,選擇 2 的 n 次冪會(huì)運(yùn)行得相對(duì)快一些治笨。
注意這個(gè)值設(shè)為 2 的 n 次冪,是為了符合cpu gpu的內(nèi)存要求赤嚼,如果不符合的話(huà)旷赖,不管用什么算法表現(xiàn)都會(huì)很糟糕。
6. 在 TensorFlow 中應(yīng)用舉例
下面這個(gè)例子是對(duì) fetch_california_housing 數(shù)據(jù)集 用一個(gè)簡(jiǎn)單的線(xiàn)性回歸預(yù)測(cè)房?jī)r(jià)更卒,在過(guò)程中用到了 mini batch 梯度下降:
損失用 MSE等孵,對(duì)每個(gè)子集 X_batch, y_batch
應(yīng)用 optimizer = tf.train.GradientDescentOptimizer
,
詳細(xì)注釋見(jiàn)代碼內(nèi):
# fetch_california_housing 數(shù)據(jù)集包含9個(gè)變量的20640個(gè)觀測(cè)值蹂空,
# 目標(biāo)變量為平均房屋價(jià)俯萌,
# 特征包括:平均收入、房屋平均年齡上枕、平均房間咐熙、平均臥室、人口辨萍、平均占用棋恼、緯度和經(jīng)度。
import numpy as np
import tensorflow as tf
from sklearn.datasets import fetch_california_housing
from sklearn.preprocessing import StandardScaler
housing = fetch_california_housing() #獲取房?jī)r(jià)數(shù)據(jù)
m, n = housing.data.shape # 獲得數(shù)據(jù)維度,矩陣的行列長(zhǎng)度
scalar = StandardScaler() #將特征進(jìn)行標(biāo)準(zhǔn)歸一化
scaled_housing_data = scalar.fit_transform( housing.data )
scaled_housing_data_plus_bias = np.c_[ np.ones( (m, 1) ), scaled_housing_data ] # np.c_是連接的含義蘸泻,加了一個(gè)全為1的列
learning_rate = 0.01
# X 和 y 為 placeholder琉苇,為后面將要傳進(jìn)來(lái)的數(shù)據(jù)占位
X = tf.placeholder( tf.float32, shape = (None, n + 1), name="X" ) # None 就是沒(méi)有限制嘲玫,可以任意長(zhǎng)
y = tf.placeholder( tf.float32, shape = (None, 1), name="y" )
# 隨機(jī)生成 theta悦施,形狀為 (n+1, n),元素在 [-1.0, 1.0) 之間
theta = tf.Variable( tf.random_uniform( [n + 1, 1], -1.0, 1.0, seed = 42 ), name="theta" )
# 線(xiàn)性回歸模型
y_pred = tf.matmul( X, theta, name="predictions" )
# 損失用 MSE
error = y_pred - y
mse = tf.reduce_mean( tf.square(error), name="mse" )
optimizer = tf.train.GradientDescentOptimizer( learning_rate = learning_rate )
training_op = optimizer.minimize( mse )
# 初始化所有變量
init = tf.global_variables_initializer()
n_epochs = 10
# 每一批內(nèi)樣本數(shù)設(shè)為 100
batch_size = 100
n_batches = int( np.ceil( m / batch_size ) ) # 總樣本數(shù)除以每一批的樣本數(shù)去团,得到批的個(gè)數(shù)抡诞,要得到比它大的最近的整數(shù)
# 從整批中獲取數(shù)據(jù)
def fetch_batch( epoch, batch_index, batch_size ):
np.random.seed( epoch * n_batches + batch_index ) # 用于 randin,每次可以得到不同的整數(shù)
indices = np.random.randint( m, size = batch_size ) # 設(shè)置隨機(jī)索引土陪,最大值為m
X_batch = scaled_housing_data_plus_bias[ indices ] # 使用索引從整批中獲取數(shù)據(jù)
y_batch = housing.target.reshape( -1, 1 )[ indices ]
return X_batch, y_batch
with tf.Session() as sess:
sess.run(init)
for epoch in range( n_epochs ):
for batch_index in range( n_batches ):
X_batch, y_batch = fetch_batch( epoch, batch_index, batch_size )
sess.run( training_op, feed_dict = {X: X_batch, y: y_batch} ) # 使用 feed_dict 將值從 placeholder 傳遞給 訓(xùn)練操作
best_theta = theta.eval() # 當(dāng)相應(yīng)的MSE小于之前的MSE時(shí)昼汗,theta將獲得新值
print("Best theta:\n", best_theta)
學(xué)習(xí)資料:
http://cs230.stanford.edu/syllabus.html
推薦閱讀 歷史技術(shù)博文鏈接匯總
http://www.reibang.com/p/28f02bb59fe5
也許可以找到你想要的:
[入門(mén)問(wèn)題][TensorFlow][深度學(xué)習(xí)][強(qiáng)化學(xué)習(xí)][神經(jīng)網(wǎng)絡(luò)][機(jī)器學(xué)習(xí)][自然語(yǔ)言處理][聊天機(jī)器人]