2013-07-05 4 views
11

Stavo implementando un sistema di ponderazione chiamato TF-IDF su un set di 42000 immagini, ciascuna costituita da 784 pixel. Questa è fondamentalmente una matrice 42000 per 784.Spiegare la differenza di velocità tra l'applicazione della funzione vettoriale di numpy VS python's for loop

Il primo metodo che ho tentato fatto uso di loop esplicite e ha preso più di 2 ore .

def tfidf(color,img_pix,img_total): 
    if img_pix==0: 
     return 0 
    else: 
     return color * np.log(img_total/img_pix) 

... 

result = np.array([]) 
for img_vec in data_matrix: 
    double_vec = zip(img_vec,img_pix_vec) 
    result_row = np.array([tfidf(x[0],x[1],img_total) for x in double_vec]) 
    try: 
     result = np.vstack((result,result_row)) 
    # first row will throw a ValueError since vstack accepts rows of same len 
    except ValueError: 
     result = result_row 

Il secondo metodo ho tentato matrici NumPy usati e preso meno di 5 minuti. Nota che data_matrix, img_pix_mat sono entrambe 42000 per 784 matrici mentre img_total è uno scalare.

result = data_matrix * np.log(np.divide(img_total,img_pix_mat)) 

Speravo che qualcuno potrebbe spiegare l'immensa differenza di velocità.

Gli autori del seguente documento intitolato "La matrice NumPy: una struttura per un calcolo numerico e ffi ciente" (http://arxiv.org/pdf/1102.1523.pdf), indicano in cima alla pagina 4 che osservano un aumento di velocità 500 volte dovuto al calcolo vettorializzato. Presumo che gran parte dell'aumento di velocità che sto vedendo sia dovuto a questo. Tuttavia, vorrei fare un ulteriore passo avanti e chiedere perché i calcoli vettoriali compatti sono molto più veloci dei loop standard di Python?

Inoltre, forse voi ragazzi potreste sapere di altri motivi per cui il primo metodo è lento. Prova/eccetto che le strutture hanno un sovraccarico? O forse la formazione di un nuovo np.array per ogni ciclo richiede molto tempo?

Grazie.

+0

Questo spiega i motivi per cui l'uso di C di Numpy è molto più veloce: http: // stackoverflow.com/q OMANDE/8385602/why-sono-NumPy-array-così-veloce. –

risposta

6

causa il funzionamento interno di NumPy, (per quanto ne so, NumPy funziona con C internamente, quindi tutto si spinge verso il basso per NumPy in realtà è molto più veloce, perché è in una lingua diversa)

edit: estraendo lo zip, e la sua sostituzione con un vstack dovrebbe andare anche più veloce, (la zip tende ad andare lentamente se gli argomenti sono molto grandi, e vstack è più veloce), (ma è anche qualcosa che lo rende numpy (quindi in C), mentre zip è python)

e sì, se ho capito bene - non sono sicuro di quello-, stai facendo 42k volte un try/except block, che dovrebbe essere decisamente negativo per la velocità,

prova:

T=numpy.ndarray((5,10)) 
for t in T: 
print t.shape 

risultati in (10,)

Questo significa che sì, se le vostre matrici sono 42kx784 matrici, si sta cercando 42k volte al try-except blocco, io parto dal presupposto che dovrebbe mettere un effetto nei tempi di calcolo, così come ogni volta facendo una zip ogni volta, ma non certo se questa sarebbe la causa principale,

(così ognuno dei tuoi 42k volte che esegui la tua roba, prende 0.17 sec, sono abbastanza sicuro che un try/except block non richiede 0,17 secondi, ma forse l'ov se causa o meno, contribuisce a questo?

provare a cambiare la seguente:

double_vec = zip(img_vec,img_pix_vec) 
result_row = np.array([tfidf(x[0],x[1],img_total) for x in double_vec]) 

a

result_row=np.array([tfidf(img_vec[i],img_pix_vec[i],img_total) for i in xrange(len(img_vec))]) 

che almeno si sbarazza della dichiarazione zip, ma non è sicuro se la dichiarazione zip porta giù il vostro tempo solo minuto, o di quasi due ore (so che lo zip è lento, rispetto al vstack insipido, ma nessun indizio se questo ti darebbe due ore di guadagno)

+0

Questo risponde alla domanda? o vuoi una risposta più tecnica? (in generale, python non è fatto per funzionare velocemente, esistono altri linguaggi per questo, ma numpy esiste per quelli che vogliono usare python ma ottengono comunque velocità che sono almeno paragonabili alle velocità che si otterrebbero in C o FORTRAN, che erano fatto per le applicazioni di numbercrunching) – usethedeathstar

+0

È lo zip che lo causa ??? (solo per sapere per un uso futuro, se è 42k volte chiamando lo zip che lo causa?) poiché sarebbe bello sapere se questo dà una differenza di 2 ore, o se sarebbe solo migliorare 30min o così, – usethedeathstar

4

numpy è scritto in C. La differenza che si sta vedendo non è dovuta a nulla di particolare come la vettorizzazione SSE; è solo che l'implementazione di C non deve passare attraverso tonnellate di dispatch del metodo di runtime e controllo delle eccezioni e così via che passa attraverso l'implementazione di Python.