推荐系统经典算法:FM的pytorch实现

        首先说明为什么用pytorch实现该算法:因为暑假里尝试过在cpu里运行的简陋版本,运行速度过于缓慢;pytorch中有现成的embedding方法可以使用并且做梯度下降比较容易。

下面先说核心算法部分:

这里的时间复杂度仍为o(kn^2),下面是化简到o(kn)

具体实现:

class FactorizationMachine(nn.Module):

    def __init__(self, field_dims, embed_dim=4):
        super(FactorizationMachine, self).__init__()

        self.embed1 = FeaturesEmbedding(field_dims, 1)
        self.embed2 = FeaturesEmbedding(field_dims, embed_dim)
        self.bias = nn.Parameter(torch.zeros((1,)))

    def forward(self, x):
        # x shape: (batch_size, num_fields)
        # embed(x) shape: (batch_size, num_fields, embed_dim)
        square_sum = self.embed2(x).sum(dim=1).pow(2).sum(dim=1)
        sum_square = self.embed2(x).pow(2).sum(dim=1).sum(dim=1)

        output = self.embed1(x).squeeze(-1).sum(dim=1) + self.bias + (square_sum - sum_square) / 2
        output = torch.sigmoid(output).unsqueeze(-1)
        return output

最后附上全部代码:

FM.py

from utils import create_dataset, Trainer
from layer import Embedding, FeaturesEmbedding, EmbeddingsInteraction, MultiLayerPerceptron

import torch
import torch.nn as nn
import torch.optim as optim

device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')
print('Training on [{}].'.format(device))

dataset = create_dataset(sample_num=100000, device=device)
field_dims, (train_X, train_y), (test_X, test_y) = dataset.train_valid_test_split()


class FactorizationMachine(nn.Module):

    def __init__(self, field_dims, embed_dim=4):
        super(FactorizationMachine, self).__init__()

        self.embed1 = FeaturesEmbedding(field_dims, 1)
        self.embed2 = FeaturesEmbedding(field_dims, embed_dim)
        self.bias = nn.Parameter(torch.zeros((1,)))

    def forward(self, x):
        # x shape: (batch_size, num_fields)
        # embed(x) shape: (batch_size, num_fields, embed_dim)
        square_sum = self.embed2(x).sum(dim=1).pow(2).sum(dim=1)
        sum_square = self.embed2(x).pow(2).sum(dim=1).sum(dim=1)

    
  • 4
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
FM(Factorization Machines)是一种经典推荐算法。它通过对特征进行二阶多项式扩展,建立了一个能够考虑特征交互的模型。在这个模型中,每个特征都有一个隐向量表示,通过对这些隐向量的乘积求和来计算二阶特征交互的权重。 下面是使用PyTorch实现FM模型的代码: ```python import torch import torch.nn as nn import torch.optim as optim from torch.utils.data import Dataset, DataLoader class FM(nn.Module): def __init__(self, n_feat, k): super(FM, self).__init__() self.n_feat = n_feat self.k = k self.linear = nn.Linear(n_feat, 1) self.embedding = nn.Embedding(n_feat, k) def forward(self, x): # x: (batch_size, n_feat) linear_part = self.linear(x).squeeze(1) # (batch_size,) embedding_part = torch.sum(self.embedding(x), dim=1) # (batch_size, k) square_of_sum = torch.sum(embedding_part, dim=1) ** 2 # (batch_size,) sum_of_square = torch.sum(embedding_part ** 2, dim=1) # (batch_size,) second_order = 0.5 * (square_of_sum - sum_of_square) # (batch_size,) y = linear_part + second_order # (batch_size,) return y class RatingDataset(Dataset): def __init__(self, data): self.data = data def __len__(self): return len(self.data) def __getitem__(self, index): x = self.data[index, :-1] y = self.data[index, -1] return x, y if __name__ == '__main__': # 读取数据 data = torch.tensor([ [0, 1, 1], [1, 0, 1], [1, 1, 1], [0, 0, 0], [0, 1, 0], [1, 0, 0], ], dtype=torch.long) target = torch.tensor([5, 3, 4, 1, 2, 1], dtype=torch.float) dataset = RatingDataset(torch.cat([data, target.unsqueeze(dim=1)], dim=1)) dataloader = DataLoader(dataset, batch_size=2, shuffle=True) # 定义模型 model = FM(n_feat=3, k=2) # 定义损失函数和优化器 criterion = nn.MSELoss() optimizer = optim.SGD(model.parameters(), lr=0.01) # 训练模型 for epoch in range(100): for x, y in dataloader: optimizer.zero_grad() y_pred = model(x) loss = criterion(y_pred, y) loss.backward() optimizer.step() print('Epoch [{}/{}], Loss: {:.4f}'.format(epoch+1, 100, loss.item())) # 预测 with torch.no_grad(): x_test = torch.tensor([[0, 1, 0], [1, 1, 0]], dtype=torch.long) y_test = torch.tensor([0, 0], dtype=torch.float) y_pred = model(x_test) print('Test Loss: {:.4f}'.format(criterion(y_pred, y_test).item())) print('Predictions:', y_pred) ``` 在这个代码中,我们首先定义了一个继承自`nn.Module`的`FM`类,其中`linear`是一阶线性部分的权重,`embedding`是二阶交互部分的权重。在`forward`函数中,我们首先计算一阶部分的输出,然后计算二阶部分的输出,并将两部分相加得到最终输出。 接下来我们定义了一个继承自`Dataset`的`RatingDataset`类,用于读取数据和构建数据集。在主函数中,我们首先读取数据并构建数据集和数据加载器。然后定义了一个`FM`模型、一个均方误差损失函数和一个随机梯度下降优化器。在训练过程中,我们遍历数据集中的所有样本,计算损失并更新模型参数。最后,我们使用训练好的模型对测试集进行预测,并输出预测结果和测试误差。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值