J'ai une matrice Je veux une nouvelle matrice, où la valeur de l'entrée dans la ligne I et la colonne J est le produit de toutes les entrées de la rangée de la ligne d'A, Sauf pour la cellule de cette ligne dans la colonne JTH. P> B = np.zeros((3, 3))
for i in range(3):
for j in range(3):
B[i, j] = np.prod(i, A[[x for x in range(3) if x != j]])
5 Réponses :
Si vous êtes prêt à tolérer une seule boucle:
B = np.empty_like(A)
mask = np.ones(A.shape[1], dtype=bool)
for col in range(A.shape[1]):
mask[col] = False
B[:,col] = np.prod(A[:,mask], 1)
mask[col] = True
+1, la mémoire-sage, cependant, les deux sont équivalents. L'indexation à l'aide d'un masque booléen crée également une copie. Il n'y a aucun avantage à la deuxième version. (L'indexation booléenne est une forme d'indexation "fantaisie" qui en fait toujours une copie. Contrairement à la tranchée normale, il n'y a aucun moyen de décrire le résultat en termes de décalage et de progrès.)
@Joekington: Tu as raison, merci. Savez-vous s'il existe un moyen plus intelligent de sous-ensemble les colonnes de la façon dont nous avons besoin? Nous voudrions peut-être éviter une copie, mais nous devons exprimer l'idée "toutes les colonnes sauf une" pour toute colonne arbitraire. Je ne vois pas comment cela est possible avec des compensations et des progrès, mais vous savez peut-être une autre façon qui pourrait sauver la mémoire ici? Ou peut-être qu'il n'y a pas de moyen dans Numpy aujourd'hui.
Si vous êtes prêt à tolérer une petite erreur, vous pouvez utiliser la solution que vous avez proposée pour la première fois.
A += 1e-10 np.around(np.repeat(np.prod(A, 1, keepdims = True), 3, axis = 1) / A, 9)
une variation de votre solution à l'aide de répéter code>, utilise [:, NONE] code>. def foo(A):
h,w = A.shape
I = (np.arange(w)[:,None]+np.arange(1,w))
I1 = np.array(I)%w
P = A[:,I1].prod(2)
return P
Je ne pense pas que c'est fait i> s'il y a des zéros. Le 0ème élément de la première rangée devrait être de 0,25, n'est-ce pas?
J'ai corrigé ce problème, bien que la solution soit plus méchante que ce que j'aimerais.
Malheureusement, je ne pense pas que cela fonctionnera non plus. Disons qu'il y a deux zéros d'affilée: alors chaque ligne de sortie doit être nulle car chaque produit contient un zéro. Mais votre nouvelle méthode va transformer les zéros dans le produit des éléments non nulés (car ils prendront le cas où les zéros sont remplacés par 1.), il est beaucoup plus facile de voir si vous utilisez une matrice 4x4 pour tester, qui a un rangée avec deux éléments non nuls et deux zéros.
[Par "chaque ligne de sortie" i bien sûr signifiait "chaque élément de la ligne de sortie", et non que l'ensemble de la matrice de sortie doit être nul.]
HPaulj: Je n'ai pas remarqué que vous avez déjà inclus une version de ce que j'avais à l'esprit, mais j'ai également inclus une modification pour moi aussi. Votre version n'est pas entièrement correcte; Mais peu importe la grande différence de vitesse me surprend quelque peu. En effet, le prod est repris sur un axe de petite foulée, nous devrions donc obtenir un bon comportement de cache, de sorte que le seul coût supplémentaire consiste à concabler le tableau; Pourtant, l'approche Epsilon rend trois passes sur la matrice en dehors du produit réel ... Je ne l'obtiens pas tout à fait.
Je comprends maintenant ... pas assez de sommeil. Ma méthode nécessite des opérations O (N3), par opposition à O (N2)
J'ai posté une autre méthode, qui est O (n ^ 2). Curieux de voir comment il se compare.
im sur la course, donc je n'ai pas le temps de résoudre cette solution; Mais quelle carte d'identité est créée une vue circulaire contiguë sur le dernier axe, au moyen de concaténer la matrice à elle-même le long de la dernière axe, puis utilisez np.lib.index_tricks.as_strided pour sélectionner les éléments appropriés pour prendre un NP.Prod sur . Pas de boucles Python, pas d'approximation numérique.
Edit: Ici vous allez: P>
import numpy as np
A = np.array([[0.2, 0.4, 0.6],
[0.5, 0.5, 0.5],
[0.5, 0.0, 0.5],
[0.6, 0.4, 0.2]])
B = np.concatenate((A,A),axis=1)
C = np.lib.index_tricks.as_strided(
B,
A.shape +A.shape[1:],
B.strides+B.strides[1:])
D = np.prod(C[...,1:], axis=-1)
print D
Cela fonctionne la même chose que ma version suivante.
Mais np.allclose (ajusté (A), double_cumprod (a)) code> retourne vrai.
En effet, cela fait, mais les grandes matrices entraînent des zéros partout. ~ 0.5 ** 1000 insère systématiquement vos flotteurs. Essayez d'imprimer le résultat pour une petite matrice.
Voici une méthode O (n ^ 2) sans boucles Python ni approximation numérique: Remarque: il semble être environ deux fois plus lent que la méthode d'approximation numérique, qui est dans ligne avec attente. p> p>
Sur ma grande matrice, cela teste un peu plus vite que l'approximation de Blaz.
Je l'ai également testé, mais avec une matrice ponctuelle flottante 1000x1000. Dans ce cas, l'approximation tire à l'avance sur ma machine, mais pour des INT, ils sont à peu près égale à la vitesse.
Cette approche cumprod devient plus évidente lorsque le problème est indiqué comme prod (A [J,: I-1]) * Prod (a [J, I + 1:]) code>. C'est-à-dire le produit de 2 séquences. »Comme indiqué à l'origine le problème axé sur l'élimination de l'élimination du A [j, i] code> à partir d'un seul prod () code>.