版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

本文链接:https://blog.csdn.net/LQ_qing/article/details/100521923

一、时序数据

卷积神经网络是针对二维位置相关的图片,它采取权值共享的思想,使用一个滑动的窗口去提取每一个位置相关的信息,自然界除了位置相关的信息以外,还存在另一种跟时序相关的数据类型,例如:序列信号,语音信号。对于按时间轴不停产生的信号,神经网络中,我们称其为temporal signals,而循环神经网络处理的就是拥有时序相关或者前后相关的数据类型(Sequence)。

二、embedding数据类型转换

计算机是无法处理时序数据的,所以,我们必须把这些时序数据转化成数值类型,以文本为例,文字和数值之间并没有一一对应的关系,而且,文字之间还有语义关系,没有大小关系,要是我们能找到一种表示方法能很好的表达文字之间的语义关系,那么用于训练或者分类就会很有帮助,而我们把这一转化过程统称为embedding。

在循环神经网络中,我们通常用下面的格式进行表示训练数据:

[ b, seq_len, fearture_len ]

b:一个批次的大小。seq_len:时序数据的长度(一句话有seq_len个单词,一段录音有seq_len时刻等)。fearture_len:对于每一个seq_len,我们用多少纬度来表示(一个单词,我们可以用长度为4的向量表示)

例如:

我喜欢你  =====》[ 1, 4, 4 ]: 只有一句话,所以b=1,这句话有4个汉字,所以seq_len=4,每个汉字,我们用一个4纬的向量表示,所以,fearture_len=4。同理,对于一段长达10秒的语音信号,我们可以这样表示为 [ 1, 10, 10 ]。

备注:在本篇博文中,我们只讨论文本处理即word embedding,对于语言序列不给予过多讨论。

三、word embedding

文本的转换不仅仅是逻辑上的转换,或者简单的一对一关系,其中还要包括语义上的转换。所以,word embedding需要满足一下两个条件:

1)语义相关。

单词在语义空间的相似度需要在数值空间表现出来(可利用位置距离或者概率表示),例如:输入king这个单词的话,那么在语义空间中和king相关的所有词都必须在数值空间中,与king的位置靠近(距离的远近代表着相关的程度)。

2)可训练。

下面,我们将利用layers简单的实现一次word embedding过程:

数据:I love it   ====》[ 1, 3, 4 ]

第一步:为三个单词设置一个编号。

第二步:调用layers的embedding接口,创建一个embedding层,并设置这个层的纬度。

第三步:把x输入embedding层中,embedding层就会为x随机初始化一个tensor对象

当前的embedding结果是不符合要求的,我们会通过后续训练去优化embedding。

四、循环神经网络

通过word embedding,我们可以把句子中的所有单词数值化后,映射到向量空间中去,为了得到最佳的word embedding结果,我们会把数值化的单词输入全连接网络中进行训练,具体如下:

每一个单词都输入到单独的全连接层中,得到的结果用于对情感的划分,但是,当句子过长时,其网络的层数和参数都会成直线上升,而且,当我们变换句子顺序时,其输出结果不变,即没有保留上下之间的语境信息。

针对参数上述问题,我们提出权重共享的思想,即每一个全连接层共享同一个w和b:

针对语义信息,由于现有网络没有全局的综合的高层的语义信息抽取过程,所以,我们需要一个全局的数据去存储整个句子的语义信息,即需要一个容器去存储从第一个单词到最后一个单词的总体语义信息,该容器被称为memory。

                          如上图所示,h0为初始memory,h1~h5是每一层输出的memory,后一层利用下面的公式会用到前一层的语境信息,

h_2=x@w_x + h_1@w_h_h

所以最后一层就拥有了全局的语境信息,最后,我们可以利用这个全局的语境信息去做分类。

通过观察上图中的全连接层,我们发现每一个全连接层的结构都是一样的(都是x@w_x + h_t@w_h_h形式),所以,我们把这些全连接层折叠起来就成了RNN循环神经网络了。具体公式如下:

备注:在RNN中,激活函数通常用thah(),ht为t时刻的memory,yt表示RNN在循环完毕后,利用一个全连接层汇总RNN中提取的高维特征,用于最终结果的分类。

五、RNN的可训练性

所有神经网络结构,都需要能进行反向梯度更新,那么,RNN是怎么求解梯度的呢?首先,我们把RNN网络按时间轴进行展开:

RNN公式:           h_t =tanh(W_I_x +W_Rh_t_-_1)                        y_t=W_0h_t

loss函数:            losee = MSE(y,x)

我们对W_R进行求导:

