【问题标题】:Khatri product of matrices using np.tensordot使用 np.tensordot 的矩阵的 Khatri 积
【发布时间】:2017-09-01 09:28:45
【问题描述】:

我正在尝试将张量 (m, n, o) 分解为矩阵 A(m, r)、B (n, r) 和 C (k, r)。这称为 PARAFAC 分解。 Tensorly 已经进行了这种分解。

一个重要的步骤是将 A、B 和 C 相乘以获得形状为 (m, n, o) 的张量。

Tensorly 这样做如下:

def kt_to_tensor(A, B, C):
    factors = [A, B, C]
    for r in range(factors[0].shape[1]):
        vecs = np.ix_(*[u[:, r] for u in factors])
        if r:
            res += reduce(np.multiply, vecs)
        else:
            res = reduce(np.multiply, vecs)
    return res

但是,我使用的包 (Autograd) 不支持 np.ix_ 操作。因此我写了一个更简单的定义如下:

def new_kt_to_tensor(A, B, C):
    m, n, o = A.shape[0], B.shape[0], C.shape[0]
    out = np.zeros((m, n, o))
    k_max = A.shape[1]
    for alpha in range(0, m):
        for beta in range(0, n):
            for delta in range(0, o):
                for k in range(0, k_max):
                    out[alpha, beta, delta]=out[alpha, beta, delta]+ A[alpha, k]*B[beta, k]*C[delta, k]
    return out

然而,事实证明,这个实现也有一些 autograd 不支持的方面。但是,autograd 确实支持np.tensordot

我想知道如何使用np.tensordot 来获得这个乘法。我认为 Tensorflow 的 tf.tensordot 也会有类似的功能。

预期的解决方案应该是这样的:

def tensordot_multplication(A, B, C):
    """
    use np.tensordot
    """

【问题讨论】:

  • 我对您的ix_ 评论感到惊讶。很长一段时间以来,这一直是 numpy 的一部分。 reduce 可能需要在 PY3 中导入。
  • @hpaulj :Numpy 确实支持这些。但是,Autograd 不允许使用 .ix_ 来计算梯度。见:github.com/HIPS/autograd/issues/210
  • ix_ 只是进行 Divakar 的第一种方法所做的那种维度扩展。 reduce 应用乘法部分。
  • 好的。只是 Autograd 目前不支持 ix_
  • 我看了Autograd。显然它解析了 numpy 代码,并有自己的“符号”渐变。它实际上并没有运行您的功能。 ix_ 位于一个名为 np.lib.index_tricks 的文件中,并提供各种索引快捷方式,但没有新功能。

标签: python numpy tensorflow tensor scikit-tensor


【解决方案1】:

不要认为np.tensordot 在这里会帮助你,因为它需要展开不参与减和的轴,因为我们有保持对齐的要求在执行乘法时,最后一个轴在三个输入之间对齐。因此,使用tensordot,您将需要额外的处理并且需要更多的内存。

我建议两种方法 - 一种使用broadcasting,另一种使用np.einsum

方法#1:使用broadcasting -

(A[:,None,None,:]*B[:,None,:]*C).sum(-1)

解释:

  • A 扩展到4D,通过在axis=(1,2) 处引入新轴和None/np.newaxis。

  • 通过在axis=(1) 引入新轴,将B 类似地扩展到3D

  • 保持 C 不变并执行元素乘法,得到 4D 数组。

  • 最后,sum-reduction 沿着 4D 数组的最后一个轴进入。

示意图-

A        : m        r
B        :    n     r
C        :       k  r

=> A*B*C : m  n  k  r
=> out   : m  n  k    # (sum-reduction along last axis)

方法 #2: 使用 np.einsum -

np.einsum('il,jl,kl->ijk',A,B,C)

这里的想法与之前的 broadcasting 相同,但使用字符串表示法帮助我们以更简洁的方式传达轴信息。

Broadcasting 肯定可以在tensorflow 上使用,因为它有expand dimensions 的工具,而np.einsum 可能没有。

【讨论】:

  • 谢谢!这太棒了!如果您可以添加几行来解释每个解决方案,那就太好了!
  • 感谢您的编辑。它现在真的非常有用!
【解决方案2】:

您引用的代码实际上并不是 TensorLy 如何实现它,而只是文档中给出的替代实现。

TensorLy 中使用的actual code 是:

def kruskal_to_tensor(factors):
    shape = [factor.shape[0] for factor in factors]
    full_tensor = np.dot(factors[0], khatri_rao(factors[1:]).T)
    return fold(full_tensor, 0, shape)

khatri_rao 是使用 numpy.einsum 以概括 Divakar 建议的方式实现的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-04-23
    • 2017-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-20
    • 1970-01-01
    相关资源
    最近更新 更多