从本专栏开始,作者正式开始研究Python深度学习、神经网络及人工智能相关知识。前一篇讲解了TensorFlow如何保存变量和神经网络参数,通过Saver保存神经网络,再通过Restore调用训练好的神经网络。本文将详细讲解循环神经网络RNN和长短期记忆网络LSTM的原理知识,并采用TensorFlow实现手写数字识别的RNN分类案例。本文主要结合作者之前的博客和"莫烦大神"的视频,后面随着深入会讲解实践项目及应用,希望对您有所帮助。
本专栏主要结合作者之前的博客、AI经验和相关视频及论文介绍,后面随着深入会讲解更多的Python人工智能案例及应用。基础性文章,希望对您有所帮助,如果文章中存在错误或不足之处,还请海涵~作者作为人工智能的菜鸟,希望大家能与我在这一笔一划的博客中成长起来。写了这么多年博客,尝试第一个付费专栏,但更多博客尤其基础性文章,还是会继续免费分享,但该专栏也会用心撰写,望对得起读者,共勉!
代码下载地址:
https://github.com/eastmountyxz/AI-for-TensorFlow
百度网盘链接:
https://pan.baidu.com/s/19r80A-tbCXzhpyF0Cx2cew
提取码:gwg4
同时推荐前面作者另外三个Python系列文章。从2014年开始,作者主要写了三个Python系列文章,分别是基础知识、网络爬虫和数据分析。2018年陆续增加了Python图像识别和Python人工智能专栏。
前文:
[Python人工智能] 一.TensorFlow2.0环境搭建及神经网络入门
[Python人工智能] 二.TensorFlow基础及一元直线预测案例
[Python人工智能] 三.TensorFlow基础之Session、变量、传入值和激励函数
[Python人工智能] 四.TensorFlow创建回归神经网络及Optimizer优化器
[Python人工智能] 五.Tensorboard可视化基本用法及绘制整个神经网络
[Python人工智能] 六.TensorFlow实现分类学习及MNIST手写体识别案例
[Python人工智能] 七.什么是过拟合及dropout解决神经网络中的过拟合问题
[Python人工智能] 八.卷积神经网络CNN原理详解及TensorFlow编写CNN
[Python人工智能] 九.gensim词向量Word2Vec安装及《庆余年》中文短文本相似度计算
[Python人工智能] 十.Tensorflow+Opencv实现CNN自定义图像分类案例及与机器学习KNN图像分类算法对比
[Python人工智能] 十一.Tensorflow如何保存神经网络参数
一.循环神经网络
在编写代码之前,我们需要介绍什么是RNN,RNN是怎样运行的以及RNN的结构。
1.RNN原理
循环神经网络英文是Recurrent Neural Networks,简称RNN。假设有一组数据data0、data1、data2、data3,使用同一个神经网络预测它们,得到对应的结果。如果数据之间是有关系的,比如做菜下料的前后步骤,英文单词的顺序,如何让数据之间的关联也被神经网络学习呢?这就要用到——RNN。
假设存在ABCD数字,需要预测下一个数字E,会根据前面ABCD顺序进行预测,这就称为记忆。预测之前,需要回顾以前的记忆有哪些,再加上这一步新的记忆点,最终输出output,循环神经网络(RNN)就利用了这样的原理。
首先,让我们想想人类是怎么分析事物之间的关联或顺序的。人类通常记住之前发生的事情,从而帮助我们后续的行为判断,那么是否能让计算机也记住之前发生的事情呢?
在分析data0时,我们把分析结果存入记忆Memory中,然后当分析data1时,神经网络(NN)会产生新的记忆,但此时新的记忆和老的记忆没有关联,如上图所示。在RNN中,我们会简单的把老记忆调用过来分析新记忆,如果继续分析更多的数据时,NN就会把之前的记忆全部累积起来。
RNN结构如下图所示,按照时间点t-1、t、t+1,每个时刻有不同的x,每次计算会考虑上一步的state和这一步的x(t),再输出y值。在该数学形式中,每次RNN运行完之后都会产生s(t),当RNN要分析x(t+1)时,此刻的y(t+1)是由s(t)和s(t+1)共同创造的,s(t)可看作上一步的记忆。多个神经网络NN的累积就转换成了循环神经网络,其简化图如下图的左边所示。
总之,只要你的数据是有顺序的,就可以使用RNN,比如人类说话的顺序,电话号码的顺序,图像像素排列的顺序,ABC字母的顺序等。在前面讲解CNN原理时,它可以看做是一个滤波器滑动扫描整幅图像,通过卷积加深神经网络对图像的理解。
而RNN也有同样的扫描效果,只不过是增加了时间顺序和记忆功能。RNN通过隐藏层周期性的连接,从而捕获序列化数据中的动态信息,提升预测结果。
2.RNN应用
RNN常用于自然语言处理、机器翻译、语音识别、图像识别等领域,下面简单分享RNN相关应用所对应的结构。
RNN情感分析:
当分析一个人说话情感是积极的还是消极的,就用如下图所示的RNN结构,它有N个输入,1个输出,最后时间点的Y值代表最终的输出结果。
RNN图像识别:
此时有一张图片输入X,N张对应的输出。
RNN机器翻译:
输入和输出分别两个,对应的是中文和英文,如下图所示。
二.LSTM RNN原理详解
接下来我们看一个更强大的结构,称为LSTM。
1.为什么引入LSTM
RNN是在有序的数据上进行学习的,RNN会像人一样对先前的数据发生记忆,但有时候也会像老爷爷一样忘记先前所说。为了解决RNN的这个弊端,提出了LTSM技术,它的英文全称是Long short-term memory,长短期记忆,也是当下最流行的RNN之一。
假设现在有一句话,如下图所示,RNN判断这句话是红烧排骨,这时需要学习,而“红烧排骨“在句子开头。
"红烧排骨"这个词需要经过长途跋涉才能抵达,要经过一系列得到误差,然后经过反向传递,它在每一步都会乘以一个权重w参数。如果乘以的权重是小于1的数,比如0.9,0.9会不断地乘以误差,最终这个值传递到初始值时,误差就消失了,这称为梯度消失或梯度离散。
反之,如果误差是一个很大的数,比如1.1,则这个RNN得到的值会很大,这称为梯度爆炸。
梯度消失或梯度爆炸:
在RNN中,如果你的State是一个很长的序列,假设反向传递的误差值是一个小于1的数,每次反向传递都会乘以这个数,0.9的n次方趋向于0,1.1的n次方趋向于无穷大,这就会造成梯度消失或梯度爆炸。
这也是RNN没有恢复记忆的原因,为了解决RNN梯度下降时遇到的梯度消失或梯度爆炸问题,引入了LSTM。
2.LSTM
LSTM是在普通的RNN上面做了一些改进,LSTM RNN多了三个控制器,即输入、输出、忘记控制器。左边多了个条主线,例如电影的主线剧情,而原本的RNN体系变成了分线剧情,并且三个控制器都在分线上。
输入控制器(write gate):
在输入input时设置一个gate,gate的作用是判断要不要写入这个input到我们的内存Memory中,它相当于一个参数,也是可以被训练的,这个参数就是用来控制要不要记住当下这个点。
输出控制器(read gate):
在输出位置的gate,判断要不要读取现在的Memory。
忘记控制器(forget gate):
处理位置的忘记控制器,判断要不要忘记之前的Memory。
LSTM工作原理为:如果分线剧情对于最终结果十分重要,输入控制器会将这个分线剧情按重要程度写入主线剧情,再进行分析;如果分线剧情改变了我们之前的想法,那么忘记控制器会将某些主线剧情忘记,然后按比例替换新剧情,所以主线剧情的更新就取决于输入和忘记控制;最后的输出会基于主线剧情和分线剧情。
通过这三个gate能够很好地控制我们的RNN,基于这些控制机制,LSTM是延缓记忆的良药,从而带来更好的结果。
三.Tensorflow编写RNN代码
接下来我们通过手写数字图片集数据编写RNN代码。RNN是基于顺序的数据,想象下图片的顺序,它是一行一行像素组成的,最终判定图片的数字属于哪类。
第一步,打开Anaconda,然后选择已经搭建好的“tensorflow”环境,运行Spyder。
第二步,导入扩展包。
import tensorflow as tf
from tensorflow. examples. tutorials. mnist import input_data
第三步,下载数据集。
由于MNIST数据集是TensorFlow的示例数据,所以我们只需要下面一行代码,即可实现数据集的读取工作。如果数据集不存在它会在线下载,如果数据集已经被下载,它会被直接调用。
mnist = input_data. read_data_sets( 'MNIST_data' , one_hot= True )
第四步,定义参数。
learning_rate = 0.001
train_iters = 100000
batch_size = 128
n_inputs = 28
n_steps = 28
n_hidden_units = 128
n_classes = 10
第五步,定义placeholder,用于传入值xs和ys至神经网络。
x = tf. placeholder( tf. float32, [ None , n_steps, n_inputs] )
y = tf. placeholder( tf. float32, [ None , n_classes] )
第六步,定义权重和误差变量。
权重和偏置包括输入和输出值,需要注意其设置的形状。
weights = {
'in' : tf. Variable( tf. random_normal( [ n_inputs, n_hidden_units] ) ) ,
'out' : tf. Variable( tf. random_normal( [ n_hidden_units, n_classes] ) ) ,
}
biases = {
'in' : tf. Variable( tf. constant( 0.1 , shape= [ n_hidden_units, ] ) ) ,
'out' : tf. Variable( tf. constant( 0.1 , shape= [ n_classes, ] ) ) ,
}
第七步,定义RNN神经网络。
RNN定义分别对应三层,X输入、Cell为中心计算、H为最终输出,需要注意数据形状的变化。在RNN运算过程中,每一步的输出都存储在outputs序列中,LSTM包括c_state(主线)和m_state(分线)。最终输出结果为Cell的输出和权重输出的乘积,再加上输出偏置。(详见注释)
def RNN ( X, weights, biases) :
X = tf. reshape( X, [ - 1 , n_inputs] )
X_in = tf. matmul( X, weights[ 'in' ] ) + biases[ 'in' ]
X_in = tf. reshape( X_in, [ - 1 , n_steps, n_hidden_units] )
lstm_cell = tf. nn. rnn_cell. BasicLSTMCell( n_hidden_units, forget_bias= 1.0 , state_is_tuple= True )
_init_state = lstm_cell. zero_state( batch_size, dtype= tf. float32)
outputs, states = tf. nn. dynamic_rnn( lstm_cell, X_in, initial_state= _init_state, time_major= False )
results = tf. matmul( states[ 1 ] , weights[ 'out' ] ) + biases[ 'out' ]
return results
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
第八步,定义误差和准确度。
pre = RNN( x, weights, biases)
cost = tf. reduce_mean( tf. nn. softmax_cross_entropy_with_logits( logits= pre, labels= y) )
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
while step * batch_size < train_iters:
batch_xs, batch_ys = mnist. train. next_batch( batch_size)
batch_xs = batch_xs. reshape( [ batch_size, n_steps, n_inputs] )
sess. run( [ train_step] , feed_dict= {
x: batch_xs,
y: batch_ys,
} )
if step % 20 == 0 :
print ( sess. run( accuracy, feed_dict= {
x: batch_xs,
y: batch_ys,
} ) )
step += 1
1 2 3 4 5 6 7 8 9 10 11
12 13 14 15 16 17 18 19 20 21 22 23
最终输出结果如下所示,可以看到,最早预测的准确度结果非常低为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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
完整代码如下:
"""
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
n_steps = 28
n_hidden_units = 128
n_classes = 10
x = tf. placeholder( tf. float32, [ None , n_steps, n_inputs] )
y = tf. placeholder( tf. float32, [ None , n_classes] )
weights = {
'in' : tf. Variable( tf. random_normal( [ n_inputs, n_hidden_units] ) ) ,
'out' : tf. Variable( tf. random_normal( [ n_hidden_units, n_classes] ) ) ,
}
biases = {
'in' : tf. Variable( tf. constant( 0.1 , shape= [ n_hidden_units, ] ) ) ,
'out' : tf. Variable( tf. constant( 0.1 , shape= [ n_classes, ]
) ) ,
}
def RNN ( X, weights, biases) :
X = tf. reshape( X, [ - 1 , n_inputs] )
X_in = tf. matmul( X, weights[ 'in' ] ) + biases[ 'in' ]
X_in = tf. reshape( X_in, [ - 1 , n_steps, n_hidden_units] )
lstm_cell = tf. nn. rnn_cell. BasicLSTMCell( n_hidden_units, forget_bias= 1.0 , state_is_tuple= True )
_init_state = lstm_cell. zero_state( batch_size, dtype= tf. float32)
outputs, states = tf. nn. dynamic_rnn( lstm_cell, X_in, initial_state= _init_state, time_major= False )
results = tf. matmul( states[ 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) )
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
while step * batch_size < train_iters:
batch_xs, batch_ys = mnist. train. next_batch( batch_size)
batch_xs = batch_xs. reshape( [ batch_size, n_steps, n_inputs] )
sess. run( [ train_step] , feed_dict= {
x: batch_xs,
y: batch_ys,
} )
if step % 20 == 0 :
print ( sess. run( accuracy, feed_dict= {
x: batch_xs,
y: batch_ys,
} ) )
step += 1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
注意,在运行代码过程中可能会报错“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回归、文本识别、图像识别、语音识别等内容。如果读者有什么想学习的,也可以私聊我,我去学习并应用到你的领域。
最后,希望这篇基础性文章对您有所帮助,如果文章中存在错误或不足之处,还请海涵~作为人工智能的菜鸟,我希望自己能不断进步并深入,后续将它应用于图像识别、网络安全、对抗样本等领域,指导大家撰写简单的学术论文,一起加油!
CSDN20周年快乐,感恩有你,一路同行。也非常高兴这周女神来武汉看望我,未来的人生路一起走。2020年第一篇文章,新年快乐喔!
PS:这是作者的第一个付费专栏,会非常用心的去撰写,写了八年的免费文章,这也算知识付费的一个简单尝试吧!毕竟读博也不易,写文章也花费时间和精力,但作者更多的文章会免费分享。如果您购买了该专栏,有Python数据分析、图像处理、人工智能、网络安全的问题,我们都可以深入探讨,尤其是做研究的同学,共同进步~
(By:Eastmount 2020-01-03 下午6点夜于珞珈山
http://blog.csdn.net/eastmount/
)
作者theano人工智能系列:
[Python人工智能] 一.神经网络入门及theano基础代码讲解
[Python人工智能] 二.theano实现回归神经网络分析
[Python人工智能] 三.theano实现分类神经网络及机器学习基础
[Python人工智能] 四.神经网络和深度学习入门知识
[Python人工智能] 五.theano实现神经网络正规化Regularization处理
[Python人工智能] 六.神经网络的评价指标、特征标准化和特征选择
[Python人工智能] 七.加速神经网络、激励函数和过拟合
参考文献:
[1] 冈萨雷斯著. 数字图像处理(第3版)[M]. 北京:电子工业出版社,2013.
[2] 杨秀璋, 颜娜. Python网络数据爬取及分析从入门到精通(分析篇)[M]. 北京:北京航天航空大学出版社, 2018.
[3]
“莫烦大神” 网易云视频地址
[4]
https://study.163.com/course/courseLearn.htm?courseId=1003209007
[5]
TensorFlow【极简】CNN - Yellow_python大神
[6]
基于深度神经网络的定向激活功能开发相位信息的声源定位 - 章子雎Kevin
[7]
https://github.com/siucaan/CNN_MNIST
[8]
https://github.com/eastmountyxz/AI-for-TensorFlow
[9]
LSTM和GRU很难?别担心,这有一份超生动的图解