TensorFlow实现RNN循环神经网络


Posted in Python onFebruary 28, 2018

RNN(recurrent neural Network)循环神经网络

主要用于自然语言处理(nature language processing,NLP)

RNN主要用途是处理和预测序列数据

RNN广泛的用于 语音识别、语言模型、机器翻译

RNN的来源就是为了刻画一个序列当前的输出与之前的信息影响后面节点的输出

RNN 是包含循环的网络,允许信息的持久化

RNN会记忆之前的信息,并利用之前的信息影响后面节点的输出

RNN的隐藏层之间的节点是有相连的,隐藏层的输入不仅仅包括输入层的输出,还包括上一时刻隐藏层的输出。

RNN会对于每一个时刻的输入结合当前模型的状态给出一个输出

RNN理论上被看作同一个神经网络结构被无限复制的结果,目前RNN无法做到真正的无限循环,一般以循环体展开。

RNN图:

TensorFlow实现RNN循环神经网络

RNN最擅长的问题是与时间序列相关的

RNN对于一个序列数据,可以将序列上不同时刻的数据依次输入循环神经网络的输入层,而输出可以是对序列中下一个时刻的预测,也可以是对当前时刻信息的处理结果。

RNN 的关键点之一就是他们可以用来连接先前的信息到当前的任务上

展开后的RNN

TensorFlow实现RNN循环神经网络

循环体网络中的参数在不同的时刻也是共享的

RNN的状态是通过一个向量来表示,这个向量的维度也称为RNN隐藏层的大小

假如该向量为h,输入为x,激活函数为tanh,则有如图:

TensorFlow实现RNN循环神经网络

前向传播的计算过程:

TensorFlow实现RNN循环神经网络

理论上RNN可以支持任意长度的序列,但是如果序列太长会导致优化时实现梯度消失的问题,一般会设置最大长度,超长会对其截断。

 代码实现简单的RNN:

import numpy as np 
 
# 定义RNN的参数。 
X = [1,2] 
state = [0.0, 0.0] 
w_cell_state = np.asarray([[0.1, 0.2], [0.3, 0.4]]) 
w_cell_input = np.asarray([0.5, 0.6]) 
b_cell = np.asarray([0.1, -0.1]) 
w_output = np.asarray([[1.0], [2.0]]) 
b_output = 0.1 
 
# 执行前向传播过程。 
for i in range(len(X)): 
  before_activation = np.dot(state, w_cell_state) + X[i] * w_cell_input + b_cell 
  state = np.tanh(before_activation) 
  final_output = np.dot(state, w_output) + b_output 
  print ("before activation: ", before_activation) 
  print ("state: ", state) 
  print ("output: ", final_output)

LSTM(long short-term memory)长短时记忆网络: 

LSTM解决了RNN不支持长期依赖的问题,使其大幅度提升记忆时长

RNN被成功应用的关键就是LSTM。

LSTM是一种拥有三个“门”结构的特殊网络结构。

TensorFlow实现RNN循环神经网络

粉色的圈代表 pointwise 的操作,诸如向量的和,而黄色的矩阵就是学习到的神经网络层。合在一起的线表示向量的连接,分开的线表示内容被复制,然后分发到不同的位置。

LSTM核心思想:

LSTM 的关键就是细胞状态,水平线在图上方贯穿运行。

细胞状态类似于传送带。直接在整个链上运行,只有一些少量的线性交互,信息在上面流传保持不变会很容易。

TensorFlow实现RNN循环神经网络

LSTM 有通过精心设计的称作为“门”的结构来去除或者增加信息到细胞状态的能力

“门”是一种让信息选择式通过的方法,包含一个sigmoid 神经网络层和一个 pointwise (按位做乘法)的操作。

之所以称之为“门”,因为使用Sigmoid 作为激活函数的层会输出 0 到 1 之间的数值,描述每个部分有多少信息量可以通过这个结构。

0 代表“不许任何量通过”,1 就指“允许任意量通过”!

LSTM的公式:

TensorFlow实现RNN循环神经网络

代码实现:

import tensorflow as tf 
 
 
# 定义一个LSTM结构 
lstm = rnn_cell.BasicLSTMCell(lstm_hidden_size) 
 
# 将LSTM中的状态初始化为全0数组,每次使用一个batch的训练样本 
state = lstm.zero_state(batch_size,tf.float32) 
 
# 定义损失函数 
loss = 0.0 
 
