Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I apply a matrix transform to each row of a NumPy array efficiently?

Let's say I have a 2d NumPy ndarray, like so:

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

Conceptually speaking, what I want to do is this:

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

I have an extremely slow, brute-force method which functionally achieves this:

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 ) )

However, this seems like the sort of operation that NumPy should do well with. I assume that - as someone new to NumPy - I'm just missing something fundamental in the documentation. Any pointers?

Note that if it's faster to create a new ndarray rather than edit it in-place, that can work for what I'm doing, too; speed of the operation is the primary concern.

like image 937
user3089880 Avatar asked Dec 11 '13 07:12

user3089880


People also ask

How do you convert a matrix to a NumPy array?

We can use numpy. flatten() function to convert the matrix to an array. It takes all N elements of the matrix placed into a single dimension array.

How can I make NumPy array faster?

The key to making it fast is to use vectorized operations, generally implemented through NumPy's universal functions (ufuncs). This section motivates the need for NumPy's ufuncs, which can be used to make repeated calculations on array elements much more efficient.


1 Answers

The lengthy series of operations you want to perform is equivalent to the following:

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

or using a new array instead of modifying the original, which should be a bit faster:

data.dot(transform_matrix.T)

Here's the explanation:

For each row:
    Transpose the row

Equivalent to transposing the matrix and then going over the columns.

    Multiply the transposed row by a transformation matrix

Left-multiplying each column of a matrix by a second matrix is equivalent to left-multiplying the whole thing by the second matrix. At this point, what you have is transform_matrix.dot(data.T)

    Transpose the result

One of the basic properties of matrix transposes is that transform_matrix.dot(data.T).T is equivalent to data.dot(transform_matrix.T).

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

The slice assignment does this.

like image 113
user2357112 supports Monica Avatar answered Oct 13 '22 11:10

user2357112 supports Monica