Python人工智能 | 十二.循环神经网络RNN和LSTM原理详解及TensorFlow分类案例
文章目录:
一.循环神经网络
1.RNN原理
2.RNN应用
二.LSTM RNN原理详解
1.为什么引入LSTM
2.LSTM
三.Tensorflow编写RNN代码
四.总结
https://github.com/eastmountyxz/
AI-for-TensorFlowhttps://github.com/eastmountyxz/
AI-for-Keras
学Python近八年,认识了很多大佬和朋友,感恩。作者的本意是帮助更多初学者入门,因此在github开源了所有代码,也在公众号同步更新。深知自己很菜,得拼命努力前行,编程也没有什么捷径,干就对了。希望未来能更透彻学习和撰写文章,也能在读博几年里学会真正的独立科研。同时非常感谢参考文献中的大佬们的文章和分享。
- https://blog.csdn.net/eastmount
一.循环神经网络
1.RNN原理
2.RNN应用
二.LSTM RNN原理详解
1.为什么引入LSTM
2.LSTM
输入控制器(write gate): 在输入input时设置一个gate,gate的作用是判断要不要写入这个input到我们的内存Memory中,它相当于一个参数,也是可以被训练的,这个参数就是用来控制要不要记住当下这个点。
输出控制器(read gate): 在输出位置的gate,判断要不要读取现在的Memory。
忘记控制器(forget gate): 处理位置的忘记控制器,判断要不要忘记之前的Memory。
三.Tensorflow编写RNN代码
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
# 下载手写数字图像数据集
mnist = input_data.read_data_sets('MNIST_data', one_hot=True)
# 设置参数
learning_rate = 0.001 # 学习效率
train_iters = 100000 # 训练次数
batch_size = 128 # 自定义
n_inputs = 28 # MNIST 输入图像形状 28*28 黑白图片高度为1
n_steps = 28 # time steps 输入图像的28行数据
n_hidden_units = 128 # 神经网络隐藏层数量
n_classes = 10 # 分类结果 数字0-0
# 设置传入的值xs和ys
x = tf.placeholder(tf.float32, [None, n_steps, n_inputs]) #每张图片28*28=784个点
y = tf.placeholder(tf.float32, [None, n_classes]) #每个样本有10个输出
# 定义权重 进入RNN前的隐藏层 输入&输出
weights = {
# (28, 128)
'in': tf.Variable(tf.random_normal([n_inputs, n_hidden_units])),
# (128, 10)
'out': tf.Variable(tf.random_normal([n_hidden_units, n_classes])),
}
# 定义偏置 进入RNN前的隐藏层 输入&输出
biases = {
# (128, )
'in': tf.Variable(tf.constant(0.1, shape=[n_hidden_units, ])),
# (10, )
'out': tf.Variable(tf.constant(0.1, shape=[n_classes, ])),
}
#---------------------------------定义RNN-------------------------------
def RNN(X, weights, biases):
# hidden layer for input to cell
#######################################################
# X (128 batch, 28 steps, 28 inputs) 28行*28列
# X ==> (128*28, 28 inputs)
X = tf.reshape(X, [-1, n_inputs])
# 隐藏层 输入
# X_in ==> (128batch*28steps, 128 hidden)
X_in = tf.matmul(X, weights['in']) + biases['in']
# 二维数据转换成三维数据
# 注意:神经网络学习时要注意其形状如何变化
# X_in ==> (128 batch, 28 steps, 128 hidden)
X_in = tf.reshape(X_in, [-1, n_steps, n_hidden_units]) # 128个隐藏层
# cell
#######################################################
# Cell结构 隐藏层数 forget初始偏置为1.0(初始时不希望forget)
lstm_cell = tf.nn.rnn_cell.BasicLSTMCell(n_hidden_units, forget_bias=1.0, state_is_tuple=True)
# RNN会保留每一步计算的结果state
# lstm cell is divided into two parts (c_state, m_state) 主线c_state 分线m_state
_init_state = lstm_cell.zero_state(batch_size, dtype=tf.float32)
# RNN运算过程 每一步的输出都存储在outputs序列中
# 常规RNN只有m_state LSTM包括c_state和m_state
outputs, states = tf.nn.dynamic_rnn(lstm_cell, X_in, initial_state=_init_state, time_major=False)
# hidden layer for output as final results
#######################################################
# 第三层加工最终的输出
# 最终输出=Cell的输出*权重输出+偏置数据
# states包含了主线剧情和分线剧情 states[1]表示分线剧情的结果 即为outputs[-1]最后一个输出结果
results = tf.matmul(states[1], weights['out']) + biases['out']
# 第二种方法
# 解包 unpack to list [(batch, outputs)..] * steps
#outputs = tf.unstack(tf.transpose(outputs, [1,0,2])) # states is the last outputs
#results = tf.matmul(outputs[-1], weights['out']) + biases['out']
return results
第八步,定义误差和准确度。
#---------------------------------定义误差和训练-------------------------------
pre = RNN(x, weights, biases)
# 预测值与真实值误差
cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=pre, labels=y))
# 训练学习 学习效率设置为0.001
train_step = tf.train.AdamOptimizer(learning_rate).minimize(cost) #梯度下降减小误差
# 预测正确个数
correct_pred = tf.equal(tf.argmax(pre, 1), tf.argmax(y, 1))
# 准确度
accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32))
第九步,初始化及训练。
#---------------------------------初始化及训练-------------------------------
init = tf.initialize_all_variables()
with tf.Session() as sess:
sess.run(init)
step = 0
# 循环每次提取128个样本
while step * batch_size < train_iters:
# 从下载好的数据集提取128个样本
batch_xs, batch_ys = mnist.train.next_batch(batch_size)
# 形状修改 [128, 28, 28]
batch_xs = batch_xs.reshape([batch_size, n_steps, n_inputs])
# 训练
sess.run([train_step], feed_dict={
x: batch_xs,
y: batch_ys,
})
# 每隔20步输出结果
if step % 20 == 0: # 20*128
print(sess.run(accuracy, feed_dict={
x: batch_xs,
y: batch_ys,
}))
step += 1
最终输出结果如下所示,可以看到,最早预测的准确度结果非常低为2.187%,最后提升到了96.87%,其结果高于之前的一般神经网络的结果87.79%(第六篇博客),由此可见TensorFlow RNN的分类学习效果还不错,并且在不断学习中。
Extracting MNIST_data\train-images-idx3-ubyte.gz
Extracting MNIST_data\train-labels-idx1-ubyte.gz
Extracting MNIST_data\t10k-images-idx3-ubyte.gz
Extracting MNIST_data\t10k-labels-idx1-ubyte.gz
0.2187500
0.6796875
0.8281250
0.8203125
0.8359375
0.8984375
0.8828125
0.8359375
0.9062500
....
0.9843750
0.9609375
0.9453125
0.9609375
0.9765625
0.9375000
0.9921875
0.9609375
0.9921875
0.9687500
完整代码如下:
# -*- coding: utf-8 -*-
"""
Created on Fri Jan 3 11:50:33 2020
@author: xiuzhang Eastmount CSDN
"""
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
# 下载手写数字图像数据集
mnist = input_data.read_data_sets('MNIST_data', one_hot=True)
# 设置参数
learning_rate = 0.001 # 学习效率
train_iters = 100000 # 训练次数
batch_size = 128 # 自定义
n_inputs = 28 # MNIST 输入图像形状 28*28 黑白图片高度为1
n_steps = 28 # time steps 输入图像的28行数据
n_hidden_units = 128 # 神经网络隐藏层数量
n_classes = 10 # 分类结果 数字0-0
#-----------------------------定义placeholder输入-------------------------
# 设置传入的值xs和ys
x = tf.placeholder(tf.float32, [None, n_steps, n_inputs]) #每张图片28*28=784个点
y = tf.placeholder(tf.float32, [None, n_classes]) #每个样本有10个输出
# 定义权重 进入RNN前的隐藏层 输入&输出
weights = {
# (28, 128)
'in': tf.Variable(tf.random_normal([n_inputs, n_hidden_units])),
# (128, 10)
'out': tf.Variable(tf.random_normal([n_hidden_units, n_classes])),
}
# 定义偏置 进入RNN前的隐藏层 输入&输出
biases = {
# (128, )
'in': tf.Variable(tf.constant(0.1, shape=[n_hidden_units, ])),
# (10, )
'out': tf.Variable(tf.constant(0.1, shape=[n_classes, ])),
}
#---------------------------------定义RNN-------------------------------
def RNN(X, weights, biases):
# hidden layer for input to cell
#######################################################
# X (128 batch, 28 steps, 28 inputs) 28行*28列
# X ==> (128*28, 28 inputs)
X = tf.reshape(X, [-1, n_inputs])
# 隐藏层 输入
# X_in ==> (128batch*28steps, 128 hidden)
X_in = tf.matmul(X, weights['in']) + biases['in']
# 二维数据转换成三维数据
# 注意:神经网络学习时要注意其形状如何变化
# X_in ==> (128 batch, 28 steps, 128 hidden)
X_in = tf.reshape(X_in, [-1, n_steps, n_hidden_units]) # 128个隐藏层
# cell
#######################################################
# Cell结构 隐藏层数 forget初始偏置为1.0(初始时不希望forget)
lstm_cell = tf.nn.rnn_cell.BasicLSTMCell(n_hidden_units, forget_bias=1.0, state_is_tuple=True)
# RNN会保留每一步计算的结果state
# lstm cell is divided into two parts (c_state, m_state) 主线c_state 分线m_state
_init_state = lstm_cell.zero_state(batch_size, dtype=tf.float32)
# RNN运算过程 每一步的输出都存储在outputs序列中
# 常规RNN只有m_state LSTM包括c_state和m_state
outputs, states = tf.nn.dynamic_rnn(lstm_cell, X_in, initial_state=_init_state, time_major=False)
# hidden layer for output as final results
#######################################################
# 第三层加工最终的输出
# 最终输出=Cell的输出*权重输出+偏置数据
# states包含了主线剧情和分线剧情 states[1]表示分线剧情的结果 即为outputs[-1]最后一个输出结果
results = tf.matmul(states[1], weights['out']) + biases['out']
# 第二种方法
# 解包 unpack to list [(batch, outputs)..] * steps
#outputs = tf.unstack(tf.transpose(outputs, [1,0,2])) # states is the last outputs
#results = tf.matmul(outputs[-1], weights['out']) + biases['out']
return results
#---------------------------------定义误差和训练-------------------------------
pre = RNN(x, weights, biases)
# 预测值与真实值误差
cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=pre, labels=y))
# 训练学习 学习效率设置为0.001
train_step = tf.train.AdamOptimizer(learning_rate).minimize(cost) #梯度下降减小误差
# 预测正确个数
correct_pred = tf.equal(tf.argmax(pre, 1), tf.argmax(y, 1))
# 准确度
accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32))
#---------------------------------初始化及训练-------------------------------
init = tf.initialize_all_variables()
with tf.Session() as sess:
sess.run(init)
step = 0
# 循环每次提取128个样本
while step * batch_size < train_iters:
# 从下载好的数据集提取128个样本
batch_xs, batch_ys = mnist.train.next_batch(batch_size)
# 形状修改 [128, 28, 28]
batch_xs = batch_xs.reshape([batch_size, n_steps, n_inputs])
# 训练
sess.run([train_step], feed_dict={
x: batch_xs,
y: batch_ys,
})
# 每隔20步输出结果
if step % 20 == 0: # 20*128
print(sess.run(accuracy, feed_dict={
x: batch_xs,
y: batch_ys,
}))
step += 1
注意,在运行代码过程中可能会报错“ValueError: Variable rnn/basic_lstm_cell/kernel already exists, disallowed. Did you mean to set reuse=True or reuse=tf.AUTO_REUSE in VarScope?”
在Spyder中有kernel选项,点击选择 “ Restart & RunAll ” 重新运行代码即可解决问题。
四.总结
写到这里,这篇文章就讲解完毕,更多TensorFlow深度学习文章会继续分享,接下来我们会分享RNN回归、文本识别、图像识别、语音识别等内容。如果读者有什么想学习的,也可以私聊我,我去学习并应用到你的领域。
最后,希望这篇基础性文章对您有所帮助,如果文章中存在错误或不足之处,还请海涵~作为人工智能的菜鸟,我希望自己能不断进步并深入,后续将它应用于图像识别、网络安全、对抗样本等领域,指导大家撰写简单的学术论文,一起加油!
读博不易,但深夜总喜欢挤时间写上一篇文章,算是对自己这么多年分享的鼓励,也希望自己能坚持,感谢家人的支持,小珞珞太可爱了。如果您也是从事Python数据分析、图像处理、人工智能、网络安全的朋友,我们可以深入探讨,尤其是做研究的同学,共同进步~
前文分享(可以点击喔):
十二.循环神经网络RNN和LSTM原理详解及TensorFlow分类案例
天行健,君子以自强不息。
地势坤,君子以厚德载物。
真诚地感谢您关注“娜璋之家”公众号,也希望我的文章能陪伴你成长,希望在技术路上不断前行。文章如果对你有帮助、有感悟,就是对我最好的回报,且看且珍惜!再次感谢您的关注,也请帮忙宣传下“娜璋之家”,初来乍到,还请多指教。
(By:Eastmount 2022-01-17 夜于东西湖)
参考文献:
[1] 冈萨雷斯著. 数字图像处理(第3版)[M]. 北京:电子工业出版社,2013.
[2] 杨秀璋, 颜娜. Python网络数据爬取及分析从入门到精通(分析篇)[M]. 北京:北京航天航空大学出版社, 2018.
[3] 罗子江等. Python中的图像处理[M]. 科学出版社, 2020.
[4]“莫烦大神” 网易云视频地址
[5] https://study.163.com/course/courseLearn.htm?courseId=1003209007
[6] TensorFlow【极简】CNN - Yellow_python大神
[7] 基于深度神经网络的定向激活功能开发相位信息的声源定位 - 章子雎Kevin
[8] https://github.com/siucaan/CNN_MNIST
[9] https://github.com/eastmountyxz/AI-for-TensorFlow
[10] LSTM和GRU很难?别担心,这有一份超生动的图解