Мало знаний, большой вызов! Эта статья участвует в "Необходимые знания для программистов«Творческая деятельность.
0. autograd
0.1 autograd
(Этот отрывок из официального перевода) можно использовать в pytorchautogradРеализовать автоматический расчет процесса обратного распространения нейронной сети. Когда мы используем autograd, прямое распространение определяет вычислительный граф, в котором все узлы графа являются тензорами, а ребра графа — функциями, которые генерируют выходные тензоры из входных тензоров. Градиент можно легко получить путем обратного распространения этого графика.
0.2 Расчетный граф
Картинка ниже — это своего рода поток сознания, и его полезно понимать, потому что официальная поговорка гласит: «Узлы — это тензоры, ребра — это функции». Я думаю, что после того, как я нарисовал его, я считал ребра функциями, но это не было похоже на тот «график», который я изучил в традиционном смысле.
import torch
x = torch.tensor([1.0], requires_grad=True)
print(x) # 输出:tensor([1.])
y = x + 1
print(y) # 输出:tensor([2.])
Согласно пункту 0.1 выше расчетный график должен выглядеть так:
Что такое конечный узел и что такое результирующий узел? Как следует из названия, за исключением того, что вывод окончательного графа вычислений является узлом результата, остальные узлы являются конечными узлами. ты можешь использовать это.is_leaf
обнаружить.
import torch
x = torch.tensor([1.0], requires_grad=True)
k = torch.tensor([2.0])
y = k * x
print(k.is_leaf) # 输出:True
print(x.is_leaf) # 输出:True
print(y.is_leaf) # 输出:False
1. .requires_grad=True
В приведенном выше коде есть.requires_grad=True
, что это?
По умолчанию атрибут require_grad Tensor имеет значение False., чтобы его градиент не отслеживался.
Тензор с этим свойством установлен в.requires_grad=True
При построении графа вычислений операции, в которых участвует этот тензор, будутотслеживатьи сохраните его в узле результатаgrad_fn
в свойствах. После отслеживания,при обратном распространенииГрадиент будет рассчитан во всех местах, где требуется градиент по ссылке расчета, и после завершения расчета тензор будет сохранен..grad
в свойствах.
import torch
# 默认情况下requires_grad=False
x = torch.tensor([1.0])
print(x) # 输出:tensor([1.])
x += 1
print(x) # 输出:tensor([2.])
# 设置requires_grad=True
y = torch.tensor([2.0], requires_grad=True)
print(y) # 输出:tensor([2.], requires_grad=True)
z = y + 1.0
print(z) # 输出:tensor([3.], grad_fn=<AddBackward0>)
print(y) # 输出:tensor([2.], requires_grad=True)
print(y.grad_fn)# None
Уведомление:
- Я вывожу y и z соответственно в последних трех строках, вы можете видеть, что y установлен
.requires_grad=True
После этого вместо сохранения операции в ygrad_fn
атрибут, но есть узел результата графа расчетаgrad_fn
в свойствах.
2. Свойство тензора .grad_fn
Как упоминалось выше, когда вы устанавливаете.requires_grad=True
После этого отслеживаются операции над этим тензором.
Но только неконечные узлы имеют этот атрибут, а конечные узлы будут отображать None.
3. .grad
import torch
y = torch.tensor([2.0], requires_grad=True)
print(y) # 输出:tensor([2.], requires_grad=True)
print(y.grad) # 输出:None
z = y + 1.0
print(z) # 输出:tensor([3.], grad_fn=<AddBackward0>)
print(y) # 输出:tensor([2.], requires_grad=True)
print(y.grad) # 输出:None
print(z.grad) # 输出:None
# 调用反向传播
z.backward()
print(y.grad) # 输出:tensor([1.])
print(z.grad) # 输出:None
Уведомление:
- После того, как операция y отслежена, ее
y.grad
пусто,только при обратном распространенииВо время выполнения вычисляется градиент, необходимый для каждого звена, и результат сохраняется вy.grad
середина - После запуска кода появляются два UserWarnings, говорящие о том, что неконечные узлы недоступны.
.grad
Атрибуты. Это потому, что я специально написал два вышеprint(z.grad)
. z является узлом результата, его атрибут grad не может быть выведен.- Неконечные узлы по умолчанию
.grad
отключено, принудительная печать выведет None - хотите сохранить узел результата
.grad
Существует два метода, один из которых заключается в добавлении после операции построения вычислительного графа.retain_grad()
, другой должен использовать.register_hook
Сам не смотрел, посмотрю, если интересно
- Неконечные узлы по умолчанию
4. with torch.no_grad()
Если вы не хотите, чтобы действие отслеживалось, вам нужно использоватьwith torch.no_grad():
.
Код, заключенный в этот оператор, не будет отслеживать градиенты.
import torch
# 设置requires_grad=True
y = torch.tensor([1.0], requires_grad=True)
print(y) # tensor([1.], requires_grad=True)
z = y + 1.0
print(z) # tensor([2.], grad_fn=<AddBackward0>)
print(z.grad_fn) # <AddBackward0 object at 0x0000017C3CFD21C0>
with torch.no_grad():
z = y - 2
print(z) # tensor([-1.])
print(z.grad_fn) # None
- во втором выводе
grad_fn
Дисплей отслеживает операцию добавления - Третий вывод печатается отдельно
grad_fn
, снова показывая, что операция сложения отслеживается - Четвертый выход установлен
with torch.no_grad():
После этого обнаружилось, что в выводе не былоgrad_fn
атрибут - Пятый вывод печатается отдельно
grad_fn
не существует, т.with torch.no_grad():
В пакете эта операция вычитания не отслеживается и свойство также очищается.
with torch.no_grad()
какой смысл?
При использовании pytorch не все операции требуют создания вычислительного графа. Для операции расчета тензора по умолчанию строится график расчета, в этом случае вы можете использоватьwith torch.no_grad():
, заставляя контент после этого не выполнять построение вычислительного графа.
5. .data
Помимо использованияwith torch.no_grad()
Вы также можете использовать тензор.data
.
import torch
# 设置requires_grad=True
y = torch.tensor([1.0], requires_grad=True)
print(y) # tensor([1.], requires_grad=True)
z = y + 1.0
print(z) # tensor([2.], grad_fn=<AddBackward0>)
print(z.grad_fn) # <AddBackward0 object at 0x0000017C3CFD21C0>
z.data = y.data - 2
print(z) # tensor([-1.])
print(z.grad_fn) # <AddBackward0 object at 0x00000226475F21C0>
относительно вышеуказанногоwith torch.no_grad()
,.data
Он также не строит график расчета и не отслеживает операции, но при этом сохранит отслеживание предыдущего шага и не очищает его.
Я Лориан, и, похоже, сегодня я снова преуспел. (^-^)В Он полностью основан на информации, которую я проверил сам, могут быть упущения, и исправления приветствуются. Спасибо♪(・ω・)ノ