NumPy에서 배열을 정규화하는 방법은 무엇입니까?


203

하나의 NumPy 배열의 표준을 원합니다. 더 구체적으로, 나는이 기능의 동등한 버전을 찾고 있습니다.

def normalize(v):
    norm = np.linalg.norm(v)
    if norm == 0: 
       return v
    return v / norm

skearn또는에 그런 것이 numpy있습니까?

이 함수는 v벡터가 0 인 상황에서 작동합니다 .


3
당신이 쓴 것에 무슨 문제가 있습니까?
ali_m

5
이것이 실제로 우려되는 경우, 엡실론이 작은 공차 인 norm <epsilon을 확인해야합니다. 또한 표준 0 벡터를 자동으로 전달하지는 않지만 raise예외 는 아닙니다 !
걸려

4
내 함수는 작동하지만 파이썬의 더 일반적인 라이브러리 안에 무언가가 있는지 알고 싶습니다. 다른 머신 러닝 기능을 작성하고 있으며 코드를보다 명확하고 읽기 쉽게하기 위해 너무 많은 새로운 기능을 정의하지 않으려 고합니다.
Donbeo

1
몇 가지 빠른 테스트 를했는데 CPU의 numpy 1.15.1 x/np.linalg.norm(x)보다 훨씬 느리지 않습니다 (약 15-20 %) x/np.sqrt((x**2).sum()).
Bill

답변:


160

scikit-learn을 사용하는 경우 다음을 사용할 수 있습니다 sklearn.preprocessing.normalize.

import numpy as np
from sklearn.preprocessing import normalize

x = np.random.rand(1000)*10
norm1 = x / np.linalg.norm(x)
norm2 = normalize(x[:,np.newaxis], axis=0).ravel()
print np.all(norm1 == norm2)
# True

2
답을 주셔서 감사하지만 sklearn.preprocessing.normalize는 shape = (n,) 또는 (n, 1)의 벡터와도 작동합니까? 이 라이브러리에 문제가 있습니다
Donbeo

normalize2D 입력이 필요합니다. axis=인수를 전달 하여 입력 배열의 행 또는 열에 정규화를 적용할지 여부를 지정할 수 있습니다 .
ali_m

9
정규화 함수의 'norm'인수는 'l1'또는 'l2'일 수 있으며 기본값은 'l2'입니다. 벡터의 합이 1 (예 : 확률 분포)이되도록하려면 정규화 함수에 norm = 'l1'을 사용해야합니다.
Ash

2
또한 np.linalg.norm(x)기본적으로 'l2'규범 을 계산합니다. 벡터의 합이 1이 되길 원한다면np.linalg.norm(x, ord=1)
Omid

참고 : x는 함수 ndarray와 함께 작동 해야합니다 normalize(). 그렇지 않으면이 될 수 있습니다 list.
Ramin Melikov

46

그러한 기능이 포함 된 배터리의 일부라면 좋았다는 데 동의합니다. 그러나 내가 아는 한 그렇지 않습니다. 다음은 임의의 축 버전이며 최적의 성능을 제공합니다.

import numpy as np

def normalized(a, axis=-1, order=2):
    l2 = np.atleast_1d(np.linalg.norm(a, order, axis))
    l2[l2==0] = 1
    return a / np.expand_dims(l2, axis)

A = np.random.randn(3,3,3)
print(normalized(A,0))
print(normalized(A,1))
print(normalized(A,2))

print(normalized(np.arange(3)[:,None]))
print(normalized(np.arange(3)))

나는 ali_m 솔루션을 깊이 테스트하지 않았지만 간단한 경우에는 효과가있는 것 같습니다. 당신의 기능이 더 나은 곳에서 상황이 있습니까?
Donbeo

1
모르겠다. 그러나 그것은 임의의 축에 대해 작동하며 길이 0 벡터에 대해 발생하는 것을 명시 적으로 제어합니다.
Eelco Hoogendoorn

1
아주 좋아요! 내 의견으로는 순서가 축보다 먼저 나올 것이지만 이것은 numpy해야합니다.
Neil G

@EelcoHoogendoorn 왜 order = 2가 다른 사람들보다 선택 되었는가?
Henry Thornton

7
유클리드 / 피 타고 란 규범이 가장 많이 사용되는 규범이기 때문에; 동의하지 않습니까?
Eelco Hoogendoorn

21

L1 규범을 얻도록 ord를 지정할 수 있습니다. 0 나누기를 피하기 위해 eps를 사용하지만 그다지 좋지는 않습니다.

def normalize(v):
    norm=np.linalg.norm(v, ord=1)
    if norm==0:
        norm=np.finfo(v.dtype).eps
    return v/norm

6
[inf, 1, 2]수율을 정규화 [nan, 0, 0]하지만 그렇게해서는 안 [1, 0, 0]됩니까?
pasbi

12

이것은 또한 당신을 위해 일할 수 있습니다

