Почему производная f (x) по отношению к «x» «x», а не 1 в pytorch?

Я пытаюсь полностью понять автоград pytorch, и я наткнулся на это: пусть f(x)=x, из базовой математики мы знаем, что f'(x)=1, однако, когда я делаю это упражнение в pytorch, я получаю это f' (х) = х.

z = torch.linspace(-1, 1, steps=5, requires_grad=True)
y = z
y.backward(z)
print("Z tensor is: {} \n Gradient of y with respect to z is: {}".format(z, z.grad))

Я бы ожидал получить тензор размера 5, полный 1, но вместо этого я получаю:

Z tensor is: tensor([-1.0000, -0.5000,  0.0000,  0.5000,  1.0000], requires_grad=True) 
 Gradient of y with respect to z is: tensor([-1.0000, -0.5000,  0.0000,  0.5000,  1.0000])

Почему это поведение pytorch?

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
4
0
867
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

После обсуждения с коллегой он обнаружил, что метод «назад()» на самом деле умножает градиент, оцененный в точке z, на саму z. Это имеет смысл для приложений нейронных сетей. Краткий фрагмент кода, чтобы понять это, выглядит следующим образом:

z = torch.linspace(1, 5, steps=5, requires_grad=True)
y = torch.pow(z,2)
y.backward(z)
print("Z tensor is: {} \n Gradient of y with respect to z is: {}".format(z, z.grad/z))

Результат:

Z tensor is: tensor([1., 2., 3., 4., 5.], requires_grad=True) 
 Gradient of y with respect to z is: tensor([ 2.,  4.,  6.,  8., 10.], grad_fn=<DivBackward0>)

В этом случае вы можете видеть, что z.grad, деленное на z, является фактическим ожидаемым градиентом z, который будет равен 2*z.

Ответ принят как подходящий

Прежде всего, учитывая z = torch.linspace(-1, 1, steps=5, requires_grad=True) и y = z, функция является векторнозначной функцией, поэтому производная от y относительно z не так проста, как 1, а представляет собой матрицу Якоби. На самом деле в вашем случае z = [z1, z2, z3, z4, z5]T верхний регистр T означает, что z является вектором-строкой. Вот что говорит официальный документ:

Во-вторых, обратите внимание, что официальный документ говорит: Теперь в этом случае y больше не является скаляром. torch.autograd не может напрямую вычислить полный якобиан, но если нам просто нужно векторно-якобианское произведение, просто передайте вектор обратно в качестве аргумента связь. В этом случае x.grad — это не фактическое значение градиента (матрица), а векторно-якобианское произведение.

Обновлено: x.grad - это фактический градиент, если ваш вывод y является скаляром. См. пример здесь:

z = torch.linspace(-1, 1, steps=5, requires_grad=True)
y = torch.sum(z)
y.backward()
z.grad 

Это выведет:

tensor([1., 1., 1., 1., 1.])

Как видите, это градиент. Обратите внимание, что единственное отличие состоит в том, что здесь y — это скалярное значение, а в вашем примере — векторное значение. grad может быть неявно создан только для скалярных выходов

Вы можете задаться вопросом, а что, если градиент не является константой, например, зависит от ввода z, как в этом случае.

z = torch.linspace(-1, 1, steps=5, requires_grad=True)
y = torch.sum(torch.pow(z,2))
y.backward()
z.grad

Результат:

tensor([-2., -1.,  0.,  1.,  2.])

Это то же самое, что

z = torch.linspace(-1, 1, steps=5, requires_grad=True)
y = torch.sum(torch.pow(z,2))
y.backward(torch.tensor(1.))
z.grad

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

Спасибо! Я читал документацию раньше, но я не был полностью уверен, что это значит. Я думаю, что это немного вводит в заблуждение, называя векторно-якобианское произведение просто «выпускным».

Sergio 10.04.2019 16:28

Другие вопросы по теме