Dans cet article, comment écrivez-vous le calcul matriciel bidimensionnel suivant dans numpy de Python? C'est.
for i in range(0, ni-1):
for j in range(0, nj-1):
y[i, j] = x[i, j] + x[i+1, j] - x[i+1, j+1] * x[i, j+1]
Plus tard, nous comparerons les performances. La version Python est la 3.7.4. J'utilise anaconda3-2019.10.
COVID-19 + En changeant d'emploi, j'ai décidé de gagner du temps et d'apprendre une nouvelle langue chaque jour alors que je restais coincé chez moi à Tokyo. Python semble être la chose principale dans le prochain lieu de travail, donc Python. Je dois réduire mon argent pour être sérieux, j'ai donc suivi un cours à Udemy et passé environ une semaine à apprendre les bases. Je programme depuis longtemps, mais Python est un débutant avec environ deux semaines d'expérience.
Après avoir essayé toutes les étapes, j'ai l'impression de pouvoir faire du développement Web avec Python, mais puisque je vais faire Python, j'aimerais faire de l'analyse de données et de l'apprentissage automatique. J'ai donc réécrit la solution de l'équation de translocation unidimensionnelle que j'ai faite il y a longtemps en Python.
▶ 1 Dimensional Flow Calculation by Python
Je n'ai pas vérifié les détails et j'ai pris des raccourcis, mais j'étais satisfait des résultats que je souhaitais pour la première fois. Mais quel sentiment d'accomplissement? Je ne pouvais pas ressentir quelque chose comme ça, alors j'ai essayé un calcul bidimensionnel, mais le calcul matriciel était extrêmement terne. Mon fantôme murmure que je ne devrais plus continuer à écrire. Et En Python
--Si vous écrivez pour, vous perdez
C'est juste une rumeur. Il a été dit que numpy etc. serait utilisé comme solution, alors j'ai essayé de l'utiliser, mais c'est juste déroutant et il semble que je ne pourrai pas l'apprendre immédiatement, alors je vais le laisser comme mémo.
Tout ce que vous pouvez obtenir en lisant cet article, c'est que vous n'avez pas à lire "Utiliser numpy pour calculer les matrices (ne pas utiliser pour)". À part cela, je ne pense pas que cela vous viendra à l'esprit même si vous le lisez, donc si vous le comprenez, vous devriez en fait bouger votre main pour le vérifier et le répéter jusqu'à ce qu'il tienne dans votre main.
Python a
list, tuple, dict, etc. pour représenter les tableaux, et pour les tableaux à deux dimensions, `` `` list
vient d'autres langages. Il est facile de comprendre s'il s'agit de x [i] [j] '' etc. Cependant, d'après la notation mathématique,
x [i, j] ''
est plus facile à comprendre. Dans le tableau de numpy```, il est écrit comme ce dernier. Comme vous pouvez le voir en l'écrivant, écrire
x [i] [j] '' plusieurs fois est ennuyeux et difficile à voir, donc comme
x [i, j]
Je suis reconnaissant de pouvoir écrire.
Puis immédiatement. Par exemple, supposons que vous ayez la formule suivante qui calcule
x, y sous la forme `` `ndarray
.
y[i, j] = x[i, j] + x[i+1, j] - x[i+1, j+1] * x[i, j+1]
Ce n'est pas une formule particulièrement significative, mais vous devriez souvent voir ce type de calcul non seulement dans les systèmes numériques, mais aussi dans le traitement des calculs numériques. Imbriquer ceci dans une boucle de i
et `` `j```,
for i in range(0, x.shape[0]-1):
for j in range(0, x.shape[1]-1):
y[i, j] = x[i, j] + x[i+1, j] - x[i+1, j+1] * x[i, j+1]
Sera. Très facile à comprendre. Si le nombre maximum de divisions est
ni, `` nj
, etc.
for i in range(0, ni-1):
for j in range(0, nj-1):
y[i, j] = x[i, j] + x[i+1, j] - x[i+1, j+1] * x[i, j+1]
Ça veut dire.
Au fait, dans numpy, il semble judicieux d'écrire ce calcul comme suit.
y[0:-1, 0:-1] = x[0:-1, 0:-1] + x[1:, 0:-1] - x[1:, 1:] * x[0:-1, 1:]
e? Quoi?
Si vous regardez de plus près, qu'est-ce que c'est? L'expression correspond-elle à la plage découpée? Je ne me sens pas comme ça. Je n'ai pas envie d'écrire librement.
Vérifions si cela correspond vraiment.
import numpy as np
x = np.random.randint(10, size=(100, 50))
y = np.zeros((100, 50))
for i in range(0, x.shape[0]-1):
for j in range(0, x.shape[1]-1):
y[i, j] = x[i, j] + x[i+1, j] - x[i+1, j+1] * x[i, j+1]
z = np.zeros_like(y)
z[0:-1, 0:-1] = x[0:-1, 0:-1] + x[1:, 0:-1] - x[1:, 1:] * x[0:-1, 1:]
if (z == y).all():
print('Allumettes')
else:
print('Faux')
Le résultat de l'exécution est ... correct. 0 dans la plage n'est pas nécessaire, mais par souci de compréhension. Autre
--De `0``` à` `ni, nj``` (` `x.shape [0], x.shape [1]` `) --De
1``` à
ni, nj``` (
`x.shape [0], x.shape [1]` `) --``` 1``` à
ni-1, nj-1``` (
x.shape [0] -1, x.shape [1] -1```) --De ``
2 à` `ni-3, nj-3
(
x.shape [0] -3, x.shape [1] -3 ''`)
Etc.
#0 à ni, nj (x.shape[0], x.shape[1])
for i in range(0, x.shape[0]):
for j in range(x.shape[1]):
y[i, j] = x[i, j] + x[i, j]
z[0:, 0:] = x[0:, 0:] + x[0:, 0:]
#1 à ni, nj (x.shape[0], x.shape[1])
for i in range(1, x.shape[0]):
for j in range(1, x.shape[1]):
y[i, j] = x[i, j] + x[i-1, j] - x[i-1, j-1] * x[i, j-1]
z[1:, 1:] = x[1:, 1:] + x[0:-1, 1:] - x[0:-1, 0:-1] * x[1:, 0:-1]
#1 à ni-1, nj-1 (x.shape[0]-1, x.shape[1]-1)
for i in range(1, x.shape[0]-1):
for j in range(1, x.shape[1]-1):
y[i, j] = x[i, j] + x[i-1, j] - x[i+1, j-1] * x[i, j+1]
z[1:-1, 1:-1] = x[1:-1, 1:-1] + x[0:-2, 1:-1] - x[2:, 0:-2] * x[1:-1, 2:]
#2 à ni-3, nj-3 (x.shape[0]-3, x.shape[1]-3)
for i in range(2, x.shape[0]-3):
for j in range(2, x.shape[1]-3):
y[i, j] = x[i, j] + x[i-1, j] - x[i+1, j-1] * x[i, j+1]
z[2:-3, 2:-3] = x[2:-3, 2:-3] + x[1:-4, 2:-3] - x[3:-2, 1:-4] * x[2:-3, 3:-2]
Hmmm, est-ce quelque chose comme ça?
# i,j de n à ni-m, nj-Boucle à m
# x[i, j], x[i-ln, j], x[i+ln, j-ln], x[i, j+ln]Etc
for i in range(n, x.shape[0]-m):
for j in range(n, x.shape[1]-m):
y[i, j] = x[i, j] + x[i-ln, j] - x[i+ln, j-ln] * x[i, j+ln]
z[n:-m, n:-m] = x[n:-m, n:-m] + x[n-ln:-m-ln, n:-m] - \
x[n+ln:-m+ln, n-ln:-m-ln] * x[n:-m, n+ln:-m+ln
Beaucoup de désordre sommaire. C'est extrêmement difficile à lire, alors je vais en faire un tableau.
start | end | i | i-1 | i+1 | i-ln |
---|---|---|---|---|---|
0 | ni | 0: |
- | - | - |
0 | ni-1 | 0:-1 |
- | 1: |
- |
1 | ni | 1: |
0:-1 |
- | - |
1 | ni-1 | 1:-1 |
0:-2 |
2: |
- |
n | ni-m | n:-m |
n-1:-m-1 |
n+1:-m+1 |
n-ln:-m-ln |
※ ni = x.shape[0]
Est-ce correct? C'est difficile à comprendre, peu importe comment vous l'écrivez. En tant que débutant en Python, j'ai la franche impression qu'il ne devrait pas être utilisé du point de vue de la maintenabilité. Au moins à ce stade, je le pensais.
J'ai bouclé et mesuré pour que le calcul tourne 100 millions de fois. Dans le premier calcul unidimensionnel, j'ai rendu le maillage plus fin et calculé environ 20 millions de fois, il semble donc qu'il y en ait plusieurs 100 millions de fois, mais dans le calcul réel, il n'y en a pas du tout. Il était difficile de faire correspondre les fractions, alors laissez-le tel quel. Le résultat de la mesure est la moyenne de 10 exécutions chacune.
loop | for (sec) |
slice (sec) |
ave: s/f % |
max: s/f % |
min: s/f % |
median: s/f % |
---|---|---|---|---|---|---|
100,007,840 | 148.3013 | 1.3558 | 0.91% | 0.95% | 0.88% | 0.91% |
10,020,160 | 13.4111 | 0.1179 | 0.88% | 1.00% | 0.72% | 0.86% |
1,024,160 | 1.4228 | 0.0146 | 1.03% | 1.20% | 0.84% | 1.04% |
110,720 | 0.1536 | 0.0017 | 1.10% | 1.35% | 0.96% | 1.08% |
Joiko écrasante! !! !! Pepe
Ce n'est pas au niveau de la maintenabilité. Terminer à peu près à environ 1% signifie qu'un calcul qui prend une heure se terminera en 36 secondes. Et un jour? Pour une semaine? ?? 1 mois? ?? ?? Pour la lisibilité, il n'y a absolument aucune option à utiliser. Veuillez écrire dans les commentaires.
Cependant, que ce calcul numpy soit rapide ou non est une autre affaire. Il semble que numpy soit implémenté en langage C et en Fortran, mais il est plus rapide d'imbriquer des boucles dans Fortran! Je pense qu'il y a quelque chose comme ça. Non vérifié.
c'est tout. Je pense qu'il y a quelque chose qui devrait être fait plus comme ça, mais une fois que c'est fait.
Recommended Posts