NumPy 배열을 특정 범위 내로 정규화하는 방법은 무엇입니까?


136

오디오 또는 이미지 배열에서 일부 처리를 수행 한 후에는 파일로 다시 쓰기 전에 범위 내에서 정규화해야합니다. 다음과 같이 할 수 있습니다 :

# Normalize audio channels to between -1.0 and +1.0
audio[:,0] = audio[:,0]/abs(audio[:,0]).max()
audio[:,1] = audio[:,1]/abs(audio[:,1]).max()

# Normalize image to between 0 and 255
image = image/(image.max()/255.0)

덜 장황하고 편리한 기능 방법이 있습니까? matplotlib.colors.Normalize()관련이없는 것 같습니다.

답변:


137
audio /= np.max(np.abs(audio),axis=0)
image *= (255.0/image.max())

사용 /=*=따라서 일부 메모리를 저장, 당신은 중간 임시 배열을 제거 할 수 있습니다. 곱셈은 ​​나눗셈보다 비싸지 않으므로

image *= 255.0/image.max()    # Uses 1 division and image.size multiplications

보다 약간 빠르다

image /= image.max()/255.0    # Uses 1+image.size divisions

여기서는 기본적인 numpy 메소드를 사용하고 있기 때문에 이것이 가능한 한 numpy의 효율적인 솔루션이라고 생각합니다.


전체 작업은 컨테이너 배열의 dtype을 변경하지 않습니다. 원하는 정규화 된 값은 부동 소수점이므로 in-place 연산을 수행하기 전에 audioimage배열에 부동 소수점 dtype이 있어야합니다. 아직 부동 소수점 dtype이 아닌 경우을 사용하여 변환해야합니다 astype. 예를 들어

image = image.astype('float64')

7
곱셈이 나눗셈보다 저렴한 이유는 무엇입니까?
endolith

19
왜 그런지 정확히 모르겠습니다. 그러나 나는 그것을 timeit으로 확인한 주장에 대해 확신합니다. 곱셈을 사용하면 한 번에 한 자리 숫자로 작업 할 수 있습니다. 나누기, 특히 큰 제수를 사용하면 많은 자릿수로 작업해야하며, 제수가 배당에 들어가는 횟수를 "추측"해야합니다. 하나의 나눗셈 문제를 해결하기 위해 많은 곱셈 문제가 발생합니다. 나누기를하는 컴퓨터 알고리즘은 인간의 긴 나누기와 같지 않지만 그럼에도 불구하고 곱셈보다 더 복잡하다고 생각합니다.
unutbu

14
빈 이미지의 경우 0으로 나누기를 언급 할 가치가 있습니다.
cjm2671

7
@endolith 곱셈은 어셈블리 수준에서 구현되는 방식 때문에 나눗셈보다 저렴합니다. 나눗셈 알고리즘뿐만 아니라 나눗셈 알고리즘도 병렬화 할 수 없습니다. en.wikipedia.org/wiki/Binary_multiplier
mjones.udri

5
곱셈에 찬성하여 나누기의 수를 최소화하는 것은 잘 알려진 최적화 기술입니다.
mjones.udri

73

배열에 양수 데이터와 음수 데이터가 모두 포함되어 있으면 다음을 수행하십시오.

import numpy as np

a = np.random.rand(3,2)

# Normalised [0,1]
b = (a - np.min(a))/np.ptp(a)

# Normalised [0,255] as integer: don't forget the parenthesis before astype(int)
c = (255*(a - np.min(a))/np.ptp(a)).astype(int)        

# Normalised [-1,1]
d = 2.*(a - np.min(a))/np.ptp(a)-1

배열에가 포함되어 있으면 nan한 가지 해결책은 다음과 같이 제거하는 것입니다.

def nan_ptp(a):
    return np.ptp(a[np.isfinite(a)])

b = (a - np.nanmin(a))/nan_ptp(a)

그러나 상황에 따라 nan다르게 취급하고 싶을 수도 있습니다 . 예를 들어 값을 보간하여 예를 들어 0으로 바꾸거나 오류를 발생시킵니다.

마지막으로 OP의 질문이 아닌 경우에도 언급 할 가치가 있습니다 .

e = (a - np.mean(a)) / np.std(a)

2
원하는 내용에 따라 데이터를 뒤집기 때문에 올바르지 않습니다. 예를 들어 정규화를 [0, 1]로 설정하면 최대 값은 0이고 최소값은 1로 설정됩니다. [0, 1]의 경우 결과를 1에서 간단히 빼서 올바른 정규화를 얻을 수 있습니다.
Alan Turing

@AlanTuring을 지적 해 주셔서 감사합니다. 데이터가 양수 값과 음수 값을 모두 포함하는 경우에만 코드가 게시되었습니다. 오디오 데이터에는 다소 흔할 수 있습니다. 그러나 실제 값을 정규화하기 위해 답변이 업데이트됩니다.
Tactopoda

