Press "Enter" to skip to content

电影短评情感分析:各大模型江湖再见

倒腾豆瓣电影短评情感分析也有一阵时间了,一直抓着这个不放也不是个事,得赶紧腾出时间去总结下KG。本文算是笔者对情感分析的进阶篇,也是关于情感分类模型覆盖最全的文章。首先,从传统的特征提取方面对比了BOW、TF-IDF、N-Gram技术,并使用不同的机器学习算法构建了不同的子模型,然后又采用了Stacking模型融合技术对短评情感进行了进一步的探索,最后进阶到深度学习,构建神经网络模型进行文本分类。全文各个模型并不是参数最优,但也有一定的参考价值,因为针对不同的数据集,模型的预测结果都是不尽相同的。言归正传,下面一起来看看电影短评情感分析的结果吧!

 

往期回顾

 

首先介绍下笔者先前写的几篇关于电影短评的文章:第一篇文章介绍的是如何构建高质量的情感分析数据集,第二篇是采用MNB做的一个baseline模型,第三篇是数据集的原始来源。本文使用的数据集来自文章[1],整个训练集正负样本各220000条,测试集正负样本各24912条。

 

浅谈影评情感分析数据集的构建
豆瓣电影短评数据情感分析Baseline
14万电影800万影评数据集介绍

 

这三篇文章主要是情感分析初始篇,模型层面的东西基本上没有涉及。本篇则是从模型出发分析短评情感。在文章内容篇幅上,笔者将从以下几个大方向构建电影短评情感分析模型:

基于Bag-Of-Words特征的文本分类模型
基于TF-IDF特征的文本分类模型
基于Stacking模型融合的情感分析
基于深度学习的短评情感分析

基于Bag-Of-Words特征的文本分类模型

 

笔者首先对短评数据进行了分词,然后算出每个短评的bow特征,并在此基础上训练了LR、MMB、RF、GBDT四个模型,当然各个模型都没有进行很深程度的调优。从Table 1可以看出,bow-LR模型整体上预测结果最好,AUC达到了0.9399,其他预测指标也达到了0.87。

Table 1 测试集预测结果对比(BoW)

 

模型名称AccuracyPrecisionRecallF1-ScoreAUC
bow-LR0.8680.870.870.870.9399
bow-MNB0.8650.860.860.860.9342
bow-RF0.8180.820.820.820.8902
bow-GBDT0.75570.760.760.760.8535

 

核心代码如下:

 

transformer = CountVectorizer(analyzer=process.process_line)
transformer.fit(X)X = transformer.transform(X)

 

基于TF-IDF特征的文本分类

 

TF-IDF在文本处理中经常用到,至少在我的工作中是用到的较多,比如计算文本相似度的时候,比较简单而且常用的做法就是,先将句子的TF-IDF值算出来,然后根据欧式距离计算相似度。TF-IDF(词频-逆文档频率)技术,是文本向量化的常用做法,从文本中提取特征以供后续的算法使用。

 

在这一小节里,特征方面最开始尝试了基于word的tfidf,然后又尝试了word-ngram-tfidf,后来将word-level替换成char-level,基于char构建n-gram。当然,关于ngram的n究竟该怎幺取,也是一个值得考量的因子,读者如有兴趣,可以尝试下3-gram to 6-gram。针对不同的特征,笔者对比了LR、RF、MNB、GBDT四个算法,四个模型除了RF和GBDT是基于tree的,其他的都是不同类型的,以示区分。共训练了12个模型,各个模型的结果如Table 2所示。

Table 2 测试集预测结果对比(TF-IDF)

模型名称AccuracyPrecisionRecallF1-ScoreAUC
word-level-tfidf-LR0.8720.870.870.870.9438
word-level-tfidf-MNB0.8620.860.860.860.9394
word-level-tfidf-RF0.82190.820.820.820.8930
word-level-tfidf-GBDT0.7230.720.720.710.8183
word-ngram-tfidf-LR0.87240.870.870.870.9439
word-ngram-tfidf-MNB0.86420.860.860.860.9399
word-ngram-tfidf-RF0.82120.820.820.820.8925
word-ngram-tfidf-GBDT0.76300.770.760.760.8588
char-ngram-tfidf-LR0.88660.890.890.890.9552
char-ngram-tfidf-MNB0.86570.870.870.870.9410
char-ngram-tfidf-RF0.82760.830.830.830.9009
char-ngram-tfidf-GBDT0.76860.780.770.770.8613

 

