Hoe een array in NumPy normaliseren naar een eenheidsvector?

Ik wil een NumPy-array converteren naar een eenheidsvector. Meer specifiek ben ik op zoek naar een equivalente versie van deze functie

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

Is er zoiets in skearnof numpy?

Deze functie werkt in een situatie waarin vde 0-vector is.


Antwoord 1, autoriteit 100%

Als je scikit-learn gebruikt, kun je 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

Antwoord 2, autoriteit 28%

Ik ben het ermee eens dat het fijn zou zijn als een dergelijke functie deel uitmaakte van de meegeleverde batterijen. Maar dat is het niet, voor zover ik weet. Hier is een versie voor willekeurige assen en optimale prestaties.

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

Antwoord 3, autoriteit 12%

Dit kan ook voor jou werken

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

Maar mislukt wanneer vlengte heeft 0.

In dat geval, introduceren van een kleine constante om te voorkomen dat de nul divisie dit oplost.


Antwoord 4, Autoriteit 12%

U kunt Ord specificeren om de L1-norm te krijgen.
Om nul divisie te voorkomen, gebruik ik EPS, maar dat is misschien niet geweldig.

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

Antwoord 5, Autoriteit 6%

U noemde SCI-kit Leer, dus ik wil een andere oplossing delen.

SCI-KIT LEREN MinMaxScaler

In Sci-Kit Leer, er is een API genaamd MinMaxScalerdie het waardebereik kan aanpassen zoals u wilt.

Het behandelt ook met nan-problemen voor ons.

Nans worden behandeld als ontbrekende waarden: buitengewoon in fit en onderhouden
in transformatie. … Zie Referentie [1]

CODEMESTER

De code is eenvoudig, typ gewoon

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

Verwijzing


Antwoord 6, Autoriteit 5%

Als u multidimensionale gegevens heeft en u wilt dat elke as wordt genormaliseerd naar zijn maximum of zijn som:

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

Gebruikt numpys piek tot piekfunctie.

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

Antwoord 7, autoriteit 4%

Er is ook de functie unit_vector()om vectoren te normaliseren in het populaire transformatiesmodule door Christoph Gohlke:

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

Antwoord 8, autoriteit 4%

Als je met 3D-vectoren werkt, kun je dit beknopt doen met behulp van de toolbelt vg. Het is een lichte laag bovenop numpy en het ondersteunt enkele waarden en gestapelde vectoren.

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

Ik heb de bibliotheek gemaakt bij mijn laatste opstart, waar het werd gemotiveerd door gebruik als dit: eenvoudige ideeën die veel te uitgebreid zijn in NumPy.


Antwoord 9, autoriteit 4%

Als u met een multidimensionale array werkt, is de volgende snelle oplossing mogelijk.

Stel dat we een 2D-array hebben, die we willen normaliseren op de laatste as, terwijl sommige rijen een nulnorm hebben.

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

Antwoord 10, autoriteit 3%

Zonder sklearnen met alleen numpy.
Definieer gewoon een functie:.

Ervan uitgaande dat de rijen de variabelenzijn en de kolommen de voorbeelden(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)

uitvoer:

X
array([[1, 2, 3],
       [4, 5, 6]])
stdmtx(X)
array([[-1.,  0.,  1.],
       [-1.,  0.,  1.]])

Antwoord 11, autoriteit 2%

Als u n-dimensionale kenmerkvectoren die zijn opgeslagen in een 3D-tensor wilt normaliseren, kunt u ook PyTorch gebruiken:

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

Antwoord 12, autoriteit 2%

Als je geen uiterste precisie nodig hebt, kan je functie worden teruggebracht tot:

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

Other episodes