文本情感分析(一):基于词袋模型(VSM、LSA、n-gram)的文本表示

现在自然语言处理用深度学习做的比较多,我还没试过用传统的监督学习方法做分类器,比如SVM、Xgboost、随机森林,来训练模型。因此,用Kaggle上经典的电影评论情感分析题,来学习如何用传统机器学习方法解决分类问题。

通过这个情感分析的题目,我会整理做特征工程、参数调优和模型融合的方法,这一系列会有四篇文章。这篇文章整理文本特征工程的内容。

文本的特征工程主要包括数据清洗、特征构造、降维和特征选择等。

首先是数据清洗,比如去停用词、去非字母汉字的特殊字符、大写转小写、去掉html标签等。

然后是特征构建,可以基于词袋模型构造文本特征,比如向量空间模型的词频矩阵、Tf-Idf矩阵,又比如LSA和LDA,也可以用word2vec、glove等文本分布式表示方法,来构造文本特征。此外还可以用n-gram构造文本特征。

接下来可以选择是否降维,可以用PCA或SVD等方法对文本特征矩阵进行降维。

最后选择效果比较突出的1个或几个特征来训练模型。

一、基于向量空间模型的文本特征表示

向量空间模型(Vector Space Model,VSM)也就是单词向量空间模型,区别于LSA、PLSA、LDA这些话题向量空间模型,但是单词向量空间模型和话题向量空间模型都属于词袋模型,又和word2vec等文本分布式表示方法相区别。

向量空间模型的基本想法是:给定一个文本,用一个向量表示该文本的语义,向量的每一维对应一个单词,其数值是该单词在该文本中出现的频数或Tf-Idf。那么每个文本就是一个向量,特征数量为所有文本中的单词总数,通过计算向量之间的余弦相似度可以得到文本的相似度。

而文本集合中的所有文本的向量就会构成一个单词-文本矩阵,元素为单词的频数或Tf-Idf。

在我们这个Kaggle案例中,单词-文本矩阵的行数为样本的数量,列数为单词的数量,训练集中样本有25000条,选取最高频的5000个单词,故矩阵X是(25000,5000)的矩阵。我们以词频和Tf-Idf作为文本特征,计算出两个单词-文本矩阵,然后分别训练随机森林二分类器。

首先导入所需要的库。

import os,re
import numpy as np
import pandas as pd

from bs4 import BeautifulSoup

from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.ensemble import RandomForestClassifier
from sklearn import metrics 

import nltk

from nltk.corpus import stopwords

第一步:读取训练数据,一共25000条评论数据。

"""第一步:用pandas读取训练数据"""

datafile = os.path.join(‘..‘, ‘data‘, ‘labeledTrainData.tsv‘)
# escapechar=‘\\‘用来去掉转义字符‘\‘
df = pd.read_csv(datafile, sep=‘\t‘, escapechar=‘\\‘)
print(‘Number of reviews: {}‘.format(len(df)))
df.head()

第二步:对影评数据做预处理。

大概有以下环节:

  1. 去掉html标签
  2. 移除标点
  3. 切分成词/token
  4. 去掉停用词
  5. 重组为新的句子
"""第二步:数据预处理"""

eng_stopwords = stopwords.words(‘english‘)

# 去掉html标签
# 去掉非英文字符
# 去停用词
# 重新组合为句子
def clean_text(text):
    text = BeautifulSoup(text, ‘html.parser‘).get_text()
    text = re.sub(r‘[^a-zA-Z]‘, ‘ ‘, text)
    words = text.lower().split()
    words = [w for w in words if w not in eng_stopwords]
    return ‘ ‘.join(words)

df[‘clean_review‘] = df.review.apply(clean_text)
df.head()

第三步:用向量空间模型抽取文本特征

分别计算单词的词频和Tf-Idf,作为文本特征,计算单词-文本矩阵。

"""第三步:用VSM抽取文本特征"""

# 统计词频,作为文本特征,计算文本-单词矩阵
vectorizer_freq = CountVectorizer(max_features = 5000)
train_vsm_freq = vectorizer_freq.fit_transform(df.clean_review).toarray()
print("以词频为元素的文本-单词矩阵的维度是:\n\n",train_vsm_freq.shape)

# 计算tfidf,作为另一种文本特征,计算文本-单词矩阵
vectorizer_tfidf=TfidfVectorizer(max_features=5000)
train_vsm_tfidf=vectorizer_tfidf.fit_transform(df.clean_review).toarray()

