其他分享
首页 > 其他分享> > 电影推荐系统(推荐系统的hello work)

电影推荐系统(推荐系统的hello work)

作者:互联网

什么是推荐系统?

互联网的信息越来越多,用户面对大量数据信息的时候,无法获得对自己真正有用的部分,造成信息超载问题。

推荐系统就是解决信息超载的一个办法。

推荐系统依据用户的历史行为、社交关系、兴趣点等信息去判断用户当前需要或感兴趣物品/服务的应用。

推荐是去预测用户对某个他没有使用过的物品/服务的喜欢程度(一般是打分机制),物品/服务可以是电影、书、音乐、新闻等;

推进系统核心任务主要是把用户和信息关联起来,

背景介绍

推荐问题的发展历史

1994年, Minncsota, GroupLcns 研究组论文

目前已经广泛应用到很多商业应用系统

尤其是网络购物平台: 亚马逊,京东,淘宝等

Google新闻: 38%的点击量来自推荐等等。

新闻:今日头条

视频:抖音推荐短视频

推荐系统的输入(三元组)

user(用户) + item(物品/服务) + review(用户对物品的评价)

User & user Profile(用户画像)

Item(物品) & Item Profile(物品对应特征)

Review (user 对 item 的评价)

推荐系统的输出

基本原理

利用用户行为数据

p(u,i)=vϵS(u,K)(i) WuvRvi p(u,i) = \sum_{v\epsilon S(u,K)\bigcap(i)}\ W_{uv}R_{vi} p(u,i)=vϵS(u,K)⋂(i)∑​ Wuv​Rvi​

​ 参数说明:u 用户, i 物品

​		1. S(u, K): 包含和用户u 兴趣最接近的 K 个用户
​		2. N(i): 对物品 i 有过行为的用户集合
​		3. Wuv : 用户u 和 用户 v 的兴趣相似度
​		4. Rvi: 代表用户v 对物品 i 的兴趣
  1. 基于图的推荐算法
  2. 二分图又称作二部图,是图论中的一种特殊模型。

利用用户标签数据

利用上下文信息

利用社交网络

MovieLens 数据集

使用 jupyter notebook分析MovieLens 数据集

导入需要的模块

import numpy as np
import pandas as pd
import matplotlib.pylab as plt

读取对应的数据集显示

header = ['user_id', 'item_id', 'rating', 'timestamp']
src_data = pd.read_csv('ml-100k/u.data', sep='\t', names = header)
src_data.head()

按user_id 排序

user_data = pd.DataFrame(src_data)
user_data.sort_values(by='user_id')

对应的数据集

# 用户信息: 用户ID,年龄,性别,职业,邮政编码
u_cols = ['user_id', 'age', 'sex', 'occupation', 'zip_code']
users = pd.read_csv('ml-100k/u.user', sep='|', names=u_cols, encoding='latin-1')

# 评分信息: 用户ID,电影ID,评分,时间戳
r_cols = ['user_id', 'movie_id', 'rating', 'unix_timestamp']
ratings = pd.read_csv('ml-100k/u.data', sep='\t', names=r_cols, encoding='latin-1')

# 电影信息:电影ID,电影标题,发布时间,上映时间,IMBD地址
m_cols = ['movie_id', 'title', 'release_date', 'video_release_date', 'imbd_url']
movies = pd.read_csv('ml-100k/u.item', sep='|', names=m_cols, usecols=range(5), encoding='latin-1')

把用户,物品,评分这些表结合

# 把这些数据融合
movie_ratings = pd.merge(users, ratings)
merge_data = pd.merge(movie_ratings, movies)
merge_data.head()

找出评论次数最多的电影
安装电影标题分为不同的组(groups), 并且用size()函数得到
每一部电影的个数(即每部电影被评论的次数),按照从大到小排序,取最大的前20部电影

title_size = merge_data.groupby('title').size()
sort_val = title_size.sort_values(ascending=False)[:20]
print(sort_val)

评分最高的十部电影
按照电影名称分组
取出至少被评论过100次的电影按照平均评分从大到小排序,取最大的10部电影

