神經網絡訓練過程中,根據每batch訓練數據前向傳播的結果,計算損失函數,再由損失函數根據梯度下降法更新每一個網絡參數,在參數更新過程中使用到一個學習率(learning rate),用來定義每次參數更新的幅度。
過小的學習率會降低網絡優化的速度,增加訓練時間,過大的學習率可能導致網絡參數在最終的極優值兩側來回擺動,導致網絡不能收斂。實踐中證明有效的方法是設置一個根據迭代次數衰減的學習率,可以兼顧訓練效率和后期的穩定性。分段常數衰減
分段常數衰減是在事先定義好的訓練次數區間上,設置不同的學習率常數。剛開始學習率大一些,之后越來越小,區間的設置需要根據樣本量調整,一般樣本量越大區間間隔應該越小。
tf中定義了tf.train.piecewise_constant 函數,實現了學習率的分段常數衰減功能。
tf.train.piecewise_constant(
x,
boundaries,
values,
name=None
)
- x: 標量,指代訓練次數
- boundaries: 學習率參數應用區間列表
- values: 學習率列表,values的長度比boundaries的長度多一個
- name: 操作的名稱
# coding:utf-8
import matplotlib.pyplot as plt
import tensorflow as tf
num_epoch = tf.Variable(0, name='global_step', trainable=False)
boundaries = [10, 20, 30]
learing_rates = [0.1, 0.07, 0.025, 0.0125]
y = []
N = 40
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
for num_epoch in range(N):
learing_rate = tf.train.piecewise_constant(num_epoch, boundaries=boundaries, values=learing_rates)
lr = sess.run([learing_rate])
y.append(lr)
x = range(N)
plt.plot(x, y, 'r-', linewidth=2)
plt.title('piecewise_constant')
plt.show()

分段常數衰減可以讓調試人員針對不同任務設置不同的學習率,進行 精細調參,要求調試人員對模型和數據集有深刻認識,要求較高。
指數衰減
指數衰減是比較常用的衰減方法,學習率是跟當前的訓練輪次指數相關的。
tf中實現指數衰減的函數是 tf.train.exponential_decay()。tf.train.exponential_decay(
learning_rate,
global_step,
decay_steps,
decay_rate,
staircase=False,
name=None
)
- learning_rate: 初始學習率
- global_step: 當前訓練輪次,epoch
- decay_step: 定義衰減周期,跟參數staircase配合,可以在decay_step個訓練輪次內保持學習率不變
- decay_rate,衰減率系數
- staircase: 定義是否是階梯型衰減,還是連續衰減,默認是False,即連續衰減(標准的指數型衰減)
- name: 操作名稱
函數返回學習率數值,計算公式是:
decayed_learning_rate = learning_rate *
decay_rate ^ (global_step / decay_steps)
# coding:utf-8
import matplotlib.pyplot as plt
import tensorflow as tf
num_epoch = tf.Variable(0, name='global_step', trainable=False)
y = []
z = []
N = 200
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
for num_epoch in range(N):
# 階梯型衰減
learing_rate1 = tf.train.exponential_decay(
learning_rate=0.5, global_step=num_epoch, decay_steps=10, decay_rate=0.9, staircase=True)
# 標准指數型衰減
learing_rate2 = tf.train.exponential_decay(
learning_rate=0.5, global_step=num_epoch, decay_steps=10, decay_rate=0.9, staircase=False)
lr1 = sess.run([learing_rate1])
lr2 = sess.run([learing_rate2])
y.append(lr1)
z.append(lr2)
x = range(N)
fig = plt.figure()
ax = fig.add_subplot(111)
ax.set_ylim([0, 0.55])
plt.plot(x, y, 'r-', linewidth=2)
plt.plot(x, z, 'g-', linewidth=2)
plt.title('exponential_decay')
ax.set_xlabel('step')
ax.set_ylabel('learing rate')
plt.show()

