我试图理解在TensorLy中实现的张量的Kronecker乘积的代码。以下是代码:
def kron(self, a, b):
"""Kronecker product of two tensors.
Parameters
----------
a, b : tensor
The tensors to compute the kronecker product of.
Returns
-------
tensor
"""
s1, s2 = self.shape(a)
s3, s4 = self.shape(b)
a = self.reshape(a, (s1, 1, s2, 1))
b = self.reshape(b, (1, s3, 1, s4))
return self.reshape(a * b, (s1 * s3, s2 * s4))我知道self.shape(a)会给出张量a (行、列、片)的形状。因此,我们在s1和s2中采用了b的形状,在s3和s4中则采用了b的形状。
a = self.reshape(a, (s1, 1, s2, 1))重塑张量'a',但我发现很难理解什么是(s1, 1, s2, 1),我们为什么要这么做?(1, s3, 1, s4)也是如此。另外,我们为什么要做这个self.reshape(a * b, (s1 * s3, s2 * s4))呢?
这似乎是一个非常开放的问题,但我刚刚开始,并希望得到帮助!
发布于 2019-11-18 13:59:09
这是一个相当常见的使用广播的伎俩。以这种方式将单元尺寸插入a和b中会发生以下情况:
在第一轴中,复制b.
b被复制s1次数,为了匹配第二轴的每一行,a被复制s3次数以匹配每一行的第三轴,b被复制s2次数,与a.
a被复制s4次数,匹配b.的每一列
当你做乘法时,你会得到每个元素组合的4D乘积。元素result[i, j, m, n]来自a[i, m] * b[j, n],最终的整形在内存中接受相同的数据,并将前两个和最后两个轴组合在一起,而不需要重新排列数据。
让我们来看看一个简单的例子:
a = [[1, 2, 3],
[2, 3, 4],
[3, 4, 5]]
b = [[6, 7]]形状从(3, 3)和(1, 2)更改为(3, 1, 3, 1)和(1, 1, 1, 2)。这不会改变内存中的布局,因此a变成
[[[[1], [2], [3]]],
[[[2], [3], [4]]],
[[[3], [4], [5]]]]b变成
[[[[6, 7]]]]结果将是(3, 1, 3, 2),如下所示:
[[[[1*6, 1*7], [2*6, 2*7], [3*6, 3*7]]],
[[[2*6, 2*7], [3*6, 3*7], [4*6, 4*7]]],
[[[3*6, 3*7], [4*6, 4*7], [5*6, 5*7]]]]当您将其重塑为最终结果时,内存布局将保持不变,但形状将更改为(3*1, 3*2)。
[[1*6, 1*7, 2*6, 2*7, 3*6, 3*7],
[2*6, 2*7, 3*6, 3*7, 4*6, 4*7],
[3*6, 3*7, 4*6, 4*7, 5*6, 5*7]]瞧,看看a和b的Kronecker产品。
https://stackoverflow.com/questions/58915428
复制相似问题