天天看點

tensorflow Optimizer算法

我的書:

tensorflow Optimizer算法

淘寶購買連結

當當購買連結

京東購買連結

##tensorflow優化器

種類如下,其中Optimizer是基類

tf.train.Optimizer
    tf.train.GradientDescentOptimizer
    tf.train.AdadeltaOptimizer
    tf.train.AdagradOptimizer
    tf.train.AdagradDAOptimizer
    tf.train.MomentumOptimizer
    tf.train.AdamOptimizer
    tf.train.FtrlOptimizer
    tf.train.ProximalGradientDescentOptimizer
    tf.train.ProximalAdagradOptimizer
    tf.train.RMSPropOptimizer
           

##tf.train.GradientDescentOptimizer

###梯度下降法

設:

h θ ( x ) = θ 1 x h_\theta(x)=\theta_1x hθ​(x)=θ1​x,其參數是 θ 1 \theta_1 θ1​,則其損失函數是:

J ( θ 1 ) = 1 2 m ∑ i = 1 m ( h θ ( x ( i ) ) − y ( i ) ) 2 J(\theta_1)=\frac{1}{2m}\sum_{i=1}^m(h_\theta(x^{(i)})-y^{(i)})^2 J(θ1​)=2m1​∑i=1m​(hθ​(x(i))−y(i))2

則 θ 1 \theta_1 θ1​通過如下求得:

m i n i m i z e θ 1 J ( θ 1 ) minimize_{\theta_1}J(\theta_1) minimizeθ1​​J(θ1​)

###梯度下降原理

設樣本集合是{(1,1), (2,2), (3,3)}.下圖是 θ 1 \theta_1 θ1​和 J ( θ 1 ) J(\theta_1) J(θ1​)變化情況。

tensorflow Optimizer算法

θ j = θ j − α ∂ ∂ θ j J ( θ 0 , θ 1 ) \theta_{j}=\theta_j-\alpha \frac{\partial}{\partial \theta_j}J(\theta_0,\theta_1) θj​=θj​−α∂θj​∂​J(θ0​,θ1​)

對參數中向量 θ \theta θ中的每個分量 θ j \theta_j θj​,疊代減去速率因子 η ∗ d J ( θ ) d θ j \eta*\frac{dJ(\theta)}{d\theta_j} η∗dθj​dJ(θ)​

###梯度下降法

####批量梯度下降法

$\theta_j=\theta_j-\eta \cdot \bigtriangledown_{\theta}J(\theta) $

如上例:

h ( θ ) = ∑ j = 0 n θ j x j h(\theta)=\sum_{j=0}^n\theta_jx_j h(θ)=∑j=0n​θj​xj​

J ( θ ) = 1 2 m ∑ i = 1 m ( y i − h θ ( x i ) ) 2 J(\theta)=\frac{1}{2m}\sum_{i=1}^m(y^i-h_\theta(x^i))^2 J(θ)=2m1​∑i=1m​(yi−hθ​(xi))2

2.求解方法

∂ J ( θ ) ∂ θ j = − 1 m ∑ i = 1 m ( y i − h θ ( x i ) ) x j i \frac{\partial{J(\theta)}}{\partial \theta_j}=-\frac{1}{m}\sum_{i=1}^m(y^i-h_\theta(x^i))x_j^i ∂θj​∂J(θ)​=−m1​∑i=1m​(yi−hθ​(xi))xji​

θ j = θ j + 1 m ∑ i = 1 m ( y i − h θ ( x i ) ) x j i \theta_j=\theta_j+\frac{1}{m}\sum_{i=1}^{m}(y^i-h_\theta(x^i))x_j^i θj​=θj​+m1​∑i=1m​(yi−hθ​(xi))xji​

全局最優,但是m很大時,計算量較大。

for i in range(nb_epochs):
  params_grad = evaluate_gradient(loss_function, data, params)
  params = params - learning_rate * params_grad
           