紅色的是階梯型指數衰減,在一定輪次內學習率保持一致,綠色的是標准的指數衰減,即連續型指數衰減。
自然指數衰減
自然指數衰減是指數衰減的一種特殊情況,學習率也是跟當前的訓練輪次指數相關,只不過以 e 為底數。
tf中實現自然指數衰減的函數是 tf.train.natural_exp_decay()tf.train.natural_exp_decay(
learning_rate,
global_step,
decay_steps,
decay_rate,
staircase=False,
name=None
)
- learning_rate: 初始學習率
- global_step: 當前訓練輪次,epoch
- decay_step: 定義衰減周期,跟參數staircase配合,可以在decay_step個訓練輪次內保持學習率不變
- decay_rate,衰減率系數
- staircase: 定義是否是階梯型衰減,還是連續衰減,默認是False,即連續衰減(標准的指數型衰減)
- name: 操作名稱
自然指數衰減的計算公式是:
decayed_learning_rate = learning_rate * exp(-decay_rate * global_step)
# coding:utf-8
import matplotlib.pyplot as plt
import tensorflow as tf
num_epoch = tf.Variable(0, name='global_step', trainable=False)
y = []
z = []
w = []
m = []
N = 200
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
for num_epoch in range(N):
# 階梯型衰減
learing_rate1 = tf.train.natural_exp_decay(
learning_rate=0.5, global_step=num_epoch, decay_steps=10, decay_rate=0.9, staircase=True)
# 標准指數型衰減
learing_rate2 = tf.train.natural_exp_decay(
learning_rate=0.5, global_step=num_epoch, decay_steps=10, decay_rate=0.9, staircase=False)
# 階梯型指數衰減
learing_rate3 = tf.train.exponential_decay(
learning_rate=0.5, global_step=num_epoch, decay_steps=10, decay_rate=0.9, staircase=True)
# 標准指數衰減
learing_rate4 = tf.train.exponential_decay(
learning_rate=0.5, global_step=num_epoch, decay_steps=10, decay_rate=0.9, staircase=False)
lr1 = sess.run([learing_rate1])
lr2 = sess.run([learing_rate2])
lr3 = sess.run([learing_rate3])
lr4 = sess.run([learing_rate4])
y.append(lr1)
z.append(lr2)
w.append(lr3)
m.append(lr4)
x = range(N)
fig = plt.figure()
ax = fig.add_subplot(111)
ax.set_ylim([0, 0.55])
plt.plot(x, y, 'r-', linewidth=2)
plt.plot(x, z, 'g-', linewidth=2)
plt.plot(x, w, 'r-', linewidth=2)
plt.plot(x, m, 'g-', linewidth=2)
plt.title('natural_exp_decay')
ax.set_xlabel('step')
ax.set_ylabel('learing rate')
plt.show()

左下部分的兩條曲線是自然指數衰減,右上部分的兩條曲線是指數衰減,可見自然指數衰減對學習率的衰減程度要遠大於一般的指數衰減,一般用於可以較快收斂的網絡,或者是訓練數據集比較大的場合。
多項式衰減
多項式衰減是這樣一種衰減機制:定義一個初始的學習率,一個最低的學習率,按照設置的衰減規則,學習率從初始學習率逐漸降低到最低的學習率,並且可以定義學習率降低到最低的學習率之后,是一直保持使用這個最低的學習率,還是到達最低的學習率之后再升高學習率到一定值,然后再降低到最低的學習率(反復這個過程)。
tf中實現多項式衰減的函數是 tf.train.polynomial_decay()
tf.train.polynomial_decay(
learning_rate,
global_step,
decay_steps,
end_learning_rate=0.0001,
power=1.0,
cycle=False,
name=None
)
- learning_rate: 初始學習率
- global_step: 當前訓練輪次,epoch
- decay_step: 定義衰減周期
- end_learning_rate:最小的學習率,默認值是0.0001
- power: 多項式的冪,默認值是1,即線性的
- cycle: 定義學習率是否到達最低學習率后升高,然后再降低,默認False,保持最低學習率
- name: 操作名稱
多項式衰減的學習率計算公式:
global_step = min(global_step, decay_steps)
decayed_learning_rate = (learning_rate - end_learning_rate) *
(1 - global_step / decay_steps) ^ (power) +
end_learning_rate
如果定義 cycle為True,學習率在到達最低學習率后往復升高降低,此時學習率計算公式為:
decay_steps = decay_steps * ceil(global_step / decay_steps)
decayed_learning_rate = (learning_rate - end_learning_rate) *
(1 - global_step / decay_steps) ^ (power) +
end_learning_rate
# coding:utf-8
import matplotlib.pyplot as plt
import tensorflow as tf
y = []
z = []
N = 200
global_step = tf.Variable(0, name='global_step', trainable=False)
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
for global_step in range(N):
# cycle=False
learing_rate1 = tf.train.polynomial_decay(
learning_rate=0.1, global_step=global_step, decay_steps=50,
end_learning_rate=0.01, power=0.5, cycle=False)
# cycle=True
learing_rate2 = tf.train.polynomial_decay(
learning_rate=0.1, global_step=global_step, decay_steps=50,
end_learning_rate=0.01, power=0.5, cycle=True)
lr1 = sess.run([learing_rate1])
lr2 = sess.run([learing_rate2])
y.append(lr1)
z.append(lr2)
x = range(N)
fig = plt.figure()
ax = fig.add_subplot(111)
plt.plot(x, z, 'g-', linewidth=2)
plt.plot(x, y, 'r--', linewidth=2)
plt.title('polynomial_decay')
ax.set_xlabel('step')
ax.set_ylabel('learing rate')
plt.show()

