从本专栏开始,作者正式研究Python深度学习、神经网络及人工智能相关知识。前一篇文章分享了卷积神经网络CNN原理,并通过Keras编写CNN实现了MNIST分类学习案例。这篇文章将详细讲解循环神经网络RNN的原理知识,并采用Keras实现手写数字识别的RNN分类案例及可视化呈现。基础性文章,希望对您有所帮助!
本专栏主要结合作者之前的博客、AI经验和相关视频(强推"莫烦大神"视频)及论文介绍,后面随着深入会讲解更多的Python人工智能案例及应用。基础性文章,希望对您有所帮助,如果文章中存在错误或不足之处,还请海涵~作者作为人工智能的菜鸟,希望大家能与我在这一笔一划的博客中成长起来。写了这么多年博客,尝试第一个付费专栏,但更多博客尤其基础性文章,还是会继续免费分享,但该专栏也会用心撰写,望对得起读者,共勉!
代码下载地址:https://github.com/eastmountyxz/AI-for-TensorFlow
代码下载地址:https://github.com/eastmountyxz/AI-for-Keras
博客下载地址:https://github.com/eastmountyxz/CSDNBlog-AI-for-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如何保存神经网络参数
- [Python人工智能] 十二.循环神经网络RNN和LSTM原理详解及TensorFlow编写RNN分类案例
- [Python人工智能] 十三.如何评价神经网络、loss曲线图绘制、图像分类案例的F值计算
- [Python人工智能] 十四.循环神经网络LSTM RNN回归案例之sin曲线预测 丨【百变AI秀】
- [Python人工智能] 十五.无监督学习Autoencoder原理及聚类可视化案例详解
- [Python人工智能] 十六.Keras环境搭建、入门基础及回归神经网络案例
- [Python人工智能] 十七.Keras搭建分类神经网络及MNIST数字图像案例分析
- [Python人工智能] 十八.Keras搭建卷积神经网络及CNN原理详解
- [Python人工智能] 十九.Keras搭建循环神经网络分类案例及RNN原理详解
补充一张深度学习的思维导图。
在编写代码之前,我们需要介绍什么是RNN,RNN是怎样运行的以及RNN的结构。
循环神经网络英文是Recurrent Neural Networks,简称RNN。RNN的本质概念是利用时序信息,在传统神经网络中,假设所有的输入(以及输出)都各自独立。但是,对于很多任务而言,这非常局限。举个例子,假如你想根据一句没说完的话,预测下一个单词,最好的办法就是联系上下文的信息。而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的累积就转换成了循环神经网络,其简化图如下图的左边所示。例如,如果序列中的句子有5个单词,那么,横向展开网络后将有五层神经网络,一层对应一个单词。
总之,只要你的数据是有顺序的,就可以使用RNN,比如人类说话的顺序,电话号码的顺序,图像像素排列的顺序,ABC字母的顺序等。在前面讲解CNN原理时,它可以看做是一个滤波器滑动扫描整幅图像,通过卷积加深神经网络对图像的理解。
而RNN也有同样的扫描效果,只不过是增加了时间顺序和记忆功能。RNN通过隐藏层周期性的连接,从而捕获序列化数据中的动态信息,提升预测结果。
RNN常用于自然语言处理、机器翻译、语音识别、图像识别等领域,下面简单分享RNN相关应用所对应的结构。
RNN情感分析: 当分析一个人说话情感是积极的还是消极的,就用如下图所示的RNN结构,它有N个输入,1个输出,最后时间点的Y值代表最终的输出结果。
RNN图像识别: 此时有一张图片输入X,N张对应的输出。
RNN语言建模和文本生成: 通过训练RNN模型,我们可以基于给出的一个单词序列,预测下一个单词。这对于语言建模和文本生成而言是非常有价值的。同时,语言模型可以用于评估一个句子出现的可能性,这对机器翻译而言也是非常重要的(因为高概率的句子通常是正确的)。
RNN机器翻译: 输入和输出分别两个,对应的是中文和英文,如下图所示。
机器翻译类似于语言建模,我们首先输入源语(例如德语),需要输出是目标语(例如英语)。关键区别是,在机器翻译中,翻译的第一个字可能会需要所有已输入句子的信息,所以只有看到全部输入之后才能输出。
最后再补充一些有趣的RNN应用。
RNN描述照片: RNN被应用于生成描述未被标签的图片模型。并且,两者结合的模型组合甚至可以依据图片特征排列生成文字,以及图片中特征的对应位置。如下图:
RNN写学术论文或脚本:
RNN作曲、作画: 后续作者尝试完成该示例。
相关论文:
- Recurrent neural network based language model 《基于循环神经网络的语言模型》
- Extensions of Recurrent neural network based language model 《基于循环神经网络拓展的语言模型》
- Generating Text with Recurrent Neural Networks 《利用循环神经网络生成文本》
- A Recursive Recurrent Neural Network for Statistical Machine Translation 《用于统计类机器翻译的递归型循环神经网络》
- Sequence to Sequence Learning with Neural Networks 《利用神经网络进行序列至序列的学习》
- Joint Language and Translation Modeling with Recurrent Neural Networks 《利用循环神经网络进行语言和翻译的建模》
- Towards End-to-End Speech Recognition with Recurrent Neural Networks 《利用循环神经网络进行端对端的语音识别》
接着我们讲解如何在Keras代码中编写RNN。
第一步,打开Anaconda,然后选择已经搭建好的“tensorflow”环境,运行Spyder。
第二步,导入扩展包。
import numpy as np
from keras.datasets import mnist
from keras.utils import np_utils
from keras.models import Sequential
from keras.layers import SimpleRNN, Activation, Dense
from keras.optimizers import Adam
第三步,定义参数。
TIME_STEPS = 28 # 时间点数据 每次读取1行共28次 same as the height of the image
INPUT_SIZE = 28 # 每行读取28个像素点 same as the width of the image
BATCH_SIZE = 50 # 每个批次训练50张图片
BATCH_INDEX = 0
OUTPUT_SIZE = 10 # 每张图片输出分类矩阵
CELL_SIZE = 50 # RNN中隐藏单元
LR = 0.001 # 学习率
第四步,载入MNIST数据及预处理。
- X_train.reshape(-1, 1, 28, 28) / 255
将每个像素点进行标准化处理,从0-255转换成0-1的范围。 - np_utils.to_categorical(y_train, nb_classes=10)
调用up_utils将类标转换成10个长度的值,如果数字是3,则会在对应的地方标记为1,其他地方标记为0,即{0,0,0,1,0,0,0,0,0,0}。
由于MNIST数据集是Keras或TensorFlow的示例数据,所以我们只需要下面一行代码,即可实现数据集的读取工作。如果数据集不存在它会在线下载,如果数据集已经被下载,它会被直接调用。
# 下载MNIST数据
# training X shape (60000, 28x28), Y shape (60000, )
# test X shape (10000, 28x28), Y shape (10000, )
(X_train, y_train), (X_test, y_test) = mnist.load_data()
# 数据预处理
# 参数-1表示样例的个数 28*28表示像素长度和宽度
X_train = X_train.reshape(-1, 28, 28) / 255 # normalize
X_test = X_test.reshape(-1, 28, 28) / 255 # normalize
# 将类向量转化为类矩阵 数字 5 转换为 0 0 0 0 0 1 0 0 0 0 矩阵
y_train = np_utils.to_categorical(y_train, num_classes=10)
y_test = np_utils.to_categorical(y_test, num_classes=10)
第五步,创建RNN神经网络。
# 创建RNN模型
model = Sequential()
# RNN cell
model.add(SimpleRNN(
# 设置输入batch形状 批次数量50 时间点28 每行读取像素28个
# for batch_input_shape, if using tensorflow as the backend, we have to put None for the batch_size.
# Otherwise, model.evaluate() will get error.
batch_input_shape = (None, TIME_STEPS, INPUT_SIZE),
# RNN输出给后一层的结果为50
output_dim = CELL_SIZE,
unroll=True,
))
# output layer
model.add(Dense(OUTPUT_SIZE)) # 全连接层 输出对应10分类
model.add(Activation('softmax')) # 激励函数 tanh
第六步,定义神经网络优化器并激活神经网络。
# optimizer
adam = Adam(LR)
# We add metrics to get more results you want to see
# 激活神经网络
model.compile(optimizer=adam, # 加速神经网络
loss='categorical_crossentropy', # 损失函数
metrics=['accuracy']) # 计算误差或准确率
第七步,训练及预测。
for step in range(4001):
# 分批截取数据 BATCH_INDEX初始值为0 BATCH_SIZE为50 取28个步长和28个INPUT_SIZE
# data shape = (batch_num, steps, inputs/outputs)
X_batch = X_train[BATCH_INDEX: BATCH_INDEX+BATCH_SIZE, :, :]
Y_batch = y_train[BATCH_INDEX: BATCH_INDEX+BATCH_SIZE, : ]
# 计算误差
cost = model.train_on_batch(X_batch, Y_batch)
# 累加参数
BATCH_INDEX += BATCH_SIZE
# 如果BATCH_INDEX累加大于总体的个数 则重新赋值0开始分批计算
BATCH_INDEX = 0 if BATCH_INDEX >= X_train.shape[0] else BATCH_INDEX
# 每隔500步输出
if step % 500 == 0:
# 评价算法
cost, accuracy = model.evaluate(
X_test, y_test,
batch_size=y_test.shape[0],
verbose=False)
print('test cost: ', cost, 'test accuracy: ', accuracy)
# -*- coding: utf-8 -*-
"""
Created on Fri Feb 23 18:43:06 2020
@author: xiuzhang Eastmount CSDN
Wuhan fighting!
"""
import numpy as np
from keras.datasets import mnist
from keras.utils import np_utils
from keras.models import Sequential
from keras.layers import SimpleRNN, Activation, Dense
from keras.optimizers import Adam
#------------------------------定义参数------------------------------
TIME_STEPS = 28 # 时间点数据 每次读取1行共28次 same as the height of the image
INPUT_SIZE = 28 # 每行读取28个像素点 same as the width of the image
BATCH_SIZE = 50 # 每个批次训练50张图片
BATCH_INDEX = 0
OUTPUT_SIZE = 10 # 每张图片输出分类矩阵
CELL_SIZE = 50 # RNN中隐藏单元
LR = 0.001 # 学习率
#---------------------------载入数据及预处理---------------------------
# 下载MNIST数据
# training X shape (60000, 28x28), Y shape (60000, )
# test X shape (10000, 28x28), Y shape (10000, )
(X_train, y_train), (X_test, y_test) = mnist.load_data()
# 数据预处理
# 参数-1表示样例的个数 28*28表示像素长度和宽度
X_train = X_train.reshape(-1, 28, 28) / 255 # normalize
X_test = X_test.reshape(-1, 28, 28) / 255 # normalize
# 将类向量转化为类矩阵 数字 5 转换为 0 0 0 0 0 1 0 0 0 0 矩阵
y_train = np_utils.to_categorical(y_train, num_classes=10)
y_test = np_utils.to_categorical(y_test, num_classes=10)
#---------------------------创建RNN神经网络---------------------------
# 创建RNN模型
model = Sequential()
# RNN cell
model.add(SimpleRNN(
# 设置输入batch形状 批次数量50 时间点28 每行读取像素28个
# for batch_input_shape, if using tensorflow as the backend, we have to put None for the batch_size.
# Otherwise, model.evaluate() will get error.
batch_input_shape = (None, TIME_STEPS, INPUT_SIZE),
# RNN输出给后一层的结果为50
output_dim = CELL_SIZE,
unroll=True,
))
# output layer
model.add(Dense(OUTPUT_SIZE)) # 全连接层 输出对应10分类
model.add(Activation('softmax')) # 激励函数 tanh
#---------------------------神经网络优化器---------------------------
# optimizer
adam = Adam(LR)
# We add metrics to get more results you want to see
# 激活神经网络
model.compile(optimizer=adam, # 加速神经网络
loss='categorical_crossentropy', # 损失函数
metrics=['accuracy']) # 计算误差或准确率
#--------------------------------训练和预测------------------------------
for step in range(4001):
# 分批截取数据 BATCH_INDEX初始值为0 BATCH_SIZE为50 取28个步长和28个INPUT_SIZE
# data shape = (batch_num, steps, inputs/outputs)
X_batch = X_train[BATCH_INDEX: BATCH_INDEX+BATCH_SIZE, :, :]
Y_batch = y_train[BATCH_INDEX: BATCH_INDEX+BATCH_SIZE, : ]
# 计算误差
cost = model.train_on_batch(X_batch, Y_batch)
# 累加参数
BATCH_INDEX += BATCH_SIZE
# 如果BATCH_INDEX累加大于总体的个数 则重新赋值0开始分批计算
BATCH_INDEX = 0 if BATCH_INDEX >= X_train.shape[0] else BATCH_INDEX
# 每隔500步输出
if step % 500 == 0:
# 评价算法
cost, accuracy = model.evaluate(
X_test, y_test,
batch_size=y_test.shape[0],
verbose=False)
print('test cost: ', cost, 'test accuracy: ', accuracy)
输出结果如下图所示,训练4000次,每隔500次输出一次误差cost和正确率。从下面的结果可以发现,误差不断减小,正确率不断提高,说明RNN在不断学习。真正做神经网络实验时,我们会针对不同的参数和样本、算法进行比较,也希望这篇文章对您有帮助。
test cost: 2.3657307624816895 test accuracy: 0.07580000162124634
test cost: 0.5747528076171875 test accuracy: 0.840399980545044
test cost: 0.4435984492301941 test accuracy: 0.863099992275238
test cost: 0.3612927794456482 test accuracy: 0.897599995136261
test cost: 0.30560624599456787 test accuracy: 0.9138000011444092
test cost: 0.3092554211616516 test accuracy: 0.9089999794960022
test cost: 0.2737627327442169 test accuracy: 0.9168999791145325
test cost: 0.22912506759166718 test accuracy: 0.9351000189781189
test cost: 0.23802728950977325 test accuracy: 0.9323999881744385
为了更好地比较训练次数和误差、Accuracy,我们可以增加可视化分析。其运行结果如下图所示:
此时的完整代码如下:
# -*- coding: utf-8 -*-
# -*- coding: utf-8 -*-
"""
Created on Fri Feb 23 18:43:06 2020
@author: xiuzhang Eastmount CSDN
Wuhan fighting!
"""
import numpy as np
from keras.datasets import mnist
from keras.utils import np_utils
from keras.models import Sequential
from keras.layers import SimpleRNN, Activation, Dense
from keras.optimizers import Adam
#------------------------------定义参数------------------------------
TIME_STEPS = 28 # 时间点数据 每次读取1行共28次 same as the height of the image
INPUT_SIZE = 28 # 每行读取28个像素点 same as the width of the image
BATCH_SIZE = 50 # 每个批次训练50张图片
BATCH_INDEX = 0
OUTPUT_SIZE = 10 # 每张图片输出分类矩阵
CELL_SIZE = 50 # RNN中隐藏单元
LR = 0.001 # 学习率
#---------------------------载入数据及预处理---------------------------
# 下载MNIST数据
# training X shape (60000, 28x28), Y shape (60000, )
# test X shape (10000, 28x28), Y shape (10000, )
(X_train, y_train), (X_test, y_test) = mnist.load_data()
# 数据预处理
# 参数-1表示样例的个数 28*28表示像素长度和宽度
X_train = X_train.reshape(-1, 28, 28) / 255 # normalize
X_test = X_test.reshape(-1, 28, 28) / 255 # normalize
# 将类向量转化为类矩阵 数字 5 转换为 0 0 0 0 0 1 0 0 0 0 矩阵
y_train = np_utils.to_categorical(y_train, num_classes=10)
y_test = np_utils.to_categorical(y_test, num_classes=10)
#---------------------------创建RNN神经网络---------------------------
# 创建RNN模型
model = Sequential()
# RNN cell
model.add(SimpleRNN(
# 设置输入batch形状 批次数量50 时间点28 每行读取像素28个
# for batch_input_shape, if using tensorflow as the backend, we have to put None for the batch_size.
# Otherwise, model.evaluate() will get error.
batch_input_shape = (None, TIME_STEPS, INPUT_SIZE),
# RNN输出给后一层的结果为50
output_dim = CELL_SIZE,
unroll=True,
))
# output layer
model.add(Dense(OUTPUT_SIZE)) # 全连接层 输出对应10分类
model.add(Activation('softmax')) # 激励函数 tanh
#---------------------------神经网络优化器---------------------------
# optimizer
adam = Adam(LR)
# We add metrics to get more results you want to see
# 激活神经网络
model.compile(optimizer=adam, # 加速神经网络
loss='categorical_crossentropy', # 损失函数
metrics=['accuracy']) # 计算误差或准确率
#--------------------------------训练和预测------------------------------
cost_list = []
acc_list = []
step_list = []
for step in range(4001):
# 分批截取数据 BATCH_INDEX初始值为0 BATCH_SIZE为50 取28个步长和28个INPUT_SIZE
# data shape = (batch_num, steps, inputs/outputs)
X_batch = X_train[BATCH_INDEX: BATCH_INDEX+BATCH_SIZE, :, :]
Y_batch = y_train[BATCH_INDEX: BATCH_INDEX+BATCH_SIZE, : ]
# 计算误差
cost = model.train_on_batch(X_batch, Y_batch)
# 累加参数
BATCH_INDEX += BATCH_SIZE
# 如果BATCH_INDEX累加大于总体的个数 则重新赋值0开始分批计算
BATCH_INDEX = 0 if BATCH_INDEX >= X_train.shape[0] else BATCH_INDEX
# 每隔200步输出
if step % 200 == 0:
# 评价算法
cost, accuracy = model.evaluate(
X_test, y_test,
batch_size=y_test.shape[0],
verbose=False)
# 写入列表
cost_list.append(cost)
acc_list.append(accuracy)
step_list.append(step)
print('test cost: ', cost, 'test accuracy: ', accuracy)
#--------------------------------绘制相关曲线------------------------------
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import host_subplot
# 绘制曲线图
host = host_subplot(111)
plt.subplots_adjust(right=0.8) # ajust the right boundary of the plot window
par1 = host.twinx()
# 设置类标
host.set_xlabel("Iterations")
host.set_ylabel("Loss")
par1.set_ylabel("Accuracy")
# 绘制曲线
p1, = host.plot(step_list, cost_list, "bo-", linewidth=2, markersize=12, label="cost")
p2, = par1.plot(step_list, acc_list, "gs-", linewidth=2, markersize=12, label="accuracy")
# 设置颜色
host.axis["left"].label.set_color(p1.get_color())
par1.axis["right"].label.set_color(p2.get_color())
# 绘图
plt.legend(loc="upper left")
plt.title("Keras for RNN - Eastmount CSDN")
plt.draw()
plt.show()
写到这里,这篇文章就结束了。接着请同学们思考几个问题:
- 为什么cost和accuracy会波动呢?预测结果不是一直上升或下降。
- 学习率之前设置为LR=0.001,它对我们的实验是否有影响呢?
- 上图仅比较了迭代次数和cost、accuracy,是否可以比较学习率呢?
- 其他的评价指标是否可以评价RNN的分类实验呢?比如Precision、Recall、F1等。
- 神经网络的激励函数、神经层数是否有可以比较呢?
- 如何比较数字0-9不同类标的性能呢?如何验证RNN比普通的神经网络效果更好?
这些实验都是我们在做论文研究或项目评价常见的一些问题,希望读者带着这些问题,结合自己的需求进行深入的思考,更希望大家能学以致用。最后如果文章对您有帮助,请点赞、评论、收藏,这将是我分享最大的动力。
总之,本文通过Keras实现了一个RNN分类学习的案例,并详细介绍了循环神经网络原理知识。最后,希望这篇基础性文章对您有所帮助,如果文章中存在错误或不足之处,还请海涵~作为人工智能的菜鸟,我希望自己能不断进步并深入,后续将它应用于图像识别、网络安全、对抗样本等领域,指导大家撰写简单的学术论文,一起加油!
感恩能与大家在华为云遇见!
希望能与大家一起在华为云社区共同成长。原文地址:https://blog.csdn.net/Eastmount/article/details/104458677
(By:娜璋之家 Eastmount 2021-11-09 夜于武汉)
参考文献:
[1] 神经网络和机器学习基础入门分享 - 作者的文章
[2] 斯坦福机器学习视频NG教授: https://class.coursera.org/ml/class/index
[3] 书籍《游戏开发中的人工智能》、《游戏编程中的人工智能技术》
[4] 网易云莫烦老师视频(强推 我付费支持老师一波)
[5] [Python人工智能] 八.卷积神经网络CNN原理详解及TensorFlow编写CNN
[6] 机器学习实战—MNIST手写体数字识别 - RunningSucks
[7] https://github.com/siucaan/CNN_MNIST
[8] https://study.163.com/course/courseLearn.htm?courseId=1003340023
[9] https://github.com/MorvanZhou/tutorials/blob/master/kerasTUT/7-RNN_Classifier_example.py
[10] 来自谷歌大脑工程师的RNN系列教程 | RNN的基本介绍 - CNET科技行者
[11] 深度学习文本分类实战报告:CNN,RNN&HAN - AI研习社
[12] 深度学习导论 - 读李宏毅《1天搞懂深度学习》 - 慢慢的燃烧