Sto cercando di aggiornare / modificare i parametri di un modello di rete neurale e quindi avere il passaggio in avanti della rete neurale aggiornata essere nel grafico di calcolo (indipendentemente da quanti cambiamenti / aggiornamenti facciamo).
Ho provato questa idea ma ogni volta che lo faccio pytorch imposta i miei tensori aggiornati (all'interno del modello) come foglie, il che uccide il flusso di gradienti verso le reti che voglio ricevere gradienti. Uccide il flusso di gradienti perché i nodi foglia non fanno parte del grafico di calcolo nel modo in cui voglio che siano (poiché non sono veramente foglie).
Ho provato più cose ma nulla sembra funzionare. Ho creato un codice fittizio autonomo che stampa i gradienti delle reti che desidero avere gradienti:
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}')
se qualcuno sa come fare per favore dammi un ping ... Ho impostato il numero di volte per l'aggiornamento su 2 perché l'operazione di aggiornamento dovrebbe essere nel grafico di calcolo un numero arbitrario di volte ... quindi DEVE funzionare per 2.
Post fortemente correlati:
- SO: Come si possono avere parametri in un modello pytorch non essere foglie ed essere nel grafico di calcolo?
- forum pytorch: https://discuss.pytorch.org/t/how-does-one-have-the-parameters-of-a-model-not-be-leafs/70076
Cross-postato:
backward
? Vale a direretain_graph=True
e / ocreate_graph=True
?