Градиента нет в pytorch, когда он не должен - PullRequest
0 голосов
/ 27 ноября 2018

Я пытаюсь получить / отследить градиент переменной, используя pytorch, где у меня есть эта переменная, передать ее первой функции, которая ищет какое-то минимальное значение какой-либо другой переменной, затем вводится вывод первой функциидля второй функции, и все это повторяется несколько раз.

Вот мой код:

import torch

def myFirstFunction(parameter_current_here):
    optimalValue = 100000000000000
    Optimal = 100000000000000
    for j in range(2, 10):
        i = torch.ones(1, requires_grad=True)*j
        with torch.enable_grad():
            optimalValueNow = i*parameter_current_here.sum()
        if (optimalValueNow < optimalValue):
            optimalValue = optimalValueNow
            Optimal = i
    return optimalValue, Optimal

def mySecondFunction(Current):
    with torch.enable_grad():
        y = (20*Current)/2 + (Current**2)/10
    return y

counter = 0
while counter < 5:
    parameter_current = torch.randn(2, 2, requires_grad=True)

    outputMyFirstFunction = myFirstFunction(parameter_current)
    outputmySecondFunction = mySecondFunction(outputMyFirstFunction[1])
    outputmySecondFunction.backward()

    print("outputMyFirstFunction after backward:",
               outputMyFirstFunction)
    print("outputmySecondFunction after backward:",
               outputmySecondFunction)
    print("parameter_current Gradient after backward:",
               parameter_current.grad)

    counter = counter + 1

Параметр_current.grad не равен ни для одной итерации, когда он, очевидно, не должен быть равен нулю.Что я делаю неправильно?И как я могу это исправить?

Ваша помощь по этому вопросу будет принята с благодарностью.Большое спасибо!

Али

Ответы [ 2 ]

0 голосов
/ 29 ноября 2018

Поскольку мне не совсем понятно, что вы на самом деле хотите архивировать, кроме вычисления градиентов для parameter_current, я просто сосредоточен на описании того, почему это не работает, и что вы можете сделать для точного вычисления градиентов.

Я добавил несколько комментариев в код, чтобы было более понятно, в чем проблема.

Но вкратце проблема в том, что ваш parameter_current не является частью вычисления вашего проигрыша соотв.тензор, который вы называете backward(), для которого outputmySecondFunction.

Так что в настоящее время вы вычисляете градиенты только для i, так как вы установили для него requires_grad=True.

Пожалуйста, проверьтекомментарии для деталей:

import torch

def myFirstFunction(parameter_current_here):
    # I removed some stuff to reduce it to the core features
    # removed torch.enable_grad(), since it is enabled by default
    # removed Optimal=100000000000000 and Optimal=i, they are not used
    optimalValue=100000000000000
    for j in range(2,10):
        # Are you sure you want to compute gradients this tensor i? 
        # Because this is actually what requires_grad=True does.
        # Just as a side note, this isn't your problem, but affects performance of the model.
        i= torch.ones(1,requires_grad=True)*j
        optimalValueNow=i*parameter_current_here.sum()
        if (optimalValueNow<optimalValue):
            optimalValue=optimalValueNow

    # Part Problem 1:
    # optimalValueNow is multiplied with your parameter_current
    # i is just your parameter i, nothing else
    # lets jump now the output below in the loop: outputMyFirstFunction
    return optimalValueNow,i

def mySecondFunction(Current):
    y=(20*Current)/2 + (Current**2)/10
    return y

counter=0
while counter<5:
    parameter_current = torch.randn(2, 2,requires_grad=True)

    # Part Problem 2:
    # this is a tuple (optimalValueNow,i) like described above
    outputMyFirstFunction=myFirstFunction(parameter_current)
    # now you are taking i as an input
    # and i is just torch.ones(1,requires_grad=True)*j
    # it as no connection to parameter_current
    # thus nothing is optimized
    outputmySecondFunction=mySecondFunction(outputMyFirstFunction[1])

    # calculating gradients, since parameter_current is not part of the computation 
    # no gradients will be computed, you only get gradients for i
    # Btw. if you would not have set requires_grad=True for i, you actually would get an error message
    # for calling backward on this
    outputmySecondFunction.backward()

    print("outputMyFirstFunction after backward:",outputMyFirstFunction)
    print("outputmySecondFunction after backward:",outputmySecondFunction)
    print("parameter_current Gradient after backward:",parameter_current.grad)

    counter=counter+1

Итак, если вы хотите вычислить градиенты для parameter_current, вам просто нужно убедиться, что это часть вычисления тензора, который вы называете backward(), вы можете сделатьнапример, изменив:

outputmySecondFunction=mySecondFunction(outputMyFirstFunction[1])

на:

outputmySecondFunction=mySecondFunction(outputMyFirstFunction[0])

Будет иметь этот эффект, как только вы измените его, вы получите градиенты для parameter_current!

Надеюсь, это поможет!



Полный рабочий код:

import torch

def myFirstFunction(parameter_current_here):
    optimalValue=100000000000000
    for j in range(2,10):
        i= torch.ones(1,requires_grad=True)*j
        optimalValueNow=i*parameter_current_here.sum()
        if (optimalValueNow<optimalValue):
            optimalValue=optimalValueNow

    return optimalValueNow,i

def mySecondFunction(Current):
    y=(20*Current)/2 + (Current**2)/10
    return y

counter=0
while counter<5:
    parameter_current = torch.randn(2, 2,requires_grad=True)
    outputMyFirstFunction=myFirstFunction(parameter_current)
    outputmySecondFunction=mySecondFunction(outputMyFirstFunction[0]) # changed line
    outputmySecondFunction.backward()

    print("outputMyFirstFunction after backward:",outputMyFirstFunction)
    print("outputmySecondFunction after backward:",outputmySecondFunction)
    print("parameter_current Gradient after backward:",parameter_current.grad)

    counter=counter+1

Вывод:

outputMyFirstFunction after backward: (tensor([ 1.0394]), tensor([ 9.]))
outputmySecondFunction after backward: tensor([ 10.5021])
parameter_current Gradient after backward: tensor([[ 91.8709,  91.8709],
        [ 91.8709,  91.8709]])
outputMyFirstFunction after backward: (tensor([ 13.1481]), tensor([ 9.]))
outputmySecondFunction after backward: tensor([ 148.7688])
parameter_current Gradient after backward: tensor([[ 113.6667,  113.6667],
        [ 113.6667,  113.6667]])
outputMyFirstFunction after backward: (tensor([ 5.7205]), tensor([ 9.]))
outputmySecondFunction after backward: tensor([ 60.4772])
parameter_current Gradient after backward: tensor([[ 100.2969,  100.2969],
        [ 100.2969,  100.2969]])
outputMyFirstFunction after backward: (tensor([-13.9846]), tensor([ 9.]))
outputmySecondFunction after backward: tensor([-120.2888])
parameter_current Gradient after backward: tensor([[ 64.8278,  64.8278],
        [ 64.8278,  64.8278]])
outputMyFirstFunction after backward: (tensor([-10.5533]), tensor([ 9.]))
outputmySecondFunction after backward: tensor([-94.3959])
parameter_current Gradient after backward: tensor([[ 71.0040,  71.0040],
        [ 71.0040,  71.0040]])
0 голосов
/ 29 ноября 2018

Я предполагаю, что проблема в with torch.enable_grad(): утверждениях.После выхода из оператора with torch.enable_grad() больше не применяется, и torch очищает грады после запуска функций.

...