Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/302.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/video/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 用np.tensordot求矩阵的Khatri积_Python_Numpy_Tensorflow_Tensor_Scikit Tensor - Fatal编程技术网

Python 用np.tensordot求矩阵的Khatri积

Python 用np.tensordot求矩阵的Khatri积,python,numpy,tensorflow,tensor,scikit-tensor,Python,Numpy,Tensorflow,Tensor,Scikit Tensor,我试图将张量(m,n,o)分解成矩阵a(m,r),B(n,r)和C(k,r)。这被称为PARAFAC分解。已经进行了这种分解 一个重要的步骤是将A、B和C相乘,得到形状张量(m、n、o) 张力如下所示: 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])

我试图将张量(m,n,o)分解成矩阵a(m,r),B(n,r)和C(k,r)。这被称为PARAFAC分解。已经进行了这种分解

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

张力如下所示:

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
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)不支持
np.ix
操作。因此,我写了一个更简单的定义如下:

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
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
    """

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

我建议使用两种方法,一种是使用,另一种是使用

方法#1:使用
广播
-

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

  • A
    扩展到
    4D
    ,方法是在
    轴=(1,2)
    处引入具有None/np.newaxis的新轴

  • 同样地,通过在轴=(1)处引入新的轴,将
    B
    扩展到
    3D

  • 保持
    C
    原样,执行元素乘法,生成
    4D
    数组

  • 最后,总和减少沿
    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
当然可以在
tensorflow
上使用,因为它有工具可以使用,而
np.einsum
可能不是。

您提到的代码实际上不是如何紧张地实现它,而只是文档中给出的替代实现

在TensorLy中使用的是:

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)

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

谢谢!这太棒了!如果您可以添加几行解释每个解决方案,那就太好了!谢谢你的编辑。现在真的很有用了!我对你的评论感到惊讶。这已经成为numpy的一部分很长时间了。
reduce
可能需要在PY3中导入。@hpaulj:Numpy不支持这些。但是,Autograd不允许使用.ix_u计算梯度。请参阅:
ix
只进行Divakar第一种方法所做的维度扩展。
reduce
应用乘法部分。好的。只是Autograd目前不支持ix_,我看的是
Autograd
。显然,它解析numpy代码,并实现自己的“符号”渐变。它实际上并没有运行你的函数
ix
位于一个名为
np.lib.index
的文件中,提供了多种索引快捷方式,但没有新功能。