背景
《少年的你》这部国产青春剧影响还是蛮大的,票房达到了14亿,从票房上看,这部电影在大陆制作的青春剧中比较成功,演员:易烊千玺+周冬雨,当然会引起一些流量效应,但是许多演员对这部电影的剧情、演员的演技评价颇好,包括自己的姐姐也非常喜欢;同时它也陷入了抄袭东野圭吾的《白夜行》和《嫌疑人X的献身》的热议,引起许多原著粉丝的不满。下面就利用逻辑回归(LogisticRegression)对《少年的你》的一些短评进行情感分析,看一看已经观影的人对这部电影的评价如何。
获取数据
数据是从豆瓣电影——《少年的你》短评上获取的
虽说图中显示的有220200条短评,我却只爬取到600条,但当一个小的数据集样本也是足够的
爬虫过程并不难,不再过多概述
处理数据
需要的库和工具
import pandas as pd
import jieba
import re
工具:jupyter notebook
数据整理
数据读取如下图
数据内容:名字,短评,评价
由于爬取的短评内容分为500个样本和100个样本,所以需要先将两个数据集整合成一个数据集
利用pandas的merge方法即可
在rating这一列中,数据还是列表格式,可观性也比较差,很容易能推断出10-50分为五个等级,也就是我们在网页上看到的几星评价,为了分析便利,可以写一个函数将rating分为1-5五个等级
def rating(e):
if '50' in e:
return 5
elif '40' in e:
return 4
elif '30' in e:
return 3
elif '20' in e:
return 2
else:
return 1
data['new_rating'] = data['rating'].map(rating)
data.head()
运行后数据如下图
那么问题又来了,对于评价只有好评和坏差评之分,可是rating有五个等级怎么办呢?
可以先将三星评价删去,因为这些评价大概率为中性评价,然后将四星和五星定为好评,用1表示;再将一星和二星定位差评,用-1表示
new_data = data[data['new_rating']!=3]
new_data['sentiment'] = new_data['new_rating'].apply(lambda x : +1 if x>3 else -1)
new_data
样本只剩下557个,说明有43个三星中性评价被删去
好评和差评的比率大约为3.5:1,可以看出喜欢这部电影的人还是比较多的
但是样本也出现了样本不均衡的问题,这会对后期建模有一定的影响
怎么判定一句短评是好还是差? |
我喜欢你 | 我讨厌你 |
---|---|---|
喜欢 | 讨厌 |
不就可以根据一句话中的一些单词进行判断嘛,所以下一步用jieba库对每一条短评进行分词
在分词前我们可以先分析一下文本,里面会有许多对情感分析没有影响的内容,比如数字和字母,所以分词时可以将其剔除
#分词
def cut_word(text):
text = jieba.cut(str(text),cut_all=False)
return ' '.join(text)
new_data['new_short'] = new_data['short'].apply(cut_word)
#剔除数字
def remove_num(new_short):
return re.sub(r'\d+','',new_short)
#剔除字母
def remove_word(new_short):
return re.sub(r'[a-z]+','',new_short)
new_data['new_short'] = new_data['new_short'].apply(remove_num)
new_data['new_short'] = new_data['new_short'].apply(remove_word)
分词效果如下
文本中就可以看到一些带有个人情感的单词,比如无私奉献,矫情等等
逻辑回归建模
需要的库
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.linear_model import LogisticRegression
import numpy as np
from pandas import DataFrame
分析与建模
第一步需要对分析好的数据进行数据划分,分为训练集和测试集
train_data,test_data = train_test_split(new_data,train_size = 0.8,random_state = 0)
#文本提取
transfer = CountVectorizer()
train_word = transfer.fit_transform(train_data['new_short'])
test_word = transfer.transform(test_data['new_short'])
#稀疏矩阵
print('new_data:\n',train_word.toarray())
#特征值
print('feature_name:\n',transfer.get_feature_names())
第二步对分词后的文本进行特征值提取,可以生成一个对应的稀疏矩阵,并且得到稀疏矩阵对应的特征值
第三步利用逻辑回归建模,即让训练集中的特征值和目标值进行拟合,从而生成一个模型
x_train,x_test,y_train,y_test = train_test_split(new_data['new_short'],new_data['sentiment'],train_size = 0.8,random_state = 0)
x_train = train_word
x_test = test_word
model = LogisticRegression()
model.fit(x_train,y_train)
y_predict = model.predict(x_test)
print('布尔比对:\n',y_predict==y_test)
score = model.score(x_test,y_test)
print('模型准确率:\n',score)
得出预测结果和模型准确率如下
模型准确率为85.7%,建模效果一般
我们可以从测试集文本中挑选出一些例子进行验证,观察一下情感分析是否正确
example = test_data[50:55]
example[['short','new_rating','sentiment']]
如果想要观察完整短评,可以写一个迭代器,将短评完整输出
不过在图中我们就可以看出这些短评的语意是如何的,比如第三个涉及抄袭,所以对应sentiment为-1
通过逻辑回归的predict_proba可以获得一个评价为好评的概率,也就是概率越接近于1,这条短评越可能是好评,同理短评为差评的概率接近于0
possibility = model.predict_proba(test_word)[:,1]
test_data.loc[:,'possibility'] = possibility
test_data.head()
得出数据如下图
之后可以通过索引得到对《少年的你》评价最好的五条和最差的五条短评
同样迭代可查看完整短评,可以看到好评Top5写的都比较多,也比较走心,大部分是在说这部电影反射出的社会问题——校园霸凌;而差评Top5都指出这部电影是在抄袭,引起许多人的不满
上图为在短评中出现次数较多的单词:
(演技 青春 少年 希望 喜欢)——这些词应该是出至于一些好评,属于正面词汇,可以影响评价夹带着的情感
(欺凌 保护 校园 霸凌 )——这些词语是陈述电影背景的词语,虽然有些带有负面情感,但还需根据短评句子的语意才能判断好差之分
(抄袭)——这个单词出现67次,而sentiment为-1的短评一共才有122个,通过分析也可得知带有抄袭的评价大概率为差评
总结
一部票房可以达到14亿的电影,一定有它的独到之处,不论是演员阵容或者是背景题材,但是一部确定抄袭的电影注定不会成为一部好电影,作为一个路人,对《少年的你》是否抄袭不能做出判断;但任何人的知识产权不能被侵犯是一定的!
公众号“奶糖猫”后台回复“少年的你”可获取源码和数据供参考,感谢支持。
来源:51CTO
作者:wx5e623980d6448
链接:https://blog.51cto.com/14746554/2476358