乘以包含矩阵的张量,遵循矩阵乘法规则。

huangapple go评论59阅读模式
英文:

Multiply tensors containing matrices, following matrix multiplication rule

问题

以下是翻译好的内容:

假设我有一个张量其中`A`、`B`、`C``D`都是2x2矩阵

```python
M = [[A, B],
     [C, D]]

如何计算其幂n,例如n=2,使用Python或MATLAB?

M^2 = [[A@A + B@C, A@B + B@D],
       [C@A + D@C, C@B + D@D]]

这里的幂遵循正常的矩阵乘法规则;只是元素本身是矩阵。我尝试了matmulmatrix_powerpagemtimes,但都不起作用。


<details>
<summary>英文:</summary>

Say I have a tensor, where `A`, `B`, `C`, and `D` are all 2x2 matrices:

M = [[A, B],
[C, D]]


How do I get to the power of `n`, for example with `n=2`, with Python or MATLAB

M^2 = [[A@A + B@C, A@B + B@D],
[C@A + D@C, C@B + D@D]]


Here the power just follows the normal matrix multiplication rule; it&#39;s just that the elements are matrices themselves. I tried `matmul`, `matrix_power`, and `pagemtimes`, but nothing works.

</details>


# 答案1
**得分**: 3

您只是计算由连接小矩阵`A`到`D`创建的4x4块矩阵的普通矩阵乘积。

在MATLAB中,使用一些任意矩阵,您的预期结果如下:

```matlab
A = [1, 2
     3, 4];
B = [5, 6
     7, 8];
C = [9, 10
     11, 12];
D = [13, 14
     15, 16];

res = [A*A + B*C, A*B + B*D
       C*A + D*C, C*B + D*D]
res =
   118   132   174   188
   166   188   254   276
   310   356   494   540
   358   412   574   628

4x4块矩阵及其平方如下:

M = [A, B
     C, D];
res2 = M^2
res2 =
   118   132   174   188
   166   188   254   276
   310   356   494   540
   358   412   574   628
英文:

You are just computing the normal matrix product of the 4x4 block matrix created by joining the smaller matrices A through D.

In MATLAB, your expected result using some arbitrary matrices:

A = [1, 2
     3, 4];
B = [5, 6
     7, 8];
C = [ 9, 10
     11, 12];
D = [13, 14
     15, 16];

res = [A*A + B*C, A*B + B*D
       C*A + D*C, C*B + D*D]
res =
   118   132   174   188
   166   188   254   276
   310   356   494   540
   358   412   574   628

The 4x4 block matrix, and its square:

M = [A, B
     C, D];
res2 = M^2
res2 =
   118   132   174   188
   166   188   254   276
   310   356   494   540
   358   412   574   628

答案2

得分: 2

这里是代码的翻译部分:

也许不是最高效的方法但这是一个手动解决方案

M = np.random.randint(0, 10, (2, 2, 2, 2))