\frac{\partial E_t}{\partial W_R} = \sum_{i=0}^{t}{\frac{\partial E_t}{\partial y_t}\frac{\partial y_t}{\partial h_t}\frac{\partial h_t}{\partial h_i}\frac{\partial h_i}{\partial W_R}}

假设t=1,则:

\frac{\partial E_1}{\partial W_R} = \frac{\partial E_1}{\partial y_1}\frac{\partial y_1}{\partial h_1}\frac{\partial h_1}{\partial h_0}\frac{\partial h_0}{\partial W_R}

假设t=2,则:

\frac{\partial E_2}{\partial W_R} =\frac{\partial E_1}{\partial y_1}\frac{\partial y_1}{\partial h_1}\frac{\partial h_1}{\partial h_0}\frac{\partial h_0}{\partial W_R} + \frac{\partial E_2}{\partial y_2}\frac{\partial y_2}{\partial h_2}\frac{\partial h_2}{\partial h_1}\frac{\partial h_1}{\partial h_0}\frac{\partial h_0}{\partial W_R}

我们可以发现,由于\frac{\partial E_t}{\partial y_t},\frac{\partial y_t}{\partial h_t},\frac{\partial h_i}{\partial W_R}是已知的,所以可以直接求解导数,但是\frac{\partial h_t}{\partial h_i}是未知的,我们把\frac{\partial h_t}{\partial h_i}进行展开可得:

\frac{\partial h_t}{\partial h_i} = \frac{\partial h_t}{\partial h_t_{-1}}\frac{\partial h_t_{-1}}{\partial h_t_{-2}}.....\frac{\partial h_i_{+1}}{\partial h_i}=\prod ^{t-1}_{k-i}\frac{\partial h_k_{+1}}{\partial h_k}

利用RNN公式可得:

\frac{\partial h_k_{+1}}{\partial h_k}=diag(f(W_I_{xi}+W_R_{h_i-1})) W_R

则求1到k时刻的梯度为:

\frac{\partial h_k}{\partial h_1} =\prod ^{k}_{i}diag(f(W_I_{xi}+W_R_{h_i-1})) W_R

所以,\frac{\partial h_t}{\partial h_i}也是可求的,这里提示一下,k时刻会得到{W_R}的k次方,这一项会导致RNN很容易出现梯度弥散或者梯度爆炸。

六、RNN训练时数据纬度的变化

本小节,博主将详细叙述在一次word embedding的循环网络训练过程中,其内部数据纬度的变化。

第一步:输入一个批次的训练数据集  [ b, seq_len, fearture_len ] = [ 128, 80, 100 ],由于seq_len是句子的长度,而一次RNN网络处理的是一个单词,所以,我们按seq_len进行展开,则数据纬度变成:[ b, fearture_len ] = [ 128, 100 ]。

第二步:根据公式h_2=x@w_x + h_1@w_h_h可得:

h = [b,feature_len]@[fearture_len, hidden_len] + [b, hidden_len]@[bidden_len, hidden_len]

则[fearture_len, hidden_len] = [ 100, 64],[b, hidden_len]=[128, 64],[bidden_len, hidden_len]=[64,64],这样我们就可以把[b, 100]纬度的数据降纬到[ b, 64 ]。

实战部分

七、IMDB数据集简介

IMDB数据集包含了50000条偏向明显的电影评论,其中25000条作为训练集,25000作为测试集,其标签只有pos/neg两种,属于二分类问题,这里给出网上收集到的百度云下载链接:

链接:https://pan.baidu.com/s/1jcAZiGy0zeo9VjUKBDLZHA

提取码:3aka

八、代码讲解

本实战分部分主要是使用两层的SimpleRNNCell实现对IMDB数据集的训练。在下一章里,我们将使用层的方式和LSTM以及GRU方式实现对IMDB数据集的训练。之所以选择使用SimpleRNNCell来实现,主要是为了向大家讲解RNN的原理,希望能帮助到大家。

第一行代码:利用Tensorflow提供的接口加载数据集,在加载的同时,设置网络识别单词的最大个数(num_words),因为英语单词至少有5万多个,网络不可能把所有单词都记住,而且我们日常使用的也很少,所以,当设置total_words=10000时,代表的意思是,网络只对10000个不同单词进行编码。对于超过10000的单词用同一个特殊符号表示。

后两行代码:设置句子的长度,因为,句子的长度会直接影响到RNN的循环次数,所以,为了训练方便,我们会把句子进行截断成相同长度,例如:maxlen=80,代表着训练数据中的句子都会变成80个单词,多的舍去,少的补零。

构建dataset对象,并设置每一个Batch的大小,drop_remainder=True的意思是当数据不足以构成一个Batch时,舍去。

下面是模型构建中的代码

由于我们使用的是两层RNN,每一层都需要一个初始memory。units表示RNN影藏层的纬度,本次实战设置为64,

