Search code examples
pythonarrayspython-3.xdivide-by-zeronormalize

Normalizing vectors contained in an array


I've got an array, called X, where every element is a 2d-vector itself. The diagonal of this array is filled with nothing but zero-vectors. Now I need to normalize every vector in this array, without changing the structure of it.

First I tried to calculate the norm of every vector and put it in an array, called N. After that I wanted to divide every element of X by every element of N. Two problems occured to me:

1) Many entries of N are zero, which is obviously a problem when I try to divide by them.

2) The shapes of the arrays don't match, so np.divide() doesn't work as expected.

Beyond that I don't think, that it's a good idea to calculate N like this, because later on I want to be able to do the same with more than two vectors.

import numpy as np

# Example array
X = np.array([[[0, 0], [1, -1]], [[-1, 1], [0, 0]]])
# Array containing the norms
N = np.vstack((np.linalg.norm(X[0], axis=1), np.linalg.norm(X[1], 
axis=1)))
R = np.divide(X, N)

I want the output to look like this:

R = np.array([[[0, 0], [0.70710678, -0.70710678]], [[-0.70710678, 0.70710678], [0, 0]]])

Solution

  • You do not need to use sklearn. Just define a function and then use list comprehension:

    Assuming that the 0th dimension of the X is equal to the number of 2D arrays that you have, use this:

    import numpy as np
    
    # Example array
    X = np.array([[[0, 0], [1, -1]], [[-1, 1], [0, 0]]])
    
    def stdmtx(X):
        X= X - X.mean(axis =1)[:, np.newaxis]
        X= X / X.std(axis= 1, ddof=1)[:, np.newaxis]
        return np.nan_to_num(X)
    
    R = np.array([stdmtx(X[i,:,:]) for i in range(X.shape[0])])
    

    The desired output R:

    array([[[ 0.        ,  0.        ],
            [ 0.70710678, -0.70710678]],
    
           [[-0.70710678,  0.70710678],
            [ 0.        ,  0.        ]]])