当前位置:   article > 正文

RNN循环神经网络实例_rnn demo

rnn demo

最近又忍不住把RNN这一块儿的东西给过了一遍,感觉还是有一些收获!所以想着给记录下来,因为也看到有人给我提意见说:我写的关于算法的文章太多了,还是要好好搞学术研究,所以就想着最近多更几篇关于深度学习网络方面的文章。

关于RNN循环神经网络的具体概念我就不细讲了,稍微把概念给提下吧,然后会说说其变形模型,以及会给出两个demo讲述其在不同领域的应用,方便大家理解!

1. RNN循环神经网络介绍

上面这张图算是最最最经典的也是最一般的RNN网络结构了。

 因为要讲解步骤,所以用这张图来表示步骤,上图其实是把RNN给展开成我们熟悉的全连接神经网络了,这样我们会比较熟悉。步骤如下:

基于上述步骤可实现一简单的RNN神经网络,核心流程如下demo所示:

  1. import numpy as np
  2. import os
  3. os.environ["TF_CPP_MIN_LOG_LEVEL"] = "2"
  4. X = [1, 2]
  5. state = [0.0, 0.0]
  6. # 定义不同输入部分的权重
  7. w_cell_state = np.asarray([[0.1, 0.2], [0.3, 0.4]])
  8. w_cell_input = np.asarray([0.5, 0.6])
  9. b_cell = np.asarray([0.1, -0.1])
  10. # 定义输出层的权重
  11. w_output = np.asarray([[0.1], [0.2]])
  12. b_output = 0.1
  13. # 按照时间顺序执行循环神经网络的前向传播过程
  14. for i in range(len(X)):
  15. before_activation = np.dot(state, w_cell_state) + X[i]*w_cell_input+b_cell
  16. state = np.tanh(before_activation)
  17. # 计算当前时刻的最终输出
  18. final_output = np.dot(state, w_output) + b_output
  19. # 输出每一时刻的信息
  20. print("before_activation", before_activation)
  21. print("state", state)
  22. print("final_output", final_output)

只说这个最简单的网络,肯定是没有意思的!所以接下来我会分享一个用RNN来识别手写字体的demo。

2. RNN神经网络识别手写字体

  1. import tensorflow as tf
  2. from tensorflow.examples.tutorials.mnist import input_data
  3. from tensorflow.contrib import rnn
  4. import os
  5. os.environ["TF_CPP_MIN_LOG_LEVEL"] = "2"
  6. # 载入数据
  7. mnist = input_data.read_data_sets("MNIST_data", one_hot=True)
  8. # 设置模型的参数
  9. # 对应输入图片的宽
  10. n_inputs = 28
  11. # 对应输入图片的行
  12. max_time = 28
  13. # 隐藏单元,实质上不是神经元,即LSTM单元
  14. lstm_size = 100
  15. # 图片总共有10个分类
  16. n_classes = 10
  17. # 每批次总共有50个样本
  18. batch_size = 50
  19. n_batch = mnist.train.num_examples//batch_size
  20. # 这里的None=50
  21. x = tf.placeholder(tf.float32, [None, 784])
  22. y = tf.placeholder(tf.float32, [None, 10])
  23. # 初始化权值
  24. weights = tf.Variable(tf.truncated_normal([lstm_size, n_classes], stddev=0.1))
  25. # 初始化偏置值
  26. biases = tf.Variable(tf.constant(0.1, shape=[n_classes]))
  27. # 定义RNN网络
  28. def RNN(X, weights, biases):
  29. inputs = tf.reshape(X, [-1, max_time, n_inputs])
  30. lstm_cell = rnn.BasicLSTMCell(lstm_size)
  31. # outputs维度为shape=(?, 28, 100);final_state维度为shape=(?, 100)
  32. outputs, final_state = tf.nn.dynamic_rnn(lstm_cell, inputs, dtype=tf.float32)
  33. print("shape(outputs)", outputs)
  34. print("shape(final_state)", final_state)
  35. # 如果使用Seq2Seq模型,则调用outputs;反之则使用final_state
  36. results = tf.nn.softmax(tf.matmul(final_state[1], weights)+biases)
  37. return results
  38. # 计算RNN的返回结果
  39. prediction = RNN(x, weights, biases)
  40. # 损失函数--交叉熵
  41. cross_entropy = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(labels=y, logits=prediction))
  42. # 使用AdamOptimizer进行优化
  43. train_op = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)
  44. # 结果放在一个布尔型列表中
  45. crroect_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(prediction, 1))
  46. # 求准确率
  47. accuracy = tf.reduce_mean(tf.cast(crroect_prediction, tf.float32))
  48. # 开始训练模型
  49. with tf.Session() as sess:
  50. sess.run(tf.global_variables_initializer())
  51. for epoch in range(10):
  52. for batch in range(n_batch):
  53. batch_xs, batch_ys = mnist.train.next_batch(batch_size)
  54. sess.run(train_op, feed_dict={x: batch_xs, y:batch_ys})
  55. acc = sess.run(accuracy, feed_dict={x: mnist.test.images, y: mnist.test.labels})
  56. print("Iter "+str(epoch)+", Testing Accuracy="+str(acc))

