社会焦点

如何用TensorFlow构建RNN?这里有一份极简的教程

字号+ 作者: 来源: 2017-04-30

如何用TensorFlow构建RNN?这里有一份极简的教程,基于rnn生成古诗词,用rnn做推荐,.size 和.length的区别,lstm rnn的损失函数,tensorflow tf.nn.rnn_cell

  王小新 编译自 KDnuggets

  量子位 出品 | 公众号 QbitAI

  本文作者Erik Hallström是一名深度学习研究工程师,他的这份教程以Echo-RNN为例,介绍了如何在TensorFlow环境中构建一个简单的循环神经网络。

  什么是RNN?

  RNN是循环神经网络(Recurrent Neural Network)的英文缩写,它能结合数据点之间的特定顺序和幅值大小等多个特征,来处理序列数据。更重要的是,这种网络的输入序列可以是任意长度的。

  举一个简单的例子:数字时间序列,具体任务是根据先前值来预测后续值。在每个时间步中,循环神经网络的输入是当前值,以及一个表征该网络在之前的时间步中已经获得信息的状态向量。该状态向量是RNN网络的编码记忆单元,在训练网络之前初始化为零向量。

  如何用TensorFlow构建RNN?这里有一份极简的教程

  图1:RNN处理序列数据的步骤示意图。

  本文只对RNN做简要介绍,主要专注于实践:如何构建RNN网络。如果有网络结构相关的疑惑,建议多看看说明性文章。

  关于RNN的介绍,强烈推荐《A Critical Review of Recurrent Neural Networks for Sequence Learning》,这篇出自加州大学圣地亚哥分校研究人员的文章介绍了几乎所有最新最全面的循环神经网络。(地址:https://arxiv.org/pdf/1506.00019.pdf)

  在了解RNN网络的基本知识后,就很容易理解以下内容。

  构建网络

  我们先建立一个简单的回声状态网络(Echo-RNN)。这种网络能记忆输入数据信息,在若干时间步后将其回传。我们先设定若干个网络常数,读完文章你就能明白它们的作用。

  from__future__ importprint_function, pision importnumpy asnp importtensorflow astf importmatplotlib.pyplot aspltnum_epochs = 100total_series_length = 50000truncated_backprop_length = 15state_size = 4num_classes = 2echo_step = 3batch_size = 5num_batches = total_series_length//batch_size//truncated_backprop_length 生成数据

  现在生成随机的训练数据,输入为一个随机的二元向量,在echo_step个时间步后,可得到输入的“回声”,即输出。

  defgenerateData():x = np.array(np.random.choice( 2, total_series_length, p=[ 0.5, 0.5])) y = np.roll(x, echo_step) y[ 0:echo_step] = 0x = x.reshape((batch_size, - 1)) # The first index changing slowest, subseries as rowsy = y.reshape((batch_size, - 1)) return(x, y)

  包含batch_size的两行代码,将数据重构为新矩阵。神经网络的训练,需要利用小批次数据(mini-batch),来近似得到关于神经元权重的损失函数梯度。在训练过程中,随机批次操作能防止过拟合和降低硬件压力。整个数据集通过数据重构转化为一个矩阵,并将其分解为多个小批次数据。

  如何用TensorFlow构建RNN?这里有一份极简的教程

  图2:重构数据矩阵的示意图,箭头曲线指示了在不同行上的相邻时间步。浅灰色矩形代表“0”,深灰色矩形代表“1”。 构建计算图

  首先在TensorFlow中建立一个计算图,指定将要执行的运算。该计算图的输入和输出通常是多维数组,也被称为张量(tensor)。我们可以利用CPU、GPU和远程服务器的计算资源,在会话中迭代执行该计算图。

  变量和占位符

  本文所用的基本TensorFlow数据结构是变量和占位符。占位符是计算图的“起始节点”。在运行每个计算图时,批处理数据被传递到占位符中。另外,RNN状态向量也是存储在占位符中,在每一次运行后更新输出。

  batchX_placeholder = tf.placeholder(tf.float32, [batch_size, truncated_backprop_length])batchY_placeholder = tf.placeholder(tf.int32, [batch_size, truncated_backprop_length])init_state = tf.placeholder(tf.float32, [batch_size, state_size])

  网络的权重和偏差作为TensorFlow的变量,在运行时保持不变,并在输入批数据后进行逐步更新。

  W = tf.Variable(np.random.rand(state_size+ 1, state_size), dtype=tf.float32)b = tf.Variable(np.zeros(( 1,state_size)), dtype=tf.float32)W2 = tf.Variable(np.random.rand(state_size, num_classes),dtype=tf.float32)b2 = tf.Variable(np.zeros(( 1,num_classes)), dtype=tf.float32)

  下图表示了输入数据矩阵,以及虚线窗口指出了占位符的当前位置。在每次运行时,这个“批处理窗口”根据箭头指示方向,以定义好的长度从左边滑到右边。在示意图中,batch_size(批数据数量)为3,truncated_backprop_length(截断反传长度)为3,total_series_length(全局长度)为36。这些参数是用来示意的,与实际代码中定义的值不一样。在示意图中序列各点也以数字标出。

  如何用TensorFlow构建RNN?这里有一份极简的教程

  图3:训练数据的示意图,用虚线矩形指示当前批数据,用数字标明了序列顺序。 拆分序列

  现在开始构建RNN计算图的下个部分,首先我们要以相邻的时间步分割批数据。

  # Unpack columnsinputs_series = tf.unpack(batchX_placeholder, axis= 1)labels_series = tf.unpack(batchY_placeholder, axis= 1)view raw

  如下图所示,可以按批次分解各列,转成list格式文件。RNN会同时从不同位置开始训练时间序列:在示例中分别从4到6、从16到18和从28到30。用plural和series做变量名,是为了强调该变量为list文件,用来在每一步中表示具有多个位置的时间序列。

  如何用TensorFlow构建RNN?这里有一份极简的教程

  图4:将数据拆分为多列的原理图,用数字标出序列顺序,箭头表示相邻的时间步。

  在我们的时间序列数据中,在三个位置同时开启训练,所以在前向传播时需要保存三个状态。我们在参数定义时就已经考虑到这一点了,故将init_state设置为3。

  前向传播

  接下来,我们继续构建计算图中执行RNN计算功能的模块。

  # Forward passcurrent_state = init_statestates_series = [] forcurrent_input ininputs_series: current_input = tf.reshape(current_input, [batch_size, 1]) input_and_state_concatenated = tf.concat( 1, [current_input, current_state]) # Increasing number of columnsnext_state = tf.tanh(tf.matmul(input_and_state_concatenated, W) + b) # Broadcasted additionstates_series.append(next_state) current_state = next_state

转载请注明出处。


1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章