####随機梯度下降法

對每一個樣本 x i x^i xi根據label y i y^i yi進行更新

θ j = θ j − η ⋅ ▽ θ J ( θ ; x ( i ) ; y ( i ) ) \theta_j=\theta_j-\eta\cdot \bigtriangledown_{\theta}J(\theta;x^{(i)};y^{(i)}) θj​=θj​−η⋅▽θ​J(θ;x(i);y(i))

如上例:

J ( θ ) = 1 2 m ∑ i = 1 m ( y i − h θ ( x i ) ) 2 J(\theta)=\frac{1}{2m}\sum_{i=1}^m(y^i-h_\theta(x^i))^2 J(θ)=2m1​∑i=1m​(yi−hθ​(xi))2

梯度更新:

θ j = θ j + ( y i − h θ ( x i ) ) x j i , 對 每 一 個 j 求 解 \theta_j=\theta_j+(y^i-h_\theta(x^i))x_j^i,對每一個j求解 θj​=θj​+(yi−hθ​(xi))xji​,對每一個j求解

for i in range(nb_epochs):
  np.random.shuffle(data)
  for example in data:
    params_grad = evaluate_gradient(loss_function, example, params)
    params = params - learning_rate * params_grad
           

####mini-batch 梯度下降法

θ j = θ j − η ⋅ ▽ θ J ( θ ; x ( i ; i + n ) ; y ( i ; i + n ) ) \theta_j=\theta_j-\eta\cdot \bigtriangledown_{\theta}J(\theta;x^{(i;i+n)};y^{(i;i+n)}) θj​=θj​−η⋅▽θ​J(θ;x(i;i+n);y(i;i+n))

如n取50的情況:

for i in range(nb_epochs):
  np.random.shuffle(data)
  for batch in get_batches(data, batch_size=50):
    params_grad = evaluate_gradient(loss_function, batch, params)
    params = params - learning_rate * params_grad
           

###問題

1.合适的學習率, α \alpha α比較難獲得

α \alpha α過大導緻震蕩無法得到最優解,過小導緻學習過程漫長。

2.對所有參數學習率隻有一個,如果資料是稀疏的,并且特征具有不同的頻率時,更傾向于對不同頻率特征使用不同的學習率,對很少發生的特征采用較大的學習率。

3.目标函數門限需要提前定義,一旦計算中小于門限就停止,資料排程訓練的選擇對其有影響,通常使用shuffle打斷以減小這種影響。

4.高維非凸誤差函數最小求解技術難度大。

##tf.train.AdadeltaOptimizer

該算法不需要手動調優學習速率 α \alpha α,抗噪聲能力強,可以選擇不同的模型結構。

Adadelta是對Adagrad的擴充。Adadelta隻累加強定大小的項,并且也不直接存儲這些項,僅僅是計算對應的平均值。

上一節的參數更新模型是:

θ t + 1 = θ t − α d J ( θ ) d θ t \theta_{t+1}=\theta_t-\alpha\frac{dJ(\theta)}{d\theta_t} θt+1​=θt​−αdθt​dJ(θ)​

為友善,把 d J ( θ ) d θ t \frac{dJ(\theta)}{d\theta_t} dθt​dJ(θ)​記作 g t g_t gt​,把平滑後的梯度記作 E [ g ] t E[g]_t E[g]t​,則其平方表示如下:

E [ g 2 ] t = ρ E [ g 2 ] t − 1 + ( 1 − ρ ) g t 2 E[g^2]_t=\rho E[g^2]_{t-1}+(1-\rho)g_t^2 E[g2]t​=ρE[g2]t−1​+(1−ρ)gt2​

其中 ρ \rho ρ是平滑/衰減因子。其均方根得到的該值如下:

R M S [ g ] t = E [ g 2 ] t + ϵ RMS[g]_t=\sqrt{E[g^2]_t+\epsilon} RMS[g]t​=E[g2]t​+ϵ

