梯度下降、隨機梯度下降和批量梯度下降


轉載請注明出處,樓燚(yì)航的blog,http://www.cnblogs.com/louyihang-loves-baiyan/

這幾種方法呢都是在求最優解中經常出現的方法,主要是應用迭代的思想來逼近。在梯度下降算法中,都是圍繞以下這個式子展開:

\[\frac {\partial}{\partial \theta}{J(\theta)} = \frac{\partial}{\partial \theta} \frac{1}{2} \sum_{i=1}^{m}(h_\theta(x)-y)^2 \]

其中在上面的式子中\(h_\theta(x)\)代表,輸入為x的時候的其當時\(\theta\)參數下的輸出值,與y相減則是一個相對誤差,之后再平方乘以1/2,並且其中

\[h(x)=h_\theta(x)=\theta_0+\theta_1x_1+\theta_2x_2 \]

這里我列舉了一個簡單的例子,當然實際的x可以有n多個維度。我們知道曲面上方向導數的最大值的方向就代表了梯度的方向,因此我們在做梯度下降的時候,應該是沿着梯度的反方向進行權重的更新,可以有效的找到全局的最優解。這個\(\theta\)的更新過程可以描述為

\[\theta_i=\theta_i-\alpha\frac{\partial}{\partial \theta} J(\theta) = \theta_i-\alpha(h_\theta(x)-y)x_i \]

我一開始看這個式子也沒怎么看明白,后來想了一下,運來就是根據每一個x的分量以及當時的偏差值進行\(\theta\)的更新,其中\(\alpha\)為步長,一開始沒搞清楚步長和學習速率的關系。這里提一下其實這兩個是一個概念,叫法不一樣,最優化問題中叫步長,但一般在神經網絡中也叫學習速率,比較好理解。


對比梯度下降和隨機梯度下降和批量梯度下降

之前看的知識比較零散,沒有一個系統的解釋說明,看了一些網上的博主的分析,總結了一下自己的理解。

  • 梯度下降:梯度下降就是我上面的推導,要留意,在梯度下降中,對於\(\theta\)的更新,所有的樣本都有貢獻,也就是參與調整\(\theta\).其計算得到的是一個標准梯度。因而理論上來說一次更新的幅度是比較大的。如果樣本不多的情況下,當然是這樣收斂的速度會更快啦~

  • 隨機梯度下降:可以看到多了隨機兩個字,隨機也就是說我用樣本中的一個例子來近似我所有的樣本,來調整\(\theta\),因而隨機梯度下降是會帶來一定的問題,因為計算得到的並不是准確的一個梯度,容易陷入到局部最優解中

  • 批量梯度下降:其實批量的梯度下降就是一種折中的方法,他用了一些小樣本來近似全部的,其本質就是我1個指不定不太准,那我用個30個50個樣本那比隨機的要准不少了吧,而且批量的話還是非常可以反映樣本的一個分布情況的。

例子這里我參照其他博主的例子做了一些修改,首先是梯度下降

#-*- coding: utf-8 -*-
import random
#This is a sample to simulate a function y = theta1*x1 + theta2*x2
input_x = [[1,4], [2,5], [5,1], [4,2]]  
y = [19,26,19,20]  
theta = [1,1]
loss = 10
step_size = 0.001
eps =0.0001
max_iters = 10000
error =0
iter_count = 0
while( loss > eps and iter_count < max_iters):
	loss = 0
	#這里更新權重的時候所有的樣本點都用上了
	for i in range (3):
		pred_y = theta[0]*input_x[i][0]+theta[1]*input_x[i][1]
		theta[0] = theta[0] - step_size * (pred_y - y[i]) * input_x[i][0]
		theta[1] = theta[1] - step_size * (pred_y - y[i]) * input_x[i][1]
	for i in range (3):
		pred_y = theta[0]*input_x[i][0]+theta[1]*input_x[i][1]
		error = 0.5*(pred_y - y[i])**2
		loss = loss + error
	iter_count += 1
	print 'iters_count', iter_count

print 'theta: ',theta 
print 'final loss: ', loss
print 'iters: ', iter_count

