J'essaie de mettre à jour / changer les paramètres d'un modèle de réseau neuronal et de faire ensuite passer le transfert vers l'avant du réseau neuronal mis à jour dans le graphique de calcul (peu importe le nombre de changements / mises à jour que nous faisons).
J'ai essayé cette idée, mais chaque fois que je le fais, pytorch définit mes tenseurs mis à jour (à l'intérieur du modèle) comme des feuilles, ce qui tue le flux de dégradés vers les réseaux que je souhaite recevoir. Cela tue le flux de gradients parce que les nœuds feuilles ne font pas partie du graphe de calcul comme je le veux (car ils ne sont pas vraiment des feuilles).
J'ai essayé plusieurs choses mais rien ne semble fonctionner. J'ai créé un code factice autonome qui imprime les gradients des réseaux que je souhaite avoir:
import torch
import torch.nn as nn
import copy
from collections import OrderedDict
# img = torch.randn([8,3,32,32])
# targets = torch.LongTensor([1, 2, 0, 6, 2, 9, 4, 9])
# img = torch.randn([1,3,32,32])
# targets = torch.LongTensor([1])
x = torch.randn(1)
target = 12.0*x**2
criterion = nn.CrossEntropyLoss()
#loss_net = nn.Sequential(OrderedDict([('conv0',nn.Conv2d(in_channels=3,out_channels=10,kernel_size=32))]))
loss_net = nn.Sequential(OrderedDict([('fc0', nn.Linear(in_features=1,out_features=1))]))
hidden = torch.randn(size=(1,1),requires_grad=True)
updater_net = nn.Sequential(OrderedDict([('fc0',nn.Linear(in_features=1,out_features=1))]))
print(f'updater_net.fc0.weight.is_leaf = {updater_net.fc0.weight.is_leaf}')
#
nb_updates = 2
for i in range(nb_updates):
print(f'i = {i}')
new_params = copy.deepcopy( loss_net.state_dict() )
## w^<t> := f(w^<t-1>,delta^<t-1>)
for (name, w) in loss_net.named_parameters():
print(f'name = {name}')
print(w.size())
hidden = updater_net(hidden).view(1)
print(hidden.size())
#delta = ((hidden**2)*w/2)
delta = w + hidden
wt = w + delta
print(wt.size())
new_params[name] = wt
#del loss_net.fc0.weight
#setattr(loss_net.fc0, 'weight', nn.Parameter( wt ))
#setattr(loss_net.fc0, 'weight', wt)
#loss_net.fc0.weight = wt
#loss_net.fc0.weight = nn.Parameter( wt )
##
loss_net.load_state_dict(new_params)
#
print()
print(f'updater_net.fc0.weight.is_leaf = {updater_net.fc0.weight.is_leaf}')
outputs = loss_net(x)
loss_val = 0.5*(target - outputs)**2
loss_val.backward()
print()
print(f'-- params that dont matter if they have gradients --')
print(f'loss_net.grad = {loss_net.fc0.weight.grad}')
print('-- params we want to have gradients --')
print(f'hidden.grad = {hidden.grad}')
print(f'updater_net.fc0.weight.grad = {updater_net.fc0.weight.grad}')
print(f'updater_net.fc0.bias.grad = {updater_net.fc0.bias.grad}')
si quelqu'un sait comment le faire, donnez-moi un ping ... J'ai défini le nombre de fois à mettre à jour à 2 parce que l'opération de mise à jour devrait être dans le graphique de calcul un nombre arbitraire de fois ... donc ça DOIT fonctionner pour 2.
Poste fortement lié:
- SO: Comment peut-on avoir des paramètres dans un modèle pytorch qui ne soient pas des feuilles et qui soient dans le graphe de calcul?
- forum pytorch: https://discuss.pytorch.org/t/how-does-one-have-the-parameters-of-a-model-not-be-leafs/70076
Cross-posted:
backward
? A savoirretain_graph=True
et / oucreate_graph=True
?