英文:
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]]
这里的幂遵循正常的矩阵乘法规则;只是元素本身是矩阵。我尝试了matmul
、matrix_power
和pagemtimes
,但都不起作用。
<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'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
做相同的事情。在这里,j
和 l
是乘积维度的总和:
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('ijkl,jmln->imkn',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]]]])
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论