print("\n用单词向量空间模型成功抽取文本特征!\n")
以词频为元素的文本-单词矩阵的维度是:

 (25000, 5000)

用单词向量空间模型成功抽取文本特征!

第四步:训练分类器

决策树为200棵。

"""第四步:用随机森林训练二分类器"""

"""首先使用以词频为元素的文本-单词矩阵训练一个分类器"""
# 使用包外估计作为模型泛化误差的估计,即oob_score=True,那么无须再做交叉验证
forest = RandomForestClassifier(oob_score=True,n_estimators = 200)
forest = forest.fit(train_vsm_freq, df.sentiment)

第五步:评估分类器的性能

这里没有进行交叉验证了,没有划分验证集来计算准确率、召回率和AUC,直接用训练集来计算这些指标。因为随机森林通过自助采样,可以得到大约36.8%的验证集,用于评估模型的泛化误差,称这为包外估计,因此我们主要观察包外估计这个指标,来评估分类器的性能。

从评估结果来看,包外估计为0.84232。

"""第五步:评估模型"""

def model_eval(train_data):

    print("1、混淆矩阵为:\n")
    print(metrics.confusion_matrix(df.sentiment, forest.predict(train_data)))

    print("\n2、准确率、召回率和F1值为:\n")
    print(metrics.classification_report(df.sentiment,forest.predict(train_data)))

    print("\n3、包外估计为:\n")
    print(forest.oob_score_)

    print("\n4、AUC Score为:\n")
    y_predprob = forest.predict_proba(train_data)[:,1]
    print(metrics.roc_auc_score(df.sentiment, y_predprob))

print("\n====================评估以词频为特征训练的模型==================\n")
model_eval(train_vsm_freq)

第六步:以Tf-Idf作为文本特征,训练分类器

结果包外估计为0.84168,比词频矩阵的要低一点,问题不大。

"""再使用以tfidf为元素的文本-单词矩阵训练一个分类器"""

forest = RandomForestClassifier(oob_score=True,n_estimators = 200)
forest = forest.fit(train_vsm_tfidf, df.sentiment)
print("\n====================评估以tfidf为特征训练的模型==================\n")
model_eval(train_vsm_tfidf)

二、基于潜在语义分析的文本特征表示

潜在语义分析(Laten Semantic Analysis,LSA)是一种文本话题分析的方法,特点是可以通过矩阵分解(SVD或者NMF),来发现文本与单词之间的基于话题的语义关系。

LSA和VSM有什么关系呢?

1、VSM的优点是单词向量稀疏,计算效率高,但是由于自然语言中一词多义和多词一义现象的存在,基于单词向量的文本表示未必能准确表达两个文本的相似度。而LSA是用文本的话题来表示文本,文本的话题相似则文本的语义也相似,这样可以解决同义词和多义词的问题。

2、VSM得到的是单词-文本矩阵,而LSA得到的是话题-文本矩阵。LSA的话题-文本矩阵就是通过对VSM的矩阵进行矩阵分解得到的,矩阵分解的方法包括SVD奇异值分解和NMF非负矩阵分解。

如下图,NMF非负矩阵分解后得到话题-文本矩阵Y,话题为k个,样本为n个。

在这个情感分析案例中,我们把话题设为300个,把单词-文本矩阵降维成(25000, 300)的话题-文本矩阵,采用的是NMF非负矩阵分解的方法。

要注意的一点是,如果单词-文本矩阵的维度是(单词数,文本数)这种格式,也就是我们在代码中用到的格式,那么在用 sklearn.decomposition.NMF 这个包计算话题-文本矩阵时,NMF().fit_transform() 所得的是话题-文本矩阵,NMF().components_得到的是单词-话题矩阵。

而如果单词-文本矩阵的格式和上图的格式一样(转置了),那么NMF().components_得到的是话题-文本矩阵。

下面首先用NMF计算LSA的话题-文本矩阵,取以词频为元素的单词-文本矩阵来计算。对高维矩阵进行矩阵分解的时间复杂度非常高,所以我用一下LSA就好了,LDA就不敢再去尝试,因为LDA的时间复杂度更高,效果可能不一定好。

第一步:用NMF计算LSA的话题-文本矩阵

"""用NMF计算LSA的话题-文本矩阵"""

from sklearn.decomposition import NMF 

