पाइरॉच मॉडल में किसी के पास लीफ़्स नहीं है और गणना ग्राफ में कैसे हो सकता है?


10

मैं एक न्यूरल नेट मॉडल के मापदंडों को अपडेट / बदलने की कोशिश कर रहा हूं और फिर अपडेटेड न्यूरल नेट के फॉरवर्ड पास होने पर कंपीटिशन ग्राफ (चाहे हम कितने भी बदलाव / अपडेट करें) हो।

मैंने इस विचार की कोशिश की, लेकिन जब भी मैं इसे करता हूं तो मेरे अपडेट किए गए टेंसरों (मॉडल के अंदर) को लीफ्स सेट करता है, जो उन ग्रेडर के प्रवाह को मारता है जिन्हें मैं ग्रेडिएंट प्राप्त करना चाहता हूं। यह ग्रेडिएंट्स के प्रवाह को मारता है क्योंकि लीफ नोड्स गणना के ग्राफ का हिस्सा नहीं हैं जिस तरह से मैं उन्हें होना चाहता हूं (क्योंकि वे वास्तव में लीफ़ नहीं हैं)।

मैंने कई चीजों की कोशिश की है, लेकिन कुछ भी काम नहीं करता है। मैंने एक डमी कोड बनाया है जो स्वयं में निहित है जो उन नेटवर्क के ग्रेडर को प्रिंट करता है जिनकी मुझे ग्रेडर की इच्छा है:

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}')

अगर किसी को पता है कि यह कैसे करना है तो कृपया मुझे एक पिंग दें ... मैंने अपडेट होने के लिए समय की संख्या को 2 पर सेट किया क्योंकि अपडेट ऑपरेशन को कम्प्यूटेशन ग्राफ में एक मनमाना संख्या होना चाहिए ... इसलिए यह काम करना चाहिए 2।


मजबूती से संबंधित पोस्ट:

क्रॉस-पोस्ट:


आप के लिए बहस की कोशिश की backward? अर्थात् retain_graph=Trueऔर / या create_graph=True?
सिज़्मोन मस्ज़के

जवाबों:


3

नामित कार्य मोड को हटाए जाने वाले नामित मॉड्यूलों को पूरा करता है।


यह काम करता है:

import torch
import torch.nn as nn

from torchviz import make_dot

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}')
#
def del_attr(obj, names):
    if len(names) == 1:
        delattr(obj, names[0])
    else:
        del_attr(getattr(obj, names[0]), names[1:])
def set_attr(obj, names, val):
    if len(names) == 1:
        setattr(obj, names[0], val)
    else:
        set_attr(getattr(obj, names[0]), names[1:], val)

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 list(loss_net.named_parameters()):
        hidden = updater_net(hidden).view(1)
        #delta = ((hidden**2)*w/2)
        delta = w + hidden
        wt = w + delta
        del_attr(loss_net, name.split("."))
        set_attr(loss_net, name.split("."), wt)
    ##
#
print()
print(f'updater_net.fc0.weight.is_leaf = {updater_net.fc0.weight.is_leaf}')
print(f'loss_net.fc0.weight.is_leaf = {loss_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}') # None because this is not a leaf, it is overriden in the for loop above.
print(f'updater_net.fc0.weight.grad = {updater_net.fc0.weight.grad}')
print(f'updater_net.fc0.bias.grad = {updater_net.fc0.bias.grad}')
make_dot(loss_val)

उत्पादन:

updater_net.fc0.weight.is_leaf = True
i = 0
i = 1

updater_net.fc0.weight.is_leaf = True
loss_net.fc0.weight.is_leaf = False

-- params that dont matter if they have gradients --
loss_net.grad = None
-- params we want to have gradients --
hidden.grad = None
updater_net.fc0.weight.grad = tensor([[0.7152]])
updater_net.fc0.bias.grad = tensor([-7.4249])

आभार: पाइरॉच टीम से शक्तिशाली एल्बन: https://discuss.pytorch.org/t/how-does-one-have-the-parameters-of-a-model-not-be-lsfs/70076/9?u= पिनोच्चियो


दोस्तों, यह गलत है, इस कोड का उपयोग न करें, यह 1 से अधिक चरणों के लिए ग्रेडिएंट का प्रचार करने की अनुमति नहीं देता है। इसके बजाय इसका उपयोग करें: github.com/facebookresearch/higher
Pinocchio

यह काम नहीं करता ppl!
पिनोच्चियो

उच्चतर पुस्तकालय मेरे लिए अभी तक काम नहीं करता है।
पिनोच्चियो

0

आपको समान टेनर्स रखने की कोशिश करनी चाहिए, नया नहीं बनाना चाहिए।

उनकी dataविशेषता के लिए जाएं और एक नया मान सेट करें।

for (name, w) in loss_net.named_parameters():
    ....
    w.data = wt.data

यह मेरे लिए इस सवाल में काम करता है: बैकपॉपैगैशन को तोड़ने के बिना पाइरॉच वैरिएबल को एक नया मान कैसे असाइन करें?

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.