import numpy as np
normalized_v = v / np.sqrt(np.sum(v**2))

v길이가 0이면 실패합니다 .


10

다차원 데이터가 있고 각 축을 최대 또는 합계로 정규화하려는 경우 :

def normalize(_d, to_sum=True, copy=True):
    # d is a (n x dimension) np array
    d = _d if not copy else np.copy(_d)
    d -= np.min(d, axis=0)
    d /= (np.sum(d, axis=0) if to_sum else np.ptp(d, axis=0))
    return d

numpys 피크 투 피크 기능 사용 합니다.

a = np.random.random((5, 3))

b = normalize(a, copy=False)
b.sum(axis=0) # array([1., 1., 1.]), the rows sum to 1

c = normalize(a, to_sum=False, copy=False)
c.max(axis=0) # array([1., 1., 1.]), the max of each row is 1

원래 행렬에서 모든 값이 동일한 지주의하십시오. 그러면 ptp는 0이됩니다. 0으로 나누면 nan이 반환됩니다.
Milso

8

Christoph Gohlke unit_vector()의 유명한 변환 모듈 에서 벡터를 정규화 하는 기능도 있습니다 .

import transformations as trafo
import numpy as np

data = np.array([[1.0, 1.0, 0.0],
                 [1.0, 1.0, 1.0],
                 [1.0, 2.0, 3.0]])

print(trafo.unit_vector(data, axis=1))

7

sci-kit learn을 언급 했으므로 다른 솔루션을 공유하고 싶습니다.

공상 과학 배우기 MinMaxScaler

sci-kit learn MinMaxScaler에는 값 범위를 원하는대로 사용자 지정할 수 있는 API 가 있습니다.

또한 우리를위한 NaN 문제도 다룹니다.

NaN은 결 측값으로 취급됩니다. 적합하지 않고 변환 상태로 유지됩니다. ... 참조 [1] 참조

코드 샘플

코드는 간단합니다.

# Let's say X_train is your input dataframe
from sklearn.preprocessing import MinMaxScaler
# call MinMaxScaler object
min_max_scaler = MinMaxScaler()
# feed in a numpy array
X_train_norm = min_max_scaler.fit_transform(X_train.values)
# wrap it up if you need a dataframe
df = pd.DataFrame(X_train_norm)
참고

6

없이 sklearn그냥 사용 numpy합니다. 함수를 정의하십시오.

행이 변수 이고 열이 샘플 ( axis= 1) 이라고 가정합니다 .

import numpy as np

# Example array
X = np.array([[1,2,3],[4,5,6]])

def stdmtx(X):
    means = X.mean(axis =1)
    stds = X.std(axis= 1, ddof=1)
    X= X - means[:, np.newaxis]
    X= X / stds[:, np.newaxis]
    return np.nan_to_num(X)

산출:

X
array([[1, 2, 3],
       [4, 5, 6]])

stdmtx(X)
array([[-1.,  0.,  1.],
       [-1.,  0.,  1.]])

4

3D 텐서에 저장된 n 차원 피처 벡터를 정규화하려면 PyTorch를 사용할 수도 있습니다.

import numpy as np
from torch import FloatTensor
from torch.nn.functional import normalize

vecs = np.random.rand(3, 16, 16, 16)
norm_vecs = normalize(FloatTensor(vecs), dim=0, eps=1e-16).numpy()

4

3D 벡터로 작업하는 경우 toolbelt vg를 사용하여 간결하게 수행 할 수 있습니다 . numpy 위에 가벼운 레이어이며 단일 값과 누적 벡터를 지원합니다.

import numpy as np
import vg

x = np.random.rand(1000)*10
norm1 = x / np.linalg.norm(x)
norm2 = vg.normalize(x)
print np.all(norm1 == norm2)
# True

마지막 시작에서 라이브러리를 만들었습니다 .NumPy에서 너무 장황한 간단한 아이디어와 같은 용도로 동기가 부여되었습니다.


3

최대한의 정밀도가 필요하지 않으면 기능을 다음과 같이 줄일 수 있습니다.

v_norm = v / (np.linalg.norm(v) + 1e-16)

3

다차원 배열로 작업하면 빠른 솔루션이 가능합니다.

우리는 2D 배열을 가지고 있는데, 마지막 축으로 정규화하고 일부 행은 0을 갖습니다.

import numpy as np
arr = np.array([
    [1, 2, 3], 
    [0, 0, 0],
    [5, 6, 7]
], dtype=np.float)

lengths = np.linalg.norm(arr, axis=-1)
print(lengths)  # [ 3.74165739  0.         10.48808848]
arr[lengths > 0] = arr[lengths > 0] / lengths[lengths > 0][:, np.newaxis]
print(arr)
# [[0.26726124 0.53452248 0.80178373]
# [0.         0.         0.        ]
# [0.47673129 0.57207755 0.66742381]]
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.