Keras深度学习实战——使用循环神经网络构建情感分析模型

Posted 盼小辉丶

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Keras深度学习实战——使用循环神经网络构建情感分析模型相关的知识,希望对你有一定的参考价值。

Keras深度学习实战——使用循环神经网络构建情感分析模型

0. 前言

《循环神经详解与实现》一节中,我们已经了解循环神经网络 (Recurrent neural networks, RNN) 的基本原理,并且在 Keras 中实现了 RNN 模型,在本节中,我们构建 RNN 模型进行航空推文情感分类。

1. 使用循环神经网络构建情感分析模型

1.1 数据集分析

接下来,我们将实现 RNN 构建情感分析模型,所用的数据集与在《从零开始构建单词向量》一节中使用的数据集相同,即航空公司 Twitter 数据集,模型的目标是预测用户对于航空公司的评价属于正面、负面或者中立。

1.2 构建 RNN 模型进行情感分析

本节中,我们将实现在 RNN 情感分析模型。

(1) 导入相关的库和数据集:

from keras.layers import Dense
from keras.layers.recurrent import SimpleRNN
from keras.models import Sequential
from keras.layers.embeddings import Embedding
from sklearn.model_selection import train_test_split
import numpy as np
import nltk
from nltk.corpus import stopwords
import re
import pandas as pd

data=pd.read_csv('archive/Tweets.csv')
print(data.head())

(2) 预处理文本,删除标点符号、将所有单词转换为小写并删除停用词:

import nltk

stop = nltk.corpus.stopwords.words('english')
def preprocess(text):
    text=text.lower()
    text=re.sub('[^0-9a-zA-Z]+',' ',text)
    words = text.split()
    words2=[w for w in words if (w not in stop)]
    #words3=[ps.stem(w) for w in words]
    words4=' '.join(words2)
    return(words4)
data['text'] = data['text'].apply(preprocess)

(3) 提取数据集中的所有单词,并为每个单词分配一个索引:

from collections import Counter
counts = Counter()
for i,review in enumerate(data['text']):
    counts.update(review.split())
words = sorted(counts, key=counts.get, reverse=True)

nb_chars = len(words)
print(nb_chars)
word_to_int = word: i for i, word in enumerate(words, 1)
int_to_word = i: word for i, word in enumerate(words, 1)

提取到的单词示例如下:

'whitterbug', 'funnycaptain', 'referencing', 'pnbajfkmhg', 'vacatinn', 'devalue', ...

整数到单词的映射字典的示例如下:

..., 9966: 'intrusive', 9967: 'pockets', 9968: 'goingtovegas', 9969: 'getconnected', 9970: 'achieving', ...

(4) 将给定句子中的每个单词映射到与其关联的单词 ID 上,将文本评论转换为单词列表,其中每个列表均包含构成句子的单词 ID

mapped_reviews = []
for review in data['text']:
mapped_reviews.append([word_to_int[word] for word in review.split()])

# 打印示例
print('Original text:',data.loc[0]['text'])
print('Mapped text:',mapped_reviews[0])

原始评论文本和映射为单词 ID 的评论示例如下:

Original text: virginamerica dhepburn said
Mapped text: [31, 6369, 137]

(5) 提取句子的最大长度,并通过填充所有句子将其标准化为相同的长度。接下来,遍历所有评论文本,并存储每个评论的长度。此外,我们还需要计算评论的最大长度,用于将所有句子标准化为最大长度:

length_sent = []
for i in range(len(mapped_reviews)):
    length_sent.append(len(mapped_reviews[i]))
sequence_length = max(length_sent)

我们可以看到,不同的推文具有不同的长度。但是,RNN 接收的每个输入应具有相同长度。如果评论的长度小于数据集中最大的评论长度,则使用 0 值填充的评论,使所有输入具有相同的长度。

from keras.preprocessing.sequence import pad_sequences
x = pad_sequences(maxlen=sequence_length, sequences=mapped_reviews, padding="post", value=0)

(6) 构造训练和测试数据集,将目标输出转换为独热编码,并将原始数据拆分为训练数据集和测试数据集:

y = data['airline_sentiment'].values
y = np.array(pd.get_dummies(y))
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2)

(7) 构建 RNN 架构并编译模型:

embedding_vecor_length=32
max_review_length=26
model = Sequential()
model.add(Embedding(input_dim=nb_chars+1, output_dim=32, input_length = 26))