# 规定一个最大序列长度 
for i in range(num_steps): 
  # 复用之前定义的变量 
  if i > 0: 
    tf.get_variable_scope().reuse_variables() 
  # 将当前输入和前一时刻的状态传入定义的LSTM结构,得到输出和更新后的状态 
  lstm_output, state = lstm(current_input,state) 
   
  # 将当前时刻的LSTM结构的输出传入一个全连接层得到最后的输出。 
  final_output = fully_connectd(lstm_output) 
   
  # 计算当前时刻输出的损失 
  loss += calc_loss(final_output,expected_output)

双向循环神经网络

经典的循环神经网络中的状态传输是从前往后单向的,然而当前时刻的输出不仅和之前的状态有关系,也和之后的状态相关。

双向循环神经网络能解决状态单向传输的问题

双向循环神经网络是由两个循环神经网络反向上下叠加在一起组成两个循环神经网络的状态共同决定输出

也就是时间t时的输出不仅仅取决于过去的记忆,也同样取决于后面发生的事情。

TensorFlow实现RNN循环神经网络

深层(双向)循环神经网络

深层循环神经网络似于双向循环神经网络,只不过是每个时长内都有多层

深层循环神经网络有更强的学习能力

深层循环神经网络在每个时刻上将循环体结构复制多次,和卷积神经网络类似,每一层循环体中的参数是一致的,不同层的参数可以不同

TensorFlow实现RNN循环神经网络

TensorFlow中使用MultiRNNCell实现深层循环神经网络中每一个时刻的前向传播过程。剩下的步骤和RNN的构建步骤相同。

RNN中的dropout

通过dropout方法可以上卷积神经网络更加健壮,类似的用在RNN上也能取得同样的效果。

类似卷积神经网络,RNN只在最后的全连接层使用dropout。

RNN一般只在不同层循环体结构中使用dropout,不在同层循环体使用。

同一时刻t中,不同循环体之间会使用dropout

在TensorFlow中,使用DropoutWrapper类实现dropout功能。

通过input_keep_prob参数控制输入的dropout概率

通过output_keep_prob参数控制输出的dropout概率

TensorFlow样例实现RNN语言模型

代码:

import numpy as np 
import tensorflow as tf 
import reader 
  
DATA_PATH = "../datasets/PTB/data" 
HIDDEN_SIZE = 200 # 隐藏层规模 
NUM_LAYERS = 2 # 深层RNN中的LSTM结构的层数 
VOCAB_SIZE = 10000 # 单词标识符个数 
 
LEARNING_RATE = 1.0 # 学习速率 
TRAIN_BATCH_SIZE = 20 # 训练数据大小 
TRAIN_NUM_STEP = 35 # 训练数据截断长度 
 
# 测试时不需要截断 
EVAL_BATCH_SIZE = 1 # 测试数据大小 
EVAL_NUM_STEP = 1 # 测试数据截断长度 
NUM_EPOCH = 2 # 使用训练数据轮数 
KEEP_PROB = 0.5 # 节点不被dropout 
MAX_GRAD_NORM = 5 # 控制梯度膨胀参数 
 
 
# 定义一个类来描述模型结构。 
class PTBModel (object): 
  def __init__(self, is_training, batch_size, num_steps): 
 
    self.batch_size = batch_size 
    self.num_steps = num_steps 
 
    # 定义输入层。 
    self.input_data = tf.placeholder (tf.int32, [batch_size, num_steps]) 
    self.targets = tf.placeholder (tf.int32, [batch_size, num_steps]) 
 
    # 定义使用LSTM结构及训练时使用dropout。 
    lstm_cell = tf.contrib.rnn.BasicLSTMCell (HIDDEN_SIZE) 
    if is_training: 
      lstm_cell = tf.contrib.rnn.DropoutWrapper (lstm_cell, output_keep_prob=KEEP_PROB) 
    cell = tf.contrib.rnn.MultiRNNCell ([lstm_cell] * NUM_LAYERS) 
 
    # 初始化最初的状态。 
    self.initial_state = cell.zero_state (batch_size, tf.float32) 
    embedding = tf.get_variable ("embedding", [VOCAB_SIZE, HIDDEN_SIZE]) 
 
    # 将原本单词ID转为单词向量。 
    inputs = tf.nn.embedding_lookup (embedding, self.input_data) 
 
    if is_training: 
      inputs = tf.nn.dropout (inputs, KEEP_PROB) 
 
    # 定义输出列表。 
    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) 
    output = tf.reshape (tf.concat (outputs, 1), [-1, HIDDEN_SIZE]) 
    weight = tf.get_variable ("weight", [HIDDEN_SIZE, VOCAB_SIZE]) 
    bias = tf.get_variable ("bias", [VOCAB_SIZE]) 
    logits = tf.matmul (output, weight) + bias 
 
    # 定义交叉熵损失函数和平均损失。 
    loss = tf.contrib.legacy_seq2seq.sequence_loss_by_example ( 
      [logits], 
      [tf.reshape (self.targets, [-1])], 
      [tf.ones ([batch_size * num_steps], dtype=tf.float32)]) 
    self.cost = tf.reduce_sum (loss) / batch_size 
    self.final_state = state 
 
    # 只在训练模型时定义反向传播操作。 
    if not is_training: return 
    trainable_variables = tf.trainable_variables () 
 
    # 控制梯度大小,定义优化方法和训练步骤。 
    grads, _ = tf.clip_by_global_norm (tf.gradients (self.cost, trainable_variables), MAX_GRAD_NORM) 
    optimizer = tf.train.GradientDescentOptimizer (LEARNING_RATE) 
    self.train_op = optimizer.apply_gradients (zip (grads, trainable_variables)) 
 
 
 