这个demo里有处地方我需要强调一下:

  1. outputs, final_state = tf.nn.dynamic_rnn(lstm_cell, inputs, dtype=tf.float32)
  2. # 如果使用Seq2Seq模型,则调用outputs;反之则使用final_state
  3. results = tf.nn.softmax(tf.matmul(final_state[1], weights)+biases)

这里面outputs维度为shape=(?, 28, 100);final_state维度为shape=(?, 100),具体结构如下图所示:

在这个demo里我们是没用到output这个LSTM cell的,不是说它没用哈,而是在后面提到的Seq2Seq模型中会用到这个值。

3. RNN神经网络预测下一个字符

不知道大家发现没有,上面讲到的这个最基础的RNN模型中输入数据的“维度”与输出数据的“维度”是一一对应的,即Xt与Ot是相对应的。但是在实际应用中这种情形太少了,跟多的是N->M的关系,即输入数据的维度”与输出数据的“维度”是不同的。比如在机器翻译应用中,将一段汉语翻译成英文。汉语是:我英语不好,翻译成英文是:my English is poor 此处N=5,M=4明显是N与M不相等的情形,此时我们要怎么解决这个模型呢?

那问题就来了,此时我们要怎么解决这个模型呢?

为此得引入一种新的模型,这种结构又叫Encoder-Decoder模型,也可以称之为Seq2Seq模型。如下图所示:

 

还有一种做法是将c当做每一步的输入:

 

按照这个模型,我接下来将会给出能预测下一个字符的RNN模型

  1. import tensorflow as tf
  2. from tensorflow import contrib
  3. import numpy as np
  4. import os
  5. os.environ["TF_CPP_MIN_LOG_LEVEL"] = "2"
  6. sample = "这是一个基于tensorflow的RNN短句子练习"
  7. # 去重放入列表中
  8. idx2char = list(set(sample))
  9. print("idx2char", idx2char)
  10. # 转换为字典,其中把字母作键,索引作为值
  11. char2idx = {c: i for i, c in enumerate(idx2char)}
  12. # 在字典里取出对应值,因为在idx2char中原sample句子的顺序已经被打乱
  13. sample_idx = [char2idx[c] for c in sample]
  14. x_data = [sample_idx[:-1]]
  15. y_data = [sample_idx[1:]]
  16. # 设置该模型的一些参数
  17. dic_size = len(char2idx)
  18. rnn_hidden_size = len(char2idx)
  19. num_classes = len(char2idx)
  20. batch_size = 1
  21. sequence_length = len(sample) - 1
  22. X = tf.placeholder(tf.int32, [None, sequence_length])
  23. Y = tf.placeholder(tf.int32, [None, sequence_length])
  24. # 将input转化为one-hot类型数据输出,此时X的维度变为[None, sequence_length, num_classes]
  25. X_one_hot = tf.one_hot(X, num_classes)
  26. cell = tf.contrib.rnn.BasicLSTMCell(num_units=rnn_hidden_size, state_is_tuple=True)
  27. initial_state = cell.zero_state(batch_size, tf.float32)
  28. outputs, states = tf.nn.dynamic_rnn(cell, X_one_hot, initial_state=initial_state, dtype=tf.float32)
  29. # 加一层全连接层,相当于加一层深度,使预测更准确
  30. outputs = contrib.layers.fully_connected(inputs=outputs, num_outputs=num_classes, activation_fn=None)
  31. print("outputs", tf.shape(outputs))
  32. weights = tf.ones([batch_size, sequence_length])
  33. # 此处包装了encoder和decoder
  34. sequence_loss = tf.contrib.seq2seq.sequence_loss(logits=outputs, targets=Y, weights=weights)
  35. loss = tf.reduce_mean(sequence_loss)
  36. train = tf.train.GradientDescentOptimizer(learning_rate=0.1).minimize(loss)
  37. prediction = tf.argmax(outputs, axis=2)
  38. with tf.Session() as sess:
  39. sess.run(tf.global_variables_initializer())
  40. for i in range(3000):
  41. l, _ = sess.run([loss, train], feed_dict={X: x_data, Y: y_data})
  42. result = sess.run(prediction, feed_dict={X: x_data})
  43. # print char using dic
  44. result_str = [idx2char[c] for c in np.squeeze(result)]
  45. print(i, "loss:", l, "Prediction:", "".join(result_str))
  46. print(len(result_str))

模型Run起来的结果如下:

 

可以看到:效果还是不错的!暂时就分享到这儿了,有想到更好的东西再来补充!

 

 

本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/978329
推荐阅读
相关标签
  

闽ICP备14008679号