豆瓣电影为互联网用户提供了一个可以分享电影评论及观点的平台。用户在提供影评的同时还可以为电影打分。
数据字典
# 引入必要的包
import csv
import os
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import time
%matplotlib notebook
# 解决matplotlib显示中文问题
# 仅适用于Windows
plt.rcParams['font.sans-serif'] = ['SimHei'] # 指定默认字体
plt.rcParams['axes.unicode_minus'] = False # 解决保存图像是负号'-'显示为方块的问题
# MacOS请参考 http://wenda.chinahadoop.cn/question/5304 修改字体配置
# 指定数据集路径
dataset_path = '../data'
datafile = os.path.join(dataset_path, 'DMSC.csv')
# 停用词表路径
stop_words_path = '../stop_words'
# 加载数据
raw_data = pd.read_csv(datafile)
print('数据集有{}条记录。'.format(len(raw_data)))
数据集有2125056条记录。
# 电影名称
print('数据集包含{}部电影。'.format(len(raw_data['Movie_Name_CN'].unique())))
print(raw_data['Movie_Name_CN'].unique())
数据集包含28部电影。
['复仇者联盟2' '大鱼海棠' '美国队长3' '十二生肖' '九层妖塔' '大圣归来' '栀子花开' '夏洛特烦恼' '钢铁侠1' '西游降魔篇'
'西游伏妖篇' '爱乐之城' '泰囧' '何以笙箫默' '湄公河行动' '七月与安生' '复仇者联盟' '后会无期' '寻龙诀' '长城' '左耳'
'美人鱼' '小时代1' '小时代3' '釜山行' '变形金刚4' '你的名字' '疯狂动物城']
# 电影平均得分
movie_mean_score = raw_data.groupby('Movie_Name_CN')['Star'].mean().sort_values(ascending=False)
movie_mean_score.plot(kind='bar')
plt.tight_layout()
<IPython.core.display.Javascript object>
# 去除空值(如果有的话)
cln_data = raw_data.dropna().copy()
# 建立新的一列,如果打分>=3.0,为正面评价1,否则为负面评价0
cln_data['Positively Rated'] = np.where(cln_data['Star'] >= 3, 1, 0)
# 数据预览
cln_data.head()
ID | Movie_Name_EN | Movie_Name_CN | Crawl_Date | Number | Username | Date | Star | Comment | Like | Positively Rated | |
---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | Avengers Age of Ultron | 复仇者联盟2 | 2017-01-22 | 1 | 然潘 | 2015-05-13 | 3 | 连奥创都知道整容要去韩国。 | 2404 | 1 |
1 | 1 | Avengers Age of Ultron | 复仇者联盟2 | 2017-01-22 | 2 | 更深的白色 | 2015-04-24 | 2 | 非常失望,剧本完全敷衍了事,主线剧情没突破大家可以理解,可所有的人物都缺乏动机,正邪之间、... | 1231 | 0 |
2 | 2 | Avengers Age of Ultron | 复仇者联盟2 | 2017-01-22 | 3 | 有意识的贱民 | 2015-04-26 | 2 | 2015年度最失望作品。以为面面俱到,实则画蛇添足;以为主题深刻,实则老调重弹;以为推陈出... | 1052 | 0 |
3 | 3 | Avengers Age of Ultron | 复仇者联盟2 | 2017-01-22 | 4 | 不老的李大爷耶 | 2015-04-23 | 4 | 《铁人2》中勾引钢铁侠,《妇联1》中勾引鹰眼,《美队2》中勾引美国队长,在《妇联2》中终于... | 1045 | 1 |
4 | 4 | Avengers Age of Ultron | 复仇者联盟2 | 2017-01-22 | 5 | ZephyrO | 2015-04-22 | 2 | 虽然从头打到尾,但是真的很无聊啊。 | 723 | 0 |
# 加载停用词表
stopwords1 = [line.rstrip() for line in open(os.path.join(stop_words_path, '中文停用词库.txt'), 'r', encoding='utf-8')]
stopwords2 = [line.rstrip() for line in open(os.path.join(stop_words_path, '哈工大停用词表.txt'), 'r', encoding='utf-8')]
stopwords3 = [line.rstrip() for line in open(os.path.join(stop_words_path, '四川大学机器智能实验室停用词库.txt'), 'r', encoding='utf-8')]
stopwords = stopwords1 + stopwords2 + stopwords3
# 处理文本数据
import re
import jieba.posseg as pseg
def proc_text(raw_line):
"""
处理文本数据
返回分词结果
"""
# 1. 使用正则表达式去除非中文字符
filter_pattern = re.compile('[^\u4E00-\u9FD5]+')
chinese_only = filter_pattern.sub('', raw_line)
# 2. 结巴分词+词性标注
word_list = pseg.cut(chinese_only)
# 3. 去除停用词,保留有意义的词性
# 动词,形容词,副词
used_flags = ['v', 'a', 'ad']
meaninful_words = []
for word, flag in word_list:
#
if (word not in stopwords) and (flag in used_flags):
meaninful_words.append(word)
return ' '.join(meaninful_words)
# 测试一条记录
test_text = cln_data.loc[5, 'Comment']
print('原文本:', test_text)
print('\n\n处理后:', proc_text(test_text))
原文本: 剧情不如第一集好玩了,全靠密集笑点在提神。僧多粥少的直接后果就是每部寡姐都要换着队友谈恋爱,这特么比打斗还辛苦啊,真心求放过~~~(结尾彩蛋还以为是洛基呢,结果我呸!)
处理后: 好玩 全 提神 直接 换 谈恋爱 打斗 辛苦 求 放过
# 处理数据集中的所有文本
cln_data['Words'] = cln_data['Comment'].apply(proc_text)
cln_data.head()
ID | Movie_Name_EN | Movie_Name_CN | Crawl_Date | Number | Username | Date | Star | Comment | Like | Positively Rated | Words | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | Avengers Age of Ultron | 复仇者联盟2 | 2017-01-22 | 1 | 然潘 | 2015-05-13 | 3 | 连奥创都知道整容要去韩国。 | 2404 | 1 | 知道 |
1 | 1 | Avengers Age of Ultron | 复仇者联盟2 | 2017-01-22 | 2 | 更深的白色 | 2015-04-24 | 2 | 非常失望,剧本完全敷衍了事,主线剧情没突破大家可以理解,可所有的人物都缺乏动机,正邪之间、... | 1231 | 0 | 失望 完全 没 理解 缺乏 正邪 团结 分裂 团结 积攒 搞 出 写 肤浅 混乱 笑 点算 |
2 | 2 | Avengers Age of Ultron | 复仇者联盟2 | 2017-01-22 | 3 | 有意识的贱民 | 2015-04-26 | 2 | 2015年度最失望作品。以为面面俱到,实则画蛇添足;以为主题深刻,实则老调重弹;以为推陈出... | 1052 | 0 | 失望 不足 全 明显 刻意 紧张 激动 太弱 |
3 | 3 | Avengers Age of Ultron | 复仇者联盟2 | 2017-01-22 | 4 | 不老的李大爷耶 | 2015-04-23 | 4 | 《铁人2》中勾引钢铁侠,《妇联1》中勾引鹰眼,《美队2》中勾引美国队长,在《妇联2》中终于... | 1045 | 1 | 勾引 勾引 勾引 表白 告诉 治疗 不孕 不育 作战 变成 验孕 棒 坚决 相信 快 死 回来 |
4 | 4 | Avengers Age of Ultron | 复仇者联盟2 | 2017-01-22 | 5 | ZephyrO | 2015-04-22 | 2 | 虽然从头打到尾,但是真的很无聊啊。 | 723 | 0 | 打到 无聊 |
# 将处理后的数据集保存
saved_data = cln_data[['Words', 'Positively Rated']].copy()
saved_data.dropna(subset=['Words'], inplace=True)
saved_data.to_csv(os.path.join(dataset_path, 'douban_cln_data.csv'), encoding='utf-8', index=False)
# 分割训练集与测试集
from sklearn.model_selection import train_test_split
X_train_data, X_test_data, y_train, y_test = train_test_split(saved_data['Words'], saved_data['Positively Rated'], test_size=1/4, random_state=0)
X_train_data.shape
(1593724,)
print('X__train_data 第一条记录:\n\n', X_train_data.iloc[1])
print('\n\n训练集样本数: {},测试集样本数:{}'.format(len(X_train_data), len(X_test_data)))
X__train_data 第一条记录:
讨厌
训练集样本数: 1593724,测试集样本数:531242
from sklearn.feature_extraction.text import TfidfVectorizer
# max_features指定语料库中频率最高的词
n_dim = 10000
vectorizer = TfidfVectorizer(max_features=n_dim)
X_train = vectorizer.fit_transform(X_train_data.values)
X_test = vectorizer.transform(X_test_data.values)
X_train.shape
(1593724, 10000)
print('特征维度:', len(vectorizer.get_feature_names()))
print('语料库中top{}的词:'.format(n_dim))
vectorizer.get_feature_names()
特征维度: 10000
语料库中top10000的词:
['一乐',
'一亮',
'一大',
'一惊',
'一星',
'一昧',
'一晃',
'一烂',
'一爽',
'一笑',
'一观',
'万般',
'上么',
'上乘',
'上买',
'上交',
'上任',
'上传',
'上作',
'上做',
'上写',
'上分',
'上到',
'上刷',
'上加',
'上劲',
'上升',
'上吊',
'上吹',
'上唱',
'上头',
'上好',
'上少',
'上差',
'上床',
'上当',
'上得',
'上心',
'上快',
'上成',
'上手',
'上扬',
'上找',
'上放',
'上映',
'上有',
'上气',
'上涨',
'上演',
'上火',
'上班',
'上用',
'上瘾',
'上看',
'上空',
'上笑',
'上算',
'上给',
'上缴',
'上网',
'上能',
'上船',
'上装',
'上见',
'上说',
'上课',
'上身',
'上过',
'上进',
'上道',
'上钩',
'上阵',
'上限',
'上集',
'上靠',
'上风',
'下不去',
'下乡',
'下令',
'下会',
'下作',
'下來',
'下决心',
'下凡',
'下到',
'下咽',
'下嘴',
'下回',
'下坠',
'下墓',
'下大',
'下好',
'下小',
'下属',
'下得',
'下心',
'下意识',
'下手',
'下拍',
'下斗',
'下映',
'下有',
'下架',
'下档',
'下棋',
'下楼',
'下水',
'下泪',
'下流',
'下滑',
'下班',
'下用',
'下看',
'下笔',
'下给',
'下能',
'下落',
'下让',
'下讲',
'下课',
'下贱',
'下足',
'下跪',
'下车',
'下载',
'下达',
'下过',
'下降',
'下限',
'下集',
'下雨',
'下雪',
'下饭',
'下马',
'不上',
'不中',
'不为',
'不久',
'不乏',
'不乱',
'不予',
'不亏',
'不亚于',
'不休',
'不似',
'不低',
'不住',
'不作',
'不俗',
'不信',
'不倦',
'不假',
'不像',
'不入',
'不关',
'不冷',
'不准',
'不减',
'不出',
'不出意外',
'不利',
'不利于',
'不到',
'不刷',
'不剩',
'不功',
'不加',
'不动',
'不卖',
'不厌',
'不厚',
'不去',
'不受',
'不变',
'不可',
'不吃',
'不合',
'不吝',
'不和',
'不善',
'不喜',
'不回',
'不困',
'不在',
'不均',
'不坏',
'不堪',
'不复',
'不多',
'不够',
'不夠',
'不太好',
'不失',
'不失为',
'不好受',
'不好意思',
'不好玩',
'不妙',
'不妥',
'不孕',
'不孝',
'不安',
'不完',
'不宜',
'不小',
'不屈',
'不屑',
'不差',
'不幸',
'不应',
'不开',
'不弃',
'不弱',
'不强',
'不得劲',
'不得好死',
'不忍',
'不急',
'不怪',
'不息',
'不悔',
'不惜',
'不想',
'不愧',
'不愧为',
'不愿',
'不慢',
'不懂',
'不懈',
'不报',
'不换',
'不掉',
'不放',
'不敌',
'不救',
'不教',
'不散',
'不无',
'不明',
'不易',
'不显',
'不景气',
'不服',
'不朽',
'不来',
'不枉',
'不死',
'不毁',
'不水',
'不求',
'不活',
'不演',
'不火',
'不灭',
'不灵',
'不烂',
'不烦',
'不烧',
'不熟',
'不燃',
'不爱',
'不爽',
'不犯',
'不理',
'不甘',
'不生',
'不用',
'不由',
'不畏',
'不留',
'不痛',
'不白',
'不看',
'不着',
'不知',
'不破',
'不硬',
'不祥',
'不离',
'不稳',
'不笑',
'不符',
'不算',
'不糙',
'不累',
'不纯',
'不给',
'不缺',
'不羁',
'不美',
'不耐烦',
'不耻',
'不聊',
'不肯',
'不胖',
'不腻',
'不良',
'不落',
'不虐',
'不虚',
'不行',
'不装',
'不见',
'不解',
'不计',
'不认',
'不讨',
'不让',
'不评',
'不该',
'不详',
'不谈',
'不谢',
'不负',
'不败',
'不贵',
'不费',
'不赖',
'不足',
'不足以',
'不躁',
'不轻',
'不进',
'不违',
'不迷',
'不适',
'不选',
'不逊',
'不通',
'不造',
'不過',
'不配',
'不酷',
'不醒',
'不重',
'不錯',
'不错',
'不长',
'不闷',
'不闹',
'不雷',
'不露',
'不靠',
'不顺',
'不顾',
'不高',
'丑恶',
'丑爆',
'丑陋',
'专注',
'专访',
'丢下',
'丢人',
'丢到',
'丢失',
'丢弃',
'丢掉',
'丢脸',
'丢进',
'两拨',
'严厉',
'严密',
'严峻',
'严格',
'严肃',
'严苛',
'严谨',
'严重',
'丧命',
'丧失',
'丧生',
'丧病',
'个人爱好',
'个大',
'个爽',
'丰厚',
'丰富',
'丰沛',
'丰满',
'丰盈',
'丰盛',
'串到',
'串成',
'串接',
'串烧',
'串起',
'串连',
'临别',
'临危',
'临场感',
'临摹',
'临死',
'临近',
'为主',
'为先',
'为名',
'为救',
'为爱',
'为生',
'为辅',
'为重',
'为难',
'为首',
'主叫',
'主宰',
'主得',
'主持',
'主讲',
'举办',
'举动',
'举手',
'举报',
'举止',
'举起',
'久违',
'乏力',
'乏味',
'乐乐',
'乐于',
'乐得',
'乐观',
'乐视',
'乐趣',
'乖巧',
'乖张',
'乖戾',
'乘坐',
'习惯于',
'买下',
'买不到',
'买不起',
'买买',
'买到',
'买卖',
'买好',
'买得起',
'买成',
'买来',
'买账',
'买错',
'乱世',
'乱入',
'乱写',
'乱加',
'乱发',
'乱叫',
'乱战',
'乱打',
'乱扯',
'乱搞',
'乱改',
'乱来',
'乱舞',
'乱讲',
'乱说',
'乱跑',
'乱造',
'乱飞',
'了上',
'了下',
'了不得',
'了不起',
'了为',
'了买',
'了了',
'了于',
'了以',
'了会',
'了倒',
'了值',
'了假',
'了做',
'了像',
'了写',
'了冲',
'了减',
'了出',
'了分',
'了别',
'了到',
'了刷',
'了前',
'了剧',
'了加',
'了卖',
'了去',
'了反',
'了变',
'了叫',
'了吐',
'了向',
'了听',
'了呆',
'了和',
'了哭',
'了哮',
'了啸',
'了噜',
'了回',
'了坏',
'了复',
'了够',
'了大',
'了头',
'了好',
'了完',
'了害',
'了对',
'了少',
'了差',
'了开',
'了张',
'了当',
'了得',
'了心',
'了忘',
'了快',
'了念',
'了怒',
'了怪',
'了恩',
'了想',
'了愿',
'了成',
'了手',
'了打',
'了扣',
'了找',
'了抖',
'了拍',
'了换',
'了撑',
'了放',
'了有',
'了来',
'了欠',
'了死',
'了毁',
'了比',
'了求',
'了没',
'了泪',
'了演',
'了漫',
'了灭',
'了烂',
'了然',
'了爱',
'了爽',
'了版',
'了生',
'了用',
'了留',
'了略',
'了白',
'了直',
'了看',
'了睡',
'了祝',
'了票',
'了穿',
'了笑',
'了等',
'了算',
'了结',
'了给',
'了能',
'了致',
'了苏',
'了虐',
'了行',
'了补',
'了装',
'了要',
'了视',
'了解',
'了触',
'了言',
'了让',
'了讲',
'了论',
'了说',
'了请',
'了赞',
'了车',
'了过',
'了近',
'了违',
'了连',
'了选',
'了长',
'了门',
'了非',
'了靠',
'了顾',
'了额',
'了高',
'予以',
'予死',
'予演',
'争取',
'争吵',
'争夺',
'争执',
'争论',
'争辩',
'争锋',
'二愣子',
'亏了',
'亏得',
'亏心',
'亏欠',
'亏死',
'互助',
'互打',
'互损',
'互换',
'互換',
'互殴',
'互生',
'互穿',
'互虐',
'互补',
'些小',
'亡命',
'亢奋',
'交互',
'交出',
'交到',
'交叠',
'交往',
'交待',
'交战',
'交换',
'交接',
'交換',
'交替',
'交给',
'交谈',
'交足',
'交错',
'交集',
'亦可',
'产出',
'享受',
'享用',
'亮丽',
'亮出',
'亮起',
'亲切',
'亲密',
'亲测',
'亲爱',
'亵渎',
'仅供',
'仅凭',
'仅剩',
'仅存',
'仅限',
'仅靠',
'仇杀',
'介么',
'介入',
'介意',
'介绍',
'从事',
'从到',
'从容',
'仓促',
'仔细',
'仗义',
'付出',
'付费',
'付钱',
'代替',
'令人咋舌',
'以待',
'以求',
'以示',
'以致于',
'仰头',
'仰慕',
'仰拍',
'仰望',
'仰视',
'任意',
'仿照',
'仿若',
'企及',
'休假',
'休息',
'休闲',
'优于',
'优劣',
'优异',
'优秀',
'优美',
'优越',
'优酷',
'优雅',
'会变',
'伟大',
'传出',
'传到',
'传唱',
'传得',
'传承',
'传来',
'传给',
'传达',
'传送',
'传递',
'传销',
'传阅',
'伤亡',
'伤到',
'伤及',
'伤害',
'伤悲',
'伤痛',
'伤透',
'伪善',
'伪装',
'估摸',
'估計',
'估计',
'伴奏',
'伴有',
'伴舞',
'伴随',
'伸出',
'伸出手',
'伸向',
'伸手',
'伺候',
'位于',
'位置',
'低下',
'低于',
'低估',
'低俗',
'低到',
'低劣',
'低成',
'低沉',
'低能',
'低落',
'低调',
'低贱',
'低迷',
'低配',
'低龄化',
'体现',
'体能',
'体谅',
'何求',
'何谈',
'作不',
'作作',
'作出',
'作到',
'作去',
'作呕',
'作大',
'作好',
'作对',
'作得',
'作怪',
'作恶',
'作成',
'作战',
'作打',
'作有',
'作来',
'作死',
'作比',
'作為',
'作用',
'作看',
'作祟',
'作笑',
'作给',
'作罢',
'作能',
'作要',
'作让',
'作证',
'作赞',
'作践',
'作逼',
'作陪',
'佩戴',
'佩服',
'使出',
'使劲',
'使命',
'使然',
'使用',
'例外',
'例行',
'供养',
'依偎',
'依恋',
'依托',
'依赖',
'依附',
'依靠',
'侠大',
'侠好',
'侠要',
'侥幸',
'侦探',
'侦查',
'侦破',
'侧漏',
'侧重',
'侮辱',
'侵入',
'侵占',
'侵犯',
'侵略',
'侵蚀',
'侵袭',
'便宜',
'便当',
'便成',
'便是',
'便秘',
'促使',
'促成',
'促进',
'俊俏',
'俊美',
'俏皮',
'俗世',
'俗到',
'俗烂',
'俗称',
'俗透',
'俘获',
'保住',
'保佑',
'保全',
'保养',
'保卫',
'保命',
'保存',
'保守',
'保护',
'保持',
'保有',
'保洁',
'保留',
'保護',
'保证',
'保重',
'保障',
'信不信',
'信奉',
'俨然',
'修为',
'修养',
'修复',
'修好',
'修得',
'修成',
'修改',
'修来',
'修炼',
'修行',
'修补',
'修长',
'修饰',
'俯冲',
'俯拍',
'俯瞰',
'俯视',
'俱佳',
'俱全',
'倍受',
'倍增',
'倒下',
'倒像',
'倒叙',
'倒吸',
'倒塌',
'倒好',
'倒戈',
'倒成',
'倒扣',
'倒斗',
'倒流',
'倒灌',
'倒置',
'倒胃',
'倒腾',
'倒贴',
'倒转',
'倒退',
'倒闭',
'倒霉',
'倔强',
'候选',
'借助',
'借来',
'借用',
'借鉴',
'借钱',
'倡导',
'倦怠',
'值会',
'值分',
'值回',
'值当',
'值得',
'值得纪念',
'值钱',
'值高',
'倾倒',
'倾向',
'倾听',
'倾尽',
'倾慕',
'倾斜',
'倾注',
'倾泻',
'倾诉',
'假到',
'假发',
'假意',
'假扮',
'假死',
'假笑',
'偏低',
'偏僻',
'偏弱',
'偏执',
'偏激',
'偏爱',
'偏离',
'偏袒',
'偏要',
'偏見',
'偏见',
'偏重',
'偏高',
'做不了',
'做为',
'做主',
'做事',
'做作',
'做做',
'做出',
'做到',
'做好',
'做工',
'做得好',
'做戏',
'做成',
'做有',
'做梦',
'做法',
'做爱',
'做生意',
'做起',
'做足',
'做错',
'做饭',
'停下',
'停下来',
'停不下',
'停不下来',
'停不住',
'停住',
'停停',
'停在',
'停歇',
'停止',
'停滞',
'停电',
'停留',
'停车',
'停过',
'停顿',
'健全',
'健壮',
'健康',
'健忘',
'健美',
'健身',
'偷师',
'偷情',
'偷懒',
'偷拍',
'偷来',
'偷盗',
'偷看',
'偷窃',
'偷窥',
'偷笑',
...]
from sklearn.linear_model import LogisticRegression
lr_model = LogisticRegression(C=100)
lr_model.fit(X_train, y_train)
LogisticRegression(C=100, class_weight=None, dual=False, fit_intercept=True,
intercept_scaling=1, max_iter=100, multi_class='ovr', n_jobs=1,
penalty='l2', random_state=None, solver='liblinear', tol=0.0001,
verbose=0, warm_start=False)
from sklearn.metrics import roc_auc_score
predictions = lr_model.predict(X_test)
print('AUC: ', roc_auc_score(y_test, predictions))
AUC: 0.580560892439