其中 ϵ \epsilon ϵ是為了防止後續計算分母為零而引入的參數常量。

Δ θ = − R M S [ Δ θ ] t − 1 R M S [ g ] t g t \Delta \theta=-\frac{RMS[\Delta \theta]_{t-1}}{RMS[g]_t}g_t Δθ=−RMS[g]t​RMS[Δθ]t−1​​gt​

θ t + 1 = θ t + Δ θ t \theta_{t+1}=\theta_t+\Delta \theta_t θt+1​=θt​+Δθt​

###ADADELTA t時刻跟新過程如下:

前提衰減因子 ρ \rho ρ,常數 ϵ \epsilon ϵ,初始的 θ \theta θ值。

1 計算變量 E [ g 2 ] 0 = 0 E[g^2]_0=0 E[g2]0​=0, E [ Δ θ 2 ] 0 = 0 E[\Delta\theta^2]_0=0 E[Δθ2]0​=0

2: for t=1:T do %%Loop over #of updates

3: 計算梯度: g t g_t gt​

4: 滑動平均梯度: E [ g 2 ] t = ρ E [ g 2 ] t − 1 + ( 1 − ρ ) g t 2 E[g^2]_t=\rho E[g^2]_{t-1}+(1-\rho)g_t^2 E[g2]t​=ρE[g2]t−1​+(1−ρ)gt2​

  1. 計算參數跟新$\Delta \theta = - \frac{RMS[\Delta \theta^2]_t}{RMS[g]_t}g_t$
               
  2. 計算更新$E[\Delta x^2]_t=\rho E[\Delta \theta^2]_{t-1}+(1-\rho)\theta^2$
               
  3. 更新參數$\theta_{t+1}=\theta_t+\Delta \theta_t$
               

8.end for

##tf.train.AdagradOptimizer

Adagrad會累加之前所有的梯度平方。

Δ θ t = − η ∑ τ t g τ 2 + ϵ ⨀ g t \Delta \theta_t=-\frac{\eta}{\sqrt{\sum_\tau^tg_{\tau}^2+ \epsilon}} \bigodot g_t Δθt​=−∑τt​gτ2​+ϵ

​η​⨀gt​

θ t + 1 = θ t − η ∑ τ t g τ 2 + ϵ ⨀ g t \theta_{t+1}=\theta_t-\frac{\eta}{\sqrt{\sum_\tau^tg_{\tau}^2+\epsilon}} \bigodot g_t θt+1​=θt​−∑τt​gτ2​+ϵ

​η​⨀gt​

通常上述的求和針對一個窗長 w w w求解,以減小運算量。

##tf.train.AdagradDAOptimizer

tf.train.MomentumOptimizer

動量法的原理是,如果梯度長時間保持一個方向(為正或者長時間為負),則增大參數更新幅度,反之,如果頻繁發生符号翻轉,則說明這是要減小參數更新幅度。可以把這一過程了解成從山頂放下一個球,會滑的越來越快。

θ t = ρ θ t − 1 − η d J ( θ ) d θ t \theta_t=\rho\theta_{t-1}-\eta\frac{dJ(\theta)}{d\theta_t} θt​=ρθt−1​−ηdθt​dJ(θ)​

##tf.train.AdamOptimizer

Adam(Adaptive Moment Estimation)加上了bias校正和momentum,在優化末期,梯度更稀疏時,它比RMSprop稍微好點。

m t = β 1 m t − 1 + ( 1 − β 1 ) g t m_t=\beta_1m_{t-1}+(1-\beta_1)g_t mt​=β1​mt−1​+(1−β1​)gt​

v t = β 2 v t − 1 + ( 1 − β 2 ) g t 2 v_t=\beta_2v_{t-1}+(1-\beta_2)g_t^2 vt​=β2​vt−1​+(1−β2​)gt2​