# 使用给定的模型model在数据data上运行train_op并返回在全部数据上的perplexity值 
def run_epoch(session, model, data, train_op, output_log, epoch_size): 
  total_costs = 0.0 
  iters = 0 
  state = session.run(model.initial_state) 
 
  # 训练一个epoch。 
  for step in range(epoch_size): 
    x, y = session.run(data) 
    cost, state, _ = session.run([model.cost, model.final_state, train_op], 
                    {model.input_data: x, model.targets: y, model.initial_state: state}) 
    total_costs += cost 
    iters += model.num_steps 
 
    if output_log and step % 100 == 0: 
      print("After %d steps, perplexity is %.3f" % (step, np.exp(total_costs / iters))) 
  return np.exp(total_costs / iters) 
 
 
# 定义主函数并执行 
def main(): 
  train_data, valid_data, test_data, _ = reader.ptb_raw_data(DATA_PATH) 
 
  # 计算一个epoch需要训练的次数 
  train_data_len = len(train_data) 
  train_batch_len = train_data_len // TRAIN_BATCH_SIZE 
  train_epoch_size = (train_batch_len - 1) // TRAIN_NUM_STEP 
 
  valid_data_len = len(valid_data) 
  valid_batch_len = valid_data_len // EVAL_BATCH_SIZE 
  valid_epoch_size = (valid_batch_len - 1) // EVAL_NUM_STEP 
 
  test_data_len = len(test_data) 
  test_batch_len = test_data_len // EVAL_BATCH_SIZE 
  test_epoch_size = (test_batch_len - 1) // EVAL_NUM_STEP 
 
  initializer = tf.random_uniform_initializer(-0.05, 0.05) 
  with tf.variable_scope("language_model", reuse=None, initializer=initializer): 
    train_model = PTBModel(True, TRAIN_BATCH_SIZE, TRAIN_NUM_STEP) 
 
  with tf.variable_scope("language_model", reuse=True, initializer=initializer): 
    eval_model = PTBModel(False, EVAL_BATCH_SIZE, EVAL_NUM_STEP) 
 
  # 训练模型。 
  with tf.Session() as session: 
    tf.global_variables_initializer().run() 
 
    train_queue = reader.ptb_producer(train_data, train_model.batch_size, train_model.num_steps) 
    eval_queue = reader.ptb_producer(valid_data, eval_model.batch_size, eval_model.num_steps) 
    test_queue = reader.ptb_producer(test_data, eval_model.batch_size, eval_model.num_steps) 
 
    coord = tf.train.Coordinator() 
    threads = tf.train.start_queue_runners(sess=session, coord=coord) 
 
    for i in range(NUM_EPOCH): 
      print("In iteration: %d" % (i + 1)) 
      run_epoch(session, train_model, train_queue, train_model.train_op, True, train_epoch_size) 
 
      valid_perplexity = run_epoch(session, eval_model, eval_queue, tf.no_op(), False, valid_epoch_size) 
      print("Epoch: %d Validation Perplexity: %.3f" % (i + 1, valid_perplexity)) 
 
    test_perplexity = run_epoch(session, eval_model, test_queue, tf.no_op(), False, test_epoch_size) 
    print("Test Perplexity: %.3f" % test_perplexity) 
 
    coord.request_stop() 
    coord.join(threads) 
 
