【推荐算法 学习与复现】-- 深度学习系列 -- AutoRec

        个人简单理解 AutoRec 模型就是利用神经网络模型来实现矩阵分解的过程,数学表达上和LFM 隐语义模型很类似。假设图中蓝色神经元代表的为 k 层单隐藏层,图中 的 V M 分别代表输入到隐藏层、以及隐藏层到输出的参数矩阵,用数学表达形式就是:

h(\boldsymbol{r} ; \theta)=f(\boldsymbol{W} \cdot g(\boldsymbol{V} \boldsymbol{r}+\mu)+b)

        其中,f() 和 g() 为输出层、隐藏层的激活函数。 其实从形式上来看,假设输入层维度为 n×m n表示batchsize,不考虑偏置项,第一层参数的维度为 m × k, 第二层参数的维度为 k × m,输入特征经过编码解码的结构后,特征维度不变,用于对输入中存在空值的地方进行预测,而优化的目标就是计算  在输入层存在的值与对应输出层输出值之间的均方差(只对原先存在的值进行计算,这里与LFM的思路是一致的),同时为了防止过拟合,加入L2正则化,最终如下:

\min _{\theta} \sum_{i=1}^{n}\left\|\boldsymbol{r}^{(i)}-h\left(\boldsymbol{r}^{(i)} ; \theta\right)\right\|_{0}^{2}+\frac{\lambda}{2} \cdot\left(\|W\|_{F}^{2}+\|V\|_{F}^{2}\right)

对比 LFM 中的优化目标:

C=\sum_{(u, i) \in K}\left(r_{u i}-\hat{r}_{u i}\right)^{2}=\sum_{(u, i) \in K}\left(r_{u i}-\sum_{k=1}^{K} p_{u, k} q_{k, i}\right)^{2}+\lambda\left\|p_{u}\right\|^{2}+\lambda\left\|q_{i}\right\|^{2}

        两者其实是一样的,只不过LFM中的输出层的值为 通过用户矩阵和物品矩阵相乘得到,而AutoRec输出层值为通过两层神经网络计算得到。这里我们也选用 SGD 作为优化方法,直接使用pytorch搭建神经网络,自动进行梯度计算和回传,不需要像 LFM 中得显示的计算梯度和更新。

【推荐算法 学习与复现】-- 协同过滤算法族-- LFM_Big_Huang的博客-CSDN博客icon-default.png?t=M3C8https://blog.csdn.net/Big_Huang/article/details/124201746?spm=1001.2014.3001.5501

代码复现:

数据下载链接:

协同过滤算法族数据示例-深度学习文档类资源-CSDN文库icon-default.png?t=M3C8https://download.csdn.net/download/Big_Huang/85144402?spm=1001.2014.3001.5501

import torch
import torch.nn as nn
import numpy as np
import pandas as pd
from torch.autograd import Variable
import torch.optim as optim
import torch.nn.functional as F

class AutoRec(nn.Module):
    def __init__(self, user_nums, hidden_features):
        super().__init__()

        self.__encoder = nn.Sequential(
            nn.Linear(user_nums, hidden_features, bias=True),
            nn.Sigmoid()
            
        )
        # 解码器输出激活函数不能用Sigmoid,会限制输出
        self.__decoder = nn.Sequential(
            nn.Linear(hidden_features, user_nums, bias=True)
        )

    def forward(self, x):
        return self.__decoder(self.__encoder(x))

def l2_regularization(model):
    loss = 0
    for name, param in model.named_parameters():
        # 去除掉对偏置项的正则化
        if name[-4:] != 'bias':
            loss += torch.linalg.norm(param.flatten(), 2)
    return loss

def lossFunction(y, pred, mask, lamda, model):
    return F.mse_loss(pred * mask, y) + 0.5 * lamda * l2_regularization(model)


model = AutoRec(5, 2)
optimizer = optim.SGD(model.parameters(), lr=0.03)
user_item = pd.read_csv("./data.csv", index_col=0).fillna(0) # 空值全用0填充,计算Loss的时候仅对非空评分
user_item_matrix = torch.from_numpy(np.array(user_item)).float()
# 仅对存在值的区域进loss计算,制造掩膜
mask_matrix = user_item_matrix > 0



# 训练阶段
for epoch in range(2000):
    # 遍历每一行
    loss_epoch = 0
    for i in range(user_item_matrix.shape[1]):
        item_col = Variable(user_item_matrix[:, i])
        mask_col = Variable(mask_matrix[:, i])
        # forward 过程
        output = model(item_col)
        # loss: Mean Squared Error + L2 regularization
        loss = lossFunction(item_col, output, mask_col, 0.04, model)
        loss_epoch += loss.item()

        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
    print("epoch {}:    loss:{}".format(epoch, loss_epoch/user_item_matrix.shape[1]))

# 推理阶段
for i in range(user_item_matrix.shape[1]):
    item_col = Variable(user_item_matrix[:, i])
    mask_col = Variable(mask_matrix[:, i])
    output = model(item_col)
    print("label: {}:  ======>  pred: {}".format(item_col.numpy(), output.detach().numpy()))


进行推理一下,效果还可以

第五行第一个0是待预测的值,算出来接近5, 墙裂推荐 属于是。

参考:

1. 《深度学习推荐系统》

2. https://datawhalechina.github.io/fun-rec/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值