情感分析简介

文本情感分析(Sentiment Analysis)是自然语言处理(NLP)方法中常见的应用,也是一个有趣的基本任务,尤其是以提炼文本情绪内容为目的的分类。它是对带有情感色彩的主观性文本进行分析、处理、归纳和推理的过程。

本文将介绍情感分析中的情感极性(倾向)分析。所谓情感极性分析,指的是对文本进行褒义、贬义、中性的判断。在大多应用场景下,只分为两类。例如对于“喜爱”和“厌恶”这两个词,就属于不同的情感倾向。

本文将详细介绍如何使用深度学习模型中的LSTM模型来实现文本的情感分析。

文本介绍及语料分析

evaluation,label

用了一段时间,感觉还不错,可以,正面

电视非常好,已经是家里的第二台了。第一天下单,第二天就到本地了,可是物流的人说车坏了,一直催,客服也帮着催,到第三天下午5点才送过来。父母年纪大了,买个大电视画面清晰,趁着耳朵还好使,享受几年。,正面

电视比想象中的大好多,画面也很清晰,系统很智能,更多功能还在摸索中,正面

不错,正面

用了这么多天了,感觉还不错。夏普的牌子还是比较可靠。希望以后比较耐用,现在是考量质量的时候。,正面

物流速度很快,非常棒,今天就看了电视,非常清晰,非常流畅,一次非常完美的购物体验,正面

非常好,客服还特意打电话做回访,正面

物流小哥不错,辛苦了,东西还没用,正面

送货速度快,质量有保障,活动价格挺好的。希望用的久,不出问题。,正面

接着我们需要对语料做一个简单的分析:

数据集中的情感分布;

数据集中的评论句子长度分布。

使用以下Python脚本,我们可以统计出数据集中的情感分布以及评论句子长度分布。

import pandas as pd

import matplotlib.pyplot as plt

from matplotlib import font_manager

from itertools import accumulate

# 设置matplotlib绘图时的字体

my_font = font_manager.FontProperties(fname="/Library/Fonts/Songti.ttc")

# 统计句子长度及长度出现的频数

df = pd.read_csv('./corpus.csv')

print(df.groupby('label')['label'].count())

df['length'] = df['evaluation'].apply(lambda x: len(x))

len_df = df.groupby('length').count()

sent_length = len_df.index.tolist()

sent_freq = len_df['evaluation'].tolist()

# 绘制句子长度及出现频数统计图

plt.bar(sent_length, sent_freq)

plt.title("句子长度及出现频数统计图", fontproperties=my_font)

plt.xlabel("句子长度", fontproperties=my_font)

plt.ylabel("句子长度出现的频数", fontproperties=my_font)

plt.savefig("./句子长度及出现频数统计图.png")

plt.close()

# 绘制句子长度累积分布函数(CDF)

sent_pentage_list = [(count/sum(sent_freq)) for count in accumulate(sent_freq)]

# 绘制CDF

plt.plot(sent_length, sent_pentage_list)

# 寻找分位点为quantile的句子长度

quantile = 0.91

#print(list(sent_pentage_list))

for length, per in zip(sent_length, sent_pentage_list):

if round(per, 2) == quantile:

index = length

break

print("\n分位点为%s的句子长度:%d." % (quantile, index))

# 绘制句子长度累积分布函数图

plt.plot(sent_length, sent_pentage_list)

plt.hlines(quantile, 0, index, colors="c", linestyles="dashed")

plt.vlines(index, 0, quantile, colors="c", linestyles="dashed")

plt.text(0, quantile, str(quantile))

plt.text(index, 0, str(index))

plt.title("句子长度累积分布函数图", fontproperties=my_font)

plt.xlabel("句子长度", fontproperties=my_font)

plt.ylabel("句子长度累积频率", fontproperties=my_font)

plt.savefig("./句子长度累积分布函数图.png")

plt.close()

输出的结果如下:

label

正面 1908

负面 2375

Name: label, dtype: int64

分位点为0.91的句子长度:183.

可以看到,正反面两类情感的比例差不多。句子长度及出现频数统计图如下:

句子长度累积分布函数图如下:

可以看到,大多数样本的句子长度集中在1-200之间,句子长度累计频率取0.91分位点,则长度为183左右。

使用LSTM模型

接着我们使用深度学习中的LSTM模型来对上述数据集做情感分析,笔者实现的模型框架如下:

完整的Python代码如下:

# -*- coding: utf-8 -*-

import pickle

import numpy as np

import pandas as pd

from keras.utils import np_utils, plot_model

from keras.models import Sequential

from keras.preprocessing.sequence import pad_sequences

from keras.layers import LSTM, Dense, Embedding, Dropout

from sklearn.model_selection import train_test_split

from sklearn.metrics import accuracy_score

# 导入数据