紅色的學習率衰減曲線對應 cycle = False,下降后不再上升,保持不變,綠色的學習率衰減曲線對應 cycle = True,下降后往復升降。
多項式衰減中設置學習率可以往復升降的目的是為了防止神經網絡后期訓練的學習率過小,導致網絡參數陷入某個局部最優解出不來,設置學習率升高機制,有可能使網絡跳出局部最優解。
余弦衰減
余弦衰減的衰減機制跟余弦函數相關,形狀也大體上是余弦形狀。tf中的實現函數是:
tf.train.cosine_decay()
tf.train.cosine_decay(
learning_rate,
global_step,
decay_steps,
alpha=0.0,
name=None
)
- learning_rate:初始學習率
- global_step: 當前訓練輪次,epoch
- decay_steps: 衰減步數,即從初始學習率衰減到最小學習率需要的訓練輪次
- alpha=: 最小學習率
- name: 操作的名稱
余弦衰減學習率計算公式:
global_step = min(global_step, decay_steps)
cosine_decay = 0.5 * (1 + cos(pi * global_step / decay_steps))
decayed = (1 - alpha) * cosine_decay + alpha
decayed_learning_rate = learning_rate * decayed
改進的余弦衰減方法還有:
線性余弦衰減,對應函數 tf.train.linear_cosine_decay()
噪聲線性余弦衰減,對應函數 tf.train.noisy_linear_cosine_decay()
# coding:utf-8
import matplotlib.pyplot as plt
import tensorflow as tf
y = []
z = []
w = []
N = 200
global_step = tf.Variable(0, name='global_step', trainable=False)
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
for global_step in range(N):
# 余弦衰減
learing_rate1 = tf.train.cosine_decay(
learning_rate=0.1, global_step=global_step, decay_steps=50)
# 線性余弦衰減
learing_rate2 = tf.train.linear_cosine_decay(
learning_rate=0.1, global_step=global_step, decay_steps=50,
num_periods=0.2, alpha=0.5, beta=0.2)
# 噪聲線性余弦衰減
learing_rate3 = tf.train.noisy_linear_cosine_decay(
learning_rate=0.1, global_step=global_step, decay_steps=50,
initial_variance=0.01, variance_decay=0.1, num_periods=0.2, alpha=0.5, beta=0.2)
lr1 = sess.run([learing_rate1])
lr2 = sess.run([learing_rate2])
lr3 = sess.run([learing_rate3])
y.append(lr1)
z.append(lr2)
w.append(lr3)
x = range(N)
fig = plt.figure()
ax = fig.add_subplot(111)
plt.plot(x, z, 'b-', linewidth=2)
plt.plot(x, y, 'r-', linewidth=2)
plt.plot(x, w, 'g-', linewidth=2)
plt.title('cosine_decay')
ax.set_xlabel('step')
ax.set_ylabel('learing rate')
plt.show()

紅色標准余弦衰減,學習率從初始曲線過渡到最低學習率;
藍色線性余弦衰減,學習率從初始線性過渡到最低學習率;
綠色噪聲線性余弦衰減,在線性余弦衰減基礎上增加了隨機噪聲;
倒數衰減
倒數衰減指的是一個變量的大小與另一個變量的大小成反比的關系,具體到神經網絡中就是學習率的大小跟訓練次數有一定的反比關系。
tf中實現倒數衰減的函數是 tf.train.inverse_time_decay()。tf.train.inverse_time_decay(
learning_rate,
global_step,
decay_steps,
decay_rate,
staircase=False,
name=None
)
- learning_rate:初始學習率
- global_step:用於衰減計算的全局步數
- decay_steps:衰減步數
- decay_rate:衰減率
- staircase:是否應用離散階梯型衰減(否則為連續型)
- name:操作的名稱
倒數衰減的計算公式:
decayed_learning_rate =learning_rate/(1+decay_rate* global_step/decay_step)
# coding:utf-8
import matplotlib.pyplot as plt
import tensorflow as tf
y = []
z = []
N = 200
global_step = tf.Variable(0, name='global_step', trainable=False)
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
for global_step in range(N):
# 階梯型衰減
learing_rate1 = tf.train.inverse_time_decay(
learning_rate=0.1, global_step=global_step, decay_steps=20,
decay_rate=0.2, staircase=True)
# 連續型衰減
learing_rate2 = tf.train.inverse_time_decay(
learning_rate=0.1, global_step=global_step, decay_steps=20,
decay_rate=0.2, staircase=False)
lr1 = sess.run([learing_rate1])
lr2 = sess.run([learing_rate2])
y.append(lr1)
z.append(lr2)
x = range(N)
fig = plt.figure()
ax = fig.add_subplot(111)
plt.plot(x, z, 'r-', linewidth=2)
plt.plot(x, y, 'g-', linewidth=2)
plt.title('inverse_time_decay')
ax.set_xlabel('step')
ax.set_ylabel('learing rate')
plt.show()

倒數衰減不固定最小學習率,迭代次數越多,學習率越小。