1
votes

Multiplication numpy sur l'axe

J'ai 2 tableaux numpy, l'un est de forme (2, 5, 10) et l'autre est de forme (2, 5, 10, 10) . La multiplication que je souhaite est [[x1 [i] [j] * x2 [i] [j] pour j dans la plage (5)] pour i dans la plage (2)] Cela fonctionne comme prévu mais est assez lent, et je voulais multiplier directement x1 * x2 mais numpy n'aime pas ça. Existe-t-il une méthode numpy pour multiplier sur un axe donné?

J'ai essayé le numpy.multiply car il dit que "axis" est un mot clé non valide pour ufunc "multiplier"

x1 = np.arange(100).reshape((2, 5, 10))
x2 = np.arange(1000).reshape((2, 5, 10, 10))
x = [[x1[i][j] * x2[i][j] for j in range(5)] for i in range(2)] # slow method that works
x = np.multiply(x1, x2, axis=2) # What I'm looking for but doesn't work.


1 commentaires

La dernière dimension de x1 correspond-elle à la dernière de x2 ou la deuxième à la dernière?


3 Réponses :


2
votes

Une façon de faire cela, en supposant que vous êtes d'accord avec x comme type np.array , est de mieux utiliser Diffusion NumPy (voir la réponse de @ hpaulj):

%timeit np.array([[x1[i][j] * x2[i][j] for j in range(3)] for i in range(2)])
# 13.6 µs ± 388 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
%timeit x1[:, :, None, :] * x2
# 1.4 µs ± 10.4 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

Timewise est une accélération d'environ 10 fois:

import numpy as np

x1 = np.arange((2 * 3 * 4)).reshape((2, 3, 4))
x2 = np.arange((2 * 3 * 4 * 4)).reshape((2, 3, 4, 4))
x = [[x1[i][j] * x2[i][j] for j in range(3)] for i in range(2)]) # slow method that works

# : using NumPy broadcasting
y = x1[:, :, None, :] * x2

np.all(np.array(x) == y)
# True


1 commentaires

Merci beaucoup, exactement ce que je cherchais! Je vais regarder dans cette diffusion, ça a l'air bizarre mais très affectif ^^



1
votes
x1[:, :, None, :] * x2
x1[:, :, :, None] * x2

0 commentaires

0
votes

En utilisant votre entrée, nous avons

x1.shape (2, 5, 10) x2.shape (2, 5, 10, 10)

Vous pouvez utiliser np.tensordot pour multiplier le long d'axes arbitraires - tant qu'ils correspondent en dimension.

x3 = np.tensordot (x1, x2, (1,1)) x3.forme (2, 10, 2, 10, 10)

tensordot vous permet également de multiplier et d'ajouter sur un certain nombre d'axes. Dans ce cas par exemple.

x4 = np.tensordot (x1, x2, ((0,1), (0,1))) x4.forme (10, 10, 10)

Ici, l'argument ((0,1), (0,1)) fait référence aux axes de x1 et x2, respectivement.


1 commentaires

tensordot convertit le problème en un appel np.dot , en remodelant et en transposant les entrées (et les sorties). Cela implique une somme de produits, même si la dimension pertinente est la taille 1. Je ne pense pas que l'OP avait des sommes en tête. Et le résultat souhaité par OP est la forme (2,5,10,10), pas (2,10,2,10,10)!