让笔者比较意外的是,GBDT和RF的结果居然比LR还要差,不过稍微想了下也感觉正常,主要是没有经过细致的调参。在上述12个模型中,基于char的ngram特征结合LR,测试集的预测结果,不管是precision还是recall、F1,都达到了0.89,AUC也高达0.9552,相对其他的模型,确实要高出一筹。说明一下,上述模型中基于word的ngram取得是[1,2,3]-gram,基于char的ngram是[2,3]-gram。

 

在算法上,笔者没有尝试SVM、xgboost、LightGBM等大众算法,一方面是SVM训练的速度过慢;另一方面是后面还会构建其他算法模型,传统的仅做参考吧。不过,虽然现在很多企业都转向了做深度学习模型,但传统的特征提取构建模型的方式还是值得学习一下的,毕竟知识掌握了就是自己的,缕清之后也就多了一份自信,没掌握的存放在电脑上的,那都是资料!!

 

基于Stacking模型融合的情感分类模型

 

关于stacking融合技术,整个过程如Fig 1所示。首先将数据集划分为训练集和测试集,训练集主要用于sub-Model训练,训练方式有两种,一种基于cross-validation,一种是单纯的训练。两种方式具体的过程如下:

Stacking-CV-Model:将训练集分成k份,在使用算法A进行交叉验证过程中,分别将每份作为测试集其余4分作为训练集训练分类模型,最后得到5个模型和5个测试集的预测结果,我们将算法A交叉验证得到的Out-Of-Fold结果作为一个特征集。如果有5个算法,每个算法得到的oof结果都是一个特征集,最后将其合并作为新的训练集(Meta Feature)。
Stacking-Model:将训练集分成k份,假设有5个算法用于stacking子模型中,那幺算法1采用第5份作为测试集,其余4份作为训练集,依此论推,算法2采用采用第4份作为测试机,算法3采用第3份作为测试集,算法4采用第2份作为测试集,算法1采用第5份作为测试机,其余作为训练集,最后将每个算法预测的测试集的结果合并,作为新的特征,即新的训练集(Meta Feature)。

如果有新的数据需要预测,那幺都需要按照上述过程预测出新的特征,然后使用Meta algorithm预测出最终的结果。Stacking融合模型的代码已上传至github,仅供参考: https://github.com/csuldw/MachineLearning/blob/master/stacking/stacking.py

 

 

Fig 1. stacking策略模型(分为两个阶段,第一阶段是model 1-model 5,用于训练出新的特征,第二阶段是Meta Algorithm,训练最终的分类模型)

 

在短评情感分类中,关于stacking模型,笔者尝试了几个,如Table 3所示。从数据上可以看出,在特征都为bag-of-words的情况下,bow(lr+MNB+RF)+xgboost 融合的结果的确比Table 1的各个子模型预测的结果好。单独从Table 3来看,xgboost作为layer 2的Meta算法比LR作为meta Algorithm 要稍微好一些。而针对不同的特征,基于char的ngram仍然要高出bow和word-tfidf特征,其AUC达到了0.9592。

Table 3 测试集模型预测结果对比(Stacking模型融合)

子模型Meta_ClassifierAccuracyPrecisionRecallF1-ScoreAUC
char-ngram-tfidf(lr+MNB+RF)LR0.88300.880.880.880.9539
char-ngram-tfidf(lr+MNB+RF)xgboost0.89340.890.890.890.9592
bow(lr+MNB+RF)xgboost0.87510.890.880.880.9444
word-tfidf(lr+MNB+RF)xgboost0.87390.870.870.870.9465

 

基于深度学习的情感分析

 

上面采用了传统机器学习方法构建了文本分类模型,接下来将使用深度学习技术进行文本分类。至于两者到底谁更好,我们大可不必太过较真。记得去年公司内部的多语言情感分类比赛,第一名是将BERT、fastText与传统机器学习算法进行融合而构建的stacking模型,第二名则是采用纯粹的传统机器学习方法进行融合。比赛当中,对数据的处理真的比算法更重要,有时候看起不起眼的算法,只要特征工程做的好,结果都是出乎意料的。说这些并不是指深度学习不行,只是想让大家以客观的心态去看待它,不要将其神话了。对于文本分类,之前使用比较多的深度学习算法还属RNN,比如LSTM、GRU等。在BERT出来之后,对文本分类的精度又提升了一个level。笔者在做情感分析的时候,并没有尝试去使用BERT算法,仅仅是将深度学习模型框架搭建了起来,后续要使用的话,直接调用就行了!关于深度学习模型的调参,笔者也没有花太多的时间,主要是在Mac上训练一个网络速度太慢了,一个LSTM,跑几十万的训练数据,一个epoch差不多20多分钟,整个模型训练下来也要好几个小时,真的是耗不起!基于LSTM的模型框架Fig 2所示:

