एक निश्चित सीमा के भीतर एक 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

चूँकि हम यहाँ बुनियादी सुदूर विधियों का उपयोग कर रहे हैं, मुझे लगता है कि यह उतना ही कारगर है जितना कि खसखस ​​में मौजूद घोल।


इन-प्लेस ऑपरेशंस कंटेनर एरे के dtype को नहीं बदलते हैं। चूंकि वांछित सामान्यीकृत मान फ़्लोट होते हैं, audioऔर imageइन-प्लेस संचालन होने से पहले फ़्लोट-पॉइंट पॉइंट dtype होने की आवश्यकता होती है। यदि वे पहले से फ्लोटिंग-पॉइंट dtype के नहीं हैं, तो आपको उनका उपयोग करके परिवर्तित करना होगा astype। उदाहरण के लिए,

image = image.astype('float64')

7
विभाजन की तुलना में गुणा कम महंगा क्यों है?
एंडोलिथ

19
मुझे ठीक से पता नहीं क्यों। हालाँकि, मैं दावे के प्रति आश्वस्त हूँ, समय के साथ जाँच की है। गुणा के साथ, आप एक समय में एक अंक के साथ काम कर सकते हैं। विभाजन के साथ, विशेष रूप से बड़े विभाजकों के साथ, आपको कई अंकों के साथ काम करना होगा, और भाजक कितनी बार लाभांश में "अनुमान" लगाएगा। आप एक विभाजन समस्या को हल करने के लिए कई गुणा समस्याएं करते हैं। विभाजन करने के लिए कंप्यूटर एल्गोरिथ्म मानव लंबे विभाजन के समान नहीं हो सकता है, लेकिन फिर भी मेरा मानना ​​है कि यह गुणा से अधिक जटिल है।
अनटुब

14
संभवत: रिक्त चित्रों के लिए एक विभाजन को शून्य से उल्लेख करने योग्य है।
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 के साथ बदलना, या एक त्रुटि उठाना।

अंत में, भले ही यह ओपी का सवाल नहीं है, मानकीकरण :

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

2
आप जो चाहते हैं उसके आधार पर, यह सही नहीं है, क्योंकि यह डेटा को फ़्लिप करता है। उदाहरण के लिए [0, 1] के सामान्यीकरण को 0 पर रखता है और 1. को 0 पर घटाता है। [0, 1] के लिए, आप सही सामान्यीकरण प्राप्त करने के लिए परिणाम को 1 से घटा सकते हैं।
एलन ट्यूरिंग

यह इंगित करने के लिए धन्यवाद @AlanTuring कि बहुत मैला था। कोड, जैसा कि पोस्ट किया गया है, केवल तभी काम किया जाता है जब डेटा में सकारात्मक और नकारात्मक दोनों मूल्य होते हैं। यह ऑडियो डेटा के लिए सामान्य हो सकता है। हालाँकि, उत्तर किसी भी वास्तविक मान को सामान्य करने के लिए अद्यतन किया जाता है।
टैक्टोपोडा

1
पिछले एक के रूप में भी उपलब्ध है scipy.stats.zscore
लेविस्ट्रिक

d नमूने के चिन्ह को फ्लिप कर सकता है। यदि आप उस संकेत को रखना चाहते हैं जिसका आप उपयोग कर सकते हैं: f = a / np.max(np.abs(a))... जब तक कि पूरी सरणी सभी शून्य (DivideByZero से बचें)।
पिमिन कोंस्टेंटिन केफालकोस 13

1
numpy.ptp()रिटर्न 0, अगर वह श्रेणी है, लेकिन nanअगर nanसरणी में एक है। हालांकि, यदि सीमा 0 है, तो सामान्यीकरण को परिभाषित नहीं किया गया है। जैसा कि हम
0.27 के

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 = पैमाना ([1,2,3,4], अक्ष = 0, with_mean = True, with_std = True, copy = True) मुझे एक त्रुटि देता है
Yfiua

X = पैमाना (np.array ([1,2,3,4]), अक्ष = 0, with_mean = True, with_std = True, copy = True) मुझे [0,0,0,0] का एक सरणी देता है
यफुआ

sklearn.preprocessing.scale () का बैकड्रॉप है कि आप नहीं जानते कि क्या चल रहा है। कारक क्या है? अंतराल का क्या संपीड़न?
मास्टरकंट्रोलोग्राम

ये scikit प्रीप्रोसेसिंग तरीके (स्केल, minmax_scale, maxabs_scale) का उपयोग केवल एक धुरी के साथ किया जाता है (इसलिए या तो नमूने (पंक्तियों को स्केल करें) या फीचर्स (कॉलम) को अलग-अलग। पूरे सरणी पर सीमा की गणना करने के लिए, या दो से अधिक आयामों के साथ सरणियों का उपयोग करें।
टोबी

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()

क्या आप इसे स्पष्ट कर सकते हैं? कोष्ठक इसे बिना किसी से अलग व्यवहार करते हैं?
एंडोलिथ

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 शून्य होगी। आप अपनी आवश्यकताओं के लिए feature_range को समायोजित कर सकते हैं, या यहां तक ​​कि एक स्केल स्केलर sk.StandardScaler () का उपयोग कर सकते हैं


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वस्तु थी।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.