构建两层简单的Cell,并启用dropout功能。

这是RNN循环完毕后的全连接层,输出一个结果。下面给出自定义层的完整代码

把输入的训练数据进行一次embedding操作,并设置两个memory的初始状态。

把seq_len纬度进行展开,把结果传入SimpleRNNCell中,得到每一层的输出值和memory。

把循环后的结果放入全连接层中,并利用sigmoid函数进行缩放。下面给出自定义模型的完整代码

下面给出整体代码:


  1. import os
  2. import tensorflow as tf
  3. from tensorflow import keras
  4. from tensorflow.keras import layers
  5. import numpy as np
  6. import time
  7. os.environ["TF_CPP_MIN_LOG_LEVEL"] = '2'
  8. total_words = 10000
  9. max_review_len = 80
  10. batchsz = 128
  11. embedding_len = 100
  12. (x_train, y_train) , (x_test, y_test) = keras.datasets.imdb.load_data(num_words = total_words)
  13. x_train = keras.preprocessing.sequence.pad_sequences(x_train, maxlen = max_review_len)
  14. x_test = keras.preprocessing.sequence.pad_sequences(x_test, maxlen = max_review_len)
  15. db_train = tf.data.Dataset.from_tensor_slices((x_train, y_train))
  16. db_train = db_train.shuffle(1000).batch(batchsz, drop_remainder=True)
  17. db_test = tf.data.Dataset.from_tensor_slices((x_test, y_test))
  18. db_test = db_test.shuffle(1000).batch(batchsz, drop_remainder=True)
  19. print('x_train shape:', x_train.shape, tf.reduce_max(y_train), tf.reduce_min(y_train))
  20. print('x test shape:', x_test.shape)
  21. class MyRnn(keras.Model):
  22. def __init__(self, units):
  23. super(MyRnn,self).__init__()
  24. self.state0 = [tf.zeros([batchsz, units])]
  25. self.state1 = [tf.zeros([batchsz, units])]
  26. self.embedding = layers.Embedding(total_words, embedding_len,
  27. input_length = max_review_len)
  28. self.rnn_cell0 = layers.SimpleRNNCell(units, dropout=0.2)
  29. self.rnn_cell1 = layers.SimpleRNNCell(units, dropout=0.2)
  30. self.outlayer = layers.Dense(1)
  31. def call(self, inputs, training=None):
  32. x = self.embedding(inputs)
  33. state0 = self.state0
  34. state1 = self.state1
  35. for word in tf.unstack(x, axis=1):
  36. out0, state0 = self.rnn_cell0(word, state0, training)
  37. out1, state1 = self.rnn_cell1(out0, state1)
  38. x = self.outlayer(out1)
  39. prob = tf.sigmoid(x)
  40. return prob
  41. def main():
  42. units = 64
  43. epoch = 4
  44. start_time = time.time()
  45. model = MyRnn(units)
  46. model.compile(optimizer= keras.optimizers.Adam(0.001),
  47. loss=tf.losses.BinaryCrossentropy(),
  48. metrics = ['accuracy'])
  49. model.fit(db_train, epochs= epoch, validation_data = db_test)
  50. model.evaluate(db_test)
  51. end_time = time.time()
  52. print('all time: ' ,end_time - start_time)
  53. if __name__ == '__main__':
  54. main()

在下一章中,少奶奶将继续讲解RNN网络的不足和改进,依旧是理论+实战,欢迎大家观看

开篇:开启Tensorflow 2.0时代

第一章:Tensorflow 2.0 实现简单的线性回归模型(理论+实践)

第二章:Tensorflow 2.0 手写全连接MNIST数据集(理论+实战)

第三章:Tensorflow 2.0 利用高级接口实现对cifar10 数据集的全连接(理论+实战实现)

第四章:Tensorflow 2.0 实现自定义层和自定义模型的编写并实现cifar10 的全连接网络(理论+实战)

第五章:Tensorflow 2.0 利用十三层卷积神经网络实现cifar 100训练(理论+实战)

第六章:优化神经网络的技巧(理论)

第七章:Tensorflow2.0 RNN循环神经网络实现IMDB数据集训练(理论+实践)

第八章:Tensorflow2.0 传统RNN缺陷和LSTM网络原理(理论+实战)