movie_stats = merge_data.groupby('title')
# 使用agg 函数通过一个字典{’rating':[np.size, np.mean]}来按照key即rating
rating_agg = movie_stats.agg({'rating': [np.size, np.mean]})
# 依据布尔(true, false)排序
take_100 = rating_agg['rating']['size'] >= 100
# print(take_100)
sort_raring = rating_agg[take_100].sort_values([('rating', 'mean')], ascending=False)
sort_raring[:10]

直方图查看用户的年龄分布

plt.hist(users.age, bins=30, color='red', alpha=0.75)
plt.xlabel('age')
plt.ylabel('count of users')
plt.show()

用户年龄分组

# 将用户年龄分组
labels = ['10-19', '20-29', '30-39', '40-49', '50-59', '60-69', '70-79']
merge_data['age_group'] = pd.cut(merge_data.age, range(10, 81, 10), right=False, labels=labels)
merge_data[['age', 'age_group']].drop_duplicates()[:10]
# 每个年龄段用户评分偏好
merge_data.groupby('age_group').agg({'rating':[np.size, np.mean]})

推荐系统框架: surprise

摘自官网surprise简要概述:

Surprise was designed with the following purposes in mind:

​ 大体上是说,推荐系统被设计时,充分考虑了用户控制,减轻数据集的处理,可以使用内置的数据集(Movielens, Jester), 提供了大量的基本算法,能更容易实现新的想法, 提供算法分析、模型评估、比较算法性能的工具。一个简单的Python 推荐系统引擎库

安装方法

pip install numpy
pip install scikit-surprise

也可以 anaconda 安装:

conda install -c conda-forge scikit-surprise

也可以从git clone github官网安装最新版本

pip install numpy cython
git clone https://github.com/NicolasHug/surprise.git
cd surprise
python setup.py install

基本算法

算法类名 描述
random_pred.NormalPredictor 依据训练集的分布特征随机给预测值
baseline_only.BaselineOnly 给定用户和Item, 给出基于baseline的估计值
knns.KNNBasic 最基础的协同过滤
knns.KNNWithMeans 将每个用户评分的均值考虑在内的协同过滤实现
knns.KNNWithZScore 一种基本的协同过滤算法,考虑到每个用户的Z分数标准化。
knns.KNNBaseline 考虑基线评级的协同过滤
matrix_factorization.SVD SVD(奇异值)实现
matrix_factorization.SVDpp SVD++
matrix_factorization.NMF 基于矩阵分解的协同过滤
slope_one.SlopeOne 一个简单但精确的协同过滤算法
co_clustering.CoClustering 基于协同聚类的协同过滤算法

交叉验证迭代器

KFold 一个基本的交叉验证迭代器。
RepeatedKFold 重复KFold交叉验证。
ShuffleSplit 具有随机顺练集和测试集的基本交叉验证迭代器。
LeaveOneOut 交叉验证迭代器,其中每个用户在测试集合中只有一个评级。
PredefinedKFold 使用load_from_folds 方法加载数据集时的交叉验证迭代器。

相识度准则

cosine 计算所有用户(或物品)对之间的余弦相似度。
msd 计算所有用户(或物品)对之间的均方差异相似度
pearson 计算所有用户(或物品)对之间的Pearson相关系数。
pearson_baseline 计算所有用户(或项目)对之间的(缩小的)Pearson相关系数,使用基线进行居中而不是平均值。

精度评估

rmse 计算RMSE (均方根误差).
mae 计算MAE (平均绝对误差).
fcp 计算 FCP (协调对的分数).

自带三个数据集

上面的都可以在各自的网站下载到,都分有时间段收集的数据集。

加载数据集

Dataset.load_builtin 加载内置数据集。
Dataset.load_from_file 从(自定义)文件加载数据集。
Dataset.load_from_folds 加载数据集,其中折叠(用于交叉验证)由某些文件预定义。
Dataset.folds 生成器函数迭代数据集的折叠。
DatasetAutoFolds.split 将数据集拆分为折叠以供接下来的交叉验证。

surprise官方实例

from surprise import SVD
from surprise import Dataset
from surprise.model_selection import cross_validate

# Load the movielens-100k dataset (download it if needed).
data = Dataset.load_builtin('ml-100k')

# Use the famous SVD algorithm.
algo = SVD()

# Run 5-fold cross-validation and print results.
cross_validate(algo, data, measures=['RMSE', 'MAE'], cv=5, verbose=True)

Output

				评估5次分裂的算法SVD的RMSE,MAE。                      
                                                                           
            Fold 1  Fold 2  Fold 3  Fold 4  Fold 5  Mean    Std            
RMSE        0.9311  0.9370  0.9320  0.9317  0.9391  0.9342  0.0032         
MAE         0.7350  0.7375  0.7341  0.7342  0.7375  0.7357  0.0015         
Fit time    6.53    7.11    7.23    7.15    3.99    6.40    1.23           
Test time   0.26    0.26    0.25    0.15    0.13    0.21    0.06 

如何计算某一个用户(user)对某一个物品(item)的评分?

根据预测结果,获取TOP-N的函数

def get_top_n(predictions, n = 10):
    top_n = defaultdict(list)
    
    # uid: 用户ID
    # iid: 物品ID
    # est: 估计得分
    for uid, iid, true_r, est, _ in predictions:
        top_n[uid].append((iid, est))
        
    # 为每一个用户都寻找 K 个得分最高的item
    for uid, user_ratings in top_n.items():
        user_ratings.sort(key=lambda x: x[1], reverse=True)
        top_n[uid] = user_ratings[:n]
        
    return top_n

自带 ml-100k数据TOP-N 推荐

每一个用户评分最高的10个物品Item

# 首先在movielens数据集上训练SVD算法。
data = Dataset.load_builtin('ml-100k')
# 转换,这样才能获取数据集详细信息
trainset = data.build_full_trainset()
algo = SVD()
algo.fit(trainset)

testset = trainset.build_anti_testset()
predictions = algo.test(testset)

top_n = get_top_n(predictions, n = 10)

for uid, user_ratings in top_n.items():
    print(uid, [iid for (iid, _) in user_ratings])

在自己的数据上做TOP-N推荐

from surprise import SVD
from surprise import Dataset, print_perf, Reader
from surprise.model_selection import cross_validate
import os

# 指定文件所在路径,mydata是自己制作的数据集
file_path = os.path.expanduser('mydata.csv')
# sep: 指定数据集以什么方式去读
reader = Reader(line_format='user item rating', sep=',')
# 加载数据
data = Dataset.load_from_file(file_path, reader=reader)
trainset = data.build_full_trainset()

#训练SVD算法
algo = SVD()
algo.fit(trainset)

测试用户获取第一个用户分别对第1,2,3个item的得分

testset = [('1', '1', 0),
          ('1', '2', 0),
          ('1', '3', 0),
]
predictions = algo.test(testset)

我们如何使用协同过滤?

基于用户的协同过滤算法(UserCF):

from surprise import KNNWithMeans
from surprise import Dataset, print_perf, Reader
from surprise.model_selection import cross_validate
import os

# 指定文件所在路径
file_path = os.path.expanduser('mydata.csv')
reader = Reader(line_format='user item rating timestamp', sep='\t')
# 加载数据
data = Dataset.load_from_file(file_path, reader=reader)
trainset = data.build_full_trainset()
# 读取数据
header = ['user', 'item', 'rating', 'timestamp']
src_data = pd.read_csv('mydata.csv', sep='\t', names = header)
user_data = pd.DataFrame(src_data)
user_data.sort_values(by='user').head()

# user-base CF 得分计算
algo = KNNWithMeans(k=50, sim_options={'user_based': True})
algo.fit(trainset)

uid = str(5)
iid = str(1)
pred = algo.predict(uid, iid)
pred

基于物品的协同过滤算法(ItemCF)

# item-based CF 得分计算
# 取最相似的用户计算时,只取最相似的k个
algo = KNNWithMeans(k=50, sim_options={'user_based': False})
algo.fit(trainset)
uid = str(1)
iid = str(1)

pred = algo.predict(uid, iid)
pred

更多详细教程参考官网surprise

标签:推荐,work,用户,user,物品,surprise,data,hello
来源: https://blog.csdn.net/qq_35200479/article/details/89045967