东方耀AI技术分享

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
热搜: 活动 交友 discuz
查看: 3317|回复: 2
打印 上一主题 下一主题

[课堂笔记] 60、RNN的各种结构(多层、双向)的实现与效果对比_笔记

[复制链接]

1365

主题

1856

帖子

1万

积分

管理员

Rank: 10Rank: 10Rank: 10

积分
14429
QQ
跳转到指定楼层
楼主
发表于 2019-4-15 10:59:25 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
60、RNN的各种结构(多层、双向)的实现与效果对比_笔记


2层LSTM Cell 单向 网络 效果:
INFO:tensorflow:Step:   450, loss: 0.224, accuracy: 0.910
INFO:tensorflow:Step:   460, loss: 0.153, accuracy: 0.960
INFO:tensorflow:Step:   470, loss: 0.138, accuracy: 0.950
INFO:tensorflow:Step:   480, loss: 0.066, accuracy: 0.980
INFO:tensorflow:Step:   490, loss: 0.049, accuracy: 0.980
测试集准确率:0.9580000042915344

2层LSTM Cell 单向 网络 效果:use_peepholes=True
INFO:tensorflow:Step:   450, loss: 0.208, accuracy: 0.950
INFO:tensorflow:Step:   460, loss: 0.045, accuracy: 0.980
INFO:tensorflow:Step:   470, loss: 0.181, accuracy: 0.940
INFO:tensorflow:Step:   480, loss: 0.083, accuracy: 0.970
INFO:tensorflow:Step:   490, loss: 0.022, accuracy: 1.000
测试集准确率:0.9570000171661377

2层GRU Cell 单向 网络 效果:
INFO:tensorflow:Step:   450, loss: 0.195, accuracy: 0.920
INFO:tensorflow:Step:   460, loss: 0.104, accuracy: 0.960
INFO:tensorflow:Step:   470, loss: 0.105, accuracy: 0.970
INFO:tensorflow:Step:   480, loss: 0.184, accuracy: 0.960
INFO:tensorflow:Step:   490, loss: 0.062, accuracy: 0.990
测试集准确率:0.9559999704360962


单层GRU Cell 单向 网络 效果:
INFO:tensorflow:Step:   450, loss: 0.191, accuracy: 0.920
INFO:tensorflow:Step:   460, loss: 0.060, accuracy: 0.980
INFO:tensorflow:Step:   470, loss: 0.076, accuracy: 0.950
INFO:tensorflow:Step:   480, loss: 0.095, accuracy: 0.960
INFO:tensorflow:Step:   490, loss: 0.057, accuracy: 0.990
测试集准确率:0.9616666436195374

单层LSTM Cell 单向 网络 效果:
INFO:tensorflow:Step:   450, loss: 0.178, accuracy: 0.940
INFO:tensorflow:Step:   460, loss: 0.126, accuracy: 0.960
INFO:tensorflow:Step:   470, loss: 0.122, accuracy: 0.940
INFO:tensorflow:Step:   480, loss: 0.141, accuracy: 0.950
INFO:tensorflow:Step:   490, loss: 0.085, accuracy: 0.960
测试集准确率:0.9493333101272583


单层 LSTM与GRU Cell 双向 网络 效果:
INFO:tensorflow:Step:   450, loss: 0.219, accuracy: 0.920
INFO:tensorflow:Step:   460, loss: 0.119, accuracy: 0.960
INFO:tensorflow:Step:   470, loss: 0.123, accuracy: 0.950
INFO:tensorflow:Step:   480, loss: 0.161, accuracy: 0.960
INFO:tensorflow:Step:   490, loss: 0.085, accuracy: 0.970
测试集准确率:0.95333331823349


