pytorch F.cross_entropy не применяет градиент к весам - PullRequest
1 голос
/ 30 апреля 2020

Я пытаюсь обучить MLP с нуля, используя torch тензоры и некоторые встроенные функции потерь. У меня есть IRIS-данные, загруженные и сохраненные в тензор (100, 4) и метки (100) (целые числа 0-2) в data_tr и targets_tr. Я включил градиенты во входных данных data_tr.requires_grad=True

У меня 2-слойный MLP, инициализированный так:

W1 = torch.randn([4, 64], requires_grad=True)
W2 = torch.randn([64, 3], requires_grad=True)
b1 = torch.tensor([1.0], requires_grad=True)
b2 = torch.tensor([1.0], requires_grad=True

Я понимаю, что должен тренироваться так:

for epoch in range(num_epochs):
    W1.grad = None
    W2.grad = None
    b1.grad = None
    b2.grad = None

    f = torch.relu(data_tr @ W1 + b1) @ W2 + b2
    error = torch.nn.functional.cross_entropy(f, targets_tr)
    error.backward()

    W1 = W1 - lr * W1.grad
    W2 = W2 - lr * W2.grad
    b1 = b1 - lr * b1.grad
    b2 = b2 - lr * b2.grad

Что делает двухслойный MLP, а cross_entropy применяет softmax. Проблема в том, что ни один из весов или смещений (W1, W2, b1, b2) не имеет градиентов после обратного прохода. Таким образом, я получаю TypeError: unsupported operand type(s) for *: 'float' and 'NoneType' при первой попытке обновления веса.

1 Ответ

0 голосов
/ 01 мая 2020

Если вы хотите обновить веса без использования оптимизатора, вы должны либо использовать torch.no_grad(), либо обновить их data напрямую, чтобы гарантировать, что autograd не отслеживает операции обновления.

with torch.no_grad():
    W1 -= lr * W1.grad
    W2 -= lr * W2.grad

b1.data = b1 - lr * b1.grad
b2.data = b2 - lr * b2.grad

Обратите внимание, что в первом случае, если вы не вычитаете назначение, для requires_grad будет установлено значение False для весов, что снова приведет к значениям None для градиентов.

with torch.no_grad():
    W1 = W1 - lr * W1.grad
    W2 = W2 - lr * W2.grad
print(W1.requires_grad, W2.requires_grad)
>>> False False
...