【问题标题】:If matrix_a = [[a, b], [c, d]], and matrix_b = [[w, x], [y, z]] compute matrix_c = [[a*w + c*y, a*x + c*z], [b*w + d*y, b*x + d*z]] in Python 3?如果 matrix_a = [[a, b], [c, d]] 和 matrix_b = [[w, x], [y, z]] 计算 matrix_c = [[a*w + c*y, a*x + c*z], [b*w + d*y, b*x + d*z]] 在 Python 3 中?
【发布时间】:2021-04-25 19:10:14
【问题描述】:

如果我有两个矩阵 matrix_a = [[a, b], [c, d]] 和 matrix_b = [[w, x], [y, z]] 我希望找到以下矩阵 matrix_c = [[aw + cy, ax + cz], [bw + dy, bx + d z]] 我怎么能这样做,不仅适用于这种情况,而且适用于任意大小的 matrix_a 和 matrix_b:
a) 最简单地只使用列表理解
b) 最简单地使用一个函数,该函数将两个矩阵 matrix_a 和 matrix_b 作为输入,并返回 matrix_c
c) 和/或其他 Pythonic 方式?

以下代码是我目前的解决方案。

matrix_a = [[1, 1], [2, 1]]
matrix_b = [[25, 1.5], [30, 2.7]]

# so we should obtain matrix_c = [[85, 6.9], [55, 4.2]]

transposed_matrix_a =[list(i) for i in zip(*matrix_a)]

matrix_c = []
for i in range(len(matrix_a[0])):
    def matrix_element(function, number):
        return [function(number)*matrix_b[number][i] for i in range(len(
            matrix_b[0]))]
        
    def t_matrix_a_element(x):
        return transposed_matrix_a[i][x]

    c_vector = [matrix_element(t_matrix_a_element, i) for i in range(len(
        transposed_matrix_a[0]))]
    matrix_c.append([sum(i) for i in zip(*c_vector)])

print(matrix_c)

编辑: 明确地说,所需的计算是:
matrix_c = [[aw + cy, ax + cz], [bw + dy, bx + dz]]
matrix_c = [[1 x 25 + 2 x 30, 1 x 1.5 + 2 x 2.7], [1 x 25 + 1 x 30, 1 x 1.5 + 1 x 2.7]]
matrix_c = [[85, 6.9], [55, 4.2]]

而不是产品:
[[aw + by, ax + bz], [cw + dy, cx + d z]]

【问题讨论】:

  • 你的代码确实计算了[[85, 6.9], [55, 4.2]],但我认为不是[[aw + ay, bx + bz], [cw + cy, dx + dz]],应该是[[55, 4.2], [110, 4.2]]
  • @tevemadar 抱歉,是的,我搞混了,我现在已经编辑了问题,它是 matirx_c = [[aw + cy, ax + cz], [bw + dy, bx + dz] ] 不是 matrix_c = [[aw + ay, bx + bz], [cw + cy, dx + dz]]。谢谢。

标签: python list matrix list-comprehension


【解决方案1】:

对于 (c) 情况,您可以简单地使用 numpy 模块。

import numpy as np

a = np.array([[1, 1], [2, 1]])
b = np.array([[25, 1.5], [30, 2.7]])

print(a @ b)

[[55. ,  4.2],
 [80. ,  5.7]]

