现我们成立了梦龙工作室,工作室成员皆为985在读理工科学生,排名前20%,5%等,获得过国赛一等奖,大数据杯二等奖,美赛M奖,以一座发表ei会议,SCI二区等。旨在帮助大学生参与竞赛,如mathorcup 大数据杯,国赛,美赛,电工杯等等,入群可提问比赛或数据处理有关问题,群内开放讨论,欢迎有兴趣的朋友加群!群号:684715652
研究背景介绍
当电影产业逐渐成为重资本时,基于历史数据预测电影的热度及其商业潜力已成为利用机器学习模型进行数据分析领域的热门研究课题。 我们使用 IMBD 数据集训练了三种监督机器学习模型(随机森林、朴素贝叶斯模型和支持向量回归)来预测电影的受欢迎程度。 本研究有两个成果:(1)随机森林模型的准确率最高; (2)演员阵容中奥斯卡奖得主的数量与电影的受欢迎程度呈正相关。本文中只介绍随机森林方法。
特征选取及预处理
数据集来源
本研究总共包含四个数据集: TMDb 5000 部电影、TMDb 5000 credit、世界十大电影公司、奥斯卡奖得主。 TMDb 5000 电影数据集通过 TMDb 数据库(一个流行的用户可编辑数据库)收集,使用 4 个标签(包括演员和工作人员)描述了 4800 部不同的电影。 TMDb 5000 Credits 对其他 23 个标签的同一部电影进行了评估,包括类型、收入、预算和受欢迎程度。 世界十大电影公司收录了2020年世界十大电影公司。 奥斯卡获奖者记录了历史上所有的奥斯卡获奖者。我们将电影的受欢迎程度作为预测量。
特征选取
我们分析不同特征与电影受欢迎程度的皮尔逊相关系数,而后选取相关性最高的七个特征(预算水平、受欢迎水平、收入水平、运行时水平投票平均值、奥斯卡演员阵容、奥斯卡导演、制作公司)而后我们对特征进行预处理
特征预处理
首先我们收集到了TMDb对这4800部电影的评价,我们需要对这些评价语句进行清洗,提取出其中关键词,首先采用以下代函数:
def clean_text(var_in):
import re
tmp = re.sub("[^A-z]+", " ", var_in.lower())
return tmp
该代码的作用是将输入的语句中除了a-z字母、空格以及标点符号外其余符号全部除去,并把所有语句中的英文字母统一为小写英文字母以方便后面继续做处理。
def clean(text):
text = clean_text(text)
text_tokenized = word_tokenize(text,'english')
filtered_sentence = []
stop_words = stopwords.words('english')
m = ['s','n']
stop_words.extend(m)
for w in text_tokenized:
if w not in stop_words:
filtered_sentence.append(w)
total = ' '.join(filtered_sentence)
return total
接下来我们采取cleant函数对clean_text()函数处理后的文本进行再处理,cleant()函数首先判断所输入评价语句文本是否为空,若为空则直接返回空列表,而后利用
from nltk.tokenize import word_tokenize
所导入'word_tokenize'函数将所输入语句切成不同的英文单词,从python自带的语料库中导入stopwords,stopwords中包含了'a,an,the,this'等常见的没有情感色彩的冠词或指代词,同时我们同时将[s,n]字母添进stopwords中,将评价语句中的stopwords忽略,而后将其他单词放入total中并返回。
获得评价中的情感词后,我们继续获取关于电影的其他信息。众所周知,演员对于电影本身是至关重要的,而演员中对电影影响最大的往往是主演,所以我们对电影主演的信息进行获取。
def directorjudge(crew):
val = 0
if not crew:
return val
crew = eval(crew)
for dic in crew:
if dic['job'] == "Director":
if dic['name'] in person:
val = 1
break
return val
由于我们获取的数据是类似'Director:name of actor'这样的形式,因此我们读取字典中标签为Director的数据,而后我们事先创建一个person列表,person列表中包含了曾经获得过奥斯卡的所有演员的名字,我们判断所获取主演的名称是否位于person列表中,即判断主演中是否有曾获得奥斯卡奖项的演员,若获得则将val值置为1,否则为0。接着我们对电影的角色演员数据进行处理,类似对主演数据的处理:
def characterjudge(cast):
val = 0
if not cast:
return val
cast = eval(cast)
for dic in cast:
if dic['character'] in person:
val += 1
return val
若角色演员中有人曾获奥斯卡奖项则将val值置为1,否则为0。
接下来我们对电影的产出公司进行处理,类似上述操作,我们预先生成一个百大电影公司列表,判断电影产出公司是否位于百大之中,若是则将val置为1,若否则将val置0。
def companyjudge(cp):
val = 0
if not cp:
return val
cp = eval(cp)
for dic in cp:
if dic['name'] in company:
val += 1
return val
最后我们对最开始所提取的情感词计算tf_idf,tf_idf在此就只进行简要介绍,tf是指一个词在文档中出现的频率,idf是指逆文档频率,逆文档频率是指一个词在所有文档中所占频率与在特定文档中词频之比,某些词在所有文档中被反复提及,假设我们现在有这样一个英文语料库,主题有关车辆,那么car一次便会在所有文档中被反复提及,且在文档中出现的频率会较高,但此时我们若想评判一辆车的性能,car显然不是一个关键词,我们需要的关键词往往是只出现在特定文档中的,例如介绍比亚迪的仰望时会介绍四电机驱动,无人机伴飞,海陆两栖等,而这些词在介绍卡罗拉时明显不会出现。所以逆文档频率也是我们判断一个词关键与否的依据。最终一个词的重要与否由下列公式决定:
def create_tf_idf(df_in, out_in, min_n, max_n):
from sklearn.feature_extraction.text import TfidfVectorizer
import pandas as pd
my_tf_idf = TfidfVectorizer(ngram_range=(min_n, max_n))
my_tf_idf_text = pd.DataFrame(my_tf_idf.fit_transform(df_in).toarray())
my_tf_idf_text.columns = my_tf_idf.get_feature_names()
write_pickle(out_in, "tf_idf.pkl", my_tf_idf)
return my_tf_idf_text
我们将一个关键词的重要性分为四个等级,if_idf位于区间(0, 4.668)内将重要性设置为0,if_idf位于区间(4.668,12.922)内将重要性设置为1,if_idf位于区间(12.922,28.314)内将重要性设置为2,if_idf位于区间(28.314,+无穷)内将重要性设置为3,代码示例如下:
def classify(text):
if text < 4.668070:
val = 0
elif 12.921594 > text > 4.668070:
val = 1
elif 28.313505 > text > 12.921594:
val = 2
else:
val = 3
return val
特征汇总
最后将所有特征进行处理汇总:
#create the dataset (data)for model establishment
movies_t['popularity_level'] = movies_t['popularity'].apply(classify)
movies_t['overview'] = movies_t['overview'].apply(str)
movies_t['overview_clean'] = movies_t['overview'].apply(clean)
movies_t['keywords_clean'] = movies_t['keywords'].apply(clean)
movies_t['genres_clean'] = movies_t['genres'].apply(clean)
movies_t['budget_level'] = movies_t['budget'].apply(classifybudget)
movies_t['production_companies'] = movies_t['production_companies'].apply(companyjudge)
movies_t['runtime_level']=movies_t['runtime'].apply(classify)
movies_t['revenue_level']=movies_t['revenue'].apply(classify)
credits_t['Oscar_crew'] = credits_t['crew'].apply(directorjudge)
credits_t['Oscar_cast'] = credits_t['cast'].apply(characterjudge)
data = credits_t.merge(movies_t, how='left', on='title')[["budget_level","popularity_level","genres_clean","keywords_clean", "Oscar_crew", "Oscar_cast","production_companies","overview_clean","runtime_level","popularity"]]
随机森林模型的建立
而后建立随机森林模型,代入训练预测即可
import pandas as pd
from sklearn.ensemble import RandomForestRegressor
from sklearn.model_selection import train_test_split
from matplotlib import pyplot as plt
# Load the Diabetes dataset
columns = data.keys() # Declare the columns names
diabetes = datasets.load_diabetes()
df = pd.DataFrame(diabetes.data, columns=columns)
y = data.popularity
y = diabetes.target
# create training and testing vars
X_train, X_test, y_train, y_test = train_test_split(df, y, test_size=0.2)
print (X_train.shape, y_train.shape)
print (X_test.shape, y_test.shape)
# fit a model
rf_regressor = RandomForestRegressor(n_estimators=4000, random_state=42, verbose=3)
rf_regressor.fit(X_train, y_train)
predictions = rf_regressor.predict(X_test)
## The line / model
plt.scatter(y_test, predictions)
plt.xlabel("true value")
plt.ylabel("predictions")
print ("Score:", model.score(X_test, y_test))
在此我们将测试集设置成20%的比例,最终得到模型评分大于0.8,因此特征处理与选取合理,模型表现优良。