摘要:
合集:AI案例-NLP-零售业
数据集:MovieLens20M数据集-230MB。自1995年到2015年超过2000万部电影评分和标记活动。MovieLens20M评价收集于1995年1月到2015年3月之间,并在2016年10月17日更新为csv格式。
数据集价值:构建推荐系统
解决方案:相似度评测
一、MovieLens简介
MovieLens 是一个知名的电影推荐系统,最早由明尼苏达大学的研究团队开发。在MovieLens中,”Lens”一词具有双重意义,既指代整个推荐系统,也象征着系统的核心功能——即通过筛选和过滤大量信息来为用户提供个性化推荐。以下是对 MovieLens 的详细介绍:
基本信息
- 开发者:明尼苏达大学计算机科学系的研究人员。
- 主要功能:为用户提供个性化的电影推荐服务。
发展历程
- 早期版本(1997年):
- 最初是为在线电影租赁服务 MovieFinder 开发的推荐引擎。
- 后来在 ACM SIGIR 会议上发表相关论文,引起广泛关注。
- GroupLens 研究项目(1997年起):
- 起源于美国明尼苏达大学双城分校计算机科学与工程系。
- 旨在研究基于协作过滤的推荐系统。
- 发布了 GroupLens 推荐系统及其改进版本。
- 商业化及扩展(2000年代):
- GroupLens Research 将研究成果商业化,成立了 NetFlix Prize 竞赛。
- 通过与 Netflix 合作,推动了推荐系统技术的进步。
- 当前状态:
- 作为一个学术研究和教学平台,持续更新和维护。
- 提供了多个版本的公开数据集供学术界和企业界使用。
主要特点
- 个性化推荐:基于用户的观影历史和评分数据,利用机器学习算法生成定制化的推荐列表。
- 多样性数据集:提供了不同规模和类型的电影评分数据集,如 MovieLens 1M、10M、20M 等。
- 开源与社区支持:部分版本的代码和数据集公开可用,促进了全球范围内的研究和应用。
应用场景
- 在线视频平台:类似 Netflix 和 Hulu 这样的流媒体服务可以利用 MovieLens 的技术为用户推荐影片。
- 电子商务:电商网站可根据用户的购买历史推荐相关商品。
- 内容推荐引擎:广泛应用于新闻、音乐等多媒体内容的个性化推荐。
总之,MovieLens 不仅代表了先进的推荐算法和系统设计理念,还推动了整个推荐系统领域的发展和创新。
二、数据集内容
MovieLens20M数据集描述了5星之内的电影不受限制的标记,用于给出用户推荐。数据集包含了138493个用户对27278个电影的20000263个评分和465564个标签。此评价收集于1995年1月到2015年3月之间,并在2016年10月17日更新为csv格式。用户为随机选取,每个选取的用户至少评分20个电影。没有人员统计信息。每个用户只给出一个ID,且不涉及其他私人信息。
数据结构
不包括人员统计信息。每个用户由一个ID表示,不提供其他用户信息。
数据包含在六个文件中。
- tag.csv:包含用户对电影应用的标签:
- userId
- movieId
- tag
- timestamp
- rating.csv:包含用户对电影的评分:
- userId
- movieId
- rating
- timestamp
- movie.csv:包含电影信息:
- movieId
- title
- genres
- link.csv:包含可用于链接到其他来源的标识符:
- movieId
- imdbId
- tmbdId
- genome_scores.csv:包含电影-标签相关性数据:
- movieId
- tagId
- relevance
- genome_tags.csv:包含标签描述:
- tagId
- tag
数据样例:tag.csv
userId | movieId | tag | timestamp |
---|---|---|---|
18 | 4141 | Mark Waters | 2009/4/24 18:19 |
65 | 208 | dark hero | 2013/5/10 1:41 |
65 | 353 | dark hero | 2013/5/10 1:41 |
65 | 521 | noir thriller | 2013/5/10 1:39 |
65 | 592 | dark hero | 2013/5/10 1:41 |
65 | 668 | bollywood | 2013/5/10 1:37 |
数据样例:rating.csv
userId | movieId | rating | timestamp |
---|---|---|---|
1 | 2 | 3.5 | 2005/4/2 23:53 |
1 | 29 | 3.5 | 2005/4/2 23:31 |
1 | 32 | 3.5 | 2005/4/2 23:33 |
1 | 47 | 3.5 | 2005/4/2 23:32 |
1 | 50 | 3.5 | 2005/4/2 23:29 |
1 | 112 | 3.5 | 2004/9/10 3:09 |
1 | 151 | 4 | 2004/9/10 3:08 |
数据样例:movie.csv
movieId | title | genres |
---|---|---|
1 | Toy Story (1995) | Adventure\ |
2 | Jumanji (1995) | Adventure\ |
3 | Grumpier Old Men (1995) | Comedy\ |
4 | Waiting to Exhale (1995) | Comedy\ |
5 | Father of the Bride Part II (1995) | Comedy |
6 | Heat (1995) | Action\ |
7 | Sabrina (1995) | Comedy\ |
8 | Tom and Huck (1995) | Adventure\ |
9 | Sudden Death (1995) | Action |
10 | GoldenEye (1995) | Action\ |
数据样例:link.csv
movieId | imdbId | tmdbId |
---|---|---|
1 | 114709 | 862 |
2 | 113497 | 8844 |
3 | 113228 | 15602 |
4 | 114885 | 31357 |
5 | 113041 | 11862 |
6 | 113277 | 949 |
7 | 114319 | 11860 |
8 | 112302 | 45325 |
9 | 114576 | 9091 |
10 | 113189 | 710 |
数据样例:genome_tags.csv
tagId | tag |
---|---|
1 | 7 |
2 | 007 (series) |
3 | 18th century |
4 | 1920s |
5 | 1930s |
6 | 1950s |
7 | 1960s |
8 | 1970s |
9 | 1980s |
10 | 19th century |
11 | 3d |
12 | 70mm |
数据样例:genome_scores.csv
movieId | tagId | relevance |
---|---|---|
1 | 1 | 0.025 |
1 | 2 | 0.025 |
1 | 3 | 0.05775 |
1 | 4 | 0.09675 |
1 | 5 | 0.14675 |
1 | 6 | 0.217 |
1 | 7 | 0.067 |
版权许可协议
Deed – CC0 1.0 Universal – Creative Commons
引用要求
要在出版物中使用该数据集,请引用以下论文:
F. Maxwell Harper 和 Joseph A. Konstan。2015。The MovieLens Datasets: History and Context。ACM Transactions on Interactive Intelligent Systems (TiiS) 5, 4, Article 19 (2015年12月), 19页。
DOI=http://dx.doi.org/10.1145/2827872
三、推荐系统样例
基于MovieLens-20M数据集开发推荐系统涉及多个步骤,包括数据预处理、特征提取、模型训练和评估等。以下是一个基本的流程和示例代码:
安装
常用数据分析和传统机器学习开发包的安装方法如下:
conda create -n ml python=3.12
conda activate ml
conda install numpy pandas matplotlib seaborn statsmodels
conda install scikit-learn scipy
conda install openpyxl 3.1.5
pip install wordcloud
安装后的开发包版本信息:
python 3.12.7 h14ffc60_0 anaconda
numpy 1.26.4 py312hfd52020_0 anaconda
scipy 1.13.1 py312hbb039d4_0 anaconda
pandas 2.2.2 py312h0158946_0 anaconda
scikit-learn 1.5.1 py312h0158946_0 anaconda
matplotlib 3.9.2 py312haa95532_0 anaconda
seaborn 0.13.2 py312haa95532_0 anaconda
statsmodels 0.14.2 py312h4b0e54e_0 anaconda
openpyxl 3.1.5
WordCloud是Python的一个第三方库,主要用于从文本数据中生成词云图。词云图是一种可视化工具,它可以将文本中出现的词按照频率大小进行排列,并以不同大小的字体展示出来,使得高频词更加突出,从而方便用户快速了解文本的主要内容。
在Python中,使用WordCloud库可以非常方便地生成词云图。首先,需要将文本数据进行预处理,如去除停用词、标点符号等。然后,使用WordCloud库提供的类和方法,可以设置词云图的形状、颜色、字体等参数,并生成对应的词云图。WordCloud库还提供了一些高级功能,如支持自定义词汇频率、支持多种图片格式作为词云图背景等。此外,WordCloud库还与其他Python库(如matplotlib、PIL等)进行了集成,可以方便地将生成的词云图保存为图片文件或显示在图形界面中。
1. 数据加载与预处理
Data_Processing.ipynb
首先,加载MovieLens-20M数据集并进行必要的预处理。
# Import packages
import os
import pandas as pd
2. 数据探索与可视化
了解数据的分布和特征,进行必要的可视化。以下为数据探索与可视化的其中一个样例。
# Read the Ratings File
ratings = pd.read_csv(os.path.join(MOVIELENS_DIR, RATING_DATA_FILE),
sep='::',
engine='python',
encoding='latin-1',
names=['user_id', 'movie_id', 'rating', 'timestamp'])
# Set max_userid to the maximum user_id in the ratings
max_userid = ratings['user_id'].drop_duplicates().max()
# Set max_movieid to the maximum movie_id in the ratings
max_movieid = ratings['movie_id'].drop_duplicates().max()
# Process ratings dataframe for Keras Deep Learning model
# Add user_emb_id column whose values == user_id - 1
ratings['user_emb_id'] = ratings['user_id'] - 1
# Add movie_emb_id column whose values == movie_id - 1
ratings['movie_emb_id'] = ratings['movie_id'] - 1
print(len(ratings), 'ratings loaded')
输出:
1000209 ratings loaded
3. 基于内容的推荐模型
源码:Content_Based_and_Collaborative_Filtering_Models.ipynb
我们将构建一个基于内容的推荐引擎,该引擎根据电影类型计算电影之间的相似性。它将根据其类型建议与特定电影最相似的电影。为此,我将使用文件movies.csv。数据样例如下:
movie_id | title | genres |
---|---|---|
1 | Grumpier Old Men | Comedy |
2 | Waiting to Exhale | Comedy Drama |
3 | Father of the Bride Part II | Comedy |
词频(TF)和逆文档频率(IDF)的概念被用于信息检索系统和基于内容的过滤机制(如基于内容的推荐器)。它们用于确定文档/文章/新闻项目/电影等的相对重要性。
TF只是文档中单词的频率。IDF是在整个文档语料库中文档频率的倒数。TF-IDF之所以被主要使用,有两个原因:假设我们搜索“最新欧洲足球比赛的结果”。可以肯定的是,“的”的出现频率将高于“足球比赛”,但从搜索查询的角度来看,“足球比赛”的相对重要性更高。在这种情况下,TF-IDF加权消除了高频词在确定文档重要性时的影响。
计算出TF-IDF分数后,我们如何确定哪些关键词彼此更接近,或者更接近用户画像?这是通过使用向量空间模型来实现的,该模型根据向量之间的角度计算接近度。在这个模型中,每个关键词都存储为其属性(也是向量)的向量,在一个n维空间中,并计算向量之间的角度以确定向量之间的相似性。接下来,还根据用户对关键词先前属性的行为创建用户画像向量,并以类似的方式确定关键词与用户之间的相似性。计算这种相对度量的方法是通过取句子和词条之间角度的余弦值来计算的。使用余弦的最终原因是余弦值随着角度值的减小而增加,这表示更多的相似性。向量长度归一化后,它们变成长度为1的向量,然后余弦计算简单地是向量的求和乘积。
# Break up the big genre string into a string array
movies['genres'] = movies['genres'].str.split('|')
# Convert genres to string value
movies['genres'] = movies['genres'].fillna("").astype('str')
以下代码使用scikit-learn中的TfidfVectorizer函数,该函数将文本转换为特征向量,可以用作估计器/estimator的输入。对电影类型数据集进行TF-IDF向量化处理,并输出处理后的TF-IDF矩阵的形状。其中:
- analyzer=’word’表示按单词进行分析。
- ngram_range=(1, 2)表示考虑1-gram和2-gram,即单词和相邻单词的组合。
- min_df=0.01表示最小文档频率为0.01,即在至少1%的文档中出现的单词才会被考虑。
- stop_words=’english’表示过滤掉英文停用词。 最后,tfidf_matrix.shape输出了TF-IDF矩阵的形状,即行数和列数。行数表示电影的数量,列数表示经过TF-IDF向量化处理后的特征数量。
from sklearn.feature_extraction.text import TfidfVectorizer
# tf = TfidfVectorizer(analyzer='word',ngram_range=(1, 2),min_df=0, stop_words='english')
tf = TfidfVectorizer(analyzer='word',ngram_range=(1, 2),min_df=0.01, stop_words='english')
tfidf_matrix = tf.fit_transform(movies['genres'])
tfidf_matrix.shape
我将使用余弦相似度来计算表示两部电影之间相似性的数值量。由于我们已经使用了TF-IDF向量化器,计算点积将直接给出余弦相似度得分。因此,我们将使用sklearn的linear_kernel而不是cosine_similarities,因为它更快。
from sklearn.metrics.pairwise import linear_kernel
cosine_sim = linear_kernel(tfidf_matrix, tfidf_matrix)
cosine_sim[:4, :4]
cosine_sim[:4, :4]
显示了余弦相似度矩阵的前4行和前4列,即前4部电影的相似度分数。这个子矩阵可以帮助我们理解电影之间的相似性:
array([[1. , 0.17197755, 0.09010857, 0.1056164 ],
[0.17197755, 1. , 0. , 0. ],
[0.09010857, 0. , 1. , 0.1719888 ],
[0.1056164 , 0. , 0.1719888 , 1. ]])
我现在已经得到了数据集中所有电影的两两余弦相似度矩阵。下一步是编写一个函数,根据余弦相似度得分返回20部最相似的电影。
# Build a 1-dimensional array with movie titles
titles = movies['title']
indices = pd.Series(movies.index, index=movies['title'])
# Function that get movie recommendations based on the cosine similarity score of movie genres
def genre_recommendations(title):
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:21]
movie_indices = [i[0] for i in sim_scores]
return titles.iloc[movie_indices]
让我们尝试为几部电影获取最佳推荐,并看看推荐的效果如何。
# 输入:
genre_recommendations('Good Will Hunting (1997)').head(20)
#
输出:
25 Othello (1995)
26 Now and Then (1995)
29 Shanghai Triad (Yao a yao yao dao waipo qiao) ...
30 Dangerous Minds (1995)
35 Dead Man Walking (1995)
39 Cry, the Beloved Country (1995)
42 Restoration (1995)
52 Lamerica (1994)
54 Georgia (1995)
56 Home for the Holidays (1995)
61 Mr. Holland's Opus (1995)
66 Two Bits (1995)
77 Crossing Guard, The (1995)
79 White Balloon, The (Badkonake Sefid ) (1995)
81 Antonia's Line (Antonia) (1995)
82 Once Upon a Time... When We Were Colored (1995)
89 Journey of August King, The (1995)
92 Beautiful Girls (1996)
95 Hate (Haine, La) (1995)
112 Margaret's Museum (1995)
Name: title, dtype: object
总的来说,基于内存的协同过滤易于实现并产生合理的预测质量。然而,这种方法有一些缺点:
- 它没有解决众所周知的冷启动解决方案存在的问题,即当新用户或新项目进入系统时,数据无法及时更新。
- 它无法处理稀疏数据,这意味着很难找到对相同项目进行评分的用户。
- 当新用户或没有任何评分的新项目进入系统时,它会受到影响。
- 它倾向于推荐受欢迎的项目。
总结
以上是一个基于MovieLens20M数据集开发推荐系统的基本流程和示例代码。实际应用中,可能需要根据具体需求进行更多的优化和调整,例如使用更复杂的模型、处理冷启动问题、优化推荐结果的多样性等。
源码开源协议
MIT License
Copyright (c) 2018 James Le
四、参考资料
MovieLens 20M Dataset 推荐系统开发样例