【问题标题】:Numpy multiplication of a matrix by an array of scalars without for loop矩阵与标量数组的 Numpy 乘法,没有 for 循环
【发布时间】:2020-12-19 02:05:00
【问题描述】:

假设我有以下代码:

# define a 3x3 array
A = np.array([[-2, 1, 1], [1,-2,1], [1,1,-2]])
# define a 1D array of scalars to multiply A with
test = np.arange(10)

for i in range(len(test)):
    matrix = scipy.linalg.expm(A*test[i])

我想看看是否有一种方法可以在不使用 for 循环的情况下进行这种乘法运算。我不想使用矩阵乘法来乘以这两个数组。我将测试数组视为一组标量值,我想将 A 与 A 相乘。必须有某种鬼鬼祟祟的 numpy 方法来做到这一点。有什么想法吗?

【问题讨论】:

  • 从这些数组中创建 (10,3,3) 或 (3,3,10) 数组很容易。但是expm 接受什么?

标签: python python-3.x numpy scipy jupyter-notebook


【解决方案1】:

scipy.linalg.expm 不能与非平方矩阵一起应用:

ValueError: expected a square matrix

所以我认为最简单的方法是:

list_result = list(map(lambda i: scipy.linalg.expm(A*i), range(10)))

如果你只想要一个数组,那么:

np.concatenate(list_result) #for 2D

np.stack(list_result) #for 3D

【讨论】:

    【解决方案2】:

    您可以通过堆叠单位矩阵乘以您要使用的值来完成构建特殊矩阵的技巧。

    我将使用 3x3 矩阵作为示例,但对于任意矩阵的想法是相同的:

    假设我们要乘以矩阵:

    A = np.array([
       [1,0,1],
       [0,1,0],
       [0,0,1] 
    ])
    

    按 [2、3 和 5]。没有循环。

    我们可以构建一个包含身份的特殊矩阵来做到这一点:

    [ 2 * np.eye(3), 3 * np.eye(3), 5 * np.eye(3)]
    
    [ 0 0 2 ] [ 0 0 3] [ 0 0 5 ]
    [ 0 2 0 ] [ 0 3 0] [ 0 5 0 ]
    [ 2 0 0 ] [ 3 0 0] [ 5 0 0 ]
    
    

    我们可以通过列表推导来做到这一点:

    
    multiply_values = [2,3,5]
    
    special_matrix = np.concatenate( [ x * eye(3) for x in multiply_values ], axis=1)
    
    # special_matrix is:
    # array([[2., 0., 0., 3., 0., 0., 5., 0., 0.],
    #        [0., 2., 0., 0., 3., 0., 0., 5., 0.],
    #        [0., 0., 2., 0., 0., 3., 0., 0., 5.]])
    
    

    现在我们可以一步将矩阵相乘:

    result = np.dot( , special_matrix)
    
    # result is
    array([[2., 0., 0., 3., 0., 0., 5., 0., 0.],
           [0., 2., 0., 0., 3., 0., 0., 5., 0.],
           [0., 0., 2., 0., 0., 3., 0., 0., 5.]])
    
    

    可能这个大而宽的矩阵不是我们需要的。

    我们可以得到切片结果产品的部分结果:

    result[:,0:3]
    
    # array([[2., 0., 2.],
    #       [0., 2., 0.],
    #       [0., 0., 2.]])
    
    

    我们可以用另一种理解来处理切片:

    [ special_matrix[:,x:x+3] for x in [0,3,6] ]
    
    # or in a more general way
    
    [ special_matrix[:,x:x+A.shape[0]] for x in list(range(0,A.shape[0]**2,A.shape[0] ]
    

    【讨论】:

    • 使用广播和元素乘法,不需要dot 和串联的eyes
    【解决方案3】:

    这是对“如何在没有 for 循环的情况下通过多个标量缩放矩阵”问题的答案。这忽略了矩阵求幂,因为我认为没有 for 循环就没有办法做到这一点,但问题似乎并没有询问求幂步骤。

    您可以使用 3D 数组来使用 numpy 的矢量化乘法。

    import numpy as np
    
    A = np.array([[[-2, 1, 1], [1,-2,1], [1,1,-2]]])
    test = np.arange(10).reshape(-1,1,1)
    
    result = test*A
    

    【讨论】:

    • 是的,expm 仅适用于 (m,m) 矩阵。它使用某种版本的 Pade 近似值,它不适合“批量”计算。 en.wikipedia.org/wiki/…
    • 我喜欢使用A * np.arange(10)[:, None, None] 表示法,但结果是一样的。使用None/np.newaxis 扩展数组的维度以用于广播目的是一个很好的视觉习惯。
    • 这适用于一般问题,但正如其他人所说,我确实需要可以通过expm 函数传递的东西。但是感谢您的解决方案!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-30
    相关资源
    最近更新 更多