if __name__ == "__main__": 
  main()

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
简单介绍Python中的filter和lambda函数的使用
Apr 07 Python
使用Python将数组的元素导出到变量中(unpacking)
Oct 27 Python
详解Python函数可变参数定义及其参数传递方式
Aug 02 Python
解决pycharm的Python console不能调试当前程序的问题
Jan 20 Python
pytorch 模拟关系拟合——回归实例
Jan 14 Python
python判断变量是否为int、字符串、列表、元组、字典的方法详解
Feb 13 Python
解决import tensorflow as tf 出错的原因
Apr 16 Python
基于Python实现视频的人脸融合功能
Jun 12 Python
Python Tkinter实例——模拟掷骰子
Oct 24 Python
python 制作网站小说下载器
Feb 20 Python
python 如何在测试中使用 Mock
Mar 01 Python
使用Python开发冰球小游戏
Apr 30 Python
python使用TensorFlow进行图像处理的方法
Feb 28 #Python
使用Python搭建虚拟环境的配置方法
Feb 28 #Python
Python OpenCV获取视频的方法
Feb 28 #Python
python实现多线程行情抓取工具的方法
Feb 28 #Python
Python 记录日志的灵活性和可配置性介绍
Feb 27 #Python
python定向爬取淘宝商品价格
Feb 27 #Python
python抓取文件夹的所有文件
Feb 27 #Python
You might like
PHP下一个非常全面获取图象信息的函数
2008/11/20 PHP
PHP文件打开、关闭、写入的判断与执行代码
2011/05/24 PHP
php中opendir函数用法实例
2014/11/15 PHP
PHP使用FFmpeg获取视频播放总时长与码率等信息
2016/09/13 PHP
确保Laravel网站不会被嵌入到其他站点中的方法
2019/10/18 PHP
关于Blog顶部的滚动导航条代码
2006/09/25 Javascript
jquery 表单取值常用代码
2009/12/22 Javascript
js中将URL中的参数提取出来作为对象的实现代码
2011/08/16 Javascript
javascript学习(二)javascript常见问题总结
2013/01/02 Javascript
使用JS读秒使用示例
2013/09/21 Javascript
js+html5实现canvas绘制简单矩形的方法
2015/06/05 Javascript
一些实用性较高的js方法
2016/04/19 Javascript
jquery 点击元素后,滚动条滚动至该元素位置的方法
2016/08/05 Javascript
jquery+html仿翻页相册功能
2016/12/20 Javascript
javascript实现圣旨卷轴展开效果(代码分享)
2017/03/23 Javascript
使用 Javascript 实现浏览器推送提醒功能的示例
2017/11/03 Javascript
详解如何用模块化的方式写vuejs
2017/12/16 Javascript
[46:48]DOTA2上海特级锦标赛A组小组赛#2 Secret VS CDEC第三局
2016/02/25 DOTA
python实现定时同步本机与北京时间的方法
2015/03/24 Python
pycharm下打开、执行并调试scrapy爬虫程序的方法
2017/11/29 Python
利用Pandas 创建空的DataFrame方法
2018/04/08 Python
python的常用模块之collections模块详解
2018/12/06 Python
python使用参数对嵌套字典进行取值的方法
2019/04/26 Python
python 随机生成10位数密码的实现代码
2019/06/27 Python
python里运用私有属性和方法总结
2019/07/08 Python
python实现ftp文件传输系统(案例分析)
2020/03/20 Python
python中使用input()函数获取用户输入值方式
2020/05/03 Python
pytorch查看通道数 维数 尺寸大小方式
2020/05/26 Python
Cocopanda波兰:购买化妆品、护肤品、护发和香水
2020/05/25 全球购物
自主招生教师推荐信
2014/05/10 职场文书
优秀大专毕业生求职信
2014/08/04 职场文书
教师廉洁自律个人总结
2015/02/10 职场文书
物业前台接待岗位职责
2015/04/03 职场文书
2016猴年春节问候语
2015/11/11 职场文书
浅谈JS的二进制家族
2021/05/09 Javascript
Python装饰器详细介绍
2022/03/25 Python