Próbuję zaktualizować / zmienić parametry modelu sieci neuronowej, a następnie przekazać do przodu zaktualizowaną sieć neuronową na wykresie obliczeniowym (bez względu na to, ile zmian / aktualizacji dokonamy).
Wypróbowałem ten pomysł, ale za każdym razem, gdy to robię, pytorch ustawia moje zaktualizowane tensory (wewnątrz modelu) na liście, co zabija przepływ gradientów do sieci, które chcę odbierać. Zabija przepływ gradientów, ponieważ węzły liści nie są częścią wykresu obliczeniowego tak, jak chcę, aby były (ponieważ tak naprawdę nie są liśćmi).
Próbowałem wielu rzeczy, ale wydaje się, że nic nie działa. Stworzyłem sztuczny kod, który jest samowystarczalny, który drukuje gradienty sieci, które chcę mieć gradienty:
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}')
jeśli ktoś wie, jak to zrobić, daj mi ping ... Ustawiam liczbę aktualizacji na 2, ponieważ operacja aktualizacji powinna być na wykresie obliczeniowym dowolną liczbę razy ... więc MUSI działać dla 2)
Silnie powiązany post:
- SO: W jaki sposób parametry w modelu pytorch nie są listkami i znajdują się na wykresie obliczeniowym?
- forum pytorch: https://discuss.pytorch.org/t/how-does-one-have-the-parameters-of-a-model-not-be-leafs/70076
Przeniesiony:
- Quora: https://www.quora.com/unans answer/How-does-one-have-parameters-in-a-PyTorch-model-not-be-leaves-and-be-in-the-computation-graph
- reddit: https://www.reddit.com/r/pytorch/comments/f5gu3g/how_does_one_have_parameters_in_a_pytorch_model/
backward
? Mianowicieretain_graph=True
i / lubcreate_graph=True
?Odpowiedzi:
NIE DZIAŁA PRAWIDŁOWO, ponieważ wymienione moduły parametrów zostają usunięte.
Wydaje się, że to działa:
wynik:
Potwierdzenie: mighty albanD z zespołu pytorch: https://discuss.pytorch.org/t/how-does-one-have-the-parameters-of-a-model-not-be-leafs/70076/9?u= Pinokio
źródło
Powinieneś starać się zachować te same tensory, a nie tworzyć nowe.
Idź po ich
data
atrybut i ustaw nową wartość.To zadziałało dla mnie w tym pytaniu: Jak przypisać nową wartość do zmiennej pytorch bez przerywania propagacji wstecznej?
źródło