2009-11-23 14 views
0

J'essaie d'utiliser l'indexation de fantaisie au lieu de boucler pour accélérer une fonction dans Numpy. Au meilleur de ma connaissance, j'ai implémenté la version d'indexation de fantaisie correctement. Le problème est que les deux fonctions (loop et fantaisie-indexée) ne renvoient pas le même résultat. Je ne suis pas sûr pourquoi. Il convient de souligner que les fonctions retournent le même résultat si un tableau plus petit est utilisé (par exemple, 20 x 20 x 20). Ci-dessous j'ai inclus tout le nécessaire pour reproduire l'erreur. Si les fonctions retournent le même résultat, la ligne find_maxdiff(data) - find_maxdiff_fancy(data) doit retourner un tableau rempli de zéros.Pourquoi ces deux fonctions mathématiques ne renvoient-elles pas le même résultat?

from numpy import * 

def rms(data, axis=0): 
    return sqrt(mean(data ** 2, axis)) 

def find_maxdiff(data): 
    samples, channels, epochs = shape(data) 
    window_size = 50 
    maxdiff = zeros(epochs) 
    for epoch in xrange(epochs): 
     signal = rms(data[:, :, epoch], axis=1) 
     for t in xrange(window_size, alen(signal) - window_size): 
      amp_a = mean(signal[t-window_size:t], axis=0) 
      amp_b = mean(signal[t:t+window_size], axis=0) 
      the_diff = abs(amp_b - amp_a) 
      if the_diff > maxdiff[epoch]: 
       maxdiff[epoch] = the_diff 

    return maxdiff 

def find_maxdiff_fancy(data): 
    samples, channels, epochs = shape(data) 
    window_size = 50 
    maxdiff = zeros(epochs) 
    signal = rms(data, axis=1) 
    for t in xrange(window_size, alen(signal) - window_size): 
     amp_a = mean(signal[t-window_size:t], axis=0) 
     amp_b = mean(signal[t:t+window_size], axis=0) 
     the_diff = abs(amp_b - amp_a) 
     maxdiff[the_diff > maxdiff] = the_diff 

    return maxdiff 

data = random.random((600, 20, 100)) 
find_maxdiff(data) - find_maxdiff_fancy(data) 

data = random.random((20, 20, 20)) 
find_maxdiff(data) - find_maxdiff_fancy(data) 
+5

Quelle est l'ampleur de la différence entre les deux? Ce n'est pas le problème typique de la précision en virgule flottante qui attire tant de gens? – spender

+0

À quelle valeur entre 20x20x20 et 600x20x100 les choses commencent-elles à tourner mal? Est-ce que les choses vont mal de plus en plus progressivement et de plus en plus, ou tout à la fois? – AakashM

+0

L'ampleur des différences est plutôt grande pour être juste des erreurs en virgule flottante. – pealco

Répondre

3

Le problème est cette ligne:

maxdiff[the_diff > maxdiff] = the_diff 

Le côté gauche sélectionne seulement quelques éléments de MaxDiff, mais le côté droit contient tous les éléments de the_diff. Cela devrait fonctionner à la place:

replaceElements = the_diff > maxdiff 
maxdiff[replaceElements] = the_diff[replaceElements] 

ou simplement:

maxdiff = maximum(maxdiff, the_diff) 

Quant à savoir pourquoi la taille 20x20x20 semble fonctionner: Ceci est parce que votre taille de la fenêtre est trop grande, donc rien ne sera exécuté.

+0

Merci de m'avoir aidé à mieux comprendre comment fonctionnent les tâches de fantaisie. En outre, j'aurais dû attraper la raison stupide pourquoi la plus petite rangée fonctionnait :) Merci encore. – pealco

0

En premier lieu, de fantaisie votre signal est maintenant 2D si je comprends bien - donc je pense qu'il serait plus clair pour l'indexer de façon explicite (par exemple amp_a = moyenne (signal [t-window_size: t ,:], axe = 0) de même avec Alen (signal) -. ce devrait juste être des échantillons dans les deux cas, donc je pense qu'il serait plus clair d'utiliser cette

il est erroné chaque fois que vous faites réellement quelque chose dans la boucle t -. quand samples < window_lenght Comme dans l'exemple 20x20x20, cette boucle n'est jamais exécutée.Aussitôt que cette boucle est exécutée plus d'une fois (par exemple samples > 2 *window_length+1), les erreurs arrivent, mais je ne sais pas pourquoi - elles me semblent équivalentes