TensorFlow 中維護的集合列表
在一個計算圖中,可以通過集合(collection
)來管理不同類別的資源。比如通過 tf.add_to_collection
函數可以將資源加入一個或多個集合中,然后通過 tf.get_collection
獲取一個集合里面的所有資源(如張量,變量,或者運行TensorFlow程序所需的隊列資源等等)。比如,通過 tf.add_n(tf.get_collection('losses'))
獲得總損失。
集合名稱 | 集合內容 | 使用場景 |
---|---|---|
tf.GraphKeys.VARIABLES |
所有變量 | 持久化 TensorFlow 模型 |
tf.GraphKeys.TRAINABLE_VARIABLES |
可學習的變量(一般指神經網絡中的參數) | 模型訓練、生成模型可視化內容 |
tf.GraphKeys.SUMMARIES |
日志生成相關的張量 | TensorFlow 計算可視化 |
tf.GraphKeys.QUEUE_RUNNERS |
處理輸入的 QueueRunner | 輸入處理 |
tf.GraphKeys.MOVING_AVERAGE_VARIABLES |
所有計算了滑動平均值的變量 | 計算變量的滑動平均值 |
- TensorFlow中的所有變量都會被自動加入
tf.GraphKeys.VARIABLES
集合中,通過tf.global_variables()
函數可以拿到當前計算圖上的所有變量。拿到計算圖上的所有變量有助於持久化整個計算圖的運行狀態。 - 當構建機器學習模型時,比如神經網絡,可以通過變量聲明函數中的
trainable
參數來區分需要優化的參數(比如神經網絡的參數)和其他參數(比如迭代的輪數,即超參數),若trainable = True
,則此變量會被加入tf.GraphKeys.TRAINABLE_VARIABLES
集合。然后通過tf.trainable_variables
函數便可得到所有需要優化的參數。TensorFlow中提供的優化算法會將tf.GraphKeys.TRAINABLE_VARIABLES
集合中的變量作為 默認的優化對象。
示例
tf.get_collection
的第一個參數是集合的名字,第二個參數是要加入集合的內容:
def get_weight(shape, lambda1):
# 獲取一層神經網絡邊上的權重
var = tf.Variable(tf.random_normal(shape), dtype=tf.float32)
# 將這個權重的 L2 正則化損失加入名稱為 'losses' 的集合中
tf.add_to_collection('losses',
tf.contrib.layers.l2_regularizer(lambda1)(var))
return var
變量初始化函數
神經網絡中的參數是通過 TensorFlow 中的變量來組織、保存和使用的。TensorFlow 中提供了兩種變量機制:tf.Variable
和 tf.get_variable
.
- 變量的類型是不可以改變的。
- 變量的維度一般是不能改變的,除非設置參數
validate_shape = False
(很少去改變它)
隨機數初始化函數
函數名 | 隨機數分布 | 主要參數 |
---|---|---|
tf.random_normal |
正態分布 | 平均值、標准差、取值類型 |
tf.truncated_normal |
滿足正態分布的隨機值,但若隨機值偏離平均值超過2個標准差,則這個數會被重新隨機 | 平均值、標准差、取值類型 |
tf.random_uniform |
平均分布 | 最大、最小值、取值類型 |
tf.random_gamma |
Gramma分布 | 形狀參數alpha、尺度參數beta、取值類型 |
常量初始化函數
函數名 | 功能 | 示例 |
---|---|---|
tf.zeros |
產生全0的數組 | tf.zeros([2, 3],tf.int32) |
tf.ones |
產生全1的數組 | tf.ones([2, 3],tf.int32) |
tf.fill |
產生一個全部為給定數組的數組 | tf.fill([2,3], 9) |
tf.constant |
產生一個給定值的常量 | tf.constant([2,3,4]) |
tf.get_variable
變量初始化函數
初始化函數 | 功能 | 主要參數 |
---|---|---|
tf.constant_initializer |
將變量初始化為給定常數 | 常數的取值 |
tf.random_normal_initializer |
將變量初始化為滿足正態分布的隨機值 | 正態分布的均值和標准差 |
tf.truncated_normal_initializer |
將變量初始化為滿足正態分布的隨機值,但若隨機值偏離平均值超過2個標准差,則這個數會被重新隨機 | 正態分布的均值和標准差 |
tf.random_uniform_initializer |
將變量初始化為滿足平均分布的隨機值 | 最大、最小值 |
tf.uniform_unit_scaling_initializer |
將變量初始化為滿足平均分布但不影響輸出數量級的隨機值 | factor(產生隨機值時乘以的系數) |
tf.zeros_initializer |
將變量初始化為全0 | 變量維度 |
tf.ones_initializer |
將變量初始化為全1 | 變量維度 |
當 tf.get_variable
用於創建變量時,它和 tf.Variable
的功能是基本等價的。而 tf.get_variable
與 tf.Variable
的最大的區別在於指定變量名稱的參數。
- 對於
tf.Variable
函數,變量名稱是一個可選參數,通過name='v'
的形式給出; - 對於
tf.get_variable
函數,變量名稱是一個必填的參數。tf.get_variable
函數會根據這個名字去創建或者獲取變量。
詳細內容見 變量管理
其他
tf.clip_by_value
函數將張量限定在一定的范圍內:
import tensorflow as tf
sess = tf.InteractiveSession()
v = tf.constant([[1., 2., 3.], [4., 5., 6.]])
tf.clip_by_value(v, 2.5, 4.5).eval() # 小於2.5的數值設為2.5,大於4.5的數值設為4.5
array([[2.5, 2.5, 3. ],
[4. , 4.5, 4.5]], dtype=float32)
tf.log
對張量所有元素進行對數運算
tf.log(v).eval()
array([[0. , 0.6931472, 1.0986123],
[1.3862944, 1.609438 , 1.7917595]], dtype=float32)
tf.greater
,比較這兩個張量中的每一個元素,並返回比較結果
- 輸入是兩個張量
- 當輸入維度不一致時會進行廣播(broadcasting)
v1 = tf.constant([1., 2., 3., 4.])
v2 = tf.constant([4., 3., 2., 1.])
f = tf.greater(v1, v2)
f.eval()
array([False, False, True, True])
tf.where
比較函數
函數有三個參數:
- 第一個選擇條件根據,當選擇條件為
True
時,會選擇第二個參數中的值,否則使用第三個參數中的值:
tf.where(f, v1, v2).eval()
array([4., 3., 3., 4.], dtype=float32)
指數衰減學習率
tf.train.exponential_decay
函數指數衰減學習率。
tf.train.exponential_decay(learning_rate, global_step, decay_steps, decay_rate, staircase=False, name=None)
learning_rate
:事先設定的初始學習率decay_steps
: 衰減速度,staircase = True
時代表了完整的使用一遍訓練數據所需要的迭代輪數(= 總訓練樣本數/每個batch中的訓練樣本數)decay_rate
: 衰減系數staircase
: 默認為False
,此時學習率隨迭代輪數的變化是連續的(指數函數);為True
時,global_step/decay_steps
會轉化為整數,此時學習率便是階梯函數
示例:
TRAINING_STEPS = 100
global_step = tf.Variable(0)
LEARNING_RATE = tf.train.exponential_decay(
0.1, global_step, 1, 0.96, staircase=True)
x = tf.Variable(tf.constant(5, dtype=tf.float32), name="x")
y = tf.square(x)
train_op = tf.train.GradientDescentOptimizer(LEARNING_RATE).minimize(
y, global_step=global_step)
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
for i in range(TRAINING_STEPS):
sess.run(train_op)
if i % 10 == 0:
LEARNING_RATE_value = sess.run(LEARNING_RATE)
x_value = sess.run(x)
print("After %s iteration(s): x%s is %f, learning rate is %f." %
(i + 1, i + 1, x_value, LEARNING_RATE_value))
After 1 iteration(s): x1 is 4.000000, learning rate is 0.096000.
After 11 iteration(s): x11 is 0.690561, learning rate is 0.063824.
After 21 iteration(s): x21 is 0.222583, learning rate is 0.042432.
After 31 iteration(s): x31 is 0.106405, learning rate is 0.028210.
After 41 iteration(s): x41 is 0.065548, learning rate is 0.018755.
After 51 iteration(s): x51 is 0.047625, learning rate is 0.012469.
After 61 iteration(s): x61 is 0.038558, learning rate is 0.008290.
After 71 iteration(s): x71 is 0.033523, learning rate is 0.005511.
After 81 iteration(s): x81 is 0.030553, learning rate is 0.003664.
After 91 iteration(s): x91 is 0.028727, learning rate is 0.002436.
正則化
w = tf.constant([[1., -2.], [-3, 4]])
with tf.Session() as sess:
print(sess.run(tf.contrib.layers.l1_regularizer(.5)(w))) # 0.5 為正則化權重
print(sess.run(tf.contrib.layers.l2_regularizer(.5)(w)))
5.0
7.5
滑動平均模型
滑動平均模型會將每一輪迭代得到的模型綜合起來,從而使得最終得到的模型在測試數據上更加健壯(robust)。
tf.train.ExponentialMovingAverage
需要提供一個衰減率(decay)來控制模型更新的速度。
ExponentialMovingAverage 對每一個變量會維護一個影子變量(shadow variable),這個影子變量的初始值就是相應變量的初始值,而每次運行變量更新時,影子變量的值會更新為:
- shadow_variable 為影子變量,
- variable 為待更新變量
- decay 為衰減率,它越大模型越趨於穩定,在實際應用中decay一般會設置為接近 1 的數。
還可以使用 num_updates
參數來動態設置decay的大小:
定義變量及滑動平均類
import tensorflow as tf
# 定義一個變量用來計算滑動平均,且其初始值為0,類型必須為實數
v1 = tf.Variable(0, dtype=tf.float32)
# step變量模擬神經網絡中迭代的輪數,可用於動態控制衰減率
step = tf.Variable(0, trainable=False)
# 定義一個滑動平均的類(class)。初始化時給定了衰減率為0.99和控制衰減率的變量step
ema = tf.train.ExponentialMovingAverage(0.99, step)
# 定義一個更新變量滑動平均的操作。這里需要給定一個列表,每次執行這個操作時,此列表中的變量都會被更新。
maintain_averages_op = ema.apply([v1])
查看不同迭代中變量取值的變化。
with tf.Session() as sess:
# 初始化
init_op = tf.global_variables_initializer()
sess.run(init_op)
# 通過ema.average(v1)獲取滑動平均后的變量取值。在初始化之后變量v1的值和v1 的滑動平均均為0
print(sess.run([v1, ema.average(v1)]))
# 更新變量v1的取值
sess.run(tf.assign(v1, 5))
sess.run(maintain_averages_op)
print(sess.run([v1, ema.average(v1)]))
# 更新step和v1的取值
sess.run(tf.assign(step, 10000))
sess.run(tf.assign(v1, 10))
sess.run(maintain_averages_op)
print(sess.run([v1, ema.average(v1)]))
# 更新一次v1的滑動平均值
sess.run(maintain_averages_op)
print(sess.run([v1, ema.average(v1)]))
[0.0, 0.0]
[5.0, 4.5]
[10.0, 4.555]
[10.0, 4.60945]
- 裁剪多余維度:
tf.squeeze