赞
踩
情感极性分析,即情感分类,对带有主观情感色彩的文本进行分析、归纳。情感极性分析主要有两种分类方法:基于情感知识的方法和基于机器学习的方法。基于情感知识的方法通过一些已有的情感词典计算文本的情感极性(正向或负向),其方法是统计文本中出现的正、负向情感词数目或情感词的情感值来判断文本情感类别;基于机器学习的方法利用机器学习算法训练已标注情感类别的训练数据集训练分类模型,再通过分类模型预测文本所属情感分类。
本文具体实现与应用:
本文将综合上述情感分析的方法并结合远程简单的学习方法对爬取到的短文本评论数据进行半监督情感分类,然后将分类好的数据在深度学习模型上进行训练,并应用到新的淘宝买家评论中去,对同种类型的店铺进行好坏推荐(比如官方店铺和一些酷动城店铺到底那家卖的是真货,可以根据买家评论进行推荐与鉴别,本文所实现的现实应用)等等应用,..........
Python环境
python3.6
第三方库
本实例代码的实现使用到了多个著名的第三方模块,主要模块如下所示
1)Jieba 目前使用最为广泛的中文分词组件。
2)Gensim 用于主题模型、文档索引和大型语料相似度索引的python库,主要用于自然语言处理(NLP)和信息检索(IR)。
3)Pandas 用于高效处理大型数据集、执行数据分析任务的python库,是基于Numpy的工具包,想要代码或者向当做研究课题的可以加群457756921。
4)Numpy 用于存储和处理大型矩阵的工具包。下载地址:https://pypi.python.org/pypi/numpy
5)Scikit-learn 用于机器学习的python工具包,python模块引用名字为sklearn,安装前还需要Numpy和Scipy两个Python库。官网地址:http://scikit-learn.org/stable/
6)Matplotlib Matplotlib是一个python的图形框架,用于绘制二维图形。下载地址:https://pypi.python.org/pypi/matplotlib
7)Tensorflow Tensorflow是一个采用数据流图用于数值计算的开源软件库,用于人工智能领域。 官网地址:http://www.tensorfly.cn/ 下载https://pypi.python.org/pypi/tensorflow/1.1.0
8)keras库
数据获取
采用爬虫技术进行数据获取,获取100家体育休闲类服装店铺买家评论,并对这些短文本进行初步的数据整理。由于爬虫代码比较简单,在这里省略代码展示,各位可以采用分布式爬虫技术复现。
数据预处理
1.正负向语料预处理
首先将获取到的100家店铺评论进行数据融合,其目的就是为了训练模型,下载中文正负情感关键词及情感词,采用远程监督,其实也就是数据统计的方法进行语料的分类与简单标注,(在这里还可以扩展基于投票机制的真正半监督的数据标注工作)得到的文件夹中包含负(负向语料)和POS(正向语料)两个文件夹,而文件夹中的每一篇评论为一个TXT文档,为了方便之后的操作,需要把正向和负向评论分别规整到对应的一个txt文件中,即正向语料的集合文档(命名为pos.txt)和负向语料的集合文档(命名为neg.txt)。(此步骤代码简单,但是过程繁多,可以自行实现)
2.中文文本分词
采用结巴分词分别对正向语料,负向语料进行分词处理。特别注意,在执行代码前需要把TXT源文件手动转化成UTF-8格式,否则会报中文编码的错误。在进行分词前,需要对文本进行去除数字,字母和特殊符号的处理,使用python自带的字符串和重模块可以实现,其中字符串模块用于处理字符串操作,re模块用于正则表达式处理。具体实现代码如下所示:
- import jieba
- import jieba.analyse
- import codecs,sys,string,re
- # 文本分词
- def prepareData(sourceFile,targetFile):
- f = codecs.open(sourceFile, 'r', encoding='utf-8')
- target = codecs.open(targetFile, 'w', encoding='utf-8')
- print ('open source file: '+ sourceFile)
- print ('open target file: '+ targetFile)
- lineNum = 1
- line = f.readline()
- while line:
- print ('---processing ',lineNum,' article---')
- line = clearTxt(line)
- seg_line = sent2word(line)
- target.writelines(seg_line + '\n')
- lineNum = lineNum + 1
- line = f.readline()
- f.close()
- target.close()
- # 清洗文本
- def clearTxt(line):
- if line != '':
- line = line.strip()
- intab = ""
- outtab = ""
- trantab = string.maketrans(intab, outtab)
- pun_num = string.punctuation + string.digits
- line = line.encode('utf-8')
- line = line.translate(trantab,pun_num)
- line = line.decode("utf8")
- #去除文本中的英文和数字
- line = re.sub("[a-zA-Z0-9]","",line)
- #去除文本中的中文符号和英文符号
- line = re.sub("[\s+\.\!\/_,$%^*(+\"\';:“”.]+|[+——!,。??、~@#¥%……&*()]+".decode("utf8"), "",line)
- return line
- #文本切割
- def sent2word(line):
- segList = jieba.cut(line,cut_all=False)
- segSentence = ''
- for word in segList:
- if word != '\t':
- segSentence += word + " "
- return segSentence.strip()
- if __name__ == '__main__':
- sourceFile = 'neg.txt'
- targetFile = 'neg_cut.txt'
- prepareData(sourceFile,targetFile)
-
- sourceFile = 'pos.txt'
- targetFile = 'pos_cut.txt'
- prepareData(sourceFile,targetFile)
3.去停用词
分词完成后,即可读取停用词表中的停用词,对分词后的正负向语料进行匹配并去除停用词。去除停用词的步骤非常简单,主要有两个:
1)读取停用词表;
2)遍历分词后的句子,将每个词丢到此表中进行匹配,若停用词表存在则替换为空。
根据代码所示,停用词表的获取使用到了python特有的广播形式,一句代码即可搞定:
stopkey = [w.strip() for w in codecs.open('data\stopWord.txt', 'r', encoding='utf-8').readlines()]
读取出的每一个停用词必须要经过去符号处理即w.strip(),因为读取出的停用词还包含有换行符和制表符,如果不处理则匹配不上。代码执行完成后,得到neg_cut_stopword.txt和pos_cut_stopword.txt两个txt文件。由于去停用词的步骤是在句子分词后执行的,因此通常与分词操作在同一个代码段中进行,即在句子分词操作完成后直接调用去停用词的函数,并得到去停用词后的结果,再写入结果文件中。本文是为了便于步骤的理解将两者分开为两个代码文件执行,各位可根据自己的需求进行调整。
具体实现代码如下所示:
#去除停用词
import codecs,sys
def stopWord(sourceFile,targetFile,stopkey):
sourcef = codecs.open(sourceFile, 'r', encoding='utf-8')
targetf = codecs.open(targetFile, 'w', encoding='utf-8')
print 'open source file: '+ sourceFile
print 'open target file: '+ targetFile
lineNum = 1
line = sourcef.readline()
while line:
print '---processing ',lineNum,' article---'
sentence = delstopword(line,stopkey)
#print sentence
targetf.writelines(sentence + '\n')
lineNum = lineNum + 1
line = sourcef.readline()
print 'well done.'
sourcef.close()
targetf.close()
#删除停用词
def delstopword(line,stopkey):
wordList = line.split(' ')
sentence = ''
for word in wordList:
word = word.strip()
if word not in stopkey:
if word != '\t':
sentence += word + " "
return sentence.strip()
if __name__ == '__main__':
stopkey = [w.strip() for w in codecs.open('data\stopWord.txt', 'r', encoding='utf-8').readlines()]
sourceFile = 'neg_cut.txt'
targetFile = 'neg_cut_stopword.txt'
stopWord(sourceFile,targetFile,stopkey)sourceFile = 'pos_cut.txt'
targetFile = 'pos_cut_stopword.txt'
stopWord(sourceFile,targetFile,stopkey)
4.获取特征词向量
根据以上步骤得到了正负向语料的特征词文本,而模型的输入必须是数值型数据,因此需要将每条由词语组合而成的语句转化为一个数值型向量。常见的转化算法有Bag of Words(BOW)、Word2Vec、Doc2vec。本文采用Word2Vec词向量模型将语料转换为词向量。
由于特征词向量的抽取是基于已经训练好的词向量模型,而wiki中文语料是公认的大型中文语料,本文拟从wiki中文语料生成的词向量中抽取本文语料的特征词向量。Wiki中文语料的Word2vec模型训练在之前写过的一篇文章“利用Python实现wiki中文语料的word2vec模型构建” 中做了详尽的描述,在此不赘述。即本文从文章最后得到的wiki.zh.text.vector中抽取特征词向量作为模型的输入。
获取特征词向量的主要步骤如下:
1)读取模型词向量矩阵;
2)遍历语句中的每个词,从模型词向量矩阵中抽取当前词的数值向量,一条语句即可得到一个二维矩阵,行数为词的个数,列数为模型设定的维度;
3)根据得到的矩阵计算矩阵均值作为当前语句的特征词向量;
4)全部语句计算完成后,拼接语句类别代表的值,写入csv文件中。
主要代码如下所示:
# 返回特征词向量
def getWordVecs(wordList,model):
vecs = []
for word in wordList:
word = word.replace('\n','')
#print word
try:
vecs.append(model[word])
except KeyError:
continue
return np.array(vecs, dtype='float')
# 构建文档词向量
def buildVecs(filename,model):
fileVecs = []
with codecs.open(filename, 'rb', encoding='utf-8') as contents:
for line in contents:
logger.info("Start line: " + line)
wordList = line.split(' ')
vecs = getWordVecs(wordList,model)
#print vecs
#sys.exit()
# for each sentence, the mean vector of all its vectors is used to represent this sentence
if len(vecs) >0:
vecsArray = sum(np.array(vecs))/len(vecs) # mean
#print vecsArray
#sys.exit()
fileVecs.append(vecsArray)
return fileVecs
5.特征提取与将维操作
在此Word2vec模型设定了400的维度进行训练,得到的词向量为400维,但是这个词的特征维度太大了,好的电脑可以进行尝试训练,而且,由于特征维度的大,训练的模型不能很好的学习到重要的特征,而且致使模型参数要往大的调,运行慢而且效果不好,但是为了选择出最具代表性的词的特征,也是大家最常做的工作,即是特征工程,在此如果大家往难了做可以进行采用难一点的特征工程等,在此做文章,比如词性标注、情感词attention啦等等;但是在此为了简单实现采用了PCA进行降维,具体代码实现如下,(核心代码)
n_components = 400
pca = PCA(n_components=n_components)
pca.fit(x)
在此模型的训练可以进行很多模型的实现,比如传统机器学习模型SVM,逻辑回归,KNN啦等等,深度学习方面可以进行RNN,DNN,LSTM等一些经典方法的实现,当然可以基于经典模型进行改进与组合,比如BIRNN+attention(情感词注意,即在attention做文章等)或者RNN与其他模型的组合,在此不便多说了,但是本文给出了支持向量机(SVM)作为本次实验的中文文本分类模型及LSTM的;此实现中是在基于标注后的语聊上80%做训练集,20%做测试集;
SVM:支持向量机(SVM)是一种有监督的机器学习模型。首先采用经典的机器学习算法SVM作为分类器算法,通过计算测试集的预测精度和ROC曲线来验证分类器的有效性,一般来说ROC曲线的面积(AUC)越大模型的表现越好。
首先使用SVM作为分类器算法,随后利用matplotlib和metric库来构建ROC曲线。具体核心代码如下所示:
clf = svm.SVC(C = 2, probability = True)
clf.fit(x_pca,y)
运行代码,得到Test Accuracy: 0.87,即本次实验测试集的预测准确率为87%,ROC曲线如下图所示
LSTM:是带有记忆功能的基于时间序列的模型,该模型能够很好的应用到自然语言分类问题中去,该模型的具体原理在此不在累述,可以查阅该博客的https://blog.csdn.net/weixin_40651515/article/details/80847806进行阅读,核心代码如下所示:
- model = Sequential()
- model.add(Embedding(len(abc), 256, input_length=maxlen))
- model.add(LSTM(128))
- model.add(Dropout(0.5))
- model.add(Dense(1))
- model.add(Activation('sigmoid'))
- model.compile(loss='binary_crossentropy',optimizer='adam',metrics=['accuracy'])
-
运行该LSTM可以得到0.91~0.92左右的准确率,但是在此基础上添加attention机制及使用双向LSTM可以达到0.95~0.965左右的准确率,准确率还不是很高,可能在数据标注上还是可以继续做工作的,比如之前说的基于投票的半监督标注工作等(想要代码或者感兴趣的可以留言)。。。。。。。。。
模型训练好后,记得保存参数,以便后续的应用等,即给买家进行淘宝店家的推荐,本文最后的应用只是给买家推荐该家店是否值得出买等情况,具体应用的方式大家可以根据自己的需求进行进一步的扩展等,在此不再累述。。。。。。。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。