logo资料库

python情感分类.docx

第1页 / 共24页
第2页 / 共24页
第3页 / 共24页
第4页 / 共24页
第5页 / 共24页
第6页 / 共24页
第7页 / 共24页
第8页 / 共24页
资料共24页,剩余部分请下载后查看
使用 python+机器学习方法进行情感分析 不是有词典匹配的方法了吗?怎么还搞多个机器学习方法。 因为词典方法和机器学习方法各有千秋。 机器学习的方法精确度更高,因为词典匹配会由于语义表达的丰富性而出现很大 误差,而机器学习方法不会。而且它可使用的场景更多样。无论是主客观分类还 是正负面情感分类,机器学习都可以完成任务。而无需像词典匹配那样要深入到 词语、句子、语法这些层面。 而词典方法适用的语料范围更广,无论是手机、电脑这些商品,还是书评、影评 这些语料,都可以适用。但机器学习则极度依赖语料,把手机语料训练出来的的 分类器拿去给书评分类,那是注定要失败的。 使用机器学习进行情感分析,可以换一个相同意思的说法,就是用有监督的(需 要人工标注类别)机器学习方法来对文本进行分类。 这点与词典匹配有着本质的区别。词典匹配是直接计算文本中的情感词,得出它 们的情感倾向分值。而机器学习方法的思路是先选出一部分表达积极情感的文本 和一部分表达消极情感的文本,用机器学习方法进行训练,获得一个情感分类器。 再通过这个情感分类器对所有文本进行积极和消极的二分分类。最终的分类可以 为文本给出 0 或 1 这样的类别,也可以给出一个概率值,比如”这个文本的积极 概率是 90%,消极概率是 10%“。 Python 有良好的程序包可以进行情感分类,那就是 Python 自然语言处理包, Natural Language Toolkit ,简称 NLTK 。 NLTK 当然不只是处理情感分析,NLTK 有着整套自然语言处理的工具,从分 词到实体识别,从情感分类到句法分析,完整而丰富,功能强大。实乃居家旅行, 越货杀人之必备良药。 两本 NLTK 的参考书,非常好用。一本是《Python 自然语言处理》,这是《Natural Language Processing with Python》的中文翻译版,是志愿者翻译没有出版社 出版的,开源精神万岁!另一本是《Python Text Processing with NLTK 2.0 Cookbook》,这本书写得清晰明了,虽然是英文版的,看起来也很舒服。特别 值得一提的是,该书作者 Jacob 就是 NLTK 包的主要贡献者之一。而且他的博 客中有一系列的文章是关于使用机器学习进行情感分类的,我的代码可以说是完 全基于他的,在此表示我的感谢。
其实还有国外作者也被他启发,用 Python 来处理情感分类。比如这篇文章,写 得特别详细认真,也是我重点参考的文章,他的代码我也有所借用。 Jacob 在文章中也有提到,近段时间 NLTK 新增的 scikit-learn 的接口,使得它 的分类功能更为强大好用了,可以用很多高端冷艳的分类算法了。于是我又滚过 去看 scikit-learn 。简直是天赐我好工具,妈妈再也不用担心我用不了机器学习 啦! 有了 scikit-learn 的接口,NLTK 做分类变得比之前更简单快捷,但是相关的结 合 NLTK 和 sciki-learn 的文章实在少,这篇文章是仅有的讲得比较详细的把两 者结合的,在此也表示感谢。 但对于我而言还是有点不够的,因为中文和英文有一定的差别,而且上面提到的 一些博客里面的代码也是需要改动的。终于把一份代码啃完之后,能写出一个跑 得通的中文情感分类代码了。接下来会介绍它的实现思路和具体代码。 在这个系列的文章里面,机器学习都可以认为是有监督的分类方法。 总体流程如图: 图 1:机器学习的流程和结构(摘自《Natural Language Processing with Python》) 一、有监督意味着需要人工标注,需要人为的给文本一个类标签。 比如我有 5000 条商品评论,如果我要把这些评论分成积极和消极两类。那我就 可以先从里面选 2000 条评论,然后对这 2000 条数据进行人工标注,把这 2000 条评论标为“积极”或“消极”。这“积极”和“消极”就是类标签。
假设有 1000 条评论被标为“积极”,有 1000 条评论被标为“消极”。(两者数量相 同对训练分类器是有用的,如果实际中数量不相同,应该减少和增加数据以使得 它们数量相同) 二、之后就要选择特征。 特征就是分类对象所展现的部分特点,是实现分类的依据。我们经常会做出分类 的行为,那我们依据些什么进行分类呢? 举个例子,如果我看到一个年轻人,穿着新的正装,提着崭新的公文包,快步行 走,那我就会觉得他是一个刚入职的职场新人。在这里面,“崭新”,“正装”,“公 文包”,“快步行走”都是这个人所展现出的特点,也是我用来判断这个人属于哪一 类的依据。这些特点和依据就是特征。可能有些特征对我判断更有用,有些对我 判断没什么用,有些可能会让我判断错误,但这些都是我分类的依据。 我们没办法发现一个人的所有特点,所以我们没办法客观的选择所有特点,我们 只能主观的选择一部分特点来作为我分类的依据。这也是特征选择的特点,需要 人为的进行一定选择。 而在情感分类中,一般从“词”这个层次来选择特征。 比如这句话“手机非常好用!”,我给了它一个类标签“Positive”。里面有四个词(把 感叹号也算上),“手机”,“非常”,“好用”,“!”。我可以认为这 4 个词都对分类 产生了影响,都是分类的依据。也就是无论什么地方出现了这四个词的其中之一, 文本都可以被分类为“积极”。这个是把所有词都作为分类特征。 同样的,对这句话,我也可以选择它的双词搭配(Bigrams)作为特征。比如“手 机 非常”,“非常 好用”,“好用 !”这三个搭配作为分类的特征。以此类推,三 词搭配(Trigrams),四词搭配都是可以被作为特征的。 三、再之后特征要降维。 特征降维说白了就是减少特征的数量。这有两个意义,一个是特征数量减少了之 后可以加快算法计算的速度(数量少了当然计算就快了),另一个是如果用一定 的方法选择信息量丰富的特征,可以减少噪音,有效提高分类的准确率。 所谓信息量丰富,可以看回上面这个例子“手机非常好用!”,很明显,其实不需 要把“手机”,“非常”,“好用”,“!”这 4 个都当做特征,因为“好用”这么一个词, 或者“非常 好用”这么一个双词搭配就已经决定了这个句子是“积极”的。这就是说, “好用”这个词的信息量非常丰富。
那要用什么方法来减少特征数量呢?答案是通过一定的统计方法找到信息量丰 富的特征。 统计方法包括:词频(Term Frequency)、文档频率(Document Frequency)、 互信息(Pointwise Mutual Information)、信息熵(Information Entropy)、卡 方统计(Chi-Square)等等。 在情感分类中,用词频选择特征,也就是选在语料库中出现频率高的词。比如我 可以选择语料库中词频最高的 2000 个词作为特征。用文档频率选特征,是选在 语料库的不同文档中出现频率最高的词。而其它三个,太高端冷艳,表示理解得 还不清楚,暂且不表。。。 不过意思都是一样的,都是要通过某个统计方法选择信息量丰富的特征。特征可 以是词,可以是词组合。 四、把语料文本变成使用特征表示。 在使用分类算法进行分类之前,第一步是要把所有原始的语料文本转化为特征表 示的形式。 还是以上面那句话做例子,“手机非常好用!” 如果在 NLTK 中,如果选择所有词作为特征,其形式是这样的:[ {“手机”: True, “非常”: True, “好用”: True, “!”: True} , positive] 如果选择双词作为特征,其形式是这样的:[ {“手机 非常”: True, “非常 好用”: True, “好用 !”: True} , positive ] 如果选择信息量丰富的词作为特征,其形式是这样的:[ {“好用”: True} , positive ] (NLTK 需要使用字典和数组两个数据类型,True 表示对应的元素是特征。至 于为什么要用 True 这样的方式,我也不知道。。。反正见到的例子都是这样的。。。 有空再研究看是不是可以不这样的吧) 无论使用什么特征选择方法,其形式都是一样的。都是[ {“特征 1”: True, “特征 2”: True, “特征 N”: True, }, 类标签 ] 五、把用特征表示之后的文本分成开发集和测试集,把开发集分成训练集和开发 测试集。 机器学习分类必须有数据给分类算法训练,这样才能得到一个(基于训练数据的) 分类器。
有了分类器之后,就需要检测这个分类器的准确度。 根据《Python 自然语言处理》的方法,数据可以分为开发集合测试集。开发集 专门用于不断调整和发现最佳的分类算法和特征维度(数量),测试集应该一直 保持“不被污染”。在开发集开发完毕之后,再使用测试集检验由开发集确定的最 佳算法和特征维度的效果。具体如图: 图 2:开发集和测试集(摘自《Natural Language Processing with Python》) 一般来说,训练集的数量应该远大于测试集,这样分类算法才能找出里面的规律, 构建出高效的分类器。 用回前面的例子。假设 2000 条已经标注了积极和消极的评论数据,开发集可以 是随机的 1600 条,测试集是剩余的随机 400 条。然后开发集中,训练集可以是 随机的 1400 条,开发测试集是 200 条。 六、用不同的分类算法给训练集构建分类器,用开发测试集检验分类器的准确度 (选出最佳算法后可以调整特征的数量来测试准确度)。 这个时候终于可以使用各种高端冷艳的机器学习算法啦! 我们的目标是:找到最佳的机器学习算法。 可以使用朴素贝叶斯(NaiveBayes),决策树(Decision Tree)等 NLTK 自带 的机器学习方法。也可以更进一步,使用 NLTK 的 scikit-learn 接口,这样就可 以调用 scikit-learn 里面的所有,对,是所有机器学习算法了。我已经忍不住的 泪流满面。 其实方法很容易。只要以下五步。
1. 仅仅使用开发集(Development Set)。 2. 用分类算法训练里面的训练集(Training Set),得出分类器。 3. 用分类器给开发测试集分类(Dev-Test Set),得出分类结果。 4. 对比分类器给出的分类结果和人工标注的正确结果,给出分类器的准确度。 5. 使用另一个分类算法,重复以上三步。 在检验完所有算法的分类准确度之后,就可以选出最好的一个分类算法了。 在选出最好的分类算法之后,就可以测试不同的特征维度对分类准确度的影响了。 一般来说,特征太少则不足以反映分类的所有特点,使得分类准确率低;特征太 多则会引入噪音,干扰分类,也会降低分类准确度。所以,需要不断的测试特征 的数量,这样才可以得到最佳的分类效果。 七、选择出开发集中最佳的分类算法和特征维度,使用测试集检验得出情感分类 的准确度。 在终于得到最佳分类算法和特征维度(数量)之后,就可以动用测试集。 直接用最优的分类算法对测试集进行分类,得出分类结果。对比分类器的分类结 果和人工标注的正确结果,给出分类器的最终准确度。 用 Python 进行机器学习及情感分析,需要用到两个主要的程序包:nltk 和 scikit-learn nltk 主要负责处理特征提取(双词或多词搭配需要使用 nltk 来做)和特征选择 (需要 nltk 提供的统计方法)。 scikit-learn 主要负责分类算法,评价分类效果,进行分类等任务。 接下来会有四篇文章按照以下步骤来实现机器学习的情感分析。 1. 特征提取和特征选择(选择最佳特征) 2. 赋予类标签,分割开发集和测试集 3. 构建分类器,检验分类准确度,选择最佳分类算法 4.存储和使用最佳分类器进行分类,分类结果为概率值 首先是特征提取和选择 一、特征提取方法 1. 把所有词作为特征
def bag_of_words(words): return dict([(word, True) for word in words]) 返回的是字典类型,这是 nltk 处理情感分类的一个标准形式。 2. 把双词搭配(bigrams)作为特征 import nltk from nltk.collocations import BigramCollocationFinder from nltk.metrics import BigramAssocMeasures def bigram(words, score_fn=BigramAssocMeasures.chi_sq, n=1000): bigram_finder = BigramCollocationFinder.from_words(words) #把文本 变成双词搭配的形式 bigrams = bigram_finder.nbest(score_fn, n) #使用了卡方统计的方法, 选择排名前 1000 的双词 return bag_of_words(bigrams) 除了可以使用卡方统计来选择信息量丰富的双词搭配,还可以使用其它的方法, 比如互信息(PMI)。而排名前 1000 也只是人工选择的阈值,可以随意选择其 它值,可经过测试一步步找到最优值。 3. 把所有词和双词搭配一起作为特征 def bigram_words(words, score_fn=BigramAssocMeasures.chi_sq, n=1000): bigram_finder = BigramCollocationFinder.from_words(words) bigrams = bigram_finder.nbest(score_fn, n) return bag_of_words(words + bigrams) #所有词和(信息量大的)双词 搭配一起作为特征 二、特征选择方法 有了提取特征的方法后,我们就可以提取特征来进行分类学习了。但一般来说, 太多的特征会降低分类的准确度,所以需要使用一定的方法,来“选择”出信息量 最丰富的特征,再使用这些特征来分类。
特征选择遵循如下步骤: 1. 计算出整个语料里面每个词的信息量 2. 根据信息量进行倒序排序,选择排名靠前的信息量的词 3. 把这些词作为特征 1. 计算出整个语料里面每个词的信息量 1.1 计算整个语料里面每个词的信息量 from nltk.probability import FreqDist, ConditionalFreqDist def create_word_scores(): posWords = pickle.load(open('D:/code/sentiment_test/pos_review.pkl','r')) negWords = pickle.load(open('D:/code/sentiment_test/neg_review.pkl','r')) posWords = list(itertools.chain(*posWords)) #把多维数组解链成一维 数组 negWords = list(itertools.chain(*negWords)) #同理 word_fd = FreqDist() #可统计所有词的词频 cond_word_fd = ConditionalFreqDist() #可统计积极文本中的词频和消极 文本中的词频 for word in posWords: word_fd.inc(word) cond_word_fd['pos'].inc(word) for word in negWords: word_fd.inc(word) cond_word_fd['neg'].inc(word) pos_word_count = cond_word_fd['pos'].N() #积极词的数量 neg_word_count = cond_word_fd['neg'].N() #消极词的数量 total_word_count = pos_word_count + neg_word_count
分享到:
收藏