多层 LSTM与GRU Cell 双向 网络 效果:
INFO:tensorflow:Step:   450, loss: 0.206, accuracy: 0.950
INFO:tensorflow:Step:   460, loss: 0.156, accuracy: 0.940
INFO:tensorflow:Step:   470, loss: 0.174, accuracy: 0.950
INFO:tensorflow:Step:   480, loss: 0.083, accuracy: 0.960
INFO:tensorflow:Step:   490, loss: 0.034, accuracy: 0.990
测试集准确率:0.9553333520889282



  1. def bidirectional_dynamic_rnn(
  2.         cell_fw: 前向的rnn cell
  3.         , cell_bw:反向的rnn cell
  4.         , inputs:输入的序列
  5.         , sequence_length=None # 输入序列的实际长度(可选,默认为输入序列的最大长度)
  6.         , initial_state_fw=None:前向rnn_cell的初始状态(可选)
  7.         , initial_state_bw=None:反向rnn_cell的初始状态(可选)
  8.         , dtype=None # 初始化和输出的数据类型(可选)
  9.         , parallel_iterations=None
  10.         , swap_memory=False,
  11.         # 决定了输入输出tensor的格式:如果为true, 向量的形状必须为 `[max_time, batch_size, depth]`.
  12.         # 如果为false, tensor的形状必须为`[batch_size, max_time, depth]`.
  13.         time_major=False,
  14.         scope=None)

  15. API返回值:(outputs, output_states) => outputs存储网络的输出信息,output_states存储网络的细胞状态信息
  16. outputs: 是一个二元组, (output_fw, output_bw)构成,output_fw对应前向的rnn_cell的执行结果,
  17. 结构为:[batch_size, time_steps, output_size];
  18. output_bw对应反向的rnn_cell的执行结果,结果和output_bw一样
  19. output_states:是一个二元组,(output_state_fw, output_state_bw) 构成,
  20. output_state_fw和output_state_bw是dynamic_rnn API输出的状态值信息
