如何有效地将矩阵变换应用于NumPy数组的每一行?

时间:2013-12-11 07:16:53

标签: python arrays numpy multidimensional-array

假设我有一个2d NumPy ndarray,就像这样:

[[ 0, 1, 2, 3 ],
 [ 4, 5, 6, 7 ],
 [ 8, 9, 10, 11 ]]

从概念上讲,我想做的是:

For each row:
    Transpose the row
    Multiply the transposed row by a transformation matrix
    Transpose the result
    Store the result in the original ndarray, overwriting the original row data

我有一个非常缓慢,强力的方法,在功能上达到了这个目的:

import numpy as np
transform_matrix = np.matrix( /* 4x4 matrix setup clipped for brevity */ )
for i, row in enumerate( data ):
    tr = row.reshape( ( 4, 1 ) )
    new_row = np.dot( transform_matrix, tr )
    data[i] = new_row.reshape( ( 1, 4 ) )

然而,这似乎是NumPy应该做的那种操作。我认为 - 作为NumPy的新手 - 我只是遗漏了文档中的一些基本内容。有什么指针吗?

请注意,如果创建一个新的ndarray更快,而不是就地编辑它,那也可以用于我正在做的事情;操作速度是首要考虑因素。

2 个答案:

答案 0 :(得分:10)

您要执行的一系列操作等同于以下内容:

data[:] = data.dot(transform_matrix.T)

或使用新数组而不是修改原始数据,这应该更快一些:

data.dot(transform_matrix.T)

以下是解释:

For each row:
    Transpose the row

相当于转置矩阵然后遍历列。

    Multiply the transposed row by a transformation matrix

将矩阵的每列乘以第二矩阵相当于将整个事物左乘第二矩阵。此时,您所拥有的是transform_matrix.dot(data.T)

    Transpose the result

矩阵转置的一个基本属性是transform_matrix.dot(data.T).T等同于data.dot(transform_matrix.T)

    Store the result in the original ndarray, overwriting the original row data

切片分配就是这样做的。

答案 1 :(得分:2)

您似乎需要transpose operator

>>> np.random.seed(11)
>>> transform_matrix = np.random.randint(1, 10, (4,4))
>>> np.dot(transform_matrix, data.T).T
matrix([[ 24,  24,  17,  37],
        [ 76, 108,  61, 137],
        [128, 192, 105, 237]])

或等效地,如(A * B).T =(B.T * A.T):

>>> np.dot(data, transform_matrix.T)