Sto ancora lavorando per implementare l'aggiornamento del gradiente mini-batch sulla mia rete neurale siamese. In precedenza avevo un problema di implementazione, ovvero correctly solved here.Torcia/Lua, quale struttura di rete neurale per l'addestramento in mini-batch?
Ora mi sono reso conto che c'era anche un errore nell'architettura della mia rete neurale, che è legato alla mia incompletezza nella comprensione della corretta implementazione.
Finora, ho sempre utilizzato un approccio di discesa gradiente non minibatch, in cui stavo passando gli elementi di allenamento uno alla volta all'aggiornamento del gradiente. Ora, voglio implementare un aggiornamento gradiente tramite mini-batch, iniziando a dire con minibatch composti da N = 2 elementi.
La mia domanda è: come dovrei cambiare l'architettura della mia rete neurale siamese per renderlo in grado di gestire un mini-lotto di N = 2 elementi invece di un singolo elemento?
Questo è il (semplificato) Architettura della mia rete neurale siamese:
nn.Sequential {
[input -> (1) -> (2) -> output]
(1): nn.ParallelTable {
input
|`-> (1): nn.Sequential {
| [input -> (1) -> (2) -> output]
| (1): nn.Linear(6 -> 3)
| (2): nn.Linear(3 -> 2)
| }
|`-> (2): nn.Sequential {
| [input -> (1) -> (2) -> output]
| (1): nn.Linear(6 -> 3)
| (2): nn.Linear(3 -> 2)
| }
... -> output
}
(2): nn.CosineDistance
}
ho:
- 2 identici reti neurali siamese (superiore e inferiore) unità
- 6 ingresso
- 3 unità nascoste
- 2 unità di uscita
- coseno funzione distanza che confronta l'uscita delle due reti neurali parallele
Ecco il mio codice:
perceptronUpper= nn.Sequential()
perceptronUpper:add(nn.Linear(input_number, hiddenUnits))
perceptronUpper:add(nn.Linear(hiddenUnits,output_number))
perceptronLower= perceptronUpper:clone('weight', 'gradWeights', 'gradBias',
'bias')
parallel_table = nn.ParallelTable()
parallel_table:add(perceptronUpper)
parallel_table:add(perceptronLower)
perceptron = nn.Sequential()
perceptron:add(parallel_table)
perceptron:add(nn.CosineDistance())
Questa architettura funziona molto bene se ho una funzione di aggiornamento gradiente che prende 1 elemento; come dovrebbe modificarlo per farlo gestire un minibatch ?
EDIT: probabilmente dovrebbe usare il nn.Sequencer() class, modificando le ultime due righe del mio codice:
perceptron:add(nn.Sequencer(parallel_table))
perceptron:add(nn.Sequencer(nn.CosineDistance())).
Cosa ne pensate?
Ciao @Alexander, grazie per la risposta. Sto cercando di implementare la tua soluzione, ma rimango bloccato nell'istruzione di aggiornamento gradazione 'perceptron: backward (input_batch, targets)'. 'targets' dovrebbe contenere gli obiettivi del mio allenamento, per esempio' 0,1'. Se 'input_batch' è una lista di 2 DoubleTensor la cui dimensione è 3x5, quali dovrebbero essere le dimensioni corrette di' target'? Grazie –
@ DavideChicco.it, l'obiettivo è ridurre al minimo la distanza tra coppie di input, giusto? Quali sono i tuoi obiettivi allora? Suppongo che sia zero. Da dove proviene '0,1'? –
Sto confrontando coppie di vettori. Ogni vettore è composto da 6 valori reali. Ogni coppia può essere true (target = 1) o false (target = 0). Durante l'allenamento, chiamo 'perceptron: forward (input_batch)' e quindi 'perceptron: zeroGradParameters()' e 'perceptron: backward (input_batch, targets)'. Sto avendo problemi con le dimensioni di 'targets', che devo adattarmi alle nuove impostazioni. Un vettore di #input_batch DoubleTensors di dimensione 1 non funziona, cosa dovrei usare? Grazie –