背景
《少年的你》這部國產青春劇影響還是蠻大的,票房達到了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億的電影,一定有它的獨到之處,不論是演員陣容或者是背景題材,但是一部確定抄襲的電影注定不會成為一部好電影,作為一個路人,對《少年的你》是否抄襲不能做出判斷;但任何人的知識產權不能被侵犯是一定的!
公眾號“奶糖貓”后臺回復“少年的你”可獲取源碼和數據供參考,感謝支持。