Je travaille toujours sur l'implémentation de la mise à jour du gradient mini-batch sur mon réseau neuronal siamois. Auparavant, j'avais un problème d'implémentation, c'était correctly solved here.Torch/Lua, quelle structure de réseau neuronal pour la formation de mini-lot?
Maintenant, j'ai réalisé qu'il y avait aussi une erreur dans l'architecture de mon réseau de neurones, c'est lié à ma compréhension incomplète de la bonne implémentation. Jusqu'ici, j'ai toujours utilisé une approche de descente de gradient non-minibatch, dans laquelle je passais les éléments d'entraînement un par un à la mise à jour de gradient. Maintenant, je veux mettre en œuvre une mise à jour de gradient par mini-batch, en commençant par dire avec des minibatches faites de N = 2 éléments.
Ma question est: comment changer l'architecture de mon réseau de neurones siamois pour le rendre capable de gérer un mini-lot de N = 2 éléments au lieu d'un seul élément?
C'est le (simplifié) l'architecture de mon réseau de neurones Siamois:
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
}
Je:
- 2 réseaux de neurones Siamois identiques (supérieure et inférieure)
- 6 unités d'entrée
- 3 unités cachées
- 2 unités de sortie fonction
- distance cosinus qui compare la sortie des deux réseaux de neurones parallèles
Voici mon code:
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())
Cette architecture fonctionne très bien si j'ai une fonction de mise à jour de gradient qui prend 1 élément; comment devrait le modifier pour le laisser gérer un minibatch?
EDIT: Je devrais probablement utiliser le nn.Sequencer() class, en modifiant les deux dernières lignes de mon code:
perceptron:add(nn.Sequencer(parallel_table))
perceptron:add(nn.Sequencer(nn.CosineDistance())).
Qu'est-ce que vous en pensez?
Bonjour @Alexander, merci d'avoir répondu. J'essaie d'implémenter votre solution, mais je suis coincé dans l'instruction de mise à jour de gradient 'perceptron: backward (input_batch, targets)'. 'targets' devrait contenir les cibles de mon entraînement, par exemple' 0,1'. Si 'input_batch' est une liste de 2 DoubleTensors dont la taille est 3x5, quelles devraient être les bonnes dimensions de' target'? Merci –
@ DavideChicco.it, le but est de minimiser la distance entre les paires d'entrées, non? Quels sont vos objectifs alors? Je suppose que c'est des zéros. D'où vient 0,1? –
Je compare des paires de vecteurs. Chaque vecteur est composé de 6 valeurs réelles. Chaque paire peut être vraie (cible = 1) ou fausse (cible = 0). Pendant l'entraînement, j'appelle 'perceptron: forward (input_batch)' et ensuite 'perceptron: zeroGradParameters()' et 'perceptron: backward (input_batch, targets)'. J'ai des problèmes avec les dimensions des 'target's, que je dois adapter aux nouveaux paramètres. Un vecteur de #input_batch DoubleTensors de taille 1 ne fonctionne pas, que dois-je utiliser? Merci –