任务6 Slope one 推荐算法简单实现

任务6 Slope one 推荐算法简单实现

1. 算法原理

算法原理见这篇博客, 这篇博客写的还不错. 我只是实现了最基本的版本
Slope One算法基本原理

2. 代码实现

导入相关的包

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import torch
from tqdm import tqdm

下面这几个包是我自己手动实现的, 在之前的博客里面有具体的代码

import Metirc
from utils import loadData, rating2matrix, Split_Dataset_P
import Similarity

下面这个函数是用来计算矩阵评分差的函数的, 具体计算公式可以看最上面提到的那个博客

def calcu_delta(ratings):
    ratingsT = ratings.T
    items = ratings.shape[1]
    delta = torch.zeros(size=(items, items))
    mask = ratingsT > 1e-6
    num_rating = mask.float()
    num_rating = (num_rating).mm(num_rating.T)
    # mask = mask.T
    with tqdm(total=(1+ items) * items / 2) as tq:
        for i in range(ratingsT.shape[1]):
            for j in range(i, ratingsT.shape[1]):
                # print((ratingsT[i] - ratingsT[j]).shape)
                # print((mask[i] * mask[j]).shape)
                t1 = (ratingsT[i] - ratingsT[j]) * (mask[i] * mask[j])
                if num_rating[i, j] < 1e-6:
                    delta[i, j] = 0
                else:
                    delta[i, j] = t1.sum() / num_rating[i, j]
                delta[j, i] = -delta[i, j]
                tq.update(1)
    return delta

这个是利用矩阵的评分差, 来对用户打分进行预测. 这里我们只是对用户没有打过分的物品进行预测

def pred_score2(ratings, delta):
    mask = (ratings > 1e-6).float()
    nums = mask.sum(dim=1)
    index = torch.nonzero(ratings < 1e-6).numpy()
    result = torch.zeros_like(ratings, dtype=torch.float32)
    
    with tqdm(total=len(index)) as tq:
        for i in index:
            num = nums[i[0]].item()
            if num < 1e-6:
                result[i[0], i[1]] = 0
            else:
                 temp1 = ratings[i[0]] + delta[i[1]]
                 temp1 = temp1 * mask[i[0]]
                #  print(temp1)
                 result[i[0], i[1]] = temp1.sum() / num
            tq.update(1)
    return result

下面开始读取数据了

ratings = loadData('./', 'ml-100k')

开始读取数据
用户人数为: 943
电影数目为: 1682

把数据划分为训练集和测试集(8:2)划分的

train_data, test_data = Split_Dataset_P(ratings)

开始划分数据集
100%|██████████| 943/943 [00:05<00:00, 177.22it/s]

为了方便计算, 把打分的数据转换成一个矩阵, 方便后面的计算

train_data = rating2matrix(train_data)
test_data = rating2matrix(test_data)
train_data = torch.tensor(train_data)

开始将数据转换成矩阵
用户人数为: 943
电影数目为: 1682
100%|██████████| 79619/79619 [00:06<00:00, 12027.42it/s]
开始将数据转换成矩阵
用户人数为: 943
电影数目为: 1680
100%|██████████| 20381/20381 [00:01<00:00, 13160.30it/s]

我们对训练集来计算一下物品之间的打分差

delta = calcu_delta(train_data)

31%|███▏ | 445096/1415403.0 [01:01<02:14, 7203.28it/s]

利用上面我们得到的打分差矩阵, 利用(下面的公式来自于这篇博客一开始提到的那篇博客)
( u j ) = ∑ i ∈ S ( u B ) ( d e v i j + u i ) c a r d ‾ ( S ( u B ) ) (u_j)= \frac {\sum_{i\in S(u_B)}(dev_{ij}+u_i)}{car\underline{d}(S(u_B))} (uj)=card(S(uB))iS(uB)(devij+ui)

result = pred_score2(train_data, delta)

100%|██████████| 1506507/1506507 [01:37<00:00, 15514.23it/s]

有了打分矩阵我们就可以开始推荐了(下面这个函数在任务4里面有)

def recommend(score, k = 3):
    """通过预测的物品打分,给用户推荐前k个物品

    Args:
        score (tensor): 这个是预测的打分
        k (int, optional): 推荐前k个物品. Defaults to 3.

    Returns:
        pred, index: pred是推荐的物品对应的打分,index是推荐的物品的索引
    """
    pred, index = torch.topk(input=score, k=k, dim=1)
    return pred, index
rec_value, rec_index = recommend(result, k=10)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值