Je voudrais avoir la norme d'un tableau NumPy. Plus spécifiquement, je recherche une version équivalente de cette fonction
def normalize(v):
norm = np.linalg.norm(v)
if norm == 0:
return v
return v / norm
Y a-t-il quelque chose comme ça dans skearn
ou numpy
?
Cette fonction fonctionne dans une situation où v
est le vecteur 0.
Si vous utilisez scikit-learn, vous pouvez utiliser 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
Je conviendrais que c'était bien si une telle fonction faisait partie des piles incluses. Mais ce n'est pas, pour autant que je sache. Voici une version pour des axes arbitraires, donnant des performances optimales.
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)))
Vous pouvez spécifier ou obtenir la norme L1 ..__ Pour éviter une division nulle, j'utilise eps, mais ce n'est peut-être pas génial.
def normalize(v):
norm=np.linalg.norm(v, ord=1)
if norm==0:
norm=np.finfo(v.dtype).eps
return v/norm
Si vous avez des données multidimensionnelles et que vous voulez que chaque axe soit normalisé sur lui-même:
def normalize(d):
# d is a (n x dimension) np array
d -= np.min(d, axis=0)
d /= np.ptp(d, axis=0)
return d
Utilise numpys crête à crête fonction.
Cela pourrait aussi fonctionner pour vous
import numpy as np
normalized_v = v / np.sqrt(np.sum(v**2))
mais échoue lorsque v
a la longueur 0.
Il existe également la fonction unit_vector()
pour normaliser les vecteurs dans le populaire module transformations de 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))
Si vous voulez normaliser des vecteurs d'entités à n dimensions stockés dans un tenseur 3D, vous pouvez également utiliser 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()
Si vous travaillez avec des vecteurs 3D, vous pouvez le faire de manière concise en utilisant toolbelt vg . C'est une couche légère au-dessus de numpy et elle supporte les valeurs uniques et les vecteurs empilés.
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
J'ai créé la bibliothèque lors de mon dernier démarrage, où elle était motivée par des utilisations telles que celle-ci: des idées simples et trop verbeuses dans NumPy.
Si vous n'avez pas besoin de la plus grande précision, votre fonction peut être réduite à:
v_norm = v / (np.linalg.norm(v) + 1e-16)
Vous avez mentionné sci-kit learn, alors je veux partager une autre solution.
MinMaxScaler
Dans sci-kit learn, il existe une API appelée MinMaxScaler
qui permet de personnaliser la plage de valeurs à votre guise.
Il traite également des problèmes NaN pour nous.
Les NaN sont traités comme des valeurs manquantes: ignorés dans l'ajustement et conservés dans la transformation. ... voir la référence [1]
Le code est simple, il suffit de taper
# 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)
Sans sklearn
et en utilisant seulement numpy
. Il suffit de définir une fonction:.
En supposant que les lignes sont les variables et les colonnes les échantillons (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)
sortie:
X
array([[1, 2, 3],
[4, 5, 6]])
stdmtx(X)
array([[-1., 0., 1.],
[-1., 0., 1.]])