Perché le reti neurali convoluzionali usano tanta memoria?

3

Ho sentito che uno dei problemi principali dell'applicazione stile neurale alle immagini ad alta risoluzione è l'enorme quantità di memoria che utilizzare.

Inoltre, ho appena configurato una rete utilizzando piccolo-cnn

Questo è il mio calcolo per il numero di pesi e il numero di neuroni per strato nel mio esempio:

conv_layer_# height width depth filter_height filter_width neurons_(h*w*d) weights
1            512    512   3     3             3            786432          108    
2            256    256   6     3             3            393216          216    
3            128    128   12    3             3            196608          432    
4            64     64    24    3             3            98304           864    
5            32     32    48    3             3            49152           1728   
6            16     16    96    3             3            24576           3456   
7            8      8     192   3             3            12288           6912   

                                                           1560576         13716  

Se diamo ad ogni valore che deve essere memorizzato 8 byte (formato a virgola mobile di precisione singola), otteniamo 6297168 byte, cioè circa 12 MB. Ma la rete assegna oltre 1 GB di RAM quando lo alleno. A cosa serve tutta la memoria?

    
posta Tobias Hermann 11.07.2016 - 09:22
fonte

2 risposte

1

Ho scoperto alcuni dei fattori che possono contribuire all'effetto.

1) Almeno in tiny-cnn, alcuni buffer sono allocati non una volta ma una volta per thread di lavoro . Su una macchina con thread 8 della CPU, questo può aumentare l'utilizzo della memoria molto. In modalità di debug con MS VC ++ 2015 le seguenti due righe nel codice base allocano un grosso chunk, entrambi relativi ai thread worker: ith_in_node(i)->set_worker_size(worker_count); e ith_out_node(i)->set_worker_size(worker_count); .

2) Oltre ai valori per i neuroni e i pesi elencati nella mia domanda, anche i gradienti e alcune altre cose per i passaggi a ritroso e l'ottimizzazione devono essere memorizzati.

3) Non sono sicuro se questo è rilevante per tiny-cnn, ma molti framework sembrano utilizzare un'operazione chiamata im2col . Questo rende la convoluzione molto più veloce, esprimendola come una moltiplicazione di matrice. Ma in caso di filtri con 3 * 3 in altezza e larghezza, questo ridimensiona il numero di valori dall'input a una convoluzione fino a un fattore di 9 . Justin Johnson lo spiega nella lezione "S231n Winter 2016 Lecture 11 Convnet in pratica" che inizia alle 36:22.

4) C'è stato un errore nel mio calcolo iniziale . Quando un volume di 512 * 512 * 3 è convoluto con 6 filtri 3 * 3 e quindi viene inviato in uno strato di pool medio, il volume del risultato è 256 * 256 * 6, ma tra 512 * 512 * 6, anche con un fattore di 2 .

5) C'era un altro errore nel mio calcolo iniziale . Lo dimostro sull'ultimo livello conv (7). Richiede un volume di 16 * 16 * 96 su un volume di 8 * 8 * 192 con filtri di dimensioni 3 * 3. Questo significa che ogni filtro ha pesi 3 * 3 * 96, e ce ne sono 192, risultando in 165888 (3 * 3 * 96 * 192) pesi complessivi per questo strato, non 6912.

Quindi moltiplicando numericamente solo i primi tre fattori (8, 9 e 2) otteniamo un fattore 144, il che sembra sufficiente per spiegare l'elevato consumo di memoria.

    
risposta data 13.07.2016 - 09:56
fonte
1

Il tuo calcolo per la quantità di memoria utilizzata sembra essere correlato al numero di neuroni nella rete e memorizzare un double per ciascuno, ma non è l'unica memoria necessaria - ogni neurone conterrà anche un numero di pesi, ognuno dei quali ha probabilmente bisogno di almeno un float . Questa è l'ultima colonna del tuo output e (almeno se comprendo correttamente il programma che stai utilizzando correttamente) è il numero di pesi memorizzati per neurone . Supponendo che ogni peso sia un float , ciò equivale a poco più di 2 GB.

    
risposta data 12.07.2016 - 11:25
fonte

Leggi altre domande sui tag