1. 程式人生 > >tensorflow 優化器optimizer

tensorflow 優化器optimizer

1. 優化器的種類

Optimizer  GradientDescentOptimizer  AdagradOptimizer  AdagradDAOptimizer  MomentumOptimizer  AdamOptimizer  FtrlOptimizer  RMSPropOptimizer

 2. GradientDescentOptimizer

with tf.name_scope("cross_ent"):
    loss = tf.reduce_mean(
        tf.nn.softmax_cross_entropy_with_logits(logits=score, labels=y))
 
# Train op 
with tf.name_scope("train"):
    # Get gradients of all trainable variables
    gradients = tf.gradients(loss, var_list)  #導數
    gradients = list(zip(gradients, var_list))
 
    # Create optimizer and apply gradient descent to the trainable variables
    optimizer = tf.train.GradientDescentOptimizer(learning_rate)
    train_op = optimizer.apply_gradients(grads_and_vars=gradients)

 其中

tf.train.Optimizer.apply_gradients(grads_and_vars, global_step=None, name=None)

Apply gradients to variables.This is the second part of minimize(). It returns an Operation that applies gradients. Args:  grads_and_vars: List of (gradient, variable) pairs as returned by compute_gradients(). global_step: Optional Variable to increment by one after the variables have been updated. name: Optional name for the returned operation. Default to the name passed to the Optimizer constructor. Returns:  An Operation that applies the specified gradients. If global_step was not None, that operation also increments global_step.

█ 優化 (Optimizers)

tf中各種優化類提供了為損失函式計算梯度的方法,其中包含比較經典的優化演算法,比如GradientDescent 和Adagrad。

▶▶class tf.train.Optimizer

操作 描述
class tf.train.Optimizer 基本的優化類,該類不常常被直接呼叫,而較多使用其子類, 比如GradientDescentOptimizer, AdagradOptimizer 或者MomentumOptimizer
tf.train.Optimizer.__init__(use_locking, name) 建立一個新的優化器, 該優化器必須被其子類(subclasses)的建構函式呼叫
tf.train.Optimizer.minimize(loss, global_step=None,  var_list=None, gate_gradients=1,  aggregation_method=None, colocate_gradients_with_ops=False,  name=None, grad_loss=None) 新增操作節點,用於最小化loss,並更新var_list 該函式是簡單的合併了compute_gradients()與apply_gradients()函式 返回為一個優化更新後的var_list,如果global_step非None,該操作還會為global_step做自增操作
tf.train.Optimizer.compute_gradients(loss,var_list=None, gate_gradients=1, aggregation_method=None,  colocate_gradients_with_ops=False, grad_loss=None) 對var_list中的變數計算loss的梯度 該函式為函式minimize()的第一部分,返回一個以元組(gradient, variable)組成的列表
tf.train.Optimizer.apply_gradients(grads_and_vars, global_step=None, name=None) 將計算出的梯度應用到變數上,是函式minimize()的第二部分,返回一個應用指定的梯度的操作Operation,對global_step做自增操作
tf.train.Optimizer.get_name() 獲取名稱

▷ class tf.train.Optimizer  用法

# 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()操作,該操作不僅可以計算出梯度,而且還可以將梯度作用在變數上。如果想在使用它們之前處理梯度,可以按照以下三步驟使用optimizer :

1、使用函式compute_gradients()計算梯度

2、按照自己的願望處理梯度

3、使用函式apply_gradients()應用處理過後的梯度

例如:

# 建立一個optimizer.
opt = GradientDescentOptimizer(learning_rate=0.1)
 
# 計算<list of variables>相關的梯度
grads_and_vars = opt.compute_gradients(loss, <list of variables>)
 
# grads_and_vars為tuples (gradient, variable)組成的列表。
#對梯度進行想要的處理,比如cap處理
capped_grads_and_vars = [(MyCapper(gv[0]), gv[1]) for gv in grads_and_vars]
 
# 令optimizer運用capped的梯度(gradients)
opt.apply_gradients(capped_grads_and_vars)

選通梯度(Gating Gradients)  函式minimize() 與compute_gradients()都含有一個引數gate_gradient,用於控制在應用這些梯度時並行化的程度。

其值可以取:GATE_NONE, GATE_OP 或 GATE_GRAPH  GATE_NONE : 並行地計算和應用梯度。提供最大化的並行執行,但是會導致有的資料結果沒有再現性。比如兩個matmul操作的梯度依賴輸入值,使用GATE_NONE可能會出現有一個梯度在其他梯度之前便應用到某個輸入中,導致出現不可再現的(non-reproducible)結果 GATE_OP: 對於每個操作Op,確保每一個梯度在使用之前都已經計算完成。這種做法防止了那些具有多個輸入,並且梯度計算依賴輸入情形中,多輸入Ops之間的競爭情況出現。 GATE_GRAPH: 確保所有的變數對應的所有梯度在他們任何一個被使用前計算完成。該方式具有最低級別的並行化程度,但是對於想要在應用它們任何一個之前處理完所有的梯度計算時很有幫助的。

█ Slots

