营销最好的网站建设公司,网站建设相关工作,怎么看到网站开发时间,大题小做网站一、前言
文本情感分析是自然语言处理中非常基本的任务#xff0c;我们生活中有很多都是属于这一任务。比如购物网站的好评、差评#xff0c;垃圾邮件过滤、垃圾短信过滤等。文本情感分析的实现方法也是多种多样的#xff0c;可以使用传统的朴素贝叶斯、决策树#xff0c;…一、前言
文本情感分析是自然语言处理中非常基本的任务我们生活中有很多都是属于这一任务。比如购物网站的好评、差评垃圾邮件过滤、垃圾短信过滤等。文本情感分析的实现方法也是多种多样的可以使用传统的朴素贝叶斯、决策树也可以使用基于深度学习的CNN、RNN等。本文使用IMDB电影评论数据集基于RNN网络来实现文本情感分析。
二、数据处理
2.1 数据预览
首先需要下载对应的数据http://ai.stanford.edu/~amaas/data/sentiment/。点击下图位置 数据解压后得到下面的目录结构
- aclImdb- test- neg- pos- labeledBow.feat- urls_neg.txt- urls_pos.txt- train- neg- pos这是一个电影影评数据集neg中包含的评论是评分较低的评论而pos中包含的是评分较高的评论。我们需要的数据分别是test里面的neg和pos以及train里面的neg和posneg表示negativepos表示positive。下面我们开始处理。
2.2 导入模块
在开始写代码之前需要先导入相关模块
import os
import re
import stringimport numpy as np
from tensorflow.keras import layers
from tensorflow.keras.models import Model我的环境是tensorflow2.7部分版本的tensorflow导入方式如下
from keras import layers
from keras.models import Model可以根据自己环境自行替换。
2.3 数据读取
这里定义一个函数读取评论文件
def load_data(data_dirr/home/zack/Files/datasets/aclImdb/train):data_dirtrain的目录或test的目录输出X评论的字符串列表y标签列表0,1classes [pos, neg]X, y [], []for idx, cls in enumerate(classes):# 拼接某个类别的目录cls_path os.path.join(data_dir, cls)for file in os.listdir(cls_path):# 拼接单个文件的目录file_path os.path.join(cls_path, file)with open(file_path, encodingutf-8) as f:X.append(f.read().strip())y.append(idx)return X, np.array(y)上述函数会得到两个列表便于我们后面处理。
2.4 构建词表
在我们获取评论文本后我们需要构建词表。即统计所有出现的词给每个词一个编号也可以统计一部分多余的用unk表示。这一步会得到一个词到id的映射和id到词的映射具体代码如下
def build_vocabulary(sentences):sentences文本列表输出word2idx词到id的映射idx2wordid到词的映射word2idx {}idx2word {}# 获取标点符号及空字符punctuations string.punctuation \t\n for sentence in sentences:# 分词words re.split(f[{punctuations}], sentence.lower())for word in words:# 如果是新词if word not in word2idx:word2idx[word] len(word2idx)idx2word[len(word2idx) - 1] wordreturn word2idx, idx2word有了上面的两个映射后我们就可以将句子转换成id序列也可以把id序列转换成句子在本案例中只需要前者。
2.5 单词标记化tokenize
因为我们模型需要固定长度的数据因此在标记化时我们对句子长度进行限制
def tokenize(sentences, max_len300):sentences文本列表tokens标记化后的id矩阵形状为(句子数量, 句子长度)# 生产一个形状为(句子数量, 句子长度)的矩阵默认用空字符的id填充类型必须为inttokens np.full((len(sentences), max_len),fill_valueword2idx[], dtypenp.int32)punctuations string.punctuation \t\n for row, sentence in enumerate(sentences):# 分词words re.split(f[{punctuations}], sentence.lower())for col, word in enumerate(words):if col max_len:break# 把第row个句子的第col个词转成idtokens[row, col] word2idx.get(word, word2idx[])return tokens使用该函数就可以将句子列表转换成ndarray了。
三、构建模型并训练
3.1 构建模型
这里使用RNN来实现模型结构如下图 下面我们用程序实现这个模型
def build_model():vocab_size len(word2idx)# 构建模型inputs layers.Input(shapemax_len)x layers.Embedding(vocab_size, embedding_dim)(inputs)x layers.LSTM(64)(x)outputs layers.Dense(1, activationsigmoid)(x)model Model(inputs, outputs)return model这里需要注意下面几个地方
Embedding层的输入是(batch_size,max_len)输出是(batch_size,max_len,embedding_dim)LSTM层的输入是(batch_size,max_len,embedding_dim)输出是(batch_size,units)units就是LSTM创建时传入的值。
3.2 训练模型
下面就可以使用前面实现好的几个方法开始训练模型了代码如下
# 超参数
max_len 200
batch_size 64
embedding_dim 256
# 加载数据
X_train, y_train load_data()
X_test, y_test load_data(/home/zack/Files/datasets/aclImdb/test)
X X_train X_test
word2idx, idx2word build_vocabulary(X)
X_train tokenize(X_train, max_lenmax_len)
X_test tokenize(X_test, max_lenmax_len)# 构建模型
model build_model()
model.summary()
model.compile(optimizerrmsprop, lossbinary_crossentropy, metrics[accuracy])
model.fit(X_train, y_train,batch_sizebatch_size,epochs20,validation_data[X_test, y_test],
)经过20个epoch的训练后训练集准确率可以达到99%而验证集准确率在80%左右模型有一定程度的过拟合可以通过修改模型结构或调节超参数来进行优化。
比如修改max_len的大小、使用预训练的词嵌入、修改RNN中units的大小、修改embedding_dim的大小等。还可以添加BatchNormalization、Dropout层。
四、使用模型
模型训练好后可以用predict来预测predict的输入和embedding层的输入是一样的
while True:sentence input(请输入句子)tokenized tokenize([sentence], max_len)output model.predict(tokenized)print(消极 if output[0][0] 0.5 else 积极)下面是一些测试结果
请输入句子this is a bad movie
消极
请输入句子this is a good movie
积极
请输入句子i like this movie very much
积极
请输入句子i hate this movie very much
积极
请输入句子i will never see this movie again
积极效果不是特别理想因为训练样本通常为长文本而现在测试的是短文本。