# 对以词频为特征的单词-文本矩阵进行NMF分解
nmf = NMF(n_components=300)
# 得到话题-文本矩阵,注意如果输入进行了转置,那么得到的是单词-话题矩阵
train_lsa_freq = nmf.fit_transform(train_vsm_freq) 

print("话题-文本矩阵的维度是:\n\n",train_lsa_freq.shape)
话题-文本矩阵的维度是:

 (25000, 300)

第二步:使用LSA的话题-文本矩阵训练随机森林分类器

包外估计为0.82236,比基于VSM的效果要差2个百分点左右,毕竟特征维度降低了。本来想把话题设定为500,也就是把特征维度降到500维,可是计算时间太恐怖了,久久得不到结果。

这真是费力不讨好。

"""再使用LSA的话题-文本矩阵训练一个分类器"""

forest = RandomForestClassifier(oob_score=True,n_estimators = 200)
forest = forest.fit(train_lsa_freq, df.sentiment)
print("\n====================评估以LSA为特征训练的模型==================\n")
model_eval(train_lsa_freq)

三、用n-gram做文本表示

n-gram的意思比较简单了,没啥好说的。我这里让n-gram=(2,2),也就是每个单元都是两个单词组合而成的。

"""使用sklearn计算2-gram,得到词语-文本矩阵"""

# token_pattern的作用是,出现"bi-gram"、"two:three"这种时,可以切成"bi gram"、"two three"的形式
vectorizer_2gram = CountVectorizer(ngram_range=(2,2),token_pattern=r‘\b\w+\b‘,max_features=5000)
train_vsm_2gram = vectorizer_2gram.fit_transform(df.clean_review).toarray()
print("2-gram构成的语料库中前10个元素为:\n")
print(vectorizer_2gram.get_feature_names()[:10])
2-gram构成的语料库中前10个元素为:

[‘able get‘, ‘able make‘, ‘able see‘, ‘able watch‘, ‘absolute worst‘, ‘absolutely brilliant‘,  ‘absolutely hilarious‘, ‘absolutely love‘, ‘absolutely loved‘, ‘absolutely nothing‘]

接着再训练随机森林分类器,并评估模型。不知道怎么回事,跑了很久,死活收敛不了,有毒。。。算了,放着让它跑,我也再想想到底咋回事。

"""使用以2-gram的词频为元素的单词-文本矩阵训练一个分类器"""

forest = RandomForestClassifier(oob_score=True,n_estimators = 200)
forest = forest.fit(train_vsm_2gram, df.sentiment)
print("\n====================评估以2-gram为特征训练的模型==================\n")
model_eval(train_vsm_2gram)

最后还是重新训练第一个模型,也就是用词频作为特征的单词-文本矩阵,训练随机森林分类器。我们读取测试数据进行预测,并保存预测结果。

# 删除不用的占内容变量
#del df
#del train_vsm_freq

# 读取测试数据
datafile = os.path.join(‘..‘, ‘data‘, ‘testData.tsv‘)
df = pd.read_csv(datafile, sep=‘\t‘, escapechar=‘\\‘)
print(‘Number of reviews: {}‘.format(len(df)))
df[‘clean_review‘] = df.review.apply(clean_text)

vectorizer = CountVectorizer(max_features = 5000)
test_data_features = vectorizer.fit_transform(df.clean_review).toarray()

result = forest.predict(test_data_features)
output = pd.DataFrame({‘id‘:df.id, ‘sentiment‘:result})
# 保存
output.to_csv(os.path.join(‘..‘, ‘data‘, ‘Bag_of_Words_model.csv‘), index=False)

参考资料:

李航:《统计学习方法》(第二版) 第17章

原文地址:https://www.cnblogs.com/Luv-GEM/p/10888026.html

时间: 2024-08-04 01:20:39

文本情感分析(一):基于词袋模型(VSM、LSA、n-gram)的文本表示的相关文章

主题模型及其在文本情感分析中的应用

随着Web2.0技术的出现和发展,互联网上(包括门户网站.电子商务网站.社交网站.音/视频分享网站.论坛.博客.微博等)产生了海量的.由用户发表的对于诸如人物.事件.产品等目标实体的评论信息.例如,下面这两个短文本评论:(1)“比较了多个智能手机后选择了8150,性价比还可以.另外,就是考虑到它是3.7的屏幕,大小比较合适,否则携带很不方便.”(京东商城用户,2011.11.25):(2)“我以前在杭州做二手房地产,用温州炒房客的话说:全世界房价降了,杭州的房价永远不会降,因为他们有一道坚不可摧

