Введение в PyTorch для Xiaobai | Часть 2: Автоматическое дифференцирование

PyTorch алгоритм
Введение в PyTorch для Xiaobai | Часть 2: Автоматическое дифференцирование

?Эта статьяGitHub GitHub.com/Поехали, пошли/py слишком темно…Записано

Автоград: автоматическая дифференциация

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

autogradПакеты — это ядро ​​всех нейронных сетей в PyTorch. Давайте сначала кратко представим его, а затем перейдем к обучению нашей первой нейронной сети. ДолженautogradПакетTensorsВсе операции над обеспечивают автоматическое дифференцирование. Это среда, определяемая запуском, что означает, что ваш backprop определяется тем, как работает код, и может быть другим для каждой итерации. мы начинаем сtensorиgradientsВозьмем несколько примеров.

Тензор (тензор)

torch.Tensorявляется основным классом пакета. если его свойства.requires_gradУстановить какTrue, он начнет отслеживатьtensorвсе операции. После расчета можно звонить.backward()для автоматического вычисления всех градиентов. Градиент этого тензора будет накапливаться до.gradв свойствах.

прекратитьtensorОтслеживание истории, вы можете позвонить.detach(), что отделяет его от истории вычислений и предотвращает отслеживание будущих вычислений.

Чтобы остановить отслеживание истории (и использование памяти), вы также можете использовать кодовый блокwith torch.no_grad():Упакуйте это. Это особенно полезно при оценке моделей, поскольку модели имеютrequires_grad = TrueОбучаемые параметры хороши для настройки, но нам не нужны градиенты на этапе оценки.

Еще один класс, который очень важен для реализации autograd, — это Function. Тензор и Функция связаны друг с другом и строят ациклический график, который сохраняет историческую информацию всего полного процесса расчета. У каждого тензора есть атрибут .grad_fn, который содержит ссылку на функцию, создавшую тензор (grad_fn имеет значение None, если пользователь сам создал тензор).

Если вы хотите вычислить производную, вы можете позвонитьTensor.backward(). Если Tensor является скаляром (т. е. содержит данные одного элемента), аргументы указывать не нужно.backward(), но если в нем больше элементов, нужно указатьgradientпараметр, чтобы указать форму тензора.

import torch

Создайте тензор, установите require_grad=True, чтобы отслеживать связанные с ним вычисления.

x = torch.ones(2, 2, requires_grad=True)
print(x)
tensor([[1., 1.],
        [1., 1.]], requires_grad=True)

Выполнить операцию над тензором

y = x + 2
print(y)
tensor([[3., 3.],
        [3., 3.]], grad_fn=<AddBackward0>)

y создается в результате операции, поэтому он имеетgrad_fn.

print(y.grad_fn)
<AddBackward0 object at 0x000001787ADEDE80>

Выполните больше операций над y:

z = y * y * 3
out = z.mean()

print(z, out)
tensor([[27., 27.],
        [27., 27.]], grad_fn=<MulBackward0>) tensor(27., grad_fn=<MeanBackward0>)

.requires_grad_( ... ) изменяет флаг require_grad тензора. Введенный токен по умолчанию имеет значение False .

a = torch.randn(2, 2)
a = ((a * 3) / (a - 1))
print(a.requires_grad)

a.requires_grad_(True)
print(a.requires_grad)

b = (a * a).sum()
print(b.grad_fn)
False
True
<SumBackward0 object at 0x00000178757355B0>

Градиенты

Теперь мы применяем обратное распространение, потому чтоoutсодержит скаляр,out.backward()Эквивалентноout.backward(torch.tensor(1.)).

out.backward()

градиент печати d(out)/dx

print(x.grad)
tensor([[4.5000, 4.5000],
        [4.5000, 4.5000]])

You should have got a matrix of 4.5, Ставимout TensorЗначение устанавливается следующим образом: "oo". получится вот такая формулаo=14izio = \frac{1}{4}\sum_i z_i, zi=3(xi+2)2z_i = 3(x_i+2)^2 and zixi=1=27z_i\bigr\rvert_{x_i=1} = 27. Therefore, oxi=32(xi+2)\frac{\partial o}{\partial x_i} = \frac{3}{2}(x_i+2), hence oxixi=1=92=4.5\frac{\partial o}{\partial x_i}\bigr\rvert_{x_i=1} = \frac{9}{2} = 4.5.

также можно использоватьautogradделать много

x = torch.randn(3, requires_grad=True)

y = x * 2
while y.data.norm() < 1000:
    y = y * 2

print(y)
tensor([ 786.6164, 1688.7915,  530.0458], grad_fn=<MulBackward0>)
gradients = torch.tensor([0.1, 1.0, 0.0001], dtype=torch.float)
y.backward(gradients)

print(x.grad)
tensor([1.0240e+02, 1.0240e+03, 1.0240e-01])

Вы можете сделать это, вставив код вwith torch.no_grad(), чтобы остановить.requires_grad=TrueТензор автоматически дифференцируется.

print(x.requires_grad)
print((x ** 2).requires_grad)

with torch.no_grad():
    print((x ** 2).requires_grad)
True
True
False