model.add(SimpleRNN(50, return_sequences=False))

model.add(Dense(3, activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['acc'])
model.summary()

Embedding 层的 input_dim 参数为数据集中不重复单词的总数加 1,其会为每个单词创建一个单词向量,其中 output_dim 表示要表示创建单词维数,input_length 表示每个句子中的单词数。在 RNN 层中,如果要提取每个时间步的输出,则 return_sequences 参数为 True,在本例中,我们仅需要在处理所有输入后才会提取输出,因此 return_sequences = False
模型简要信息输出如下:

Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
embedding (Embedding)        (None, 26, 32)            477920    
_________________________________________________________________
simple_rnn (SimpleRNN)       (None, 50)                4150      
_________________________________________________________________
dense (Dense)                (None, 3)                 153       
=================================================================
Total params: 482,223
Trainable params: 482,223
Non-trainable params: 0
_________________________________________________________________

Embedding 层中,由于共计有 14934 个不重复单词,且我们使用索引 0 作为填充词,因此共有 14934 个可能的单词,每个单词都以 32 维表示,因此共有 14934 x 32 = 48223个 参数。
simpleRNN 层中,有一组权重将输入连接到具有 50 个输出的 RNN 层,由于每个时刻有 32 个输入,每个时时刻具有相同的权重 W x h W_xh Wxh,则总共使用 32 x 50=1600 个权重将输入连接到 RNN 中,每个输入对应的输出尺寸为 1 x 50
此外,计算每个时刻的网络中间状态,需要计算 X ∗ W x h X * W_xh XWxh h ( t − 1 ) ∗ W h h h^(t-1)* W_hh h(t1)Whh,并求和,其中 X X X 是输入值, W x h W_xh Wxh 是将输入层连接到 RNN 层的权重, W h h W_hh Whh 是将上一个时刻网络状态连接到当前时刻网络状态的权重, h ( t − 1 ) h^(t-1) h(t1) 是上一个时刻的网络状态,由于 X ∗ W x h X*W_xh XWxh 的输出为 1 x 50,则 h ( t − 1 ) ∗ W h h h^(t-1)* W_hh h(t1)Whh 也为 1 x 50。由于 h ( t − 1 ) h^(t-1) h(t1) 的尺寸为 1 x 40,因此 W h h W_hh Whh 矩阵的尺寸为 50 x 50。除权重外,我们还需要 50 个偏置项与 50 个输出相关联,因此共有 (32 x 50 + 50 x 50 + 50 = 4150) 个权重参数。
最后一层总共有 153 个权重参数,因为 RNN 最后时刻的 50 个输出连接到全连接层的 3 个节点上,因此具有 50 x 3 个权重和 3 个偏置,因此总共有 153 个权重参数。

(8) 拟合模型:

history = model.fit(x_train, y_train,
                validation_data=(x_test, y_test),
                epochs=10,
                batch_size=32)

训练过程中,训练、测试数据集中的准确率和损失值变化情况如下:


此模型的测试准确率约为 76%,与我们使用词向量构建情感分析中构建的基于词向量的网络相比,没有任何明显的改进。但是,通过使用更多数据样本数量的增加,该模型将具有更高的准确率。

相关链接

Keras深度学习实战(1)——神经网络基础与模型训练过程详解
Keras深度学习实战(2)——使用Keras构建神经网络
Keras深度学习实战(7)——卷积神经网络详解与实现
Keras深度学习实战(24)——从零开始构建单词向量
Keras深度学习实战(25)——使用skip-gram和CBOW模型构建单词向量
Keras深度学习实战(26)——文档向量详解
Keras深度学习实战(27)——循环神经详解与实现
Keras深度学习实战(28)——利用单词向量构建情感分析模型

以上是关于Keras深度学习实战——使用循环神经网络构建情感分析模型的主要内容,如果未能解决你的问题,请参考以下文章

Keras深度学习实战——使用长短时记忆网络构建情感分析模型

Keras深度学习实战(28)——利用单词向量构建情感分析模型

Keras深度学习实战(28)——利用单词向量构建情感分析模型

Keras深度学习实战(30)——使用文本生成模型进行文学创作

Keras深度学习实战(27)——循环神经详解与实现

Keras深度学习实战(27)——循环神经详解与实现