前言

本文使用朴素贝叶斯算法实现 豆瓣Top250电影评价的情感分析与预测。

最近在学习自然语言正负面情感的处理问题,但是绝大部分能搜索到的实践都是Kggle上IMDB影评的情感分析。

所以在这里我就用最基础的朴素贝叶斯算法来对豆瓣的影评进行情感分析与预测。

在这里我参考了 https://github.com/aeternae/IMDb_Review,万分感谢。

朴素贝叶斯分类器

贝叶斯分类是一类分类算法的总称,这类算法均以贝叶斯定理为基础,故统称为贝叶斯分类。

这种算法常用来做文章分类,垃圾邮、件垃圾评论分类,朴素贝叶斯的效果不错并且成本很低。

已知某条件概率,如何得到两个事件交换后的概率,也就是在已知P(A|B)的情况下如何求得P(B|A)。

P(B|A)表示事件A已经发生的前提下,事件B发生的概率,叫做事件A发生下事件B的条件概率。

朴素贝叶斯的公式
P ( B ∣ A ) = P ( A ∣ B ) P ( B ) P ( A ) P(B|A) = \frac{P(A|B)P(B)}{P(A)}P(B∣A)=P(A)P(A∣B)P(B)​

一个通俗易懂的视频教程

Youtube https://www.youtube.com/watch?v=AqonCeZUcC4

举个不太恰当的例子

我们想知道做程序员与秃头之间的关系,我们就可以用朴素贝叶斯公式来进行计算。

我们现在想求 P(秃头|做程序员) 的概率, 也就是做程序员就会秃头的概率

我这辈子都不会秃头 (((o(゚▽゚)o))) !!!

代入朴素贝叶斯公式

P ( 秃 头 ∣ 做 程 序 员 ) = P ( 做 程 序 员 ∣ 秃 头 ) P ( 秃 头 ) P ( 做 程 序 员 ) P(秃头|做程序员) = \frac{P(做程序员|秃头)P(秃头)}{P(做程序员)}P(秃头∣做程序员)=P(做程序员)P(做程序员∣秃头)P(秃头)​

已知数据如下表

姓名 职业 是否秃头
奎托斯 战神
杀手47号 杀手
埼玉 超人
灭霸 计生办主任
杰森 斯坦森 硬汉
某某996程序员 程序员
程序员

基于朴素贝叶斯公式,由以上这张表我们可以求出:
P ( 秃 头 ∣ 做 程 序 员 ) = 1 6 ∗ 6 7 2 7 = 21 42 = 1 2 P(秃头|做程序员) = \frac{\frac16 * \frac67}{\frac27} = \frac{21}{42} = \frac{1}{2}P(秃头∣做程序员)=72​61​∗76​​=4221​=21​
上面这个例子就简单的描述了朴素贝叶斯公式的基本用法。

接下来我就使用豆瓣Top250排行榜的影评来使用朴素贝叶斯进行好评与差评的训练与预测。

豆瓣Top250影评情感分析

首先需要豆瓣Top250影评的语料,我用Scrapy抓取了5w份语料,用于训练与验证。

豆瓣影评爬虫 GitHub - 3inchtime/douban_movie_review: 豆瓣Top250影评爬虫(用于情感分析语料)

有了语料之后我们就可以开始实际开发了。

这里建议使用jupyter来开发操作。

以下代码全部在我的Github上可以看到,欢迎大家提出建议。

GitHub - 3inchtime/douban_sentiment_analysis: 基于朴素贝叶斯实现的豆瓣影评情感分析

首先加载语料

# -*- coding: utf-8 -*-
import random
import numpy as np
import csv
import jiebafile_path = './data/review.csv'
jieba.load_userdict('./data/userdict.txt')# 读取保存为csv格式的语料
def load_corpus(corpus_path):with open(corpus_path, 'r') as f:reader = csv.reader(f)rows = [row for row in reader]review_data = np.array(rows).tolist()random.shuffle(review_data)review_list = []sentiment_list = []for words in review_data:review_list.append(words[1])sentiment_list.append(words[0])return review_list, sentiment_list

在训练之前,一般均会对数据集做shuffle,打乱数据之间的顺序,让数据随机化,这样可以避免过拟合。所以使用random.shuffle()方法打乱数据。

