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])
Author by
Yas
Updated on July 19, 2022Comments
-
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 about 8 yearsThanks, however I need to normalize each row of the matrix with the calculated norm values on each row.
-
wim about 8 yearsSo just divide by the norm, obviously
-
wim about 8 yearsUsing
ord=np.inf
for the L∞ norm -
Yas about 8 yearsTHanks, 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 about 8 yearsThanks, the problem was solved. Iayhan and wim both of your answers were correct but I can mark one as an answer, sorry for that.