NumPy में किसी सरणी को सामान्य कैसे करें?


203

मैं एक NumPy सरणी का मानदंड बनाना चाहूंगा। विशेष रूप से, मैं इस फ़ंक्शन के बराबर संस्करण की तलाश कर रहा हूं

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

क्या ऐसा कुछ है skearnया numpy?

यह फ़ंक्शन ऐसी स्थिति में काम करता है जहां v0 वेक्टर है।


3
आपने जो लिखा है उसमें क्या गलत है?
अली_म

5
यदि यह वास्तव में एक चिंता है, तो आपको आदर्श <एप्सिलॉन की जांच करनी चाहिए, जहां एप्सिलॉन एक छोटी सहिष्णुता है। इसके अलावा, मैं चुपचाप एक मानक शून्य वेक्टर वापस नहीं करूंगा, मैं raiseएक अपवाद होगा !
हुक

4
मेरा काम करता है, लेकिन मैं जानना चाहूंगा कि क्या अजगर के अधिक सामान्य पुस्तकालय के अंदर कुछ है। मैं अलग-अलग मशीन लर्निंग फ़ंक्शंस लिख रहा हूं और मैं कोड को अधिक स्पष्ट और पठनीय बनाने के लिए बहुत अधिक नए फ़ंक्शंस को परिभाषित करने से बचना
चाहूंगा

1
मैंने कुछ त्वरित परीक्षण किए और मैंने पाया कि सीपीयू पर 1.15.1 की x/np.linalg.norm(x)तुलना x/np.sqrt((x**2).sum())में बहुत धीमी (लगभग 15-20%) नहीं थी ।
बिल

जवाबों:


160

यदि आप scikit का उपयोग कर रहे हैं-जानें तो आप उपयोग कर सकते हैं 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 कार्य भी वेक्टर के आकार के साथ = (n,) या (n, 1) के साथ होता है? मुझे इस पुस्तकालय के साथ कुछ समस्याएँ आ रही हैं
डॉनबेओ

normalizeएक 2D इनपुट की आवश्यकता है। आप यह axis=निर्दिष्ट करने के लिए तर्क पास कर सकते हैं कि क्या आप अपने इनपुट ऐरे की पंक्तियों या स्तंभों पर सामान्यीकरण लागू करना चाहते हैं।
एलिअम

9
ध्यान दें कि सामान्यीकृत फ़ंक्शन का 'आदर्श' तर्क 'एल 1' या 'एल 2' हो सकता है और डिफ़ॉल्ट 'एल 2' है। यदि आप चाहते हैं कि आपके वेक्टर का योग 1 हो (उदाहरण के लिए एक वितरण) तो आपको सामान्य कार्य में आदर्श = 'l1' का उपयोग करना चाहिए।
ऐश

2
यह भी ध्यान दें कि np.linalg.norm(x)डिफ़ॉल्ट रूप से 'l2' मान की गणना करता है। यदि आप चाहते हैं कि आपकी वेक्टर राशि 1 हो तो आपको उपयोग करना चाहिएnp.linalg.norm(x, ord=1)
Omid

नोट: x फंक्शन के ndarrayसाथ काम करने के लिए होना चाहिए normalize()। अन्यथा यह एक हो सकता है list
रामिन मेलिकोव

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

मैंने एलि_म समाधान का गहराई से परीक्षण नहीं किया है, लेकिन कुछ सरल मामलों में यह काम कर रहा है। क्या आपके कार्य को बेहतर तरीके से करने की क्षमता है?
डोन्बेबो

1
मुझे नहीं पता; लेकिन यह मनमानी कुल्हाड़ियों पर काम करता है, और लंबाई 0 वैक्टर के लिए क्या होता है, इस पर हमारा स्पष्ट नियंत्रण है।
इलको होगेंडोर्न

1
बहुत अच्छा! यह सुन्न में होना चाहिए - हालांकि आदेश शायद मेरी राय में धुरी से पहले आना चाहिए।
नील जी

@EelcoHoogendoorn यह समझने के लिए उत्सुक है कि आदेश = 2 दूसरों पर क्यों चुना गया?
हेनरी थॉर्नटन

7
क्योंकि यूक्लिडियन / पाइथागोरान मानदंड सबसे अधिक बार उपयोग किया जाने वाला होता है; क्या आप सहमत नहीं होंगे?
इलको होगोगोर्नो जुले

21

L1 मानदंड प्राप्त करने के लिए आप ord निर्दिष्ट कर सकते हैं। शून्य विभाजन से बचने के लिए मैं ईपीएस का उपयोग करता हूं, लेकिन यह महान नहीं है।

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 से डिवीजन 0 पर वापस आ जाएगा।
मिल्सो

8

क्रिस्टोफ गोहलेके 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

आपने विज्ञान-किट का उल्लेख किया है, इसलिए मैं एक और समाधान साझा करना चाहता हूं।

विज्ञान-किट सीखते हैं MinMaxScaler

विज्ञान-किट में जानें, एक एपीआई कहा जाता है MinMaxScaler मूल्य श्रेणी को आप जैसे चाहें वैसे अनुकूलित कर सकते हैं।

यह हमारे लिए 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 टेंसर में संग्रहीत डायनामिक फ़ीचर वैक्टर को सामान्य करना चाहते हैं, तो आप 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

यदि आप 3 डी वैक्टर के साथ काम कर रहे हैं, तो आप टूलबेल्ट वीजी का उपयोग करके इसे संक्षिप्त रूप से कर सकते हैं । यह सुन्न के ऊपर एक हल्की परत है और यह एकल मूल्यों और स्टैक्ड वैक्टर का समर्थन करता है।

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

मैंने अपने आखिरी स्टार्टअप में पुस्तकालय बनाया, जहां यह इस तरह से उपयोग करने के लिए प्रेरित किया गया था: सरल विचार जो कि कई तरह से न्यूमॉपी में होते हैं।


3

यदि आपको अत्यधिक सटीकता की आवश्यकता नहीं है, तो आपका कार्य निम्न तक घटाया जा सकता है:

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

3

यदि आप तेज समाधान के बाद बहुआयामी सरणी के साथ काम करते हैं तो संभव है।

मान लें कि हमारे पास 2 डी सरणी है, जिसे हम अंतिम अक्ष द्वारा सामान्य करना चाहते हैं, जबकि कुछ पंक्तियों में शून्य मानदंड हैं।

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