Normalizing rows of a matrix python

30,264

Solution 1

This is the L₁ norm:

>>> np.abs(X).sum(axis=1)
array([12, 20, 13, 44, 42])

This is the L₂ norm:

>>> np.sqrt((X * X).sum(axis=1))
array([  7.07106781,  10.09950494,   7.41619849,  27.67670501,  27.45906044])

This is the L∞ norm:

>>> np.abs(X).max(axis=1)
array([ 6,  6,  5, 25, 25])

To normalise rows, just divide by the norm. For example, using L₂ normalisation:

>>> l2norm = np.sqrt((X * X).sum(axis=1))
>>> X / l2norm.reshape(5,1)
array([[ 0.14142136,  0.28284271,  0.42426407,  0.84852814],
       [ 0.39605902,  0.49507377,  0.59408853,  0.49507377],
       [ 0.13483997,  0.26967994,  0.67419986,  0.67419986],
       [ 0.14452587,  0.18065734,  0.36131469,  0.90328672],
       [ 0.18208926,  0.0728357 ,  0.36417852,  0.9104463 ]])
>>> np.sqrt((_ * _).sum(axis=1))
array([ 1.,  1.,  1.,  1.,  1.])

More direct is the norm method in numpy.linalg, if you have it available:

>>> from numpy.linalg import norm
>>> norm(X, axis=1, ord=1)  # L-1 norm
array([12, 20, 13, 44, 42])
>>> norm(X, axis=1, ord=2)  # L-2 norm
array([  7.07106781,  10.09950494,   7.41619849,  27.67670501,  27.45906044])
>>> norm(X, axis=1, ord=np.inf)  # L-∞ norm
array([ 6,  6,  5, 25, 25])

(after OP edit): You saw zero values because / is an integer division in Python 2.x. Either upgrade to Python 3, or change dtype to float to avoid that integer division:

>>> linfnorm = norm(X, axis=1, ord=np.inf)
>>> X.astype(np.float) / linfnorm[:,None]
array([[ 0.16666667,  0.33333333,  0.5       ,  1.        ],
       [ 0.66666667,  0.83333333,  1.        ,  0.83333333],
       [ 0.2       ,  0.4       ,  1.        ,  1.        ],
       [ 0.16      ,  0.2       ,  0.4       ,  1.        ],
       [ 0.2       ,  0.08      ,  0.4       ,  1.        ]])

Solution 2

You can pass axis=1 parameter:

In [58]: LA.norm(X, axis=1, ord=1)
Out[58]: array([12, 20, 13, 44, 42])


In [59]: LA.norm(X, axis=1, ord=2)
Out[59]: array([  7.07106781,  10.09950494,   7.41619849,  27.67670501,  27.45906044])
Share:
30,264
Yas
Author by

Yas

Updated on July 19, 2022

Comments

  • Yas
    Yas almost 2 years

    Given a 2-dimensional array in python, I would like to normalize each row with the following norms:

    • Norm 1: L_1
    • Norm 2: L_2
    • Norm Inf: L_Inf

    I have started this code:

    from numpy import linalg as LA
    X = np.array([[1, 2, 3, 6],
                  [4, 5, 6, 5],
                  [1, 2, 5, 5],
                  [4, 5,10,25],
                  [5, 2,10,25]])
    
    print X.shape
    x = np.array([LA.norm(v,ord=1) for v in X])
    print x
    

    Output:

       (5, 4)             # array dimension
       [12 20 13 44 42]   # L1 on each Row
    

    How can I modify the code such that WITHOUT using LOOP, I can directly have the rows of the matrix normalized? (Given the norm values above)

    I tried :

     l1 = X.sum(axis=1)
    
     print l1
     print X/l1.reshape(5,1)
    
     [12 20 13 44 42]
     [[0 0 0 0]
     [0 0 0 0]
     [0 0 0 0]
     [0 0 0 0]
     [0 0 0 0]]
    

    but the output is zero.

  • Yas
    Yas about 8 years
    Thanks, however I need to normalize each row of the matrix with the calculated norm values on each row.
  • wim
    wim about 8 years
    So just divide by the norm, obviously
  • wim
    wim about 8 years
    Using ord=np.inf for the L∞ norm
  • Yas
    Yas about 8 years
    THanks, I am fine with the way norm is calculated but while diving the matrix by norm values, I get zero values. Please see my original question modifed.
  • Yas
    Yas about 8 years
    Thanks, the problem was solved. Iayhan and wim both of your answers were correct but I can mark one as an answer, sorry for that.