2015-06-07 10 views
5

C'è un modo per evitare questo ciclo in modo da ottimizzare il codice?NumPy: come evitare questo ciclo?

import numpy as np 

cLoss = 0 
dist_ = np.array([0,1,0,1,1,0,0,1,1,0]) # just an example, longer in reality 
TLabels = np.array([-1,1,1,1,1,-1,-1,1,-1,-1]) # just an example, longer in reality 
t = float(dist_.size) 
for i in range(len(dist_)): 
    labels = TLabels[dist_ == dist_[i]] 
    cLoss+= 1 - TLabels[i]*(1. * np.sum(labels)/t) 
print cLoss 

Nota:dist_ e TLabels sono entrambi gli array numpy con la stessa forma (t,1)

+3

Che cosa stai cercando di realizzare? –

+0

Beh, credo sia corretto, 'TLabels [dist_ == dist_ [i]]' restituirà valori da 'TLabels' che hanno indici dove' dist_ == dist_ [i] '. Ad esempio, 'dist_ = array ([2,1,2])' e 'TLabels = array ([1,2,3])' così 'dist_ == dist_ [0]' restituirà 'array ([Vero, False, True]) 'than' TLabels [dist_ == dist_ [0]] = array ([1,3]) ' – farhawa

+0

Giusto per essere chiari, sono gli array' (t, 1) 'o' (t,) '? Dove è inizializzato 'cLoss'? – hpaulj

risposta

2

Non sono sicuro di cosa si desidera esattamente fare, ma si è a conoscenza di scipy.ndimage.measurements per il calcolo su array con etichette? Sembra che tu voglia qualcosa come:

cLoss = len(dist_) - sum(TLabels * scipy.ndimage.measurements.sum(TLabels,dist_,dist_)/len(dist_)) 
1

Non sono sicuro se questo è meglio dal momento che non ho capito esattamente il motivo per cui si potrebbe desiderare di fare Questo. Molte variabili nel tuo ciclo sono bivalute, quindi possono essere calcolate in anticipo.

Anche le voci di dist_ possono essere utilizzate come un commutatore booleano ma ho comunque utilizzato una copia esplicita.

dist_  = np.array([0,1,0,1,1,0,0,1,1,0]) 
TLabels  = np.array([-1,1,1,1,1,-1,-1,1,-1,-1]) 
t   = len(dist) 
dist_zeros = dist_== 0 
one_zero_sum = [sum(TLabels[dist_zeros])/t , sum(TLabels[~dist_zeros])/t] 

cLoss  = sum([1-x*one_zero_sum[dist_[y]] for y,x in enumerate(TLabels)]) 

che risulta in cLoss = 8.2. Sto usando Python3 quindi non ho verificato se si tratta di una vera divisione o meno in Python2.

2

Innanzitutto mi chiedo, che cos'è labels in ogni fase del ciclo?

Con dist_ = array([2,1,2]) e TLabels=array([1,2,3])

ottengo

[-1 1] 
[1] 
[-1 1] 

La lunghezza diversa sollevare immediatamente una bandiera di avvertimento - può essere difficile per vettorizzare questo.

Con gli array lunghi nell'esempio modificato

[-1 1 -1 -1 -1] 
[ 1 1 1 1 -1] 
[-1 1 -1 -1 -1] 
[ 1 1 1 1 -1] 
[ 1 1 1 1 -1] 
[-1 1 -1 -1 -1] 
[-1 1 -1 -1 -1] 
[ 1 1 1 1 -1] 
[ 1 1 1 1 -1] 
[-1 1 -1 -1 -1] 

I labels vettori sono tutte la stessa lunghezza. È normale, o solo una coincidenza di valori?

goccia un paio di elementi di fuori dist_ e labels sono:

In [375]: for i in range(len(dist_)): 
     labels = TLabels[dist_ == dist_[i]] 
     v = (1.*np.sum(labels)/t); v1 = 1-TLabels[i]*v 
     print(labels, v, TLabels[i], v1) 
     cLoss += v1 
    .....:  
(array([-1, 1, -1, -1]), -0.25, -1, 0.75) 
(array([1, 1, 1, 1]), 0.5, 1, 0.5) 
(array([-1, 1, -1, -1]), -0.25, 1, 1.25) 
(array([1, 1, 1, 1]), 0.5, 1, 0.5) 
(array([1, 1, 1, 1]), 0.5, 1, 0.5) 
(array([-1, 1, -1, -1]), -0.25, -1, 0.75) 
(array([-1, 1, -1, -1]), -0.25, -1, 0.75) 
(array([1, 1, 1, 1]), 0.5, 1, 0.5) 

Ancora differenti lunghezze di etichette, ma in realtà solo pochi calcoli. Esiste 1 valore v per ciascun valore dist_ diverso.

Senza elaborare tutti i dettagli, sembra che si stia calcolando solo labels*labels per ciascun valore distinto dist_ e quindi sommando quelli.

Questo sembra un problema groupBy. Si desidera dividere lo dist_ in gruppi con un valore comune e sommare alcune funzioni dei rispettivi valori TLabels corrispondenti. Python itertools ha una funzione groupBy, quindi pandas. Penso che entrambi richiedano di ordinare dist_.

Provare a ordinare dist_ e vedere se questo aggiunge chiarezza al problema.