第七章:Tensorflow2.0 RNN循环神经网络实现IMDB数据集训练(理论+实践)相关推荐

  1. Recurrent Neural Networks(RNN) 循环神经网络初探

    1. 针对机器学习/深度神经网络"记忆能力"的讨论 0x1:数据规律的本质是能代表此类数据的通用模式 - 数据挖掘的本质是在进行模式提取 数据的本质是存储信息的介质,而模式(pat ...

  2. RNN 循环神经网络系列 5: 自定义单元

    原文地址:RECURRENT NEURAL NETWORK (RNN) – PART 5: CUSTOM CELLS 原文作者:GokuMohandas 译文出自:掘金翻译计划 本文永久链接:gith ...

  3. PyTorch-09 循环神经网络RNNLSTM (时间序列表示、RNN循环神经网络、RNN Layer使用、时间序列预测案例、RNN训练难题、解决梯度离散LSTM、LSTM使用、情感分类问题实战)

    PyTorch-09 循环神经网络RNN&LSTM (时间序列表示.RNN循环神经网络.RNN Layer使用.时间序列预测案例(一层的预测点的案例).RNN训练难题(梯度爆炸和梯度离散)和解 ...

  4. [译] RNN 循环神经网络系列 2:文本分类

    原文地址:RECURRENT NEURAL NETWORKS (RNN) – PART 2: TEXT CLASSIFICATION 原文作者:GokuMohandas 译文出自:掘金翻译计划 本文永 ...

  5. rnn 循环神经网络

    rnn 循环神经网络 创建日期 星期四 10 一月 2019 rnn为 recurrent natural network, 递归神经网络 是一种基于序列的神经网络, 序列可以是时间,文本序列等,和普 ...

  6. LSTM -长短期记忆网络(RNN循环神经网络)

    文章目录 基本概念及其公式 输入门.输出门.遗忘门 候选记忆元 记忆元 隐状态 从零开始实现 LSTM 初始化模型参数 定义模型 训练和预测 简洁实现 小结 基本概念及其公式 LSTM,即(long ...

  7. RNN循环神经网络(recurrent neural network)

     自己开发了一个股票智能分析软件,功能很强大,需要的点击下面的链接获取: https://www.cnblogs.com/bclshuai/p/11380657.html 1.1  RNN循环神经网络 ...

  8. 基于RNN循环神经网络lstm的藏头诗制作

    基于RNN循环神经网络lstm的藏头诗制作 简单介绍 在一次偶然中接触到藏头诗,觉得十分有意思.但是好像都是利用古代本就有的诗句重新组合而成.比如输入清风袭来,结果如下图所示. 之后想到不如利用深度学 ...

  9. RNN循环神经网络 、LSTM长短期记忆网络实现时间序列长期利率预测

    全文链接:http://tecdat.cn/?p=25133 2017 年年中,R 推出了 Keras 包 _,_这是一个在 Tensorflow 之上运行的综合库,具有 CPU 和 GPU 功能(点 ...

最新文章

  1. Systemd 入门教程:实战篇
  2. 第13届景驰-埃森哲杯广东工业大学ACM程序设计大赛 L-回旋星空
  3. wps的高亮怎么用_怎样在WPS上实现代码语法高亮
  4. 随机迷宫 c语言思路,[原创]递归随机迷宫生成算法详解
  5. html大学生活主题班会,“大学生活”主题班会记录范文
  6. 万户OA应变大考验之新员工学习篇
  7. java编程技巧_Java编程技巧
  8. 鸿蒙大陆6.1正式版 密码,天寒大陆1.06下载 天寒大陆1.06正式版 附游戏攻略及隐藏英雄密码 魔兽防守地图 下载-脚本之家...
  9. java doc转mht_Word文档格式doc转为mht.doc
  10. 深度学习与计算机视觉教程(8) | 常见深度学习框架介绍(CV通关指南·完结)
  11. matlab矩阵处理实验报告,MATLAB矩阵实验报告.doc
  12. DIY年轻人的第一辆电动滑板车
  13. 10bit色深灰度图彩色图加载显示
  14. git推送不能完全退出错误
  15. python markdown2 样式_Python markdown2.markdown方法代碼示例
  16. HDU - 1284 钱币兑换问题 (找规律/完全背包)
  17. 3种方法封锁BT下载 1
  18. FFmpeg基础:音视频同步播放
  19. Android ANR分析-笔记
  20. Raspberry Pi: WiFi设置

热门文章

  1. java的renameTo函数的两个用法,这个看不懂算我输
  2. JSP页面在浏览器中显示HTML代码被截断显示不全
  3. STM32中断相关概念阐述
  4. 66AK2G12 ,K2GEVM开发板上编译Kernel的步骤
  5. 如何实现分布式搜索(一)实现简单的分词器
  6. AI也会遭遇瓶颈 解析人工智能技术的存储性能需求
  7. web后台管理页面布局
  8. 有一家24小时的智能图书馆开业了,不信你不去
  9. 单机版加密狗/锁与网络版加密狗/锁的区别
  10. 树莓派4b初始图形化设置 putty + vnc 笔记本电脑连接