Dans Numpy, l'utilisation de boucles est lente, donc diverses techniques sont utilisées. Il est facile d'écrire au format vectoriel ou matriciel, mais il y en a qui utilisent la diffusion. Un exemple est la génération d'une matrice de distance. Étant donné que les emplacements de plusieurs emplacements sont stockés dans «x», comment calculez-vous la distance entre eux?
Je connais Fortran depuis de nombreuses années, donc je veux écrire en utilisant des boucles.
do j = 1, n
do i = 1, n
r(i, j) = sqrt((x(i) - x(j))**2)
end do
end do
Traduit littéralement en Python
for i in range(len(x)):
for j in range(len(x)):
r[i, j] = math.sqrt((x[i] - x[j])**2)
Ce sera. Même avec ndarray, il n'y a pas de différence si la longueur est d'environ 10, mais il est plutôt plus rapide de conserver la liste.
Les opérations de tableau de Numpy (y compris les produits) sont essentiellement élément par élément. Des opérations sur des tableaux de même forme, tels que des tableaux bidimensionnels 4x3, sont effectuées sur chaque élément. Pour les éléments de tailles différentes, comme un tableau bidimensionnel 4x3 et un tableau unidimensionnel 1x3, le calcul est effectué en supposant que les lignes du tableau unidimensionnel sont répétées de sorte que les tailles soient identiques. Cette conversion est appelée "diffusion".
Pour le «x» qui stocke la position, il semble qu'un tableau sera retourné si l'opération avec la translocation est effectuée, mais ce n'est pas le cas. Il sera considéré comme ayant la même forme et sera une liste de 0.
Pour utiliser la diffusion pour générer la matrice de distance souhaitée sans boucles, augmentez d'une dimension. Utilisez np.newaxis
pour augmenter la dimension. La même chose est vraie pour "Aucun". La longueur de la dimension pour laquelle «np.newaxis» ou «Aucun» est spécifié est 1. Bien que je ne l'ai jamais utilisé, Fortran95 a une fonction intégrée appelée spread
.
np.sqrt((x - x[:, np.newaxis])**2)
Vous pouvez également utiliser les opérations nx1 et 1xn.
np.sqrt((x[np.newaxis, :] - x[:, np.newaxis])**2)
Dans mon environnement, mesurée avec % timeit
pour 10 points, la boucle de ndarray était de 69,1 μs, la boucle de liste était de 54,1 μs et celle qui évitait la boucle et augmentait la dimension de la matrice était de 3,04 μs. À 1000 points, la boucle de ndarray était de 660 ms et celle avec des dimensions de matrice augmentées était de 2,47 ms.
Utiliser ...
revient à organiser :
de sorte que le nombre de dimensions soit la dimension du tableau. La distance euclidienne d'un point dans un espace à n dimensions peut être calculée comme suit.
np.sqrt(((x[..., np.newaxis, :] - x[..., :, np.newaxis])**2).sum(axis=0))
Recommended Posts