LSTM 文本情感分析/序列分类 Keras

LSTM 文本情感分析/序列分类 Keras 请参考 http://spaces.ac.cn/archives/3414/ neg.xls是这样的 pos.xls是这样的neg=pd.read_excel('neg.xls',header=None,index=None) pos=pd.read_excel('pos.xls',header=None,index=None) #读取训练语料完毕 pos['mark']=1 neg['mark']=0 #给训练语料贴上标签 pn=pd.concat

【CV知识学习】【转】beyond Bags of features for rec scenen categories。基于词袋模型改进的自然场景识别方法

原博文地址:http://www.cnblogs.com/nobadfish/articles/5244637.html 原论文名叫Byeond bags of features:Spatial Pyramid Matching for Recognizing Natural Scene Categories. 这篇文章的中心思想就是基于词袋模型+金字塔结构的识别算法.首先简单介绍词袋模型. 1.词袋模型 Bag of words模型也成为“词袋”模型,在最初多是用来做自然语言处理,Svetla

文本情感分析(二):基于word2vec和glove词向量的文本表示

上一篇博客用词袋模型,包括词频矩阵.Tf-Idf矩阵.LSA和n-gram构造文本特征,做了Kaggle上的电影评论情感分类题. 这篇博客还是关于文本特征工程的,用词嵌入的方法来构造文本特征,也就是用word2vec词向量和glove词向量进行文本表示,训练随机森林分类器. 一.训练word2vec词向量 Kaggle情感分析题给出了三个数据集,一个是带标签的训练集,共25000条评论,一个是测试集,无标签的,用来做预测并提交结果,这两个数据集是上一篇文章里我们用过的. 此外还有一个无标签的数据

文本分类之情感分析– 停用词和惯用语

改善特征提取往往可以对分类的accuracy(和precision和召回率)有显著的正面影响.在本文中,我将评估word_feats的两项修改特征提取的方法: 过滤停用词 包含二元语法搭配 为了有效地做到这一点,我们将修改前面的代码,这样我们就可以使用任意的特征提取函数,它接收一个文件中的词,并返回特征字典.和以前一样,我们将使用这些特征来训练朴素贝叶斯分类器. import collections import nltk.classify.util, nltk.metrics from nlt

动手学深度学习--文本情感分析之RNN

?本分类是?然语?处理的?个常?任务,它把?段不定?的?本序列变换为?本的类别.它的?个?问题:使??本情感分类来分析?本作者的情绪.这个问题也叫情感分析,并有着?泛的应?.例如,我们可以分析?户对产品的评论并统计?户的满意度,或者分析?户对市场?情的情绪并?以预测接下来的?情. 这里将应?预训练的词向量和含多个隐藏层的双向循环神经?络,来判断?段不定?的?本序列中包含的是正?还是负?的情绪. 1.导入包和模块 1 import collections 2 import os 3 import

【转】用python实现简单的文本情感分析

import jieba import numpy as np # 打开词典文件,返回列表 def open_dict(Dict='hahah',path = r'/Users/zhangzhenghai/Downloads/Textming/'): path = path + '%s.txt' %Dict dictionary = open(path, 'r', encoding='utf-8') dict = [] for word in dictionary: word = word.st

R语言对推特数据进行文本情感分析

美国调查公司盖洛普公司(Gallup poll found)民调显示,至少51%美国人不赞同总统特朗普的政策.据外媒报道,特朗普上任8天以来引发51%美国人的不满,42%美国人赞同新总统的政策.该项调查共有1500名成年美国人,误差为3%. 为了验证美国民众的不满情绪,我们以R语言抓取的特朗普推特数据为例,对数据进行文本挖掘,进一步进行情感分析,从而得到很多有趣的信息. 找到推特来源是苹果手机或者安卓手机的样本,清理掉其他来源的样本 tweets <-trump_tweets_df>%sele

文本情感分析的基础在于自然语言处理、情感词典、机器学习方法等内容。以下是我总结的一些资源。

词典资源:SentiWordNet<知网>中文版中文情感极性词典 NTUSD情感词汇本体下载 自然语言处理工具和平台:哈尔滨工业大学社会计算与信息检索研究中心isnowfy/snownlp · GitHub 汉语分词:自然语言处理与信息检索共享平台 NLPIR.orgfxsjy/jieba · GitHub 语料资源:信息分类与情感发现 课程:斯坦福大学自然语言处理第七课"情感分析(Sentiment Analysis)" 网站和博客:Text Classification