Dans numpy
, certaines opérations reviennent en forme (R, 1)
mais d'autres reviennent (R,)
. Cela rendra la multiplication de la matrice plus fastidieuse car explicite reshape
est requise. Par exemple, étant donné une matrice M
, si nous voulons faire numpy.dot(M[:,0], numpy.ones((1, R)))
où R
est le nombre de lignes (bien sûr, le même problème se produit également par colonne). Nous obtiendrons une matrices are not aligned
erreur car M[:,0]
est en forme (R,)
mais numpy.ones((1, R))
est en forme (1, R)
.
Mes questions sont donc:
Quelle est la différence entre la forme
(R, 1)
et(R,)
. Je sais littéralement que c'est une liste de nombres et une liste de listes où toute la liste ne contient qu'un nombre. Je me demande simplement pourquoi ne pas concevoir denumpy
sorte qu'il favorise la forme(R, 1)
au lieu de(R,)
faciliter la multiplication de la matrice.Y a-t-il de meilleures façons pour l'exemple ci-dessus? Sans remodeler explicitement comme ceci:
numpy.dot(M[:,0].reshape(R, 1), numpy.ones((1, R)))
Réponses:
1. La signification des formes dans NumPy
Vous écrivez: «Je sais que c'est littéralement une liste de nombres et une liste de listes où toute la liste ne contient qu'un nombre» mais c'est un peu une façon inutile de penser à ce sujet.
La meilleure façon de penser aux tableaux NumPy est qu'ils se composent de deux parties, un tampon de données qui n'est qu'un bloc d'éléments bruts et une vue qui décrit comment interpréter le tampon de données.
Par exemple, si nous créons un tableau de 12 entiers:
Se
a
compose alors d'un tampon de données, arrangé quelque chose comme ceci:et une vue qui décrit comment interpréter les données:
Ici, la forme
(12,)
signifie que le tableau est indexé par un index unique qui va de 0 à 11. Conceptuellement, si nous étiquetons cet index uniquei
, le tableaua
ressemble à ceci:Si nous remodelons un tableau, cela ne change pas le tampon de données. Au lieu de cela, il crée une nouvelle vue qui décrit une manière différente d'interpréter les données. Donc après:
le tableau
b
a le même tampon de données quea
, mais maintenant il est indexé par deux indices qui vont de 0 à 2 et de 0 à 3 respectivement. Si nous étiquetons les deux indicesi
etj
, le tableaub
ressemble à ceci:ce qui signifie que:
Vous pouvez voir que le deuxième index change rapidement et que le premier index change lentement. Si vous préférez que ce soit l'inverse, vous pouvez spécifier le
order
paramètre:ce qui se traduit par un tableau indexé comme ceci:
ce qui signifie que:
Il doit maintenant être clair ce que signifie pour un tableau d'avoir une forme avec une ou plusieurs dimensions de taille 1. Après:
le tableau
d
est indexé par deux indices, dont le premier va de 0 à 11, et le deuxième est toujours 0:et donc:
Une dimension de longueur 1 est "libre" (dans un certain sens), donc rien ne vous empêche d'aller en ville:
donnant un tableau indexé comme ceci:
et donc:
Consultez la documentation des composants internes NumPy pour plus de détails sur la façon dont les tableaux sont implémentés.
2. Que faire?
Comme il
numpy.reshape
suffit de créer une nouvelle vue, vous ne devriez pas avoir peur de l'utiliser chaque fois que nécessaire. C'est le bon outil à utiliser lorsque vous souhaitez indexer un tableau d'une manière différente.Cependant, dans un calcul long, il est généralement possible d'arranger pour construire des tableaux avec la "bonne" forme en premier lieu, et ainsi minimiser le nombre de remodelages et de transpositions. Mais sans voir le contexte réel qui a conduit à la nécessité d'une refonte, il est difficile de dire ce qui devrait être changé.
L'exemple de votre question est:
mais ce n'est pas réaliste. Tout d'abord, cette expression:
calcule le résultat plus simplement. Deuxièmement, y a-t-il vraiment quelque chose de spécial dans la colonne 0? Peut-être que ce dont vous avez réellement besoin est:
la source
newaxis
si vous avez besoin d'un autre axe, par exemplea[:, j, np.newaxis]
laj
th colonnea
eta[np.newaxis, i]
lai
th ligne.(R, )
cas, la forme dendarray
est un tuple avec un seul élément, est donc imprimé par Python avec une virgule de fin. Sans la virgule supplémentaire, ce serait ambigu avec une expression entre parenthèses . Unndarray
avec une seule dimension peut être considéré comme un vecteur de colonne de longueurR
. Dans le(R, 1)
cas, le tuple a deux éléments, il peut donc être considéré comme un vecteur de ligne (ou une matrice avec 1 ligne de longueurR
.La différence entre
(R,)
et(1,R)
est littéralement le nombre d'indices que vous devez utiliser.ones((1,R))
est un tableau 2D qui se trouve n'avoir qu'une seule ligne.ones(R)
est un vecteur. En général, si la variable n'a pas de sens d'avoir plus d'une ligne / colonne, vous devez utiliser un vecteur, pas une matrice avec une dimension singleton.Pour votre cas spécifique, il existe deux options:
1) Faites simplement du deuxième argument un vecteur. Les éléments suivants fonctionnent bien:
2) Si vous voulez des opérations matricielles comme la matrice, utilisez la classe à la
matrix
place dendarray
. Toutes les matricies sont forcées à être des tableaux 2D, et l'opérateur*
fait la multiplication de la matrice au lieu de l'élément (donc vous n'avez pas besoin de point). D'après mon expérience, c'est plus de problèmes que cela en vaut la peine, mais cela peut être bien si vous avez l'habitude de matlab.la source
matrix
classe. Quel est le problème pour lamatrix
classe BTW?matrix
est que ce n'est que 2D, et aussi parce qu'il surcharge l'opérateur '*', les fonctions écrites pourndarray
peuvent échouer si elles sont utilisées sur amatrix
.La forme est un tuple. S'il n'y a qu'une seule dimension, la forme sera un nombre et juste vide après une virgule. Pour les dimensions 2+, il y aura un nombre après toutes les virgules.
la source
Pour sa classe de tableau de base, les tableaux 2D ne sont pas plus spéciaux que les tableaux 1D ou 3D. Il y a des opérations qui préservent les dimensions, certaines qui les réduisent, d'autres les combinent ou même les développent.
Autres expressions qui donnent le même tableau
MATLAB a commencé avec seulement des tableaux 2D. Les versions plus récentes autorisent plus de dimensions, mais conservent la limite inférieure de 2. Mais vous devez toujours faire attention à la différence entre une matrice de lignes et une colonne, une de forme
(1,3)
v(3,1)
. À quelle fréquence avez-vous écrit[1,2,3].'
? J'allais écrirerow vector
etcolumn vector
, mais avec cette contrainte 2d, il n'y a pas de vecteurs dans MATLAB - du moins pas au sens mathématique du vecteur comme étant 1d.Avez-vous regardé
np.atleast_2d
(également les versions _1d et _3d)?la source
1) La raison de ne pas préférer une forme de
(R, 1)
sur(R,)
est qu'elle complique inutilement les choses. Par ailleurs, pourquoi serait-il préférable d'avoir une forme(R, 1)
par défaut pour un vecteur longueur-R au lieu de(1, R)
? Il vaut mieux rester simple et explicite lorsque vous avez besoin de dimensions supplémentaires.2) Pour votre exemple, vous calculez un produit externe, vous pouvez donc le faire sans
reshape
appel en utilisantnp.outer
:la source
M[:,0]
obtient essentiellement toutes les lignes avec le premier élément, il est donc plus logique d'avoir(R, 1)
que(1, R)
. 2) Il n'est pas toujours remplaçable, parnp.outer
exemple, par un point pour la matrice de forme (1, R) puis (R, 1).matrix
objet. 2) En fait,np.outer
fonctionne indépendamment du fait que les formes sont(1, R)
,(R, 1)
ou une combinaison des deux.Il y a déjà beaucoup de bonnes réponses ici. Mais pour moi, il était difficile de trouver un exemple, où la forme ou le tableau peut casser tout le programme.
Voici donc celui-ci:
Cela échouera avec une erreur:
mais si on ajoute
reshape
àa
:cela fonctionne correctement!
la source