1
마지막으로도 사용할 수 있습니다 scipy.stats.zscore.
Lewistrick

d는 표본의 부호를 뒤집을 수 있습니다. 부호를 유지하려면 다음을 사용할 수 있습니다 : f = a / np.max(np.abs(a))... 전체 배열이 모두 0이 아닌 경우 (DivideByZero는 피하십시오).
Pimin Konstantin Kefaloukos

1
numpy.ptp()그 범위이지만, 만약 0을 반환 nan한 경우가 nan배열된다. 그러나 범위가 0이면 정규화가 정의되지 않습니다. 0으로 나누려고 할 때 오류가 발생합니다.
Tactopoda

37

을 사용하여 크기를 조정할 수도 있습니다 sklearn. 장점은 데이터를 평균 중심에 두는 것 외에도 표준 편차를 정규화 할 수 있으며 축, 피처 또는 레코드별로이를 수행 할 수 있다는 것입니다.

from sklearn.preprocessing import scale
X = scale( X, axis=0, with_mean=True, with_std=True, copy=True )

키워드 인수 axis, with_mean, with_std자기 설명하고, 기본 상태에 표시됩니다. 인수가 copy로 설정되면 작업이 현재 위치에서 수행됩니다 False. 여기에 설명서가 있습니다 .


X = scale ([1,2,3,4], axis = 0, with_mean = True, with_std = True, copy = True) 오류가 발생합니다
Yfiua

X = 스케일 (np.array ([1,2,3,4]), 축 = 0, 참 with_std = TRUE = with_mean 복사 = True)로 날 [0,0,0,0]의 어레이를 제공
Yfiua

sklearn.preprocessing.scale ()에는 무슨 일이 일어나고 있는지 모르는 백 드로가 있습니다. 요인은 무엇입니까? 간격의 압축은 무엇입니까?
MasterControlProgram

이러한 scikit 전처리 방법 (scale, minmax_scale, maxabs_scale)은 한 축에만 사용되도록 (따라서 샘플 (행) 또는 피처 (열)의 크기를 개별적으로 조정) 사용하기위한 것입니다. 전체 배열의 범위를 계산하거나 차원이 2 이상인 배열을 사용하려면
Toby

11

"i"(idiv, imul ..) 버전을 사용할 수 있으며 반 나쁘게 보이지 않습니다.

image /= (image.max()/255.0)

다른 경우에는 열을 기준으로 n 차원 배열을 정규화하는 함수를 작성할 수 있습니다.

def normalize_columns(arr):
    rows, cols = arr.shape
    for col in xrange(cols):
        arr[:,col] /= abs(arr[:,col]).max()

이것을 명확히 할 수 있습니까? 괄호는 그렇지 않은 것과 다르게 동작합니까?
endolith

1
교구민은 아무것도 바꾸지 않습니다. 요점은 사용하는 것이었다 /=대신 = .. / ..
u0b34a0f6ae

7

audio-1과 +1 image사이, 0과 255 사이 의 값을 최소-최대 스케일하려고합니다 .

를 사용하면 sklearn.preprocessing.minmax_scale문제를 쉽게 해결할 수 있습니다.

예 :

audio_scaled = minmax_scale(audio, feature_range=(-1,1))

shape = image.shape
image_scaled = minmax_scale(image.ravel(), feature_range=(0,255)).reshape(shape)

참고 : 벡터 의 규범 (길이)을 특정 값 (일반적으로 1)으로 조정하는 연산과 혼동하지 마십시오 . 일반적으로 정규화라고도합니다.


4

간단한 해결책은 sklearn.preprocessing 라이브러리에서 제공하는 스케일러를 사용하는 것입니다.

scaler = sk.MinMaxScaler(feature_range=(0, 250))
scaler = scaler.fit(X)
X_scaled = scaler.transform(X)
# Checking reconstruction
X_rec = scaler.inverse_transform(X_scaled)

오류 X_rec-X는 0입니다. 필요에 따라 feature_range를 조정하거나 standart scaler sk를 사용할 수도 있습니다.


3

나는 다음과 같은 노력 , 그리고 오류가 발생했습니다

TypeError: ufunc 'true_divide' output (typecode 'd') could not be coerced to provided output parameter (typecode 'l') according to the casting rule ''same_kind''

numpy내가 정상화에 노력했다 배열이 있었다 integer배열입니다. 버전>에서 유형 캐스팅이 더 이상 사용되지 않는 것 같습니다 .이를 해결하기 위해 1.10사용해야 numpy.true_divide()합니다.

arr = np.array(img)
arr = np.true_divide(arr,[255.0],out=None)

img이었다 PIL.Image객체.

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