jieba.load_userdict('./data/userdict.txt')这里我自己做了一个词典,防止部分结巴分词的不准确,可以提高约1%左右的准确率。

比如不是很喜欢这句,jieba会分成’不是‘,’很喜欢‘两个词,这样导致这句话很大概率会被预测为好评。

所以这里我在自定义的词典中分好了很多类似这样的词,提高了一点点准确率。

然后将全部的语料按1:4分为测试集与训练集

n = len(review_list) // 5train_review_list, train_sentiment_list = review_list[n:], sentiment_list[n:]
test_review_list, test_sentiment_list = review_list[:n], sentiment_list[:n]

分词

使用jieba分词,将语料进行分词,并且去除stopwords。

import re
import jiebastopword_path = './data/stopwords.txt'def load_stopwords(file_path):stop_words = []with open(file_path, encoding='UTF-8') as words:stop_words.extend([i.strip() for i in words.readlines()])return stop_wordsdef review_to_text(review):stop_words = load_stopwords(stopword_path)# 去除英文review = re.sub("[^\u4e00-\u9fa5^a-z^A-Z]", '', review)review = jieba.cut(review)# 去掉停用词if stop_words:all_stop_words = set(stop_words)words = [w for w in review if w not in all_stop_words]return words# 用于训练的评论
review_train = [' '.join(review_to_text(review)) for review in train_review_list]
# 对于训练评论对应的好评/差评
sentiment_train = train_sentiment_list# 用于测试的评论
review_test = [' '.join(review_to_text(review)) for review in test_review_list]
# 对于测试评论对应的好评/差评
sentiment_test = test_sentiment_list

TF*IDF与词频向量化

