我试图把张量(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但是,我使用的包(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确实支持np.tensordot。
我想知道如何使用np.tensordot来获得这个乘法。我认为Tensorflow的tf.tensordot也有类似的功能。
预期的解决方案应如下所示:
def tensordot_multplication(A, B, C):
"""
use np.tensordot
"""发布于 2017-04-06 11:27:39
不要认为np.tensordot会在这里帮助您,因为它需要展开不参与和缩减的轴,因为我们在执行乘法时需要保持三个输入之间的最后一个轴对齐。因此,使用tensordot,您将需要额外的处理,并且需要更多的内存需求。
我建议两种方法--一种用于broadcasting,另一种用于np.einsum。
方法#1 :与broadcasting -
(A[:,None,None,:]*B[:,None,:]*C).sum(-1)说明:
A扩展到4D,在axis=(1,2)上引入None/np.newaxis的新轴。B扩展到3D,在axis=(1)中引入新的轴。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一样,但是字符串符号帮助我们以更简洁的方式传递轴信息。
Broadcasting当然可以在tensorflow上使用,因为它有用于expand dimensions的工具,而np.einsum可能没有。
发布于 2017-06-06 00:32:09
https://stackoverflow.com/questions/43253670
复制相似问题