🤵♂️ 个人主页:@艾派森的个人主页
✍🏻作者简介:Python学习者
🐋 希望大家多多支持,我们一起进步!😄
如果文章对你有帮助的话,
欢迎评论 💬点赞👍🏻 收藏 📂加关注+
目录
1.项目背景
2.数据集介绍
3.技术工具
4.实验过程
4.1导入数据
4.2词云图可视化
4.3基于内容的协同过滤
4.4基于投票的过滤:人口统计学过滤
5.总结
6.源代码
1.项目背景
随着信息技术的迅猛发展和数字化媒体的普及,人们每天面临着海量的信息选择。特别是在线电影平台,如腾讯视频、爱奇艺、优酷等,拥有数以万计的电影资源。用户在如此庞大的电影库中寻找感兴趣的内容变得愈发困难,因此,一个高效、精准的推荐系统显得尤为重要。
传统的电影推荐方法,如基于流行度或者最新发布进行推荐,往往不能满足用户个性化的需求。为了提供更加个性化的电影推荐,推荐系统需要能够理解和预测用户的喜好。基于内容的推荐系统和协同过滤推荐系统是两种主流的方法。基于内容的推荐主要是通过分析用户过去的行为和电影的内容(如类型、导演、演员等)来推荐类似的电影。而协同过滤则是通过分析用户的行为和其他相似用户的行为来进行推荐。
然而,单一的推荐方法往往有其局限性。基于内容的推荐可能过于依赖电影的特征描述,而忽略了用户的个性化需求;而协同过滤则可能受限于数据的稀疏性和冷启动问题。为了克服这些问题,可以考虑将基于内容的推荐和协同过滤结合起来,形成一种混合推荐方法,即基于内容协同过滤的推荐系统。
本研究旨在构建一个基于内容协同过滤算法的电影推荐系统,通过结合电影的内容特征和用户的行为数据,为用户提供更加精准和个性化的电影推荐。通过这种方法,我们期望能够提高用户对推荐电影的满意度,并进一步提升在线电影平台的用户体验。
在上述背景下,本研究将深入探索内容协同过滤算法在电影推荐系统中的应用,以期为用户提供更加精准、个性化的电影推荐服务。
2.数据集介绍
本数据集来源于Kaggle,原始数据集共有2个文件,一个是movies.csv,一个是credits.csv。
movies.csv如下:
credits.csv如下:
3.技术工具
Python版本:3.9
代码编辑器:jupyter notebook
4.实验过程
4.1导入数据
导入第三方库并加载数据集
查看数据前五行
合并数据集
查看数据基本信息
4.2词云图可视化
自定义一个画词云图的函数
画出标题列的词云图
填充overview变量中的缺失值并可视化
4.3基于内容的协同过滤
这种类型的过滤器不涉及其他用户,如果不是我们自己。根据我们的喜好,算法会简单地挑选内容相似的商品推荐给我们。在这种情况下,推荐的多样性将会减少,但无论用户评分与否,这都是有效的。如果我们将其与上面的例子进行比较,也许用户B可能喜欢黑色喜剧,但他/她永远不会知道,除非他/她决定自主尝试,因为这个过滤器只会继续推荐反乌托邦电影或类似的电影。当然,我们可以计算许多类别的相似性:在电影的情况下,我们可以决定仅基于类型构建我们自己的推荐系统,或者我们想要包括导演,主要演员等。
向量化
我们将使用sklearn的linear_kernel()而不是cosine_similarity(),因为它更快。
自定义一个推荐函数
如果你搜索“Spectre”,下面的电影名称将被推荐
如果你搜索“John Carter”,下面的电影名称将被推荐
将字符串化后的特征解析为对应的python对象
提取类型和关键词列表
结合类型和关键词
向量化
余弦相似度
余弦相似度度量了内积空间中两个向量之间的相似度。它是由两个向量之间夹角的余弦来测量的,并确定两个向量是否大致指向相同的方向。在文本分析中,它常用于度量文档的相似度。文档可以由数千个属性表示,每个属性记录文档中特定单词(如关键字)或短语的频率。因此,每个文档都是由术语频率向量表示的对象。
我们都熟悉向量:它们可以是2D, 3D或任何d。让我们用2D来思考一下,因为它更容易在我们的脑海中描绘出来,让我们先复习一下点积的概念。两个向量的点积等于其中一个向量在另一个向量上的投影。因此,两个相同向量(即具有相同分量)之间的点积等于它们的平方模,而如果两个向量垂直(即它们不共享任何方向),则点积为零。通常,对于n维向量,点积的计算方法如下所示。
在定义相似度时,点积很重要,因为它与相似度直接相关。两个向量u和v之间相似度的定义,实际上是它们的点积和它们的大小之积的比值。
通过应用相似性的定义,如果这两个向量相同,它等于1,如果这两个向量正交,它等于0。换句话说,相似度是一个介于0到1之间的数字它告诉我们两个向量有多相似。
使用余弦相似度
如果你搜索“John Carter”,下面的电影名称将被推荐
如果你搜索“Soldier”,下面的电影名称将被推荐
4.4基于投票的过滤:人口统计学过滤
计算avarage评级
筛选符合条件的电影
根据上面计算的分数对电影进行排序
热门电影
5.总结
本研究通过构建并优化基于内容协同过滤算法的电影推荐系统,成功实现了对用户个性化电影推荐需求的精准满足。实验结果表明,该系统能够结合电影内容特征和用户行为数据,为用户提供更加符合其兴趣和偏好的电影推荐。相较于单一的推荐方法,该系统展现出了更高的推荐准确性和用户满意度,从而验证了内容协同过滤算法在电影推荐系统中的有效性和优越性。因此,该算法对于提升在线电影平台的用户体验和服务质量具有重要的应用价值。
6.源代码
import numpy as np
import pandas as pd
pd.set_option('display.max_columns', 25)
import matplotlib.pyplot as plt
import warnings
warnings.filterwarnings('ignore')
movie = pd.read_csv('tmdb_5000_movies.csv')
credit = pd.read_csv('tmdb_5000_credits.csv')
movie.head()
credit.head()
# 合并两个数据集
credit.columns = ['id','cast', 'title', 'crew']
movie= movie.merge(credit, on='id')
movie.head()
movie.info()
# 词云图
from wordcloud import WordCloud, STOPWORDS, ImageColorGenerator
import matplotlib.pyplot as plt
# 自定义一个画词云图的函数
def cloud(col):
wcloud = " ".join(f for f in movie[col])
wc_ = WordCloud(width = 2000, height = 1000, random_state=1, background_color='black', colormap='Set2', collocations=False, stopwords = STOPWORDS)
wc_.generate(wcloud)
plt.subplots(figsize=(10,6))
plt.imshow(wc_, interpolation="bilinear")
plt.axis("off")
# 画出标题列的词云图
cloud("original_title")
# 填充overview变量中的缺失值
movie["overview"] = movie["overview"].fillna("")
cloud("overview")
# Tfidf向量化
from sklearn.feature_extraction.text import TfidfVectorizer
tfidf = TfidfVectorizer(stop_words="english")
tfidf_matrix = tfidf.fit_transform(movie["overview"])
tfidf_matrix
# 我们将使用sklearn的linear_kernel()而不是cosine_similarity(),因为它更快。
from sklearn.metrics.pairwise import linear_kernel
cosine_sim = linear_kernel(tfidf_matrix, tfidf_matrix)
# 索引和电影original_title的反向映射
indices = pd.Series(movie.index, index=movie['original_title']).drop_duplicates()
# 自定义一个推荐函数
def get_recommendation(title, cosine_sim):
idx = indices[title]
sim_scores = list(enumerate(cosine_sim[idx]))
sim_scores = sorted(sim_scores, key=lambda x: x[1], reverse=True)
sim_scores = sim_scores[1:11]
movies = [i[0] for i in sim_scores]
movies = movie["original_title"].iloc[movies]
return movies
# 如果你搜索“Spectre”,下面的电影名称将被推荐
get_recommendation('Spectre', cosine_sim)
# 如果你搜索“John Carter”,下面的电影名称将被推荐
get_recommendation("John Carter", cosine_sim)
# 将字符串化后的特征解析为对应的python对象
from ast import literal_eval
features = ['keywords', 'genres']
for feature in features:
movie[feature] = movie[feature].apply(literal_eval)
movie[['original_title', 'keywords', 'genres']].head(3)
# 提取类型列表
def list_genres(x):
l = [d['name'] for d in x]
return(l)
movie['genres'] = movie['genres'].apply(list_genres)
# 提取关键字列表
def list_keyword(y):
i = [a['name'] for a in y]
return(i)
movie['keywords'] = movie['keywords'].apply(list_keyword)
# 结合类型和关键词
def genre(x):
return ''.join(' '.join(x['genres']) + ' ' + ' '.join(x['keywords']))
movie['mix'] = movie.apply(genre, axis=1)
movie["mix"]
# 向量化
from sklearn.feature_extraction.text import CountVectorizer
countvect = CountVectorizer(stop_words="english")
countvect_mat = tfidf.fit_transform(movie["mix"])
countvect_mat
from sklearn.metrics.pairwise import cosine_similarity
cos_sim = cosine_similarity(countvect_mat, countvect_mat)
# 索引和电影original_title的反向映射
movie = movie.reset_index()
indices = pd.Series(movie.index, index=movie['original_title'])
# 如果你搜索“John Carter”,下面的电影名称将被推荐
get_recommendation("John Carter", cos_sim)
# 如果你搜索“Soldier”,下面的电影名称将被推荐
get_recommendation("Soldier", cos_sim)
基于投票的过滤:人口统计学过滤
# avarage评级
avg = movie["vote_average"].mean()
# 我们将使用第90个百分位数作为截止点。换句话说,一部电影要想进入榜单,它必须比榜单上至少90%的电影获得更多的选票。
q = movie["vote_count"].quantile(0.9)
print(avg)
print(q)
# 符合条件的电影
movies = movie[movie["vote_count"] >= q]
# weighted_rating函数
def weighted_rating(x, q=q, avg=avg):
v = x['vote_count']
R = x['vote_average']
# 根据IMDB公式计算
return (v/(v+q) * R) + (q/(q+v) * avg)
# 符合条件的影片
movies["score"] = movies.apply(weighted_rating, axis=1)
# 根据上面计算的分数对电影进行排序
movies = movies.sort_values('score', ascending=False)
# 打印前10部电影
listed = movies[['original_title', 'vote_count', 'vote_average', 'score', "popularity"]].head(10)
# 可视化
import seaborn as sns
plt.subplots(figsize=(10,6))
sns.barplot(listed["score"], listed["original_title"], palette="Set2")
plt.title("Movie Vs Score")
plt.show()
# 热门电影
popular= movies.sort_values('popularity', ascending=False)
plt.figure(figsize=(12,4))
plt.barh(popular['original_title'].head(10),popular['popularity'].head(10), align='center',
color="#313131")
plt.gca().invert_yaxis()
plt.xlabel("Popularity")
plt.title("Popular Movies")
plt.show()
资料获取,更多粉丝福利,关注下方公众号获取