我试图将Tensor(m,n,o)分解为矩阵A(m,r),B(n,r)和C(k,r).这称为PARAFAC分解. Tensorly已经做了这种分解.
重要的一步是将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不支持的一些方面.但是,autograd确实支持np.tensordot.
我想知道如何使用np.tensordot来获得这个乘法.我认为Tensorflow的tf.tensordot也有类似的功能.
预期的解决方案应该是这样的:
def tensordot_multplication(A, B, C):
"""
use np.tensordot
"""
解决方法:
不要认为np.tensordot会帮助你,因为它需要展开不参与减少的轴,因为我们有对齐要求在执行乘法时保持最后一个轴在三个输入之间对齐.因此,使用tensordot,您将需要额外的处理并且在那里有更多的内存要求.
我建议两种方法 – 一种是broadcasting
,另一种是np.einsum
.
方法#1:广播 –
(A[:,None,None,:]*B[:,None,:]*C).sum(-1)
说明:
>通过在轴=(1,2)处使用None / np.newaxis引入新轴,将A扩展为4D.
>类似地,通过在轴=(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)
这个想法与之前的广播相同,但是使用字符串符号帮助我们以更简洁的方式传达轴信息.
广播肯定可用于张量流,因为它具有expand dimensions
的工具,而np.einsum可能不是.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。