FM算法

FM算法是旨在解决稀疏数据下特征组合问题
线性模型只考虑了单一特征对预测结果的影响,没有考虑组合特征对预测结果的影响。定义目标函数如下:
这里写图片描述
上式中,组合特征参数一共有n(n-1)/2g个,重要的是任意两个参数独立,但在特征非常稀疏的情况下,组合特征(xi,xj)出现同时不为0的情况较少的情况下,直接用梯度下降法对参数wij进行学习会使得大量的wij学习结果为0.训练样本不足,很容易导致参数wij不准确,影响模型的最终效果。
FM算法:
将W矩阵分解为:
这里写图片描述
目标函数进一步写成:
这里写图片描述
其中:这里写图片描述
k代表v向量的维度,直接计算复杂度为O(kn2),因为需要计算所有的两两组合特征的,但通过重新分析目标函数,计算复杂度可以从O(kn2)降低到O(kn):

在参数稀疏的情况下对参数的估计:

在稀疏的前提下,没有足够的样本直接和单独地估计w(ij)【w(ij)反映了变量i和变量j对目标函数的影响程度】,因式分解机制可以不用对每一个不同的(wij)进行单独的估计,即,在有大量的样本可以估计出参数(wij)对(wij)的估计可以帮助估计一些与(wij)关联密切的参数,如(wik,wit或是wsj这些参数)。
自己的一些理解:假如我们要估计的参数是wij=vi*vj转置,但在样本稀疏的情况下,没有足够的样本(xi和xj同时不为0)来估计wij,当将wij表示成vi向量和vj向量相乘后,当有足够的样本估计出wik后,那么就可以获得对vi的估计,这会对wij的估计有帮助,要是能有足够的样本估计出wjt以后,也会对vj的估计有帮助,最终估计到的wij比在没有充足样本下估计为0好很多;论文《Factorization Machines》中举的一个例子,因为Bob对电影StarWars和StarTrek有相似的评分,所以StarWars的因式矢量应该和StarTrek的因式矢量保持相近,所以Alice和Star Trek因式矢量的应该和Alice和Wars的因式矢量相似,因为没有充足的样本估计Alice和Star Trek,但在可以估计出AliceWars的前提下,可以近似得到w(Alice,StarTrek)。

在计算复杂度的程度来看

:因为要计算两两交互的结果,计算复杂度应该是O(k*n^2),但通过数学转换以后,可以变成O(kn):
这里写图片描述

学习FactorizationMachines的参数:
采用SGD训练模型,模型各个参数的梯度更新公式如下:
这里写图片描述
这里写图片描述

训练和测试的计算复杂度为(kn)
总结
FM可以在高稀疏的情况下对数据间交互的作用进行估计,同时可以泛化到没有观测到的数据;另外参数的个数和训练和预测的时间都是线性的,正比于特征的位数。
很好的资料

总结-2
参数因子化可以使得xhxi和xixj参数不再相互独立,因此可以在样本稀疏的情况下相对合理地估计FM二次项系数,xhxi和xixj的系数有一个共同的项vi,所有包含有xi的非零组合特征的样本都可以用来学习隐向量vi,可以有效解决数据稀疏性造成的影响。但在以前的多项式模型中,wij与whi会相互独立。
深入理解FFM原理与实践

FM(因子分解机)是一种经典的推荐算法,它可以用于处理稀疏数据并且具有较好的预测性能。下面是使用PyTorch实现FM算法的基本步骤: 1. 导入需要的库: ```python import torch import torch.nn as nn import torch.optim as optim ``` 2. 定义FM模型 ```python class FM(nn.Module): def __init__(self, input_dim, k): super(FM, self).__init__() self.k = k self.linear = nn.Linear(input_dim, 1) self.v = nn.Parameter(torch.randn(input_dim, k)) def forward(self, x): linear_part = self.linear(x) inter_part1 = torch.matmul(x, self.v) inter_part2 = torch.matmul(torch.pow(x, 2), torch.pow(self.v, 2)) inter_part = 0.5 * torch.sum(torch.sub(inter_part1, inter_part2), 1, keepdim=True) output = linear_part + inter_part return output ``` 3. 定义训练函数 ```python def train(model, dataloader, optimizer, criterion): model.train() train_loss = 0 for batch_idx, (data, target) in enumerate(dataloader): optimizer.zero_grad() output = model(data) loss = criterion(output, target) train_loss += loss.item() loss.backward() optimizer.step() return train_loss / len(dataloader.dataset) ``` 4. 定义测试函数 ```python def test(model, dataloader, criterion): model.eval() test_loss = 0 with torch.no_grad(): for data, target in dataloader: output = model(data) test_loss += criterion(output, target).item() return test_loss / len(dataloader.dataset) ``` 5. 加载数据集和设置超参数 ```python from torch.utils.data import DataLoader, Dataset class CustomDataset(Dataset): def __init__(self, x, y): self.x = x self.y = y def __getitem__(self, index): return self.x[index], self.y[index] def __len__(self): return len(self.x) X_train, y_train = ... X_test, y_test = ... train_dataset = CustomDataset(X_train, y_train) test_dataset = CustomDataset(X_test, y_test) batch_size = 64 train_dataloader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True) test_dataloader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False) input_dim = X_train.shape[1] k = 10 lr = 0.01 num_epochs = 50 ``` 6. 训练模型 ```python model = FM(input_dim, k) optimizer = optim.SGD(model.parameters(), lr=lr) criterion = nn.MSELoss() for epoch in range(num_epochs): train_loss = train(model, train_dataloader, optimizer, criterion) test_loss = test(model, test_dataloader, criterion) print(f'Epoch {epoch+1}, Train Loss: {train_loss:.4f}, Test Loss: {test_loss:.4f}') ``` 这样就可以使用PyTorch实现FM算法了。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值