優化方法與TensorFlow程序用例
前言
深度學習常常需要大量的時間和機算資源進行訓練,這也是困擾深度學習演算法開發的重大原因。雖然我們可以採用分散式並行訓練加速模型的學習,但所需的計算資源並沒有絲毫減少。而唯有需要資源更少、令模型收斂更快的最優化演算法,才能從根本上加速機器的學習速度和效果。本文僅對一些常見的優化方法進行直觀介紹和簡單的比較。
梯度下降法,是當今最流行的優化(optimization)演算法,亦是至今最常用的優化神經網路的方法。本文旨在讓你對不同的優化梯度下降法的演算法有一個直觀認識,以幫助你使用這些演算法。
梯度下降法,是當今最流行的優化(optimization)演算法,亦是至今最常用的優化神經網路的方法。與此同時,最新的深度學習程序庫都包含了各種優化梯度下降的演算法。
https://www.jiqizhixin.com/articles/2016-11-21-4
梯度下降法的核心,是最小化目標函數 J(θ),其中θ是模型的參數,θ∈Rd。它的方法是,在每次迭代中,對每個變數,按照目標函數在該變數梯度的相反方向,更新對應的參數值。其中,學習率η決定了函數到達(局部)最小值的迭代次數。換句話說,我們在目標函數的超平面上,沿著斜率下降的方向前進,直到我們遇到了超平面構成的「谷底」。如果你不熟悉梯度下降法的話,你可以在這裡找到一個很好的關於優化神經網路的介紹。
https://zhuanlan.zhihu.com/p/22252270
學習率
學習率(learning_rate)可理解為每一次梯度下降的步長,一般設置學習率小於0.1,具體多少其實算是一門玄學,全靠經驗。當學習率過大時,可能導致參數在最低點附近來回震蕩,始終到達不了最優點;當學習率過小時,前期梯度下降的速度極其慢,浪費時間。所以最優的方法是前期學習率設置大點,讓梯度迅速下降,隨後慢慢將學習率減小,以求達到最優點。
在TensorFlow中提供了類似的設置學習率方法——指數衰減法。用tf.train.exponential_decay實現。
其中0.1為初始學習率;100表示每100輪學習率變一次,這個輪數是由total_data除以batch_size得到的,也可以理解為每一個epoch學習率變一次;0.98表示每次變化為上一次學習率乘以0.98;staircase=True表示成階梯函數下降,False時表示連續衰減。
示例代碼如下所示:
import tensorflow as tfglobal_step=tf.contrib.framework.get_or_create_global_step()lr=tf.train.exponential_decay(0.1,global_step,100,0.98,staircase=True)tf.train.GradientDescentOptimizer(lr)init=tf.global_variables_initializer()with tf.Session() as sess: sess.run(init) print(sess.run(global_step))
SGD
此處的SGD指mini-batch gradient descent,SGD就是每一次迭代計算mini-batch的梯度,然後對參數進行更新,是最常見的優化方法了。是學習率,是梯度SGD完全依賴於當前batch的梯度。
import tensorflow as tfx = tf.constant([[1], [2], [3], [4]], dtype=tf.float32)y_true = tf.constant([[0], [-1], [-2], [-3]], dtype=tf.float32)W = tf.Variable([.3], dtype=tf.float32)b = tf.Variable([-.3], dtype=tf.float32)y_pred = W * x + bloss = tf.losses.mean_squared_error(labels=y_true, predictions=y_pred)optimizer = tf.train.GradientDescentOptimizer(0.01)grads_and_vars = optimizer.compute_gradients(loss)apply_updates = optimizer.apply_gradients(grads_and_vars)init = tf.global_variables_initializer()with tf.Session() as sess: sess.run(init) for i in range(200): print(i, sess.run([W, b])) sess.run(apply_updates)
#http://f.dataguru.cn/thread-861765-1-1.htmlimport tensorflow as tfimport numpy as npimport matplotlib.pyplot as plt# Prepare train datatrain_X = np.linspace(-1, 1, 100)train_Y = 2 * train_X + np.random.randn(*train_X.shape) * 0.33 + 10# Define the modelX = tf.placeholder("float")Y = tf.placeholder("float")w = tf.Variable(0.0, name="weight")b = tf.Variable(0.0, name="bias")loss = tf.square(Y - X*w - b)train_op = tf.train.GradientDescentOptimizer(0.01).minimize(loss)# Create session to runwith tf.Session() as sess: sess.run(tf.initialize_all_variables()) epoch = 1 for i in range(10): for (x, y) in zip(train_X, train_Y): _, w_value, b_value = sess.run([train_op, w, b],feed_dict={X: x,Y: y}) print("Epoch: {}, w: {}, b: {}".format(epoch, w_value, b_value)) epoch += 1#drawplt.plot(train_X,train_Y,"+")plt.plot(train_X,train_X.dot(w_value)+b_value)plt.show()
Momentum
momentum是模擬物理里動量的概念,積累之前的動量來替代真正的梯度。動量項 γ 往往被設置為 0.9 或為其他差不多的值。
train_op = tf.train.MomentumOptimizer(learning_rate=0.01,momentum=0.9).minimize(loss)
Nesterov 加速梯度法
nesterov項在梯度更新時做一個校正,避免前進太快,同時提高靈敏度。
train_op = tf.train.MomentumOptimizer(learning_rate=0.01,momentum=0.9, use_nesterov=True).minimize(loss)
下面是自適應學習率的方法:
Adagrad
Adagrad其實是對學習率進行了一個約束。
Adagrad 主要優勢之一,是它不需要對每個學習率手工地調節。而大多數演算法,只是簡單地使用一個相同地默認值如 0.1。Adagrad 地主要劣勢,是他在分母上的項中積累了平方梯度和。因為每次加入的項總是一個正值,所以累積的和將會隨著訓練過程而增大。因而,這會導致學習率不斷縮小,並最終變為一個無限小值——此時,這個演算法已經不能從數據中學到額外的信息。
train_op = tf.train.AdagradOptimizer(learning_rate=1,initial_accumulator_value=0.01).minimize(loss)
Adadelta
Adadelta是對Adagrad的擴展,最初方案依然是對學習率進行自適應約束,但是進行了計算上的簡化。Adagrad會累加之前所有的梯度平方,而Adadelta只累加固定大小的項,並且也不直接存儲這些項,僅僅是近似計算對應的平均值
在此處Adadelta其實還是依賴於全局學習率的,但是作者做了一定處理,經過近似牛頓迭代法之後,Adadelta已經不用依賴於全局學習率了。
訓練初中期,加速效果不錯,很快
訓練後期,反覆在局部最小值附近抖動
#rho: The decay rate for adadeltatrain_op = tf.train.AdadeltaOptimizer(learning_rate=100, rho=0.95).minimize(loss)
RMSprop
RMSprop可以算作Adadelta的一個特例,其實RMSprop依然依賴於全局學習率 RMSprop算是Adagrad的一種發展,和Adadelta的變體,效果趨於二者之間適合處理非平穩目標對於RNN效果很好 。
#http://blog.csdn.net/bvl10101111/article/details/72616378train_op = tf.train.RMSPropOptimizer(learning_rate=1, decay=0.9, momentum=0.9).minimize(loss)ortrain_op = tf.train.RMSPropOptimizer(learning_rate=1, decay=0.9).minimize(loss)
Adam
Adam(Adaptive Moment Estimation)本質上是帶有動量項的RMSprop,它利用梯度的一階矩估計和二階矩估計動態調整每個參數的學習率。Adam的優點主要在於經過偏置校正後,每一次迭代學習率都有個確定範圍,使得參數比較平穩。
結合了Adagrad善於處理稀疏梯度和RMSprop善於處理非平穩目標的優點 ,對內存需求較小
為不同的參數計算不同的自適應學習率 ,也適用於大多非凸優化適用於大數據集和高維空間。
# beta1: A float value or a constant float tensor.# The exponential decay rate for the 1st moment estimates.# beta2: A float value or a constant float tensor.# The exponential decay rate for the 2nd moment estimates.train_op = tf.train.AdamOptimizer(learning_rate=0.1, beta1=0.9, beta2=0.99).minimize(loss)
推薦閱讀:
※深度學習巨頭Yann Lecun 中科院自動化所座談及清華大學講座乾貨速遞(一)(內含珍貴歷史影像及學術八卦)
※Tensorflow simple code
※K-means聚類 的 Python 實現【圖文解釋】
※TensorFlow 的簡單例子
※配置深度學習主機與環境(TensorFlow+1080Ti) | 第一章:硬體選購與主機組裝
TAG:優化 | TensorFlow | 深度學習DeepLearning |