中文情感分析
情感分析在NLP领域中是应用很广泛的技术,一般用深度学习来解决这一类的问题。其实我的理解就是情感分析就是一个分类问题。这里我爬取了京东小米9的用户评论,正面和负面的评价各1000条,爬虫和整体的代码我放在了 GitHub 。然后我把预训练的词向量文件放在了 百度网盘,提取码:rxci。
我们一起来看看数据长得啥样,首先是小米9正面的评价:
然后是小米9负面的评价:
从这些数据印证了一句话,幸福的人都是相似的,不幸的人各有各的不幸。可以看到正类的评价里面基本上都是说小米9外观好看性能好,很容易就找到正类的特征词了。但是我们来看负类的小米9评价,基本上每一条负面评价吐槽的点都不一样,有对客服不满意的,有对小米活动失望的,有对没有优惠不满意的。有的正常看来似乎没有什么不满意,但是还是打了低分。这样的数据我感觉其实对结果是有一定影响的,我们如果想得到效果更好的模型,我们其实可以对数据进行筛选。好了,为了方便,我就直接用这个数据进行训练了。
首先我们逐行读取数据集,分别读取话术和标签。然后读入已经训练好的词向量 sgns.zhihu.bigram,这个训练好的词向量是一个长度为300维的。如下图所示,比如深圳这个词的300维词向量:
然后同时可以计算两个词的相似度:
同时也可以找出某一个词的最相似的 n 个词:
从上面的图可以看出,这个词向量训练的是不错的,和烤肉相似的都是一些吃的。然后我们可以用训练集构建词典,代码如下所示:
train_tokens = []
for text in train_texts_orig:
# 去掉标点
text = re.sub("[\s+\.\!\/_,$%^*(+\"\']+|[+——!,。?、aaa@qq.com#¥%……&*()]+", "",text)
# 结巴分词
cut = jieba.cut(text)
# 结巴分词的输出结果为一个生成器
# 把生成器转换为list
cut_list = [ i for i in cut ]
for i, word in enumerate(cut_list):
try:
# 将词转换为索引index
cut_list[i] = cn_model.vocab[word].index
except KeyError:
# 如果词不在字典中,则输出0
cut_list[i] = 0
train_tokens.append(cut_list)
这里我们定义一下输入token的长度:
我们长度定98就可以覆盖了95%以上的话术长度了。然后不足98的我们在前面补0:
然后我们处理好训练集之后,我们可以开始定义网络了,这里我们用双向LSTM加一个输出层,网络结构非常简单,代码如下所示:
model = Sequential()
model.add(Embedding(num_words,
embedding_dim,
weights=[embedding_matrix],
input_length = max_tokens,
trainable = False))
model.add(Bidirectional(LSTM(units=64, return_sequences=True)))
model.add(LSTM(units=16, return_sequences=False))
model.add(Dense(1, activation='sigmoid'))
# 我们使用adam以0.001的learning rate进行优化
optimizer = Adam(lr=1e-3)
代码结果如下所示:
然后我们就可以进行模型训练了,训练完成之后,我们需要一个预测的函数:
def predict_sentiment(text):
print(text)
# 去标点
text = re.sub("[\s+\.\!\/_,$%^*(+\"\']+|[+——!,。?、aaa@qq.com#¥%……&*()]+", "",text)
# 分词
cut = jieba.cut(text)
cut_list = [ i for i in cut ]
# tokenize
for i, word in enumerate(cut_list):
try:
cut_list[i] = cn_model.vocab[word].index
if cut_list[i] >= 30000:
cut_list[i] = 0
except KeyError:
cut_list[i] = 0
# padding
tokens_pad = pad_sequences([cut_list], maxlen=max_tokens,
padding='pre', truncating='pre')
# 预测
result = model.predict(x=tokens_pad)
coef = result[0][0]
if coef >= 0.5:
print('是一例正面评价','output=%.2f'%coef)
else:
print('是一例负面评价','output=%.2f'%coef)
这也是讲输入的话术去掉符号之后分词,然后向量化之后进行预测,我们可以看看预测的结果:
总的来说分类效果还是不错的。这就是用双向LSTM进行情感分析的整个流程,希望可以帮助大家理解整个的中文情感分析流程和原理,谢谢。
上一篇: python数据统计与可视化(Pandas库)统计pm2.5
下一篇: PM2.5检测