파이썬에서 2 차원 numpy 배열을 덜 장황하게 정규화하는 방법은 무엇입니까?


88

3 x 3 numpy 배열이 주어지면

a = numpy.arange(0,27,3).reshape(3,3)

# array([[ 0,  3,  6],
#        [ 9, 12, 15],
#        [18, 21, 24]])

2 차원 배열의 행을 정규화하기 위해 생각했습니다.

row_sums = a.sum(axis=1) # array([ 9, 36, 63])
new_matrix = numpy.zeros((3,3))
for i, (row, row_sum) in enumerate(zip(a, row_sums)):
    new_matrix[i,:] = row / row_sum

더 나은 방법이 있겠죠?

아마도 정리할 수 있습니다. 정규화하면 행당 항목의 합계가 1이어야합니다. 그러나 나는 그것이 대부분의 사람들에게 분명 할 것이라고 생각합니다.


17
조심해, "정상화은"일반적으로 의미 정사각형 구성 요소의 합이다. 귀하의 정의는 거의 대부분의 사람들에게 분명하지 않습니다)
coldfix

답변:


139

방송은 이것에 정말 좋습니다.

row_sums = a.sum(axis=1)
new_matrix = a / row_sums[:, numpy.newaxis]

row_sums[:, numpy.newaxis]row_sums를 존재에서 존재 (3,)로 재구성합니다 (3, 1). 당신이 할 때 a / b, a그리고 b서로에 대해 방송됩니다.

당신은에 대해 자세히 배울 수있는 방송 여기 또는 더 나은 여기를 .


29
a.sum(axis=1, keepdims=True)싱글 톤 컬럼 차원을 유지하기 위해 사용 하면 더욱 단순화 할 수 있습니다. 그런 다음을 사용하지 않고도 브로드 캐스트 할 수 있습니다 np.newaxis.
ali_m 2015

6
row_sums가 0이면 어떨까요?
asdf

7
이것은 위에서 언급 한 질문에 대한 정답입니다. 그러나 일반적인 의미의 정규화가 필요한 경우 np.linalg.norm대신 a.sum!
coldfix

1
이것이 선호 row_sums.reshape(3,1)됩니까?
Paul

1
행 합계가 0 일 수 있으므로 강력하지 않습니다.
nos

104

Scikit-learn은 normalize()다양한 정규화를 적용 할 수 있는 기능 을 제공합니다 . "합을 1로 만들기"를 L1- 노름이라고합니다. 따라서:

from sklearn.preprocessing import normalize

matrix = numpy.arange(0,27,3).reshape(3,3).astype(numpy.float64)
# array([[  0.,   3.,   6.],
#        [  9.,  12.,  15.],
#        [ 18.,  21.,  24.]])

normed_matrix = normalize(matrix, axis=1, norm='l1')
# [[ 0.          0.33333333  0.66666667]
#  [ 0.25        0.33333333  0.41666667]
#  [ 0.28571429  0.33333333  0.38095238]]

이제 행의 합계가 1이됩니다.


3
이것은 또한 고밀도 배열로 메모리에 맞지 않는 희소 배열에서 작동한다는 이점이 있습니다.
JEM_Mosig

10

나는 이것이 효과가 있다고 생각한다.

a = numpy.arange(0,27.,3).reshape(3,3)

a /=  a.sum(axis=1)[:,numpy.newaxis]

2
좋은. 소수점을 27에 추가하여 dtype을 arange로 변경합니다.
wim

4

크기가 1이되도록 각 행을 정규화하려는 경우 (즉, 행의 단위 길이가 1이거나 행에있는 각 요소의 제곱의 합이 1) :

import numpy as np

a = np.arange(0,27,3).reshape(3,3)

result = a / np.linalg.norm(a, axis=-1)[:, np.newaxis]
# array([[ 0.        ,  0.4472136 ,  0.89442719],
#        [ 0.42426407,  0.56568542,  0.70710678],
#        [ 0.49153915,  0.57346234,  0.65538554]])

확인 중 :

np.sum( result**2, axis=-1 )
# array([ 1.,  1.,  1.]) 

Axis는 np.linalg.norm에 대한 매개 변수가 아닌 것 같습니다 (더 이상?).
Ztyx 2014 년

특히 이것은 l2 표준에 해당합니다 (여기서 행의 합이 1이 l1 표준에
해당함

3

나는 다음과 같이 행 요소 합계를 1로 정규화 할 수 있다고 생각합니다 new_matrix = a / a.sum(axis=1, keepdims=1). 그리고 열 정규화는 new_matrix = a / a.sum(axis=0, keepdims=1). 이것이 hep 수 있기를 바랍니다.


2

내장 numpy 함수를 사용할 수 있습니다. np.linalg.norm(a, axis = 1, keepdims = True)


1

이것도 작동하는 것 같습니다

def normalizeRows(M):
    row_sums = M.sum(axis=1)
    return M / row_sums

1

행렬 전치를 사용할 수도 있습니다.

(a.T / row_sums).T

0

또는 람다 함수를 사용하여

>>> vec = np.arange(0,27,3).reshape(3,3)
>>> import numpy as np
>>> norm_vec = map(lambda row: row/np.linalg.norm(row), vec)

vec의 각 벡터에는 단위 표준이 있습니다.


0

다음을 사용하는 또 다른 방법이 있습니다 reshape.

a_norm = (a/a.sum(axis=1).reshape(-1,1)).round(3)
print(a_norm)

또는 None작품 사용 :

a_norm = (a/a.sum(axis=1)[:,None]).round(3)
print(a_norm)

출력 :

array([[0.   , 0.333, 0.667],
       [0.25 , 0.333, 0.417],
       [0.286, 0.333, 0.381]])

-2
normed_matrix = normalize(input_data, axis=1, norm='l1')
print(normed_matrix)

여기서 input_data는 2D 배열의 이름입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.