iters_count 219
iters_count 220
iters_count 221
iters_count 222
iters_count 223
iters_count 224
iters_count 225
theta: [3.0027765778748003, 3.997918297015663]
final loss: 9.68238055213e-05
iters: 225
[Finished in 0.2s]

隨機梯度下降

每次選取一個隨機值,隨機一個點更新\(\theta\)

#-*- coding: utf-8 -*-
import random
#This is a sample to simulate a function y = theta1*x1 + theta2*x2
input_x = [[1,4], [2,5], [5,1], [4,2]]  
y = [19,26,19,20]  
theta = [1,1]
loss = 10
step_size = 0.001
eps =0.0001
max_iters = 10000
error =0
iter_count = 0
while( loss > eps and iter_count < max_iters):
	loss = 0
	#每一次選取隨機的一個點進行權重的更新
	i = random.randint(0,3)
	pred_y = theta[0]*input_x[i][0]+theta[1]*input_x[i][1]
	theta[0] = theta[0] - step_size * (pred_y - y[i]) * input_x[i][0]
	theta[1] = theta[1] - step_size * (pred_y - y[i]) * input_x[i][1]
	for i in range (3):
		pred_y = theta[0]*input_x[i][0]+theta[1]*input_x[i][1]
		error = 0.5*(pred_y - y[i])**2
		loss = loss + error
	iter_count += 1
	print 'iters_count', iter_count

print 'theta: ',theta 
print 'final loss: ', loss
print 'iters: ', iter_count

其結果的輸出是

iters_count 1226
iters_count 1227
iters_count 1228
iters_count 1229
iters_count 1230
iters_count 1231
iters_count 1232
theta: [3.002441488688225, 3.9975844154600226]
final loss: 9.989420302e-05
iters: 1232
[Finished in 0.3s]

批量隨機梯度下降

這里用了2個樣本點

#-*- coding: utf-8 -*-
import random
#This is a sample to simulate a function y = theta1*x1 + theta2*x2
input_x = [[1,4], [2,5], [5,1], [4,2]]  
y = [19,26,19,20]  
theta = [1,1]
loss = 10
step_size = 0.001
eps =0.0001
max_iters = 10000
error =0
iter_count = 0
while( loss > eps and iter_count < max_iters):
	loss = 0
	
	i = random.randint(0,3) #注意這里,我這里批量每次選取的是2個樣本點做更新,另一個點是隨機點+1的相鄰點
	j = (i+1)%4
	pred_y = theta[0]*input_x[i][0]+theta[1]*input_x[i][1]
	theta[0] = theta[0] - step_size * (pred_y - y[i]) * input_x[i][0]
	theta[1] = theta[1] - step_size * (pred_y - y[i]) * input_x[i][1]

	pred_y = theta[0]*input_x[j][0]+theta[1]*input_x[j][1]
	theta[0] = theta[0] - step_size * (pred_y - y[j]) * input_x[j][0]
	theta[1] = theta[1] - step_size * (pred_y - y[j]) * input_x[j][1]
	for i in range (3):
		pred_y = theta[0]*input_x[i][0]+theta[1]*input_x[i][1]
		error = 0.5*(pred_y - y[i])**2
		loss = loss + error
	iter_count += 1
	print 'iters_count', iter_count

print 'theta: ',theta 
print 'final loss: ', loss
print 'iters: ', iter_count

其最后的輸出結果是

.....
iters_count 543
iters_count 544
iters_count 545
iters_count 546
iters_count 547
iters_count 548
iters_count 549
theta: [3.0023012574840764, 3.997553282857357]
final loss: 9.81717138358e-05
iters: 549

對比一下結果,每個例子我都跑了幾次,基本上都維持在哪個迭代次數,可以看到梯度下降迭代的次數最少,因為我這里樣本點少,所以這樣快。數據多了的話,你想動則幾萬的樣本計算一次的時間就夠嗆。隨機梯度的話因為每次都用一個樣本,所以收斂的速度就會慢一些。批量的話這里用了2個樣本點,因而速度基本上隨機是1200度次迭代,批量大概是550。
其實這些概念一開始沒搞明白,在Caffe中,跑網絡,里面讓你選的這個batch其實就是這么回事。你設一個比較恰當的batch值是可以幫助網絡加速收斂的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM