协调过滤算法-电影推荐

协调过滤算法-电影推荐

协调过滤概述

​ 协同过滤(Collaborative Filtering)是推荐系统中一种非常基础的方法,它主要分为两个方面:实时的协同作用和预先的过滤处理。在线协同指的是利用实时数据来识别用户可能感兴趣的商品,而离线过滤则是筛选掉一些不太适合推荐的内容,例如那些评分较低的商品,或者用户已经购买过的商品。

​ 在协同过滤的应用中,我们通常面对的是m个商品和m个用户的数据集,但只有部分用户对部分商品进行了评分,留下了许多空白的评分数据。我们的目标是利用这些有限的评分数据来预测那些未知的评分关系,并从中挑选出评分最高的商品,以便向用户推荐。

三种协同过滤推荐

​ 协同过滤推荐系统主要分为三大类:用户基础的协同过滤、项目基础的协同过滤和模型基础的协同过滤。

​ 用户基础的协同过滤侧重于衡量用户间的相似性,通过识别相似用户偏好的商品,预测目标用户可能对这些商品的评分,从而推荐评分最高的几项商品。而项目基础的协同过滤则是寻找商品间的相似性,基于用户对某些商品的评分,预测用户可能对相似商品的评分,并将评分最高的相似商品推荐给用户。例如,如果你在网上购买了一本关于机器学习的书籍,网站可能会推荐一系列与机器学习、大数据相关的书籍,这就是项目基础协同过滤的一个应用实例。

​ 我们可以对比一下用户基础和项目基础的协同过滤:用户基础的协同过滤需要实时计算用户间的相似度,其计算复杂度通常高于项目基础的协同过滤。但它能够帮助用户发现新类别的商品,带来惊喜。相比之下,项目基础的协同过滤由于商品相似性相对稳定,可以预先计算,准确性也较为可靠,但在推荐多样性上可能不如用户基础的协同过滤,难以给用户带来新鲜感。对于小型推荐系统,项目基础的协同过滤可能是更合适的选择。而对于大型推荐系统,则可以考虑用户基础的协同过滤,或者更进一步,采用模型基础的协同过滤。

​ 模型基础的协同过滤是目前最为流行的协同过滤类型,它为众多机器学习算法提供了应用场景。接下来,我们将重点介绍模型基础的协同过滤。

​ 本文为了实现推荐系统,我们通常会使用MovieLens的ml-1000k数据集,这是最常用的数据集之一。它包含了943名用户对1682部电影的100,000条评分数据。点击此处可以下载数据集。

代码实现

必要库

import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.metrics.pairwise import pairwise_distances
from sklearn.metrics import mean_squared_error
from math import sqrt
from pprint import pprint

数据读取并划分训练/测试集

# 加载数据
def create_data():
    data = pd.read_csv('../../data/CF/u.data', sep='\t', names=['user_id', 'item_id', 'rating', 'timestamp'])
    train_data, test_data = train_test_split(data, test_size=0.3, random_state=42)

    return train_data, test_data, data

train_data, test_data, data = create_data()

建立矩阵/计算相似性

# 构建矩阵
def create_matrix():
    # 获取用户和项目(电影)数量
    n_users = data.user_id.nunique()
    n_items = data.item_id.nunique()
    
    #初始化训练矩阵
    train_data_matrix = np.zeros((n_users, n_items))

    # 添加数据
    for line in train_data.itertuples():
        train_data_matrix[line[1] - 1, line[2] - 1] = line[3]
        
    # 测试矩阵,同上
    test_data_matrix = np.zeros((n_users, n_items))
    for line in test_data.itertuples():
        test_data_matrix[line[1] - 1, line[2] - 1] = line[3]
    
    # 通过余弦相似性计算矩阵相似性
    # 用户-项目(电影)计算相似性
    user_similarity = pairwise_distances(train_data_matrix, metric='cosine')
    # 项目(电影)-用户 计算相似性 计算时需转置
    item_similarity = pairwise_distances(train_data_matrix.T, metric='cosine')

    return user_similarity, item_similarity, train_data_matrix, test_data_matrix

user_similarity, item_similarity, train_data_matrix, test_data_matrix = create_matrix()

余弦相似性(Cosine Similarity)是一种衡量两个非零向量之间角度的相似性度量方法,常用于文本处理和推荐系统中。余弦相似性是通过计算两个向量的点积和它们模的乘积的比值来确定的。余弦相似性的计算公式如下:
cosine_similarity ( A , B ) = ∑ i = 1 n A i × B i ∑ i = 1 n A i 2 × ∑ i = 1 n B i 2 \text{cosine\_similarity}(A, B) = \frac{\sum_{i=1}^{n} A_i \times B_i}{\sqrt{\sum_{i=1}^{n} A_i^2} \times \sqrt{\sum_{i=1}^{n} B_i^2}} cosine_similarity(A,B)=i=1nAi2 ×i=1nBi2 i=1nAi×Bi

预测

​ 接下来,我们将进行预测。我们已经构建了用户相似度矩阵(user_similarity)和项目相似度矩阵(item_similarity),现在可以利用以下公式来实现基于用户的协同过滤(user-based CF)预测:
x ^ k , m = x ˉ k + ∑ u a s i m u ( u k , u a ) ( x a , m − x u a ˉ ) ∑ u a ∣ s i m u ( u k , u a ) ∣ \hat{x}_{k,m}=\bar{x}_{k}+\frac{\sum\limits_{u_{a}}sim_{u}(u_{k},u_{a})(x_{a,m}-\bar{x_{u_{a}}})}{\sum\limits_{u_{a}}|sim_{u}(u_{k},u_{a})|} x^k,m=xˉk+uasimu(uk,ua)uasimu(uk,ua)(xa,mxuaˉ)
​ 用户k与用户a之间的相似度是通过考虑用户a对一系列项目的评分(调整为该用户的平均评分)的加权乘积来计算的。为了保持评分在1到5的范围内,你需要对相似度进行标准化,然后计算出你想要预测的用户的平均评分总和。

​ 这里需要考虑的一个问题是,有些用户在评价所有电影时可能倾向于给出最高分或最低分。对于这些用户来说,评分的相对差异比绝对值更重要。例如,用户k可能对他最喜欢的电影给出4星,而对其他好电影给出3星。另一个用户t可能对他喜欢的电影给出5星,而对不喜欢的电影给出3星。这两位用户的电影品味可能相似,但他们使用评分系统的方式不同。

​ 在进行基于项目的协同过滤(item-based CF)推荐时,不需要调整用户的平均评分,因为我们直接使用用户的原始评分来进行预测。
x ^ k , m = ∑ i b sim i ( i m , i b ) ( x k , b ) ∑ i b ∣ sim i ( i m , i b ) ∣ \begin{align*} \hat{x}_{k,m} = \frac{\sum\limits_{i_b}{\text{sim}_i}(i_m,i_b)(x_{k,b})}{\sum\limits_{i_b}{|\text{sim}_i}(i_m,i_b)|} \end{align*} x^k,m=ibsimi(im,ib)ibsimi(im,ib)(xk,b)

# 预测
def predict(ratings, similarity, type='user'):
    if type == 'user':
        mean_user_rating = ratings.mean(axis=1)
        ratings_diff = (ratings - mean_user_rating[:, np.newaxis])
        pred = mean_user_rating[:, np.newaxis] + similarity.dot(ratings_diff) / np.array(
            [np.abs(similarity).sum(axis=1)]).T
    elif type == 'item':
        pred = ratings.dot(similarity) / np.array([np.abs(similarity).sum(axis=1)])
    return pred

item_prediction = predict(train_data_matrix, item_similarity, type='item')
user_prediction = predict(train_data_matrix, user_similarity, type='user')

评估

有众多的评价指标可供选择,但在评估预测准确性方面,根均方误差(Root Mean Squared Error, RMSE)是最受欢迎的指标之一。
R M S E = 1 N ∑ ( x i − x ^ i ) 2 \begin{align*} RMSE = \sqrt{\frac{1}{N} \sum (x_{i} - \hat{x}_{i})^{2}} \end{align*} RMSE=N1(xix^i)2
可以使用sklearn库中的mean_squared_error(MSE)函数来计算均方误差,而RMSE则是MSE的平方根。

由于我们只关心测试数据集中的预测评分,可以通过prediction[ground_truth != 0]来筛选出测试矩阵中所有非零元素,从而仅对这些元素进行评估。

# 评估
def rmse(prediction, ground_truth):
    prediction = prediction[ground_truth.nonzero()].flatten()
    ground_truth = ground_truth[ground_truth.nonzero()].flatten()
    return sqrt(mean_squared_error(prediction, ground_truth))

print('User-based CF RMSE: ' + str(rmse(user_prediction, test_data_matrix)))
print('Item-based CF RMSE: ' + str(rmse(item_prediction, test_data_matrix)))

评估结果

协调过滤算法-电影推荐_第1张图片

你可能感兴趣的:(机器学习,sklearn)