现场感知因式分解的矢量化实现

时间:2019-07-02 21:28:04

标签: python-3.x machine-learning pytorch recommender-systems

我想以向量化的方式实现现场感知因式分解模型(FFM)。在FFM中,可以通过以下方程式进行预测

$ \sum_{j_1=1}^n \sum_{j_2=j_1+1}^n (\textbf{w}_{j_1, f_2}, \textbf{w}_{j_2, f_1}) x_{j_1} x_{j_2} $

其中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中使用此模型的一些实现:

不幸的是,我无法确切地知道他们是如何做到的。

1 个答案:

答案 0 :(得分:2)

  1. 使用pytorch sparse tensors可能会帮助您加快乘法速度。

  2. 另外可能有效的方法如下: 创建 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循环之外。

希望对您有帮助。