中文情感分析

标签: 情感分析

情感分析在NLP领域中是应用很广泛的技术,一般用深度学习来解决这一类的问题。其实我的理解就是情感分析就是一个分类问题。这里我爬取了京东小米9的用户评论,正面和负面的评价各1000条,爬虫和整体的代码我放在了 GitHub 。然后我把预训练的词向量文件放在了 百度网盘,提取码:rxci。
我们一起来看看数据长得啥样,首先是小米9正面的评价:
pos
然后是小米9负面的评价:
neg
从这些数据印证了一句话,幸福的人都是相似的,不幸的人各有各的不幸。可以看到正类的评价里面基本上都是说小米9外观好看性能好,很容易就找到正类的特征词了。但是我们来看负类的小米9评价,基本上每一条负面评价吐槽的点都不一样,有对客服不满意的,有对小米活动失望的,有对没有优惠不满意的。有的正常看来似乎没有什么不满意,但是还是打了低分。这样的数据我感觉其实对结果是有一定影响的,我们如果想得到效果更好的模型,我们其实可以对数据进行筛选。好了,为了方便,我就直接用这个数据进行训练了。
首先我们逐行读取数据集,分别读取话术和标签。然后读入已经训练好的词向量 sgns.zhihu.bigram,这个训练好的词向量是一个长度为300维的。如下图所示,比如深圳这个词的300维词向量:
词向量
然后同时可以计算两个词的相似度:
相似度
同时也可以找出某一个词的最相似的 n 个词:
相似
从上面的图可以看出,这个词向量训练的是不错的,和烤肉相似的都是一些吃的。然后我们可以用训练集构建词典,代码如下所示:

train_tokens = []
for text in train_texts_orig:
    # 去掉标点
    text = re.sub("[\s+\.\!\/_,$%^*(+\"\']+|[+——!,。?、[email protected]#¥%……&*()]+", "",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:
token
然后我们处理好训练集之后,我们可以开始定义网络了,这里我们用双向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+\.\!\/_,$%^*(+\"\']+|[+——!,。?、[email protected]#¥%……&*()]+", "",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进行情感分析的整个流程,希望可以帮助大家理解整个的中文情感分析流程和原理,谢谢。

原文链接:加载失败,请重新获取