我想以向量化的方式实现现场感知因式分解模型(FFM)。在FFM中,可以通过以下方程式进行预测
其中w是取决于特征和另一个特征的字段的嵌入。有关更多信息,请参见FFM中的方程(4)
。
为此,我定义了以下参数:
import torch
W = torch.nn.Parameter(torch.Tensor(n_features, n_fields, n_factors), requires_grad=True)
现在,给定大小为x
的输入(batch_size, n_features)
,我希望能够计算前面的方程。这是我当前的(非矢量化)实现:
total_inter = torch.zeros(x.shape[0])
for i in range(n_features):
for j in range(i + 1, n_features):
temp1 = torch.mm(
x[:, i].unsqueeze(1),
W[i, feature2field[j], :].unsqueeze(0))
temp2 = torch.mm(
x[:, j].unsqueeze(1),
W[j, feature2field[i], :].unsqueeze(0))
total_inter += torch.sum(temp1 * temp2, dim=1)
不足为奇的是,此实现非常慢,因为n_features
可以轻易地达到1000!但是请注意,x
的大多数条目都是0。感谢所有输入!
编辑:
如果可以以任何方式提供帮助,请在PyTorch中使用此模型的一些实现:
不幸的是,我无法确切地知道他们是如何做到的。
答案 0 :(得分:2)
使用pytorch sparse tensors可能会帮助您加快乘法速度。
另外可能有效的方法如下: 创建 n 数组,为每个要素 i 分配一个,将在每行中保留其对应的场因子。例如对于特征i = 0
[ W[0, feature2field[0], :],
W[0, feature2field[1], :],
W[0, feature2field[n], :]]
然后计算这些数组的乘法,用X称它们为F
R[i] = F[i] * X
因此R中的每个元素都将保存F [i]与X的乘法结果,即数组。
接下来,您将每个R [i]与其转置相乘
R[i] = R[i] * R[i].T
现在您可以像之前一样在循环中进行求和
for i in range(n_features):
total_inter += torch.sum(R[i], dim=1)
请把它和一粒盐一起服用,因为我还没有测试过。无论如何,我认为这将为您指明正确的方向。
可能发生的一个问题是转置乘法,其中每个元素还将与自身相乘,然后相加。我认为这不会影响分类器,但是无论如何,您都可以使元素位于转置的对角线上并大于0(包括对角线)。
尽管如此,不过尽管如此,请还是将第一个取消挤压操作移到嵌套的for循环之外。
希望对您有帮助。