其中 m t m_t mt​是梯度均值, v t v_t vt​是梯度偏方差。這兩個值初始化時為0的張量。在訓練開始時, m t m_t mt​和 v t v_t vt​趨向于零。可以使用如下估計方法抵消:

m ^ t = m t 1 − β 1 t \hat m_t=\frac{m_t}{1-\beta_1^t} m^t​=1−β1t​mt​​

v ^ t = v t 1 − β 2 t \hat v_t=\frac{v_t}{1-\beta_2^t} v^t​=1−β2t​vt​​

θ t + 1 = θ t − η v ^ t + ϵ m ^ t \theta_{t+1}=\theta_t-\frac {\eta}{\sqrt{\hat v_t + \epsilon}}\hat m_t θt+1​=θt​−v^t​+ϵ

​η​m^t​

##tf.train.FtrlOptimizer

##tf.train.ProximalGradientDescentOptimizer

##tf.train.ProximalAdagradOptimizer

##tf.train.RMSPropOptimizer

E [ g 2 ] t = 0.9 E [ g 2 ] t − 1 + 0.1 g t 2 E[g^2]_t=0.9E[g^2]_{t-1}+0.1g_t^2 E[g2]t​=0.9E[g2]t−1​+0.1gt2​

θ ) t + 1 = θ t − η E [ g 2 ] t + ϵ ⨀ g t \theta){t+1}=\theta_t-\frac{\eta}{\sqrt{E[g^2]_t+\epsilon}}\bigodot g_t θ)t+1=θt​−E[g2]t​+ϵ

​η​⨀gt​

學習速率梯度均方根均值指數衰減。

##如何選用optimizer

對于稀疏資料,使用學習率可自适應的優化方法,不用手動調節,而且最好采用預設值

SGD通常訓練時間更長,容易陷入鞍點,但是在好的初始化和學習率排程方案的情況下,結果更可靠

如果在意更快的收斂,并且需要訓練較深較複雜的網絡時,推薦使用學習率自适應的優化方法。

Adadelta,RMSprop,Adam是比較相近的算法,在相似的情況下表現差不多。

##其它梯度優化方法

1.資料重拍(shuffle函數)和資料多次重複訓練

2.批量歸一化,防止逐級訓練中的梯度消失和溢出

3.提前終止,防止過拟合,監控驗證資料集在訓練中的損失,合适時提前終止。

4.增加高斯分布的梯度噪聲,

g t , i = g t , i + N ( 0 , δ 2 ) g_{t,i}=g_{t,i}+N(0,\delta^2) gt,i​=gt,i​+N(0,δ2)

δ t 2 = η ( 1 + t ) γ \delta_t^2=\frac{\eta}{(1+t)^{\gamma}} δt2​=(1+t)γη​

這使得網絡對初始化不敏感。

##tensorflow中使用方法

建立優化器

# Create an optimizer with the desired parameters.
opt = GradientDescentOptimizer(learning_rate=0.1)
# Add Ops to the graph to minimize a cost by updating a list of variables.
# "cost" is a Tensor, and the list of variables contains tf.Variable
# objects.
opt_op = opt.minimize(cost, var_list=<list of variables>)
           

在訓練步驟中

# Execute opt_op to do one step of training:
opt_op.run()
           

minimize()函數處理了梯度計算和參數更新兩個操作,如果想獲得梯度并單獨處理,則compute_gradients()函數用于擷取梯度,apply_gradients()用于更新參數。

# Create an optimizer.
opt = GradientDescentOptimizer(learning_rate=0.1)

# Compute the gradients for a list of variables.
grads_and_vars = opt.compute_gradients(loss, <list of variables>)

# grads_and_vars is a list of tuples (gradient, variable).  Do whatever you
# need to the 'gradient' part, for example cap them, etc.
capped_grads_and_vars = [(MyCapper(gv[0]), gv[1]) for gv in grads_and_vars]

# Ask the optimizer to apply the capped gradients.
opt.apply_gradients(capped_grads_and_vars)
           

繼續閱讀