复制代码
  1. # -*- coding: utf-8 -*-
  2. __author__ = u'东方耀 微信:dfy_88888'
  3. __date__ = '2019/4/15 11:48'
  4. __product__ = 'PyCharm'
  5. __filename__ = 'rnn_mnist_demo'


  6. """
  7.    59、RNN实战案例:手写数字图片识别(分类)
  8.    tf开发 三个模块:
  9.    1、数据提供者  api: next_batch(batch_size)
  10.    2、构建数据流图  模型结构 input LSTM fc output  metric(loss accuracy)  train_op
  11.    3、执行训练的代码 sess.run()
  12.    
  13.    def bidirectional_dynamic_rnn(
  14.         cell_fw: 前向的rnn cell
  15.         , cell_bw:反向的rnn cell
  16.         , inputs:输入的序列
  17.         , sequence_length=None # 输入序列的实际长度(可选,默认为输入序列的最大长度)
  18.         , initial_state_fw=None:前向rnn_cell的初始状态(可选)
  19.         , initial_state_bw=None:反向rnn_cell的初始状态(可选)
  20.         , dtype=None # 初始化和输出的数据类型(可选)
  21.         , parallel_iterations=None
  22.         , swap_memory=False,
  23.         # 决定了输入输出tensor的格式:如果为true, 向量的形状必须为 `[max_time, batch_size, depth]`.
  24.         # 如果为false, tensor的形状必须为`[batch_size, max_time, depth]`.
  25.         time_major=False,
  26.         scope=None)

  27. API返回值:(outputs, output_states) => outputs存储网络的输出信息,output_states存储网络的细胞状态信息
  28. outputs: 是一个二元组, (output_fw, output_bw)构成,output_fw对应前向的rnn_cell的执行结果,
  29. 结构为:[batch_size, time_steps, output_size];
  30. output_bw对应反向的rnn_cell的执行结果,结果和output_bw一样
  31. output_states:是一个二元组,(output_state_fw, output_state_bw) 构成,
  32. output_state_fw和output_state_bw是dynamic_rnn API输出的状态值信息
  33. """

  34. import tensorflow as tf
  35. from tensorflow.examples.tutorials.mnist import input_data
  36. import numpy as np
  37. import math
  38. import matplotlib.pyplot as plt

  39. tf.logging.set_verbosity(tf.logging.INFO)

  40. tf.random.set_random_seed(10)


  41. # 第一步:导入数据
  42. # 数据加载
  43. mnist = input_data.read_data_sets('mnist_data/', one_hot=True)

  44. # 样本数 55000
  45. print(mnist.train.num_examples)
  46. # images 特征矩阵 784个特征属性
  47. print(mnist.train.images.shape)
  48. # labels 目标属性10个 刚好是10个数字 进行了哑编码
  49. print(mnist.train.labels.shape)

  50. print('测试集shape:{}'.format(mnist.test.images.shape))
  51. print('验证集shape:{}'.format(mnist.validation.images.shape))

  52. # 手写数字识别的数据集主要包含三个部分:训练集(5.5w, mnist.train)、测试集(1w, mnist.test)、验证集(0.5w, mnist.validation)
  53. # 手写数字图片大小是28*28*1像素的图片(黑白),也就是每个图片由784维的特征描述


  54. # 第二步:设置超参并定义学习率调整策略
  55. learn_rate_base = 0.01
  56. # 时序长度 t1 t2 t3... t28  28个时刻
  57. num_timesteps = 28
  58. # 每个时刻输入的数据维度大小(像素值个数)
  59. input_size = 28
  60. # 一个LSTM的FP过程完成后 刚好就是处理了一张图片
  61. # (图片内部的像素点之间是有一定的依赖关系的)上下文关系 就可以用RNN

  62. num_lstm_layers = 2
  63. num_lstm_nodes = [128, 256]
  64. # 控制lstm梯度的大小 1.0是梯度的上限 如果梯度大于1.0就设为1.0 截断
  65. clip_lstm_grads = 1.0
  66. # 展示信息的间隔大小
  67. display_step = 10
  68. # 输入的样本维度大小信息 784 = 28*28
  69. input_dim = mnist.train.images.shape[1]
  70. # 输出的维度大小信息 10
  71. class_num = mnist.train.labels.shape[1]

  72. tf.logging.info('input_dim : %d' % input_dim)
  73. tf.logging.info('class_num : %d' % class_num)

  74. # 查看手写图片数据 10张图片数据与对应的y值
  75. # train_images, train_labels = mnist.train.next_batch(10)
  76. # print(train_images.shape)
  77. # print(train_labels.shape)
  78. # train_image = train_images[0]
  79. # train_label = train_labels[0]
  80. # print('实际值:', train_label)
  81. #
  82. # train_image = np.array(train_image)
  83. # train_image = train_image.reshape(28, 28)
  84. # fig = plt.figure()
  85. # plt.imshow(train_image, cmap='binary')
  86. # plt.show()


  87. def learn_rate_func(epoch):
  88.     """
  89.     根据给定的迭代批次,更新产生一个学习率的值 均匀分布策略
  90.     :param epoch:
  91.     :return:
  92.     """
  93.     return max(0.001, learn_rate_base * (0.9 ** int(epoch / 10)))


  94. #
  95. # 第三步:开始构建模型 设置输入数据的占位符
  96. _X = tf.placeholder(dtype=tf.float32, shape=[None, input_dim], name='X_origianl')
  97. y = tf.placeholder(tf.int32, [None, class_num], name='y')
  98. # batch_size是一个int32类型的标量tensor的占位符,
  99. # 使用batch_size可以让我们在训练和测试的时候使用不同的数据量
  100. batch_size = tf.placeholder(tf.int32, [])
  101. # # dropout的时候,保留率多少
  102. keep_prob = tf.placeholder(tf.float32, [])
  103. learn_rate = tf.placeholder(tf.float32, [])


  104. # 第四步:构建RNN LSTM 网络(直接将网络结构翻译成为这个代码)
  105. # 1. 输入的数据格式转换
  106. # X格式:[batch_size, num_timesteps, input_size]
  107. X = tf.reshape(_X, [-1, num_timesteps, input_size])

  108. # LSTM层
  109. # 开方(输入层size + 输出层size)
  110. # 初始化方法 仿照了
  111. scale = 1.0 / math.sqrt(input_size + num_lstm_nodes[-1]) / 3.0
  112. lstm_initializer = tf.random_uniform_initializer(minval=-scale, maxval=scale)
  113. with tf.variable_scope(name_or_scope='lstm_nn', initializer=lstm_initializer):
  114.     cells_fw = []
  115.     for i in range(num_lstm_layers):
  116.         cell = tf.nn.rnn_cell.LSTMCell(num_units=num_lstm_nodes[i], name='lstm_cell')
  117.         # cell = tf.nn.rnn_cell.LSTMCell(num_units=num_lstm_nodes[i], use_peepholes=True, name='lstm_cell')
  118.         cell = tf.nn.rnn_cell.DropoutWrapper(cell, output_keep_prob=keep_prob)
  119.         cells_fw.append(cell)
  120.     # 多层的LSTM 将两层的cell合并封装成一个MultiRNNCell
  121.     # 将多层RNN当作单层RNN来操作了
  122.     # tf.nn.rnn_cell
  123.     cell_fw = tf.nn.rnn_cell.MultiRNNCell(cells_fw, state_is_tuple=True)

  124.     cells_bw = []
  125.     for i in range(num_lstm_layers):
  126.         # cell = tf.nn.rnn_cell.LSTMCell(num_units=num_lstm_nodes[i], name='lstm_cell')
  127.         cell = tf.nn.rnn_cell.GRUCell(num_units=num_lstm_nodes[i], name='gru_cell')
  128.         # cell = tf.nn.rnn_cell.LSTMCell(num_units=num_lstm_nodes[i], use_peepholes=True, name='lstm_cell')
  129.         cell = tf.nn.rnn_cell.DropoutWrapper(cell, output_keep_prob=keep_prob)
  130.         cells_bw.append(cell)
  131.     # 多层的LSTM 将两层的cell合并封装成一个MultiRNNCell
  132.     # 将多层RNN当作单层RNN来操作了
  133.     # tf.nn.rnn_cell
  134.     cell_bw = tf.nn.rnn_cell.MultiRNNCell(cells_bw, state_is_tuple=True)



  135.     # cell_fw = tf.nn.rnn_cell.LSTMCell(num_units=num_lstm_nodes[0], name='gru_cell')
  136.     # cell_bw = tf.nn.rnn_cell.GRUCell(num_units=num_lstm_nodes[1], name='gru_cell')
  137.     # 初始的中间的隐含状态 state=0
  138.     initial_state_fw = cell_fw.zero_state(batch_size=batch_size, dtype=tf.float32)
  139.     initial_state_bw = cell_bw.zero_state(batch_size=batch_size, dtype=tf.float32)
  140.     # 让cell去处理或计算输入的序列 rnn_outputs包含了每一步的输出
  141.     # rnn_outputs shape : [batch_size, num_timesteps, hps.num_lstm_nodes[-1]]
  142.     # rnn_outputs, middle_hidden_state = tf.nn.dynamic_rnn(cell=cell, inputs=X, initial_state=initial_state)
  143.     rnn_outputs, middle_hidden_state = tf.nn.bidirectional_dynamic_rnn(cell_fw=cell_fw,
  144.                                                                        cell_bw=cell_bw,
  145.                                                                        inputs=X,
  146.                                                                        initial_state_fw=initial_state_fw,
  147.                                                                        initial_state_bw=initial_state_bw)

  148.     rnn_outputs_fw, rnn_outputs_bw = rnn_outputs
  149.     middle_hidden_state_fw, middle_hidden_state_bw = middle_hidden_state


  150.     print('rnn_outputs_fw shape:', rnn_outputs_fw.shape)
  151.     print('rnn_outputs_bw shape:', rnn_outputs_bw.shape)
  152.     # last shape [batch_size, hps.num_lstm_nodes[-1]]
  153.     # shape : [batch_size, 128]
  154.     last_fw = rnn_outputs_fw[:, -1, :]
  155.     # shape : [batch_size, 256]
  156.     last_bw = rnn_outputs_bw[:, -1, :]

  157.     last = tf.concat([last_fw, last_bw], axis=1)
  158.     # shape : [batch_size, 128+256]
  159.     print('last shape: ', last.shape)


  160. # fc
  161. # fc_initializer = tf.uniform_unit_scaling_initializer(factor=1.0, dtype=tf.float32)
  162. fc_initializer = tf.random_uniform_initializer(-1.0, 1.0, seed=10)
  163. with tf.variable_scope(name_or_scope='fc', initializer=fc_initializer):
  164.     logits = tf.layers.dense(last, class_num, name='fc')

  165. #
  166. # 第五步:构建模型的损失函数
  167. # 第六步:构建梯度下降的优化方法(一般用Adam 动量GD)
  168. # 第七步:计算模型正确率
  169. # metrics (loss accuracy)
  170. # metrics度量层(loss 与 accuracy)
  171. # 这一层并没有变量或参数需要训练 也就不需要初始化器 所以使用name_scope
  172. with tf.name_scope(name='metrics'):
  173.     # sparse_ 用这个:强大一些
  174.     # softmax_loss = tf.nn.sparse_softmax_cross_entropy_with_logits(labels=outputs, logits=logits)
  175.     # 计算_交叉熵损失函数值 用第二个版本
  176.     softmax_loss = tf.nn.softmax_cross_entropy_with_logits_v2(labels=y, logits=logits)
  177.     loss = tf.reduce_mean(softmax_loss)
  178.     # argmax [0, 2, 1, 5, 8, 2]  ---> 4
  179.     y_pred = tf.argmax(tf.nn.softmax(logits), axis=1, output_type=tf.int32)
  180.     y_true = tf.argmax(y, axis=1, output_type=tf.int32)
  181.     correct_pred = tf.equal(y_pred, y_true)
  182.     accuracy = tf.reduce_mean(tf.cast(correct_pred, dtype=tf.float32))


  183. # train_op 训练层
  184. with tf.name_scope(name='train_op'):
  185.     # 需要对训练变量的梯度进行clip  hps.clip_lstm_grads
  186.     # 获取所有训练的变量
  187.     # train_op = tf.train.AdamOptimizer(hps.learning_rate).minimize(loss, global_step=global_step)
  188.     train_vars = tf.trainable_variables()
  189.     for var in train_vars:
  190.         tf.logging.info('train variable name : %s' % var.name)
  191.     # tf.gradients(loss, train_vars) 损失值对所有变量的梯度
  192.     # grads得到截断后的梯度
  193.     grads, _ = tf.clip_by_global_norm(t_list=tf.gradients(loss, train_vars), clip_norm=clip_lstm_grads)
  194.     # 普通梯度下降 BGD SGD MBGD  动量(有速度) 冲量
  195.     # 将梯度应用到所有的变量
  196.     optimizer = tf.train.AdamOptimizer(learn_rate)
  197.     train_op = optimizer.apply_gradients(grads_and_vars=zip(grads, train_vars), name='train_op')



  198. # 第八步:会话中执行阶段(模型的训练与迭代)

  199. init_op = tf.global_variables_initializer()

  200. num_train_steps = 500
  201. batch_size_train = 100
  202. batch_size_test = 3000
  203. keep_prob_train = 0.8
  204. keep_prob_test = 1.0


  205. with tf.Session() as sess:
  206.     sess.run(init_op)
  207.     for step in range(num_train_steps):
  208.         batch_xs, batch_labels = mnist.train.next_batch(batch_size_train)
  209.         loss_val, accuracy_val, _ = sess.run(fetches=[loss, accuracy, train_op], feed_dict={
  210.             _X: batch_xs,
  211.             y: batch_labels,
  212.             keep_prob: keep_prob_train,
  213.             batch_size: batch_size_train,
  214.             learn_rate: learn_rate_func(step)
  215.         })
  216.         if step % display_step == 0:
  217.             tf.logging.info('Step: %5d, loss: %3.3f, accuracy: %3.3f' % (step, loss_val, accuracy_val))
  218.     # test
  219.     accuracy_test = sess.run(fetches=accuracy, feed_dict={
  220.         _X: mnist.test.images[:3000],
  221.         y: mnist.test.labels[:3000],
  222.         keep_prob: keep_prob_test,
  223.         batch_size: batch_size_test,
  224.     })
  225.     print('测试集准确率:{}'.format(accuracy_test))
  226.     pass







复制代码


01.png (266.79 KB, 下载次数: 176)

01.png

02.png (98.05 KB, 下载次数: 175)

02.png
让天下人人学会人工智能!人工智能的前景一片大好!
回复

使用道具 举报

0

主题

96

帖子

198

积分

注册会员

Rank: 2

积分
198
沙发
发表于 2019-7-2 14:05:53 | 只看该作者
多谢分享
回复

使用道具 举报

0

主题

2

帖子

10

积分

新手上路

Rank: 1

积分
10
板凳
发表于 2020-5-25 16:17:03 | 只看该作者
多谢分享
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|人工智能工程师的摇篮 ( 湘ICP备2020019608号-1 )

GMT+8, 2024-4-20 08:44 , Processed in 0.193908 second(s), 21 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表