一些optimizer的之類,比如 MomentumOptimizer 和 AdagradOptimizer 分配和管理著額外的用於訓練的變數。這些變數稱之為’Slots’,Slots有相應的名稱,可以向optimizer訪問的slots名稱。有助於在log debug一個訓練演算法以及報告slots狀態

操作 描述
tf.train.Optimizer.get_slot_names() 返回一個由Optimizer所建立的slots的名稱列表
tf.train.Optimizer.get_slot(var, name) 返回一個name所對應的slot,name是由Optimizer為var所建立 var為用於傳入 minimize() 或 apply_gradients()的變數
class tf.train.GradientDescentOptimizer 使用梯度下降演算法的Optimizer
tf.train.GradientDescentOptimizer.__init__(learning_rate,  use_locking=False, name=’GradientDescent’) 構建一個新的梯度下降優化器(Optimizer)
class tf.train.AdadeltaOptimizer
tf.train.AdadeltaOptimizer.__init__(learning_rate=0.001,  rho=0.95, epsilon=1e-08,  use_locking=False, name=’Adadelta’) 建立Adadelta優化器
class tf.train.AdagradOptimizer
tf.train.AdagradOptimizer.__init__(learning_rate,  initial_accumulator_value=0.1,  use_locking=False, name=’Adagrad’) 建立Adagrad優化器
class tf.train.MomentumOptimizer 使用Momentum演算法的Optimizer
tf.train.MomentumOptimizer.__init__(learning_rate,  momentum, use_locking=False,  name=’Momentum’, use_nesterov=False) 建立momentum優化器 momentum:動量,一個tensor或者浮點值
class tf.train.AdamOptimizer 使用Adam 演算法的Optimizer
tf.train.AdamOptimizer.__init__(learning_rate=0.001, beta1=0.9, beta2=0.999, epsilon=1e-08, use_locking=False, name=’Adam’) 建立Adam優化器
class tf.train.FtrlOptimizer 使用FTRL 演算法的Optimizer
tf.train.FtrlOptimizer.__init__(learning_rate,  learning_rate_power=-0.5,  initial_accumulator_value=0.1,  l1_regularization_strength=0.0,  l2_regularization_strength=0.0, use_locking=False, name=’Ftrl’) 建立FTRL演算法優化器
class tf.train.RMSPropOptimizer
tf.train.RMSPropOptimizer.__init__(learning_rate,  decay=0.9, momentum=0.0, epsilon=1e-10,  use_locking=False, name=’RMSProp’) 建立RMSProp演算法優化器
m_0 <- 0 (Initialize initial 1st moment vector)
v_0 <- 0 (Initialize initial 2nd moment vector)
t <- 0 (Initialize timestep)

論文中的 section2 的末尾所描述了更新規則,該規則使用梯度g來更新變數:

t <- t + 1 lr_t <- learning_rate * sqrt(1 - beta2^t) / (1 - beta1^t)   m_t <- beta1 * m_{t-1} + (1 - beta1) * g v_t <- beta2 * v_{t-1} + (1 - beta2) * g * g variable <- variable - lr_t * m_t / (sqrt(v_t) + epsilon)

其中epsilon 的預設值1e-8可能對於大多數情況都不是一個合適的值。例如,當在ImageNet上訓練一個 Inception network時比較好的選擇為1.0或者0.1。 需要注意的是,在稠密資料中即便g為0時, m_t, v_t 以及variable都將會更新。而在稀疏資料中,m_t, v_t 以及variable不被更新且值為零。

梯度計算與截斷(Gradient Computation and Clipping)

TensorFlow 提供了計算給定tf計算圖的求導函式,並在圖的基礎上增加節點。優化器(optimizer )類可以自動的計算網路圖的導數,但是優化器中的建立器(creators )或者專業的人員可以通過本節所述的函式呼叫更底層的方法。

操作 描述
tf.gradients(ys, xs, grad_ys=None, name=’gradients’,  colocate_gradients_with_ops=False, gate_gradients=False,  aggregation_method=None) 構建一個符號函式,計算ys關於xs中x的偏導的和, 返回xs中每個x對應的sum(dy/dx)
tf.stop_gradient(input, name=None) 停止計算梯度, 在EM演算法、Boltzmann機等可能會使用到
tf.clip_by_value(t, clip_value_min, clip_value_max, name=None) 基於定義的min與max對tesor資料進行截斷操作, 目的是為了應對梯度爆發或者梯度消失的情況
tf.clip_by_norm(t, clip_norm, axes=None, name=None) 使用L2正規化標準化tensor最大值為clip_norm 返回 t * clip_norm / l2norm(t)
tf.clip_by_average_norm(t, clip_norm, name=None) 使用平均L2正規化規範tensor資料t, 並以clip_norm為最大值 返回 t * clip_norm / l2norm_avg(t)
tf.clip_by_global_norm(t_list,  clip_norm, use_norm=None, name=None) 返回t_list[i] * clip_norm / max(global_norm, clip_norm) 其中global_norm = sqrt(sum([l2norm(t)**2 for t in t_list]))
tf.global_norm(t_list, name=None) 返回global_norm = sqrt(sum([l2norm(t)**2 for t in t_list]))