# 文件的数据中,特征为evaluation, 类别为label.

def load_data(filepath, input_shape=20):

df = pd.read_csv(filepath)

# 标签及词汇表

labels, vocabulary = list(df['label'].unique()), list(df['evaluation'].unique())

# 构造字符级别的特征

string = ''

for word in vocabulary:

string += word

vocabulary = set(string)

# 字典列表

word_dictionary = {word: i+1 for i, word in enumerate(vocabulary)}

with open('word_dict.pk', 'wb') as f:

pickle.dump(word_dictionary, f)

inverse_word_dictionary = {i+1: word for i, word in enumerate(vocabulary)}

label_dictionary = {label: i for i, label in enumerate(labels)}

with open('label_dict.pk', 'wb') as f:

pickle.dump(label_dictionary, f)

output_dictionary = {i: labels for i, labels in enumerate(labels)}

vocab_size = len(word_dictionary.keys()) # 词汇表大小

label_size = len(label_dictionary.keys()) # 标签类别数量

# 序列填充,按input_shape填充,长度不足的按0补充

x = [[word_dictionary[word] for word in sent] for sent in df['evaluation']]

x = pad_sequences(maxlen=input_shape, sequences=x, padding='post', value=0)

y = [[label_dictionary[sent]] for sent in df['label']]

y = [np_utils.to_categorical(label, num_classes=label_size) for label in y]

y = np.array([list(_[0]) for _ in y])

return x, y, output_dictionary, vocab_size, label_size, inverse_word_dictionary

# 创建深度学习模型, Embedding + LSTM + Softmax.

def create_LSTM(n_units, input_shape, output_dim, filepath):

x, y, output_dictionary, vocab_size, label_size, inverse_word_dictionary = load_data(filepath)

model = Sequential()

model.add(Embedding(input_dim=vocab_size + 1, output_dim=output_dim,

input_length=input_shape, mask_zero=True))

model.add(LSTM(n_units, input_shape=(x.shape[0], x.shape[1])))

model.add(Dropout(0.2))

model.add(Dense(label_size, activation='softmax'))

model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])

plot_model(model, to_file='./model_lstm.png', show_shapes=True)

model.summary()

return model

# 模型训练

def model_train(input_shape, filepath, model_save_path):

# 将数据集分为训练集和测试集,占比为9:1

# input_shape = 100

x, y, output_dictionary, vocab_size, label_size, inverse_word_dictionary = load_data(filepath, input_shape)

train_x, test_x, train_y, test_y = train_test_split(x, y, test_size = 0.1, random_state = 42)

# 模型输入参数,需要自己根据需要调整

n_units = 100

batch_size = 32

epochs = 5

output_dim = 20

# 模型训练

lstm_model = create_LSTM(n_units, input_shape, output_dim, filepath)

lstm_model.fit(train_x, train_y, epochs=epochs, batch_size=batch_size, verbose=1)

# 模型保存

lstm_model.save(model_save_path)

N = test_x.shape[0] # 测试的条数

predict = []

label = []

for start, end in zip(range(0, N, 1), range(1, N+1, 1)):

sentence = [inverse_word_dictionary[i] for i in test_x[start] if i != 0]

y_predict = lstm_model.predict(test_x[start:end])

label_predict = output_dictionary[np.argmax(y_predict[0])]

label_true = output_dictionary[np.argmax(test_y[start:end])]

print(''.join(sentence), label_true, label_predict) # 输出预测结果

predict.append(label_predict)

label.append(label_true)

acc = accuracy_score(predict, label) # 预测准确率

print('模型在测试集上的准确率为: %s.' % acc)

if __name__ == '__main__':

filepath = './corpus.csv'

input_shape = 180

model_save_path = './corpus_model.h5'

model_train(input_shape, filepath, model_save_path)

对上述模型,共训练5次,训练集和测试集比例为9:1,输出的结果为:

......

Epoch 5/5

......

3424/3854 [=========================>....] - ETA: 2s - loss: 0.1280 - acc: 0.9565

3456/3854 [=========================>....] - ETA: 1s - loss: 0.1274 - acc: 0.9569

3488/3854 [==========================>...] - ETA: 1s - loss: 0.1274 - acc: 0.9570

3520/3854 [==========================>...] - ETA: 1s - loss: 0.1287 - acc: 0.9568

3552/3854 [==========================>...] - ETA: 1s - loss: 0.1290 - acc: 0.9564

3584/3854 [==========================>...] - ETA: 1s - loss: 0.1284 - acc: 0.9568

3616/3854 [===========================>..] - ETA: 1s - loss: 0.1284 - acc: 0.9569

3648/3854 [===========================>..] - ETA: 0s - loss: 0.1278 - acc: 0.9572

3680/3854 [===========================>..] - ETA: 0s - loss: 0.1271 - acc: 0.9576

