tfrnnV012 - juedaiyuer/researchNote GitHub Wiki

tensorflow rnn 测试

1. 环境说明

  • 源代码版本:tensorflow-r0.12(一切为源代码笔记)
  • 命令版本:'0.12.0'

2. PTB数据集

下载数据:

http://www.fit.vutbr.cz/~imikolov/rnnlm/simple-examples.tgz

3. 首次运行

$ python2 ptb_word_lm.py --data_path=/home/juedaiyuer/test/simple-examples/data/ --model=small

4. 源代码的前世今生

源代码中的描述

Trains the model described in:
(Zaremba, et. al.) Recurrent Neural Network Regularization
http://arxiv.org/abs/1409.2329

相关论文

《RECURRENT NEURAL NETWORK REGULARIZATION》 Wojciech Zaremba

4. LSTM

4.1 伪代码

# Placeholder for the inputs in a given iteration.
words = tf.placeholder(tf.int32, [batch_size, num_steps])

lstm = tf.contrib.rnn.BasicLSTMCell(lstm_size)
# Initial state of the LSTM memory.
initial_state = state = tf.zeros([batch_size, lstm.state_size])

for i in range(num_steps):
    # The value of state is updated after processing each batch of words.
    output, state = lstm(words[:, i], state)

    # The rest of the code.
    # ...

final_state = state

4.2 BasicLSTMCell()函数

基本的LSTM循环网络单元

源代码中该段的定义,这里的size其实就是hidden_size

lstm_cell = tf.nn.rnn_cell.BasicLSTMCell(size, forget_bias=0.0, state_is_tuple=True)

4.3 DropoutWrapper

源代码中该段如下

if is_training and config.keep_prob < 1:
  lstm_cell = tf.nn.rnn_cell.DropoutWrapper(
      lstm_cell, output_keep_prob=config.keep_prob)

我们在这里使用了dropout方法。所谓dropout,就是指网络中每个单元在每次有数据流入时以一定的概率(keep prob)正常工作,否则输出0值。这是是一种有效的正则化方法,可以有效防止过拟合。在rnn中使用dropout的方法和cnn不同,推荐大家去把recurrent neural network regularization看一遍。

传递信息进行dropout,不同时刻的状态传递不进行dropout

4.4 多层LSTM结构和状态初始化

cell = tf.nn.rnn_cell.MultiRNNCell([lstm_cell] * config.num_layers, state_is_tuple=True)

各种状态进行初始化

self._initial_state = cell.zero_state(batch_size, data_type())

5. 输入预处理

with tf.device("/cpu:0"):
  embedding = tf.get_variable(
      "embedding", [vocab_size, size], dtype=data_type())
  inputs = tf.nn.embedding_lookup(embedding, input_.input_data)

if is_training and config.keep_prob < 1:
  inputs = tf.nn.dropout(inputs, config.keep_prob)

输入模型的input和target都是用词典id表示的。例如一个句子,“我/是/学生”,这三个词在词典中的序号分别是0,5,3,那么上面的句子就是[0,5,3]。显然这个是不能直接用的,我们要把词典id转化成向量,也就是embedding形式

第一步

构建一个矩阵,就叫embedding好了,尺寸为[vocab_size, size],分别表示词典中单词数目,以及要转化成的向量的维度。一般来说,向量维度越高,能够表现的信息也就越丰富。

第二步

inputs = tf.nn.embedding_lookup(embedding, input_.input_data)

6. 循环起来

现在,多层lstm单元已经定义完毕,输入也已经经过预处理了。那么现在要做的就是将数据输入lstm进行训练了。其实很简单,只要按照文本顺序依次向cell输入数据就好了。lstm上一时间段的状态会自动参与到当前时间段的输出和状态的计算当中。

outputs = []
state = self._initial_state
with tf.variable_scope("RNN"):
  for time_step in range(num_steps):
    if time_step > 0: tf.get_variable_scope().reuse_variables()
    (cell_output, state) = cell(inputs[:, time_step, :], state)
    outputs.append(cell_output)

7. 损失函数计算

source