【讨论】:

    【解决方案2】:

    尝试以下方法:

    def transpose(matrix):
        # if you just want to iterate over the 
        # transposed matrix, you can just
        # return zip(*matrix)
        return list(map(list, zip(*matrix)))
    
    matrix_c = []
    
    for row_a in matrix_a:
        row_c= []
        for val_a, row_b in zip(row_a, transpose(matrix_b)):
            val_c = sum(val_a * val_b for val_b in row_b)
            row_c.append(val_c)
        matrix_c.append(row_c)
    
    print(result)
    
    # [[55, 4.2], [110, 4.2]]
    

    另一种方式,虽然是手动的,不能自动化,但以防万一:

    >>> [[a, b], [c, d]], [[w, x], [y, z]] = matrix_a, matrix_b
    
    >>> matrix_c = [[a*w + a*y, b*x + b*z], [c*w + c*y, d*x + d*z]]
    
    >>> matrix_c
    [[55, 4.2], [110, 4.2]]
    

    【讨论】:

    • 谢谢,但我问错了问题,如果您愿意再看一遍,我的意思会有所不同吗?我的意思是 matirx_c = [[aw + cy, ax + cz], [bw + dy, bx + dz]] 不是 matrix_c = [[aw + ay, bx + bz], [cw + cy, dx + dz]]。按照您的建议创建一个名为 transpose 的函数更具可读性,我将从现在开始这样做。
    【解决方案3】:

    完全基于列表理解的问题的另一种解决方案:

    import numpy as np
    
    #mat_a = [[1, 1], [2, 1]]
    #mat_b = [[25, 1.5], [30, 2.7]]
    mat_a = np.random.random((3,4))
    mat_b = np.random.random((4,5))
    
    def matMul(A, B):
        return [list(map(lambda x:sum([i*j for i,j in x]), [list(zip(row, col)) for row in A for col in [list(i) for i in zip(*B)]]))[s*len(B[0]):s*len(B[0])+len(B[0])] for s in range(len(A)) ]
    
    print(mat_a @ mat_b)
    for row in matMul(mat_a, mat_b):
        print(row)
    

    【讨论】:

      【解决方案4】:

      对非 numpy 试试这个: (相信它更像 Pythonic ... ;-) - 比 numpy 版本)

      def matrix_mul(A, B):
          zip_b = list(zip(*B))
          return [[sum(a * b for a, b in zip(row_a, col_b))
                       for col_b in zip_b]
                  for row_a in A]
      
      # one-liner
      """ result = [[ sum(a*b for a,b in zip(X_row,Y_col))
                              for Y_col in zip(*Y)]
                    for X_row in X]
                          
      """
      

      【讨论】:

      • 谢谢,这确实看起来像 Pythonic 并且正是我想到的那种简洁代码......但是此代码中的两种解决方案都返回 [[55, 4.2], [80, 5.7]] 而所需的输出是 [[85, 6.9], [55, 4.2]] 。我认为您已经计算了 [[bw + dy, bx + dz], [cw + dy, cx + dz]] 而不是 [[aw + cy, ax + cz], [bw + dy, bx + dz]] .
      • 感谢 cmets。但是如果你检查矩阵乘法公式,那么答案是正确的。请仔细检查 - emathhelp.net/calculators/linear-algebra
      • 感谢您回复我,我去了您说的链接并选择了矩阵乘法,它返回 [[55, 4.2], [80, 5.7]] 与您的代码相同。但问题不是计算matrix_a和matrix_b的乘积,而是计算matrix_c = [[aw + cy, ax + cz], [bw + dy, bx + dz]]。乘积为 [[aw + by, ax + bz], [cw + dy, cx + bz]]。
      【解决方案5】:
      matrix_a = [[a, b], [c, d]]
      matrix_b = [[w, x], [y, z]]
      matrix_c = [[aw + cy, ax + cz], [bw + dy, bx + dz]]
      

      abcdwxyz 不是很有帮助,尤其是当有人想概括任务时,最好用索引重写,比如

      A = [a b] = [A11 A12],   B = [w x] = [B11 B12]
          [c d]   [A21 A22]        [y z]   [B21 B22]
      
      C = [a*w+c*y  a*x+c*z] = [A11*B11+A21*B21  A11*B12+A21*B22]
          [b*w+d*y  b*x+d*z]   [A12*B11+A22*B21  A12*B12+A22*B22]
      

      那么就有机会观察像

      Cij
      C11 = A11*B11+A21*B21 = Sum Ak_*Bk_ for k=1,2 and _ could be either i or j
      C12 = A11*B12+A21*B22 = Sum Aki*Bkj for k=1,2
      C21 = A12*B11+A22*B21 = Sum Aki*Bkj for k=1,2
      C22 = A12*B12+A22*B22 = Sum Ak_*Bk_ for k=1,2
      Cij = Sum Aki*Bkj
      

      您可能知道的一些事情,尽管我们继续用abcdwxyz 怪物来挖我们的眼睛。

      这是一个矩阵乘法,不是简单的A*B,而是AT*B
      然后你可以例如从Matrix Multiplication in pure Python? 获取一个乘法代码,然后写

      matrix_a = [[1, 1], [2, 1]]
      #matrix_a = [[1, 2], [3, 4]]
      matrix_b = [[25, 1.5], [30, 2.7]]
      
      transposed_matrix_a =[list(i) for i in zip(*matrix_a)]
      transposed_matrix_b =[list(i) for i in zip(*matrix_b)]
      
      print([[sum(ele_a*ele_b for ele_a, ele_b in zip(row_a, col_b)) 
              for col_b in transposed_matrix_b] for row_a in transposed_matrix_a])
      
      a,b,c,d=sum(matrix_a,[])
      w,x,y,z=sum(matrix_b,[])
      print(a*w+c*y,a*x+c*z)
      print(b*w+d*y,b*x+d*z)
      

      会产生

      [[85, 6.9], [55, 4.2]]
      85 6.9
      55 4.2
      

      (注释1,2,3,4 矩阵用于验证目的,因为原始矩阵内部有很多1,某些索引问题可能会被忽视)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-01-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-12-24
        • 2019-01-07
        • 1970-01-01
        相关资源
        最近更新 更多