3712/3854 [===========================>..] - ETA: 0s - loss: 0.1268 - acc: 0.9580

3744/3854 [============================>.] - ETA: 0s - loss: 0.1279 - acc: 0.9575

3776/3854 [============================>.] - ETA: 0s - loss: 0.1272 - acc: 0.9579

3808/3854 [============================>.] - ETA: 0s - loss: 0.1279 - acc: 0.9580

3840/3854 [============================>.] - ETA: 0s - loss: 0.1281 - acc: 0.9581

3854/3854 [==============================] - 18s 5ms/step - loss: 0.1298 - acc: 0.9577

......

给父母买的,特意用了一段时间再来评价,电视非常好,没有坏点和损坏,界面也很简洁,便于操作,稍微不足就是开机会比普通电视慢一些,这应该是智能电视的通病吧,如果可以希望微鲸大大可以更新系统优化下开机时间~电视真的很棒,性价比爆棚,值得大家考虑购买。 客服很细心,快递小哥很耐心的等我通电验货,态度非常好。 负面 正面

长须鲸和海狮回答都很及时,虽然物流不够快但是服务不错电视不错,对比了乐视小米和微鲸论性价比还是微鲸好点 负面 负面

所以看不到4k效果,但是应该可以。 自带音响,中规中矩吧,好像没有别人说的好。而且,到现在没连接上我的漫步者,这个非常不满意,因为看到网上说好像普通3.5mm的连不上或者连上了声音小。希望厂家接下来开发的电视有改进。不知道我要不要换个音响。其他的用用再说。 放在地上的是跟我混了两年的tcl,天气受潮,修了一次,下岗了。 最后,我也觉得底座不算太稳,凑合着用。 负面 负面

电视机一般,低端机不要求那么高咯。 负面 负面

很好,两点下单上午就到了,服务很好。 正面 正面

帮朋友买的,好好好好好好好好 正面 正面

......

模型在测试集上的准确率为: 0.9020979020979021.

可以看到,该模型在训练集上的准确率为95%以上,在测试集上的准确率为90%以上,效果还是相当不错的。

模型预测

接着,我们利用刚刚训练好的模型,对新的数据进行测试。笔者随机改造上述样本的评论,然后预测其情感倾向。情感预测的Python代码如下:

# -*- coding: utf-8 -*-

# Import the necessary modules

import pickle

import numpy as np

from keras.models import load_model

from keras.preprocessing.sequence import pad_sequences

# 导入字典

with open('word_dict.pk', 'rb') as f:

word_dictionary = pickle.load(f)

with open('label_dict.pk', 'rb') as f:

output_dictionary = pickle.load(f)

try:

# 数据预处理

input_shape = 180

sent = "电视刚安装好,说实话,画质不怎么样,很差!"

x = [[word_dictionary[word] for word in sent]]

x = pad_sequences(maxlen=input_shape, sequences=x, padding='post', value=0)

# 载入模型

model_save_path = './sentiment_analysis.h5'

lstm_model = load_model(model_save_path)

# 模型预测

y_predict = lstm_model.predict(x)

label_dict = {v:k for k,v in output_dictionary.items()}

print('输入语句: %s' % sent)

print('情感预测结果: %s' % label_dict[np.argmax(y_predict)])

except KeyError as err:

print("您输入的句子有汉字不在词汇表中,请重新输入!")

print("不在词汇表中的单词为:%s." % err)

输出结果如下:

输入语句: 电视刚安装好,说实话,画质不怎么样,很差!

情感预测结果: 负面

让我们再尝试着测试一些其他的评论:

输入语句: 物超所值,真心不错

情感预测结果: 正面

输入语句: 很大很好,方便安装!

情感预测结果: 正面

输入语句: 卡,慢,死机,闪退。

情感预测结果: 负面

输入语句: 这种货色就这样吧,别期待怎样。

情感预测结果: 负面

输入语句: 啥服务态度码,出了事情一个推一个,送货安装还收我50

情感预测结果: 负面

输入语句: 京东服务很好!但我买的这款电视两天后就出现这样的问题,很后悔买了这样的电视

情感预测结果: 负面

输入语句: 产品质量不错,就是这位客服的态度十分恶劣,对相关服务不予解释说明,缺乏耐心,

情感预测结果: 负面

输入语句: 很满意,电视非常好。护眼模式,很好,也很清晰。

情感预测结果: 负面

总结

当然,该模型并不是对一切该商品的评论都会有好的效果,还是应该针对特定的语料去训练,去预测。

本文主要介绍了LSTM模型在文本情感分析方面的应用,该项目已上传Github,地址为: https://github.com/percent4/Sentiment_Analysis 。

注意:不妨了解下笔者的微信公众号: Python爬虫与算法(微信号为:easy_web_scrape), 欢迎大家关注~