TF-IDF(是一种常用于信息处理和数据挖掘的加权技术。根据词语的在文本中出现的次数和在整个语料中出现的文档频率来计算一个词语在整个语料中的重要程度。

它的优点是能过滤掉一些常见的却无关紧要本的词语,同时保留影响整个文本的重要字词。

使用Countvectorizer()将一个文档转换为向量,计算词汇在文本中出现的频率。

CountVectorizer类会将文本中的词语转换为词频矩阵,例如矩阵中包含一个元素a[i] [j],它表示j词在i类文本下的词频。它通过fit_transform函数计算各个词语出现的次数。

TfidfTransformer用于统计vectorizer中每个词语的TF-IDF值。

from sklearn.feature_extraction.text import CountVectorizer, TfidfVectorizer
from sklearn.pipeline import Pipeline
from sklearn.naive_bayes import MultinomialNBcount_vec = CountVectorizer(max_df=0.8, min_df=3)tfidf_vec = TfidfVectorizer()# 定义Pipeline对全部步骤的流式化封装和管理,可以很方便地使参数集在新数据集(比如测试集)上被重复使用。
def MNB_Classifier():return Pipeline([('count_vec', CountVectorizer()),('mnb', MultinomialNB())])

max_df 这个参数的作用是作为一个阈值,当构造语料库的关键词集的时候,如果某个词的词频大于max_df,这个词不会被当作关键词。

如果这个参数是float,则表示词出现的次数与语料库文档数的百分比,如果是int,则表示词出现的次数。

min_df类似于max_df,不同之处在于如果某个词的词频小于min_df,则这个词不会被当作关键词

这样我们就成功的构造出了用于训练以及测试的Pipeline

然后用 Pipeline.fit()对训练集进行训练

再直接用 Pipeline.score() 对测试集进行预测并评分

mnbc_clf = MNB_Classifier()# 进行训练
mnbc_clf.fit(review_train, sentiment_train)# 测试集准确率
print('测试集准确率: {}'.format(mnbc_clf.score(review_test, sentiment_test)))

这样我们就完成了整个从训练到测试的全部流程。

基本上测试集的正确率在79%-80%左右。

因为电影评论中有很大一部分好评中会有负面情感的词语,例如在纪录片《海豚湾》中

我觉得大部分看本片会有感的人,都不知道,中国的白暨豚已经灭绝8年了,也不会知道,长江里的江豚也仅剩1000左右了。与其感慨,咒骂日本人如何捕杀海豚,不如做些实际的事情,保护一下长江里的江豚吧,没几年,也将绝迹了。中国人做出来的事情,也不会比小日本好到哪儿去。

所以说如果将这种类似的好评去除,则可以提高准确率。

保存训练好的模型

# 先转换成词频矩阵,再计算TFIDF值
tfidf = tfidftransformer.fit_transform(vectorizer.fit_transform(review_train))
# 朴素贝叶斯中的多项式分类器
clf = MultinomialNB().fit(tfidf, sentiment_train)with open(model_export_path, 'wb') as file:d = {"clf": clf,"vectorizer": vectorizer,"tfidftransformer": tfidftransformer,}pickle.dump(d, file)

使用训练好的模型进行影评情感预测

这里我直接贴上全部的源代码,代码非常简单,我将整个处理逻辑封装为一个类,这样就非常方便使用了。

有需要直接可以在我的Github上clone

# -*- coding: utf-8 -*-
import re
import pickleimport numpy as np
import jiebaclass SentimentAnalyzer(object):def __init__(self, model_path, userdict_path, stopword_path):self.clf = Noneself.vectorizer = Noneself.tfidftransformer = Noneself.model_path = model_pathself.stopword_path = stopword_pathself.userdict_path = userdict_pathself.stop_words = []self.tokenizer = jieba.Tokenizer()self.initialize()# 加载模型def initialize(self):with open(self.stopword_path, encoding='UTF-8') as words:self.stop_words = [i.strip() for i in words.readlines()]with open(self.model_path, 'rb') as file:model = pickle.load(file)self.clf = model['clf']self.vectorizer = model['vectorizer']self.tfidftransformer = model['tfidftransformer']if self.userdict_path:self.tokenizer.load_userdict(self.userdict_path)# 过滤文字中的英文与无关文字def replace_text(self, text):text = re.sub('((https?|ftp|file)://)?[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|].(com|cn)', '', text)text = text.replace('\u3000', '').replace('\xa0', '').replace('”', '').replace('"', '')text = text.replace(' ', '').replace('↵', '').replace('\n', '').replace('\r', '').replace('\t', '').replace(')', '')text_corpus = re.split('[!。?;……;]', text)return text_corpus# 情感分析计算def predict_score(self, text_corpus):# 分词docs = [self.__cut_word(sentence) for sentence in text_corpus]new_tfidf = self.tfidftransformer.transform(self.vectorizer.transform(docs))predicted = self.clf.predict_proba(new_tfidf)# 四舍五入,保留三位result = np.around(predicted, decimals=3)return result# jieba分词def __cut_word(self, sentence):words = [i for i in self.tokenizer.cut(sentence) if i not in self.stop_words]result = ' '.join(words)return resultdef analyze(self, text):text_corpus = self.replace_text(text)result = self.predict_score(text_corpus)neg = result[0][0]pos = result[0][1]print('差评: {} 好评: {}'.format(neg, pos))

使用时只要实例化这个分析器,并使用analyze()方法就可以了。

# -*- coding: utf-8 -*-
from native_bayes_sentiment_analyzer import SentimentAnalyzermodel_path = './data/bayes.pkl'
userdict_path = './data/userdict.txt'
stopword_path = './data/stopwords.txt'
corpus_path = './data/review.csv'analyzer = SentimentAnalyzer(model_path=model_path, stopword_path=stopword_path, userdict_path=userdict_path)
text = '倍感失望的一部诺兰的电影,感觉更像是盗梦帮的一场大杂烩。虽然看之前就知道肯定是一部无法超越前传2的蝙蝠狭,但真心没想到能差到这个地步。节奏的把控的失误和角色的定位模糊绝对是整部影片的硬伤。'
analyzer.analyze(text=text)

朴素贝叶斯算法实现 豆瓣Top250电影评价的情感分析与预测。​相关推荐

  1. ML之NB:基于NB朴素贝叶斯算法训练20类新闻文本数据集进行多分类预测

    ML之NB:基于NB朴素贝叶斯算法训练20类新闻文本数据集进行多分类预测 目录 输出结果 设计思路 核心代码 输出结果 设计思路 核心代码 vec = CountVectorizer() X_trai ...

  2. 【机器学习入门】(2) 朴素贝叶斯算法:原理、实例应用(文档分类预测)附python完整代码及数据集

    各位同学好,今天我向大家介绍python机器学习中的朴素贝叶斯算法.内容有:算法的基本原理:案例实战--新闻文档的分类预测. 案例简介:新闻数据有20个主题,有10万多篇文章,每篇文章对应不同的主题, ...

  3. 朴素贝叶斯算法——文本分类(离散型)

    朴素贝叶斯算法:按照概率分类的算法. 我们在豆瓣上经常能看到一些书籍和电影评价,有好的评价,也有差评. 关于影评好坏的结果是怎么来的呢?后台小姐姐一条条的看,然后进行分类吗?利用我们的朴素贝叶斯算法, ...

  4. 算法的优缺点_朴素贝叶斯算法的优缺点

      机器学习算法与自然语言处理推荐  来源:http://www.cnblogs.com/pinard/p/6069267.html 作者:刘建平Pinard [机器学习算法与自然语言处理导读]朴素贝 ...

  5. 朴素贝叶斯算法实现垃圾邮件过滤(Python3实现)

    目录 1.朴素贝叶斯实现垃圾邮件分类的步骤 2.邮件数据 3.代码实现 4.朴素贝叶斯的优点和缺点 1.朴素贝叶斯实现垃圾邮件分类的步骤 (1)收集数据:提供文本文件. (2)准备数据:将文本文件解析 ...

  6. 机器学习(8)朴素贝叶斯算法(20条新闻分类)

    目录 一.基础理论 二.实战:20条新闻分类 1.读取数据 2.训练集划分 3.特征工程(文本特征提取) 4.朴素贝叶斯算法训练 5.模型评估 方法一:预测值与真实值比对 方法二:计算准确率 总代码 ...

  7. 【机器学习入门】(3) 朴素贝叶斯算法:多项式、高斯、伯努利,实例应用(心脏病预测)附python完整代码及数据集

    各位同学好,今天我和大家分享一下朴素贝叶斯算法中的三大模型.在上一篇文章中,我介绍了朴素贝叶斯算法的原理,并利用多项式模型进行了文本分类预测. 朴素贝叶斯算法 -- 原理,多项式模型文档分类预测,附p ...

  8. 朴素贝叶斯算法的python实现

    朴素贝叶斯 算法优缺点 优点:在数据较少的情况下依然有效,可以处理多类别问题 缺点:对输入数据的准备方式敏感 适用数据类型:标称型数据 算法思想: 朴素贝叶斯 比如我们想判断一个邮件是不是垃圾邮件,那 ...

  9. 文本分类的基本思想和朴素贝叶斯算法原理

    文本分类的基本思想和朴素贝叶斯算法原理

最新文章

  1. 揭秘物联网之城无锡鸿山的科技密码
  2. linux实战应用案例: 777 权限表示什么,各数字又是什么含义?
  3. WPF整理-为User Control添加依赖属性
  4. (三)CSS【不多说了,前端面试 CSS 是必考知识,不过关直接回家】
  5. 程序员修神之路--高并发下如何缩短响应时间
  6. Linux用户管理命令详解,useradd、passwd
  7. qt 无框dockwidget_QT解决通过菜单方式无法让QDockWidget 显示和隐藏
  8. Makefile中的ifeq 多条件使用 ***
  9. python字符串转成数组_python将字符串转换成数组的方法
  10. 学习笔记——正则匹配方法整理
  11. java中用socket实现简单的单工通信
  12. ie9服务器win2008系统离线安装包,IE9离线安装包完整版
  13. ToStringBuilder使用
  14. java word模板 变量,Java-POI替换Word模板文档中的变量,生成Word文档
  15. HtmlEditor在线编辑器V3.0提供
  16. mysql数据库修改密码
  17. Fiddler教程系列—介绍【必看】
  18. 关于 uintptr_t和intptr_t 类型
  19. 通达信转MT4怎么弄
  20. 如何从八字中看“从医”之人

热门文章

  1. Ubuntu-QQ2013
  2. 中国海洋大学计算机调剂名单,中国海洋大学2017年接收硕士调剂考生的通知
  3. Python的random函数用法详解
  4. 开放性兼容短信邮件接口,支持各种语言接入的短信邮件平台-kewail
  5. window下键盘监控api函数详解
  6. python 生成动态库_Python 项目转.so动态库
  7. 数字验证码的识别(一)
  8. 什么是网络存储技术?DAS、NAS、SAN、IP-SAN,主要内容分别是什么?
  9. solidwors中装配图视图是斜的处理办法
  10. 降血压的药有哪些?使用注意事项有哪些