Fig 2. LSTM深度学习文本分类模型框架

 

下面是笔者采用训练LSTM的核心代码(人生苦短,我用keras, v2.2.5),注意一下,这里采用了多分类的方式来做二分类,所以调用的是 categorical_crossentropy .

 

def train_model(X_train, y_train, X_test, y_test, n_words, batch_size, n_class=2):
    embedding_layer = Embedding(n_words + 1, EMBEDDING_DIM,
                            # weights=[embedding_matrix],
                            input_length=MAX_SEQUENCE_LENGTH, dropout=0.2)
    print('Build model...')
    model = Sequential()
    model.add(embedding_layer)
    model.add(SpatialDropout1D(0.4))
    model.add(LSTM(64, dropout=0.2, recurrent_dropout=0.2))  # try using a GRU 
    model.add(Dense(n_class, activation='softmax'))
    # try using different parameters
    model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
    print(model.summary())
    model.fit(X_train, y_train, batch_size=batch_size, epochs=5, validation_data=(X_test, y_test))
    score, acc = model.evaluate(X_test, y_test, batch_size=batch_size)
    print('Test score:{}, accuracy:{}'.format(score, acc))
    return model

 

LSTM Model结构与参数数量如下:

 

Model: "sequential_1"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
embedding_1 (Embedding)      (None, 50, 128)           12800128  
_________________________________________________________________
spatial_dropout1d_1 (Spatial (None, 50, 128)           0         
_________________________________________________________________
lstm_1 (LSTM)                (None, 64)                49408     
_________________________________________________________________
dense_1 (Dense)              (None, 2)                 130       
=================================================================
Total params: 12,849,666
Trainable params: 12,849,666
Non-trainable params: 0
_________________________________________________________________

 

关于LSTM算法,这里不扩展了,感兴趣的童鞋可以参考下这篇文章 Understanding LSTM Networks 。其内部结构如Fig 3 (中)所示,:

Fig 3. RNN-vs-LSTM-vs-GRU 内部结构

 

最终的模型预测结果如Table 4所示,在没有细致的调参情况下,LSTM模型的预测能力与上述传统的机器学习模型相差不大,GRU则与LSTM几乎持平:

Table 4. 测试集模型预测结果对比(深度学习)

模型名称AccuracyPrecisionRecallF1-ScoreAUC
LSTM-Model0.86850.870.870.870.9392
GRU-Model0.86850.870.880.870.9404

 

上面只是简单的采用了LSTM和GRU来构建深度学习模型,针对分类任务,还有很多的方法可以实施。比如基于BERT预训练模型构建分类模型,或是CNN、fastText等,亦或是不同的深度网络结构,都可以用来优化模型的最终预测性能。另外,我们还可以将深度学习模型与传统的机器学习模型进行融合,构建基于深度学习和机器学习的stacking模型等等等等。当然,只追求模型的种类是绝对不行的,要深入到一个模型里面,将参数调制最优,才是学习之根本。比如深度学习模型,模型何时会收敛,如何尽量避免过拟合等等,都是一大学问。读者如有相关的问题,可以关注笔者的公众号[斗码小院],在后台或是文章中留言都可以。

 

结束语

 

本文针对豆瓣电影短评数据集,构建了四大分类模型:基于BOW特征的分类模型、基于TF-IDF特征的分类模型、基于Stacking模型融合技术的情感分类模型、基于深度学习的短评情感分析模型,共训练了20+个文本分类模型,其中传统的基于char-level-ngram-tfidf特征构建的模型,在相同的算法下,不亚于其他的word-level特征。在深度学习模型上,由于一个模型训练的时间过长,笔者并未花费太多的时间去优化。后续如果有新的进展,也会第一时间再本文的留言栏中说明。OK,关于情感分析,就到此为止吧,感谢各位读者的捧场! 需要数据集的童鞋可关注[ 斗码小院 ]公众号,回复”情感分析数据集”即可 。

 

本文的所有代码已上传至GitHub: https://github.com/csuldw/comment-sentiment-analysis ,代码如有错误,还望读者指出,多谢!

 

参考文献

 

http://www.csuldw.com
https://scikit-learn.org
https://colah.github.io/posts/2015-08-Understanding-LSTMs/
https://www.kaggle.com/ngyptr/lstm-sentiment-analysis-keras
http://dprogrammer.org/rnn-lstm-gru

Be First to Comment

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注