使用RNN进行imdb影评情感识别--use RNN to sentiment analysis
原创帖子,转载请说明出处
一、RNN神经网络结构
RNN隐藏层神经元的连接方式和普通神经网路的连接方式有一个非常明显的区别,就是同一层的神经元的输出也成为了这一层神经元的输入。当然同一时刻的输出是不可能作为这个时刻的输入的。所以是前一个时刻(t-1)的输出作为这个时刻(t)的输入。
序列结构展开示意图,s为隐藏层,o为输出层,x为输入层,U为输入层到隐层的权重矩阵,V则是隐层到输出层的权重矩阵,这个网络在t时刻接收到输入 之后,隐藏层的值是 ,输出值是 。关键一点是, 的值不仅仅取决于 ,还取决于 。
二、RNN应用范围
RNNs主要用于处理NLP类的问题,如词向量表达、语句合法性检查、词性标注等。在RNNs中,目前使用最广泛最成功的模型便是LSTMs(Long Short-Term Memory,长短时记忆模型)模型,该模型通常比vanilla RNNs能够更好地对长短时依赖进行表达,该模型相对于一般的RNNs,只是在隐藏层做了手脚。下篇文章会对LSTM进行介绍。
三、使用RNN进行影评情感分析
0x00 实验环境
tensorflow2.0,此版本的keras已经被包含到tf中,导入keras时注意加入tensorflow前缀,如果想关闭vision2.0版本的特性的话,可以使用:
import tensorflow.compat.v1 as tf
tf.disable_v2_behavior()
0x01 数据预处理
导入数据集和相应的库,这里使用imdb数据集
#导入imdb影评库
from tensorflow.keras.datasets import imdb
from tensorflow.keras.preprocessing import sequence
之后我们对数据集与训练集进行划分,下面的vocab_num代表着我要从imdb数据库中导入10000条数据,第二行的左括号与右括号代表训练集与测试集的划分
#划分训练集与测试集
#label中的0代表消极,1代表积极
vocab_num=10000
(X_train,y_train),(X_test,y_test)=imdb.load_data(num_words=vocab_num) print("----review----")
print(X_train[5])
print("----label-----")
print(y_train[5])
打印结果
----review----
[1, 6740, 365, 1234, 5, 1156, 354, 11, 14, 5327, 6638, 7, 1016, 2, 5940, 356, 44, 4, 1349, 500, 746, 5, 200, 4, 4132, 11, 2, 9363, 1117, 1831, 7485, 5, 4831, 26, 6, 2, 4183, 17, 369, 37, 215, 1345, 143, 2, 5, 1838, 8, 1974, 15, 36, 119, 257, 85, 52, 486, 9, 6, 2, 8564, 63, 271, 6, 196, 96, 949, 4121, 4, 2, 7, 4, 2212, 2436, 819, 63, 47, 77, 7175, 180, 6, 227, 11, 94, 2494, 2, 13, 423, 4, 168, 7, 4, 22, 5, 89, 665, 71, 270, 56, 5, 13, 197, 12, 161, 5390, 99, 76, 23, 2, 7, 419, 665, 40, 91, 85, 108, 7, 4, 2084, 5, 4773, 81, 55, 52, 1901]
----label-----
1
上面打印结果显示的数字代表着字典中对应单词的索引,我们使用下面的代码来找出每个索引对应的词
word2id = imdb.get_word_index()
id2word = {i: word for word,i in word2id.items()}
print('---review with word---')
print([id2word.get(i, '') for i in X_train[6]])
为了让数据能够输入 RNN 模型,所有的输入文档必须有相同的长度。我们需要设置max_words变量来限制评论的最大长度,超过该长度的评论将被截断,不足该长度的评论将被填充空值(0)。在 Keras 中,我们可以使用pad_sequences()函数来达到此目标。现在设置max_words变量的值为 500。
from tensorflow.keras.preprocessing.sequence import pad_sequences
max_words=500
X_train = pad_sequences(X_train, maxlen=max_words)
X_test = pad_sequences(X_test, maxlen=max_words)
0x02 模型建立
from tensorflow.keras import Sequential
from tensorflow.keras.layers import Embedding, LSTM, Dense, Dropout embedding_size = 32
model=Sequential()
model.add(Embedding(vocab_num,embedding_size, input_length= max_words))
model.add(LSTM(100))
model.add(Dense(1, activation='sigmoid'))
print(model.summary())
这里逐个解释一下每个参数的情况。这几步为建立神经网络的基本流程。
(1)首先,embedding_size,是第六行嵌入层的一个参数,嵌入层,要了解它,首先要知道词嵌入,这里以https://juejin.im/entry/5acc23f26fb9a028d1416bb3 这篇文章来简单介绍一下词嵌入以及embedding层的作用。词嵌入是对传统的词袋模型编码方案的改进,词袋模型可以看这篇https://www.cnblogs.com/chenyusheng0803/p/10978883.html ,
在嵌入中,单词由密集向量表示,其中向量表示将单词投影到连续向量空间中。向量空间中的单词的位置是从文本中学习的,并且基于在使用单词时围绕单词的单词。学习到的向量空间中的单词的位置被称为它的嵌入:Embedding。通俗的说,就是以一种比较准确的方式表达词的位置。
Keras提供了一个嵌入层,适用于文本数据的神经网络。它要求输入数据是整数编码的,所以每个字都用一个唯一的整数表示。例如我们这篇文章说到的imdb的词库中每个数字代表的词。嵌入层用随机权重进行初始化,并将学习训练数据集中所有单词的嵌入。
嵌入层被定义为网络的第一个隐藏层。它必须指定3个参数:
- input_dim:这是文本数据中词汇的取值可能数。例如,如果您的数据是整数编码为0-9之间的值,那么词汇的大小就是10个单词;
- output_dim:这是嵌入单词的向量空间的大小。它为每个单词定义了这个层的输出向量的大小。例如,它可能是32或100甚至更大,可以视为具体问题的超参数;
- input_length:这是输入序列的长度,就像您为Keras模型的任何输入层所定义的一样,也就是一次输入带有的词汇个数。例如,如果您的所有输入文档都由1000个字组成,那么input_length就是1000。
因此,这里的embedding_size就是嵌入单词的向量空间大小,同时,嵌入层的输出是一个二维向量,每个单词在输入文本(输入文档)序列中嵌入一个。
(2)sequential()
Keras有两种类型的模型,序贯模型(Sequential)和函数式模型(Model),函数式模型应用更为广泛,序贯模型是函数式模型的一种特殊情况。sequential model就是那种最简单的结构的模型。按顺序一层一层训练,一层一层往前的那种。没有什么环的结构。比如像前馈网络那样。Keras 的核心数据结构是“模型”,模型是一种组织网络层的方式。Keras 中主要的模型是 Sequential 模型,Sequential 是一系列网络层按顺序构成的栈。
(3) 之后加入LSTM
Keras中的LSTM函数参数可以参考这篇文章:https://blog.csdn.net/jiangpeng59/article/details/77646186 ,这里的100是指输出维度为100
(4)Dense层
这里的DENSE层添加了激活函数为sigmoid,Dense层的详细知识可以见:https://blog.csdn.net/m0_37592397/article/details/79982601
(5)model.summary是指展示model的层数现状,这里的显示结果为:
Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
embedding (Embedding) (None, 500, 32) 320000
_________________________________________________________________
lstm (LSTM) (None, 100) 53200
_________________________________________________________________
dense (Dense) (None, 1) 101
=================================================================
Total params: 373,301
Trainable params: 373,301
Non-trainable params: 0
_________________________________________________________________
None
0x03 模型训练
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
from tensorflow.keras.callbacks import EarlyStopping
#from tensorboardcolab import TensorBoardColab
#tbc = TensorBoardColab()
es = EarlyStopping(monitor = "val_loss", patience = 10)
batch_size = 64
num_epochs = 10 X_valid, y_valid = X_train[:batch_size], y_train[:batch_size]
X_train2, y_train2 = X_train[batch_size:], y_train[batch_size:] model.fit(X_train2, y_train2, validation_data=(X_valid, y_valid), batch_size=batch_size, epochs=num_epochs, callbacks = [es])
(1)model.compile
这个函数主要为设置损失函数和优化器及评估标准。参数设置如下:
- 优化器 optimizer。它可以是现有优化器的字符串标识符,如
rmsprop
或adagrad
,也可以是 Optimizer 类的实例。详见:optimizers。 - 损失函数 loss,模型试图最小化的目标函数。它可以是现有损失函数的字符串标识符,如
categorical_crossentropy
或mse
,也可以是一个目标函数。详见:losses。 - 评估标准 metrics。对于任何分类问题,你都希望将其设置为
metrics = ['accuracy']
。评估标准可以是现有的标准的字符串标识符,也可以是自定义的评估标准函数
(2)earlystipping
这个为keras封装的回调函数,具体信息可以查看https://keras.io/zh/callbacks/,具体的作用为当被监测的数量不再提升,则停止训练
(3)batch_size,num_epochs
简单说,epochs 指的就是训练过程中数据将被“轮询”多少次。
深度学习的优化算法,说白了就是梯度下降。每次的参数更新有两种方式。
第一种,遍历全部数据集算一次损失函数,然后算函数对各个参数的梯度,更新梯度。这种方法每更新一次参数都要把数据集里的所有样本都看一遍,计算量开销大,计算速度慢,不支持在线学习,这称为批梯度下降(Batch gradient descent)。
另一种,每看一个数据就算一下损失函数,然后求梯度更新参数,这个称为随机梯度下降(stochastic gradient descent)。这个方法速度比较快,但是收敛性能不太好,可能在最优点附近晃来晃去,达不到最优点。两次参数的更新也有可能互相抵消掉,造成目标函数震荡的比较剧烈。
为了克服两种方法的缺点,现在一般采用的是一种折中手段,小批的梯度下降(mini-batch gradient decent),这种方法把数据分为若干个批,按批来更新参数,这样,一个批中的一组数据共同决定了本次梯度的方向,下降起来就不容易跑偏,减少了随机性。另一方面因为批的样本数与整个数据集相比小了很多,所以计算量也不是很大。基本上现在的梯度下降都是基于 mini-batch 的,所以 Keras 的模块中经常会出现 batch_size
,就是指这个。
(4)model.fit函数启动训练
0x04 模型评估
scores = model.evaluate(X_test, y_test, verbose=0)
print('Test accuracy:', scores[1])
(1)verbose
verbose:日志显示,verbose = 0 为不在标准输出流输出日志信息,verbose = 1 为输出进度条记录,verbose = 2 为每个epoch输出一行记录
0x05 全部代码
因为懒所以麻烦各位自己复制整合了
四、总结
RNN的基本实践流程如上,这是网咯上大部分文章共同流传的一个python代码的例子,我这里将每一行代码进行讲解,适用于具备一丁点ML或者DL基础的旁友观看。
使用RNN进行imdb影评情感识别--use RNN to sentiment analysis的更多相关文章
- 学习笔记TF019:序列分类、IMDB影评分类
序列分类,预测整个输入序列的类别标签.情绪分析,预测用户撰写文字话题态度.预测选举结果或产品.电影评分. 国际电影数据库(International Movie Database)影评数据集.目标值二 ...
- 论文笔记:语音情感识别(二)声谱图+CRNN
一:An Attention Pooling based Representation Learning Method for Speech Emotion Recognition(2018 Inte ...
- RNN入门(二)识别验证码
介绍 作为RNN的第二个demo,笔者将会介绍RNN模型在识别验证码方面的应用. 我们的验证码及样本数据集来自于博客: CNN大战验证码,在这篇博客中,我们已经准备好了所需的样本数据集,不需要 ...
- RNN入门(一)识别MNIST数据集
RNN介绍 在读本文之前,读者应该对全连接神经网络(Fully Connected Neural Network, FCNN)和卷积神经网络( Convolutional Neural Netwo ...
- IMDB影评倾向分类 - N-Gram
catalogue . 数据集 . 模型设计 . 训练 1. 数据集 0x1: IMDB影评数据 本数据库含有来自IMDB的25,000条影评,被标记为正面/负面两种评价 from keras.dat ...
- 论文笔记:语音情感识别(五)语音特征集之eGeMAPS,ComParE,09IS,BoAW
一:LLDs特征和HSFs特征 (1)首先区分一下frame和utterance,frame就是一帧语音.utterance是一段语音,是比帧高一级的语音单位,通常指一句话,一个语音样本.uttera ...
- 论文笔记:语音情感识别(四)语音特征之声谱图,log梅尔谱,MFCC,deltas
一:原始信号 从音频文件中读取出来的原始语音信号通常称为raw waveform,是一个一维数组,长度是由音频长度和采样率决定,比如采样率Fs为16KHz,表示一秒钟内采样16000个点,这个时候如果 ...
- 论文笔记:语音情感识别(三)手工特征+CRNN
一:Emotion Recognition from Human Speech Using Temporal Information and Deep Learning(2018 InterSpeec ...
- TensorFlow使用RNN实现手写数字识别
学习,笔记,有时间会加注释以及函数之间的逻辑关系. # https://www.cnblogs.com/felixwang2/p/9190664.html # https://www.cnblogs. ...
随机推荐
- Spring 事务笔记
代码写着写着就钻进源码了. 概念 InfrastructureProxy 结构代理 百度查了查,这个类还没有解释. 进去看了一下: Interface to be implemented by tra ...
- Modbus协议笔记
读线圈:就是说读开关量输出的状态,看看开关量输出的到底是开着的还是关着的,这样说有点不专业,但是好明白.比如要在上位机显示开关量输出的当状态,就得用这个功能码. 写线圈:就是说读开关量输入的状态,开关 ...
- 2018.8.9 python中的动态传参与命名空间
主要内容: 1.函数参数 ----动态传参 2.名称空间与作用域 3.函数的嵌套 4.global,nonlocal关键字 一.函数参数 ------动态传参 形参的第三种:动态传参 动态传参分为两种 ...
- Java内存模型相关原则详解
在<Java内存模型(JMM)详解>一文中我们已经讲到了Java内存模型的基本结构以及相关操作和规则.而Java内存模型又是围绕着在并发过程中如何处理原子性.可见性以及有序性这三个特征来构 ...
- vue项目中v-for渲染失败
在项目中,v-for渲染列表失败,无报错,数组有数据.上网查,好多说是因为动态绑定class的原因,但是经过几番测试,都无效果. 在经过不断尝试,搜索,终于找到原因所在. 问题原因:在v-for循环中 ...
- 解决node.js使用fs读取文件出错
今天配接口,使用fs模块读取json出现了错误'no such file or directory',然后经查终于解决,特此记录. 使用nodejs的fs模块读取文件时习惯用相对路径,但是运行的时 ...
- 纯HTML+JS实现轮播
<!DOCTYPE html> <html lang="en" xmlns="http://www.w3.org/1999/xhtml"> ...
- PhpStudy2018后门漏洞预警及漏洞复现&检测和执行POC脚本
PhpStudy2018后门漏洞预警及漏洞复现&检测和执行POC脚本 phpstudy介绍 Phpstudy是国内的一款免费的PHP调试环境的程序集成包,其通过集成Apache.PHP.MyS ...
- MVC5用户控件
1. 添加一个model,用于给用户控件传递数据: 2.添加一个部分视图 . 3. 部分视图中,引入model,用于传递数据 4. 在要插入用户控件的地方,这样写 @Html.Partial(&quo ...
- 『题解』洛谷P3958 奶酪
Portal Portal1: Luogu Portal2: LibreOJ Portal3: Vijos Description 现有一块大奶酪,它的高度为\(h\),它的长度和宽度我们可以认为是无 ...