2 votes

Numpy : Alternative aux boucles, optimisation

Étant donné que je suis novice en matière de Numpy, je rencontre des problèmes pour mettre en œuvre un code particulier que j'ai écrit en C++.

for(i=0;i<h;i++)
{
    for(j=0;j<w;j++)
    {
        val=0;
        for(i1=-size;i1<=size;i1++)
        {
            for(j1=-size;j1<=size;j1++)
            {
                h1=i+i1,w1=j+j1;
                if (w1<=0) w1=w1+w;
                if (h1<=0) h1=h1+h;
                if (w1>=w) w1=w1-w;
                if (h1>=h) h1=h1-h;
                val=val+sqrt(pow(data[i][j][0]-data[h1][w1][0],2)
                            +pow(data[i][j][1]-data[h1][w1][1],2)
                            +pow(data[i][j][2]-data[h1][w1][2],2));
            }
        }
    }
}

Comme vous pouvez le voir, j'ajoute la distance euclidienne pour l'élément [i,j] à chaque élément faisant partie de la sous-matrice [i-taille à i+taille][j-taille à j+taille].

comment puis-je écrire le code en python sans avoir à utiliser des boucles pour effectuer une opération pour chaque élément du tableau numpy qui dépend de ses positions en ligne et en colonne. Ou bien il doit y avoir un moyen de l'optimiser.

Voici ma mise en œuvre actuelle qui est TRES TRES LENTE

for i in range(0,h):
    for j in range(0,w):
        for i1 in range(-window_size, window_size+1):
            for j1 in range(-window_size, window_size+1):
                h1=i+i1
                w1=j+j1
                if w1 <= 0:
                    w1+=w
                if  h1 <= 0:
                    h1+=h
                if w1 >= w:
                    w1-=w
                if h1 >= h:
                    h1-=h
                val[i][j] += np.sqrt(((source_pyr_down_3_Luv[i][j][0] - source_pyr_down_3_Luv[h1][w1][0])**2)
                                    +((source_pyr_down_3_Luv[i][j][1] - source_pyr_down_3_Luv[h1][w1][1])**2)
                                    +((source_pyr_down_3_Luv[i][j][2] - source_pyr_down_3_Luv[h1][w1][2])**2))

Il a fallu presque 6 minutes pour exécuter ce code.

3voto

Sam Sharp Points 359

Pour accéder à un sous tableau im numpy try :

data[i-size:i+size,j-size:j+size]

pour modifier ce sous-réseau (dans ce cas, un simple +1 à chaque élément) :

data[i-size:i+size,j-size:j+size] += 1

ou pour obtenir un autre tableau contenant la distance entre les éléments de 2 tableaux (de forme (n,2)) :

data3 = np.sqrt(np.power(data1[:,0]-data2[:,0],2)+ np.power(data1[:,1]-data2[:,1],2))

Je sais que ce n'est pas une réponse complète, mais j'espère que cela vous aidera à démarrer.

2voto

6502 Points 42700

Vous pouvez éviter les boucles internes explicites et calculer la matrice des distances euclidiennes directement en étendant au préalable la matrice d'origine de sorte qu'aucune vérification n'est nécessaire sur les indices des éléments :

# Extend the matrix to avoid modular access
h, w, _ = data.shape
exdata = numpy.zeros((h+2*size, w+2*size, 2), data.dtype)
exdata[size:-size, size:-size, :] = data[:,:,:]  # Fill central part
exdata[:size,:,:] = exdata[-size*2:-size,:,:]    # Copy last rows to begin
exdata[-size:,:,:] = exdata[size:size*2,:,:]     # Copy first rows to end
exdata[:,:size,:] = exdata[:,-size*2:-size,:]    # Copy last cols to begin
exdata[:,-size:,:] = exdata[:,size:size*2,:]     # Copy first cols to end

# Do the actual computation
val = 0
for i in xrange(h):
    for j in xrange(w):
        dx = numpy.copy(exdata[i:i+size*2+1, j:j+size*2+1, 0])  # all x values
        dy = numpy.copy(exdata[i:i+size*2+1, j:j+size*2+1, 1])  # all y values
        dx -= dx[size, size] # subtract central x
        dy -= dy[size, size] # subtract central y
        dx *= dx # square dx
        dy *= dy # square dy
        dx += dy # sum of squares
        val += numpy.sum(dx ** 0.5)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X