def __init__ (self, is_training, config, input_)
1 def __init__(self, is_training, config, input_):
2
3
4
5
6 self._is_training = is_training
7 self._input = input_
8 self._rnn_params = None
9 self._cell = None
10 self.batch_size = input_.batch_size
11 self.num_steps = input_.num_steps
12 size = config.hidden_size
13 vocab_size = config.vocab_size
14
15 with tf.device("/cpu:0"):
16 embedding = tf.get_variable("embedding", [vocab_size, size], dtype=data_type())
17 inputs = tf.nn.embedding_lookup(embedding, input_.input_data)
18
19 if is_training and config.keep_prob < 1:
20 inputs = tf.nn.dropout(inputs, config.keep_prob)
21
22 output, state = self._build_rnn_graph(inputs, config, is_training)
23
24 softmax_w = tf.get_variable("softmax_w", [size, vocab_size], dtype=data_type())
25 softmax_b = tf.get_variable("softmax_b", [vocab_size], dtype=data_type())
26 logits = tf.nn.xw_plus_b(output, softmax_w, softmax_b)
27 # Reshape logits to be a 3-D tensor for sequence loss
28 logits = tf.reshape(logits, [self.batch_size, self.num_steps, vocab_size])
29
30 # Use the contrib sequence loss and average over the batches
31 loss = tf.contrib.seq2seq.sequence_loss(
32 logits,
33 input_.targets,
34 tf.ones([self.batch_size, self.num_steps], dtype=data_type()),
35 average_across_timesteps=False,
36 average_across_batch=True
37 )
38
39 # Update the cost
40 self._cost = tf.reduce_sum(loss)
41 self._final_state = state
42
43 if not is_training:
44 return
45
46 self._lr = tf.Variable(0.0, trainable=False)
47 tvars = tf.trainable_variables()
48 grads, _ = tf.clip_by_global_norm(tf.gradients(self._cost, tvars), config.max_grad_norm)
49 optimizer = tf.train.GradientDescentOptimizer(self._lr)
50 self._train_op = optimizer.apply_gradients(
51 zip(grads, tvars),
52 global_step=tf.train.get_or_create_global_step()
53 )
54
55 self._new_lr = tf.placeholder(tf.float32, shape=[], name="new_learning_rate")
56 self._lr_update = tf.assign(self._lr, self._new_lr)
- 第15行
with tf.device("/cpu:0")
表示切換為 CPU 運算,"/cpu:0" 的 "0" 表示設備號,直接設為 0 即可
表示第 16, 17 行的 embedding 與 inputs 變數將存在主機的記憶體中而不是顯示卡記憶體。
參考 [0] tf.device() 指定運行設備、[1] TensorFlow using GPUs
- 第16行
embedding = tf.get_variable( "embedding", [vocab_size, size], dtype=data_type())
tf.get_variable(name, shape, initializer): name是變數的名稱,shape是變數的維度,initializer是變數初始化的方式
故 "embedding" 是變數名稱;[vocab_size, size] 是變數 embedding 的維度,表示 embedding 二維矩陣,矩陣 size = vocab_size (列) x size (行);初始化 embedding 的方式為 data_type () 函數
參考 [2] tf.get_variable 函數的使用
- 第17行
inputs = tf.nn.embedding_lookup(embedding, input_.input_data)
tf.nn.embedding_lookup 函數的用法主要是擷取一個 Tensor 裡面索引對應的元素。
tf.nn.embedding_lookup(embedding, input_.input_data)embedding 就是 tensor,input_.input_data 就是 embedding 對應的索引
參考 [3] tf.nn.embedding_lookup()
第19, 20 行:
if is_training and config.keep_prob < 1: inputs = tf.nn.dropout(inputs, config.keep_prob)
is_training 表示要訓練 model;config.keep_prob < 1 表示 keep_prob 是一個合理的機率值 (0~1之間),
inputs 使用 tf.nn.dropout 函數避免 overfitting。用法是以 "keep_prob" 的機率值隨機 deactivate 部分 inputs 中的資料
參考 [4] tf.nn.dropout()
- 第22行
output, state = self._build_rnn_graph(inputs, config, is_training)
呼叫 _build_rnn_graph() 函數,並傳入參數 inputs, config, is_training,將結果回傳給 output, state 變數中儲存。
第24, 25行
softmax_w = tf.get_variable("softmax_w", [size, vocab_size], dtype=data_type()) softmax_b = tf.get_variable("softmax_b", [vocab_size], dtype=data_type())
softmax_w & softmax_b 是變數名稱;
softmax_w 是二維資料,大小為 size x vocab_size,以 data_type() 初始化;
softmax_b 是一維資料,大小為 vocab_size,以 data_type() 初始化
- 第26行
logits = tf.nn.xw_plus_b(output, softmax_w, softmax_b)
logits = output 乘以 softmax_w 加上 softmax_b;logits, output and softmax_w 為 2-D tensor 資料;softmax_b 為 1-D tensor 資料
參考 [5] tf.nn.xw_plus_b()
第27, 28行
# Reshape logits to be a 3-D tensor for sequence loss logits = tf.reshape(logits, [self.batch_size, self.num_steps, vocab_size])
tf.reshape (tensor, shape, name=None) 表示將 "tensor" 改為 "shape" 的維度;
故 logits 改為維度 [self.batch_size, self.num_steps, vocab_size] (三維 self.batch_size x self.num_steps x vocab_size)
第30~37行
# Use the contrib sequence loss and average over the batches loss = tf.contrib.seq2seq.sequence_loss( logits, input_.targets, tf.ones([self.batch_size, self.num_steps], dtype=data_type()), average_across_timesteps=False, average_across_batch=True )
(計算 loss 略)
第39~41行
# Update the cost self._cost = tf.reduce_sum(loss) self._final_state = state
( 更新 cost 與 final state 略 )
第43, 44行
if not is_training: return
如果不是要訓練資料,則直接略過之後的程式碼,直接 return
- 第46行
self._lr = tf.Variable(0.0, trainable=False)
指定 self._lr 變數的值為 0.0,且在 training model 的過程中,此值不可被改變
lr 是 learning rate 的縮寫。
變數在計算過程中是可變的,並且在訓練過程中會自動更新或優化。
如果不允許變數被 tensorflow 更動,只能在 tensorflow 以外,以手動的方式更新,需要以 trainable=False 聲明變數是不可訓練的。
- 第47行
tvars = tf.trainable_variables()
tvars 變數中儲存的是所有設定為 trainable=True 的變數;
tf.trainable_variables(scope=None)
returns all variables created with trainable=True
[6] tf.trainable_variables()
目前大概查到 tf.trainable_variables() 是為了處理gradient explosion或者gradients vanishing的問題。當在一次迭代中權重的更新過於迅猛的話,很容易導致loss divergence。
grads, _ = tf.clip_by_global_norm(tf.gradients(self._cost, tvars), config.max_grad_norm)
參考 [7] tf.clip_by_global_norm CSDN [8] tf.clip_by_global_norm Tensorflow
optimizer = tf.train.GradientDescentOptimizer(self._lr)
optimizer 是一個 GradientDescentOptimizer 的物件,產生 GradientDescentOptimizer 物件時需要 self._lr (learning rate) 參數
參考 [9] tf.train.GradientDescentOptimizer()
self._train_op = optimizer.apply_gradients( zip(grads, tvars), global_step=tf.train.get_or_create_global_step() )
由於 apply_gradients () 不知道如何解釋,在附件中將 source code 貼上
self._new_lr = tf.placeholder(tf.float32, shape=[], name="new_learning_rate")
self._lr_update = tf.assign(self._lr, self._new_lr)
Reference
[4] tf.nn.dropout()
[7] tf.clip_by_global_norm CSDN