参考文献

lstm训练情感分析的优点_NLP入门(十)使用LSTM进行文本情感分析相关推荐

  1. NLP之情感分析:基于python编程(jieba库)实现中文文本情感分析(得到的是情感评分)之全部代码

    NLP之情感分析:基于python编程(jieba库)实现中文文本情感分析(得到的是情感评分)之全部代码 目录 全部代码 相关文章 NLP之情感分析:基于python编程(jieba库)实现中文文本情 ...

  2. bert中文文本情感分类 微博评论挖掘之Bert实战应用案例-文本情感分类

    Bert模型全称Bidirectional Encoder Representations from Transformers,主要分为两个部分:1训练语言模型(language model)的预训练 ...

  3. python中文文本分析和提取_python str(使用python对txt文本进行分析和提取)

    python 文本文件数据处理 #/usr/bin/env python3 # -*- coding: utf-8 -*- def zhidao_560604345(infile, outfile): ...

  4. lstm训练情感分析的优点_LSTM对电影评论进行简单的情感分析

    今天自己尝试使用LSTM对电影评论进行简单的情感分析 代码中npy文件: 代码使用的数据集是IMDB,网盘地址: 首先读取已经做好的词向量模型 import numpy as np # 这里有两个表, ...

  5. ip协议分析实验报告_入门工业通讯之EtherNet/IP协议分析

    写在前面 前面我们系统得说了工业控制系统的通讯,大家肯定会想到PROFINET.ETHERNET/IP.ETHERCAT等工业以太网: 技术解读PROFINET.Ethernet/IP等7种主流工业以 ...

  6. 文本情感分析方法研究小结

    文本情感分析总结 1. 文本情感分析简介 何谓文本情感分析,其实很简单,利用算法来分析提取文本中表达的情感.例如分析一个句子表达的好.中.坏等判断,高兴.悲伤.愤怒等情绪.如果能将这种文字转为情感的操 ...

  7. 基于SnowNLP的商品评论文本情感分析

           摘要:情感文本电商情感标注分析研究是当前电商数据情感挖掘学术研究的重要热点,具有极高的国际应用价值.对当前电商手机在线商品评论词典进行情感文本电商情感标注分析与词典数据情感挖掘研究具有很 ...

  8. 华为云专家带你解读文本情感分析任务

    摘要:本文主要介绍了文本情感分析的主要任务,包括词级别的情感分析.句子级情感分析以及属性级情感分析等任务的介绍,同时介绍了华为云在这三个任务上的一些进展. 1 基本概念 为什么:随着移动互联网的普及, ...

  9. TensorFlow-RNN循环神经网络 Example 2:文本情感分析

    TensorFlow-RNN文本情感分析 之前用全连接神经网络写过一个文本情感分析 http://blog.csdn.net/weiwei9363/article/details/78357670 现 ...

最新文章

  1. 增加一个dbe连接_pogo pin连接器是如何解决振动的问题?
  2. Markdown常用语法汇总
  3. netfilter与iptables表规则建立
  4. 下列哪个滤波器是非线性的_正确选择射频滤波器的八大窍门
  5. Jquery tmpl模板中if条件有多个时的写法
  6. 漂亮的NavMenu导航控件
  7. GraphQL入门之graphql-java项目的介绍
  8. 腾讯首位T17级科学家诞生!
  9. Druid学习之路 (四)Druid的数据采集格式
  10. 【OJ】洛谷函数与结构体题单题解锦集
  11. 【激活函数】PRelu激活函数
  12. 豪气十足!联想Z6 Pro法拉利定制版本首现
  13. Pluto-基于Caffe的GPU多机多卡深度学习算法产品
  14. 判断存储,是栈?还是队列?
  15. flash实验中需添加的flash.c文件
  16. NOIp2014 提高组 Day1 T1 生活大爆炸版石头剪刀布
  17. 基于Arduino UNO的光驱写字机制作
  18. vue2.0 日历日程表 ,可进行二次开发.
  19. 21.手绘Spring IOC运行时序图
  20. 解决yay官方源下载慢问题

热门文章

  1. aws日志记录到MySQL_AWS-RDS慢查询日志查看导出
  2. 一文梳理Dubbo常见面试问题
  3. PMP--项目整合管理知识点总结
  4. java大会主题曲_全AI作词作曲!2020网易未来大会主题曲《未来之歌》发布
  5. 托利多bcom怎么查看连接网络_遇到手机APP提示无网络连接,应该怎么办?
  6. 挑战微信的社交产品,不应该是什么样的?
  7. 黑马程序员C++学习-核心编程
  8. 【招聘内推】软告招聘大数据架构师
  9. linux下的oracle10g,linux下oracle10g的安装
  10. QT操作Sqlite数据库修改字段名称和删除字段