def matmatmul(a, b):

    output = np.zeros((a.shape[0], b.shape[1]), dtype=object)

    for i in range(output.shape[0):
        for j in range(output.shape[1):
            row = a[i]
            col = b[:, j]

            output[i,j] = sum([r @ c for r,c in zip(row, col)])

    return output

def matmatpow(a, n):
    if n == 1:
        return a
    else:
        output = matmatmul(a, a)

        for i in range(2, n):
            output = matmatmul(output, a)

        return output

M2 = matmatpow(M, 2)

print(M2)

[[A, B], [C, D]] = M

assert np.all(M2[0,0] == A@A + B@C)
assert np all(M2[0,1] == A@B + B@D)
assert np.all(M2[1,0] == C@A + D@C)
assert np.all(M2[1,1] == C@B + D@D)

请注意,由于代码本身包含特定的编程语法和变量名称,可能需要在实际使用时根据您的上下文和需求进行调整。

英文:

Probably not the most efficient, but here's a manual solution:

M = np.random.randint(0, 10, (2, 2, 2, 2))

def matmatmul(a, b):
    
    output = np.zeros((a.shape[0], b.shape[1]), dtype = object)
    
    for i in range(output.shape[0]):
        for j in range(output.shape[1]):
            row = a[i]
            col = b[:, j]
            
            output[i,j] = sum([r @ c for r,c in zip(row, col)])
            
    return output

def matmatpow(a, n):
    if n == 1:
        return a
    else:
        output = matmatmul(a, a)
        
        for i in range(2, n):
            output = matmatmul(output, a)
        
        return output
    
M2 = matmatpow(M, 2)

print(M2)

[[A, B], [C, D]] = M

assert np.all(M2[0,0] == A@A + B@C)
assert np.all(M2[0,1] == A@B + B@D)
assert np.all(M2[1,0] == C@A + D@C)
assert np.all(M2[1,1] == C@B + D@D)

答案3

得分: 1

以下是翻译好的内容:

Defining a set of (2,2) arrays, and their composite:
定义一组(2,2)数组以及它们的组合:

In [45]: A,B,C,D = [np.arange(i,i+4).reshape(2,2) for i in range(4)]
在 [45] 中:A、B、C、D = [np.arange(i,i+4).reshape(2,2) for i in range(4)]

In [46]: M=np.array([[A,B],[C,D]])
在 [46] 中:M = np.array([[A,B],[C,D]])

Your desired M^2 array:
您期望的 M^2 数组:

In [47]: np.array([[A@A + B@C, A@B + B@D],
...: [C@A + D@C, C@B + D@D]])
在 [47] 中:np.array([[A@A + B@C, A@B + B@D], [C@A + D@C, C@B + D@D]])

Out[47]:
结果[47]:
array([[[[12, 16],
[28, 40]],

    [[16, 20],
     [40, 52]]],


   [[[28, 40],
     [44, 64]],

    [[40, 52],
     [64, 84]]]])

The same thing using einsum. In this j and l are the sum-of-products dimensions:
使用 einsum 做相同的事情。在这里,jl 是乘积维度的总和:

In [48]: np.einsum('ijkl,jmln->imkn',M,M)
在 [48] 中:np.einsum('ijkl,jmln->imkn',M,M)

Out[48]:
结果[48]:
array([[[[12, 16],
[28, 40]],

    [[16, 20],
     [40, 52]]],


   [[[28, 40],
     [44, 64]],

    [[40, 52],
     [64, 84]]]])

matmul is the equivalent of 'ijkl,ijlm->ijkm', where ij are batch dimensions, and l is the sum-of-products. Often an einsum can be reproduced with some reshape and generalized transposing. But I'll leave that for someone else to explore.
matmul 相当于 'ijkl,ijlm->ijkm',其中 ij 是“batch”维度,而 l 是乘积的总和。通常,使用一些重塑和一般化的转置可以复制 einsum。但我将留给其他人去探索。

Playing around with the einsum indices and transposing and reshaping the arrays, I can get the equivalent of:
尝试使用 einsum 的指数、转置和重塑数组,可以获得等效的结果:

In [56]: np.matmul(M.transpose(0,2,1,3).reshape(4,4),M.transpose(0,2,1,3).reshape(4,4))
在 [56] 中:np.matmul(M.transpose(0,2,1,3).reshape(4,4),M.transpose(0,2,1,3).reshape(4,4))

Out[56]:
结果[56]:
array([[12, 16, 16, 20],
[28, 40, 40, 52],
[28, 40, 40, 52],
[44, 64, 64, 84]])

which with a bit more massaging becomes the desired (4,4,4,4)
稍微调整后,可以得到所需的 (4,4,4,4)

In [57]: np.matmul(M.transpose(0,2,1,3).reshape(4,4),M.transpose(0,2,1,3).reshape(4,4)).reshape(2,2,2,2).transpose(0,2,1,3)
在 [57] 中:np.matmul(M.transpose(0,2,1,3).reshape(4,4),M.transpose(0,2,1,3).reshape(4,4)).reshape(2,2,2,2).transpose(0,2,1,3)

Out[57]:
结果[57]:
array([[[[12, 16],
[28, 40]],

    [[16, 20],
     [40, 52]]],


   [[[28, 40],
     [44, 64]],

    [[40, 52],
     [64, 84]]])
英文:

Defining a set of (2,2) arrays, and their composite:

In [45]: A,B,C,D = [np.arange(i,i+4).reshape(2,2) for i in range(4)]    
In [46]: M=np.array([[A,B],[C,D]])

Your desired M^2 array:

In [47]: np.array([[A@A + B@C, A@B + B@D],
    ...:       [C@A + D@C, C@B + D@D]])
Out[47]: 
array([[[[12, 16],
         [28, 40]],

        [[16, 20],
         [40, 52]]],


       [[[28, 40],
         [44, 64]],

        [[40, 52],
         [64, 84]]]])

The same thing using einsum. In this j and l are the sum-of-products dimensions:

In [48]: np.einsum(&#39;ijkl,jmln-&gt;imkn&#39;,M,M)
Out[48]: 
array([[[[12, 16],
         [28, 40]],

        [[16, 20],
         [40, 52]]],


       [[[28, 40],
         [44, 64]],

        [[40, 52],
         [64, 84]]]])

matmul is the equivalent of 'ijkl,ijlm->ijkm', where ij are batch dimensions, and l is the sum-of-products. Often an einsum can be reproduced with some reshape and generalized transposing. But I'll leave that for someone else to explore.

Playing around with the einsum indices and transposing and reshaping the arrays, I can get the equivalent of:

In [56]: np.matmul(M.transpose(0,2,1,3).reshape(4,4),M.transpose(0,2,1,3).reshape(4,4))
Out[56]: 
array([[12, 16, 16, 20],
       [28, 40, 40, 52],
       [28, 40, 40, 52],
       [44, 64, 64, 84]])

which with a bit more massaging becomes the desired (4,4,4,4)

In [57]: np.matmul(M.transpose(0,2,1,3).reshape(4,4),M.transpose(0,2,1,3).reshape(4,4)).reshape(2,2,2,2).transpose(0,2,1,3)
Out[57]: 
array([[[[12, 16],
         [28, 40]],

        [[16, 20],
         [40, 52]]],


       [[[28, 40],
         [44, 64]],

        [[40, 52],
         [64, 84]]]])

huangapple
  • 本文由 发表于 2023年2月16日 05:32:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/75465639.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定