文章目錄
- torch.autograd.backward()
- 基本用法
- 非標量張量的反向傳播
- 保留計算圖
- 指定輸入張量
- 高階梯度計算
- 與 y.backward() 的區別
- torch.autograd.grad()
- 基本用法
- 非標量張量的梯度
- 高階梯度計算
- 多輸入、多輸出的梯度計算
- 未使用的輸入張量
- 保留計算圖
- 與 backward() 的區別
torch.autograd.backward()
該函數實現自動求導梯度,函數如下:
torch.autograd.backward(tensors, grad_tensors=None, retain_graph=False, create_graph=False, inputs=None)
參數介紹:
- tensors: 需要對其進行反向傳播的目標張量(或張量列表),例如:loss。
這些張量通常是計算圖的最終輸出。 - grad_tensors:與 tensors 對應的梯度權重(或權重列表)。
如果 tensors 是標量張量(單個值),可以省略此參數。
如果 tensors 是非標量張量(如向量或矩陣),則必須提供 grad_tensors,表示每個張量的梯度權重。例如:當有多個loss需要計算梯度時,需要設置每個loss的權值。 - retain_graph:是否保留計算圖。
默認值為 False,即反向傳播后會釋放計算圖。如果需要多次反向傳播,需設置為 True。 - create_graph: 是否創建一個新的計算圖,用于高階梯度計算。
默認值為 False,如果需要計算二階或更高階梯度,需設置為 True。 - inputs: 指定需要計算梯度的輸入張量(或張量列表)。
如果指定了此參數,只有這些張量的 .grad 屬性會被更新,而不是整個計算圖中的所有張量。
基本用法
import torch # 定義張量并啟用梯度計算
x = torch.tensor(2.0, requires_grad=True)
y = x ** 2 # y = x^2 # 使用 torch.autograd.backward() 觸發反向傳播
torch.autograd.backward(y) # 查看梯度
print(x.grad) # 輸出:4.0 (dy/dx = 2x, 當 x=2 時,dy/dx=4)
非標量張量的反向傳播
x = torch.tensor([1.0, 2.0, 3.0], requires_grad=True)
y = x ** 2 # y = [x1^2, x2^2, x3^2] # 指定 grad_tensors 權重
grad_tensors = torch.tensor([1.0, 1.0, 1.0]) # 權重
torch.autograd.backward(y, grad_tensors=grad_tensors) # 查看梯度
print(x.grad) # 輸出:[2.0, 4.0, 6.0] (dy/dx = 2x)
保留計算圖
如果需要多次調用反向傳播,可以設置 retain_graph=True。
x = torch.tensor(2.0, requires_grad=True)
y = x ** 3 # y = x^3 # 第一次反向傳播
torch.autograd.backward(y, retain_graph=True)
print(x.grad) # 輸出:12.0 (dy/dx = 3x^2, 當 x=2 時,dy/dx=12) # 第二次反向傳播
torch.autograd.backward(y, retain_graph=True)
print(x.grad) # 輸出:24.0 (梯度累積,12.0 + 12.0)
指定輸入張量
通過 inputs 參數,可以只計算指定張量的梯度,而忽略其他張量。
x = torch.tensor(2.0, requires_grad=True)
z = torch.tensor(3.0, requires_grad=True)
y = x ** 2 + z ** 3 # y = x^2 + z^3 # 只計算 x 的梯度
torch.autograd.backward(y, inputs=[x])
print(x.grad) # 輸出:4.0 (dy/dx = 2x)
print(z.grad) # 輸出:None (未計算 z 的梯度)
高階梯度計算
通過設置 create_graph=True,可以構建新的計算圖,用于計算高階梯度。
x = torch.tensor(2.0, requires_grad=True)
y = x ** 3 # y = x^3 # 第一次反向傳播,創建新的計算圖
torch.autograd.backward(y, create_graph=True)
print(x.grad) # 輸出:12.0 (dy/dx = 3x^2) # 計算二階梯度
x_grad = x.grad
x_grad.backward()
print(x.grad) # 輸出:18.0 (d^2y/dx^2 = 6x)
與 y.backward() 的區別
-
靈活性:
- torch.autograd.backward() 更靈活,可以對多個張量同時進行反向傳播,并指定梯度權重。
- y.backward() 是對單個張量的簡單封裝,適合常見場景。對多個loss求導時,需要指定gradient和grad_outputs相同作用。
-
梯度權重:
- torch.autograd.backward() 需要顯式提供 grad_tensors 參數(如果目標張量是非標量)。
- y.backward() 會自動處理標量張量,非標量張量需要手動傳入權重。
-
輸入控制:
- torch.autograd.backward() 可以通過 inputs 參數指定只計算某些張量的梯度。
- y.backward() 無法直接控制,只會更新計算圖中所有相關張量的 .grad。
torch.autograd.grad()
torch.autograd.grad() 是 PyTorch 中用于計算張量梯度的函數,與 backward() 不同的是,它不會更新張量的 .grad 屬性,而是直接返回計算的梯度值。它適用于需要手動獲取梯度值而不修改計算圖中張量的 .grad 屬性的場景。
torch.autograd.grad( outputs, inputs, grad_outputs=None, retain_graph=False, create_graph=False, only_inputs=True, allow_unused=False
)
參數介紹:
- outputs:
目標張量(或張量列表),即需要對其進行求導的輸出張量。 - inputs:
需要計算梯度的輸入張量(或張量列表)。
這些張量必須啟用了 requires_grad=True。 - grad_outputs:
與 outputs 對應的梯度權重(或權重列表)。
如果 outputs 是標量張量,可以省略此參數;如果是非標量張量,則需要提供權重,表示每個輸出張量的梯度權重。 - retain_graph:
是否保留計算圖。
默認值為 False,即反向傳播后會釋放計算圖。如果需要多次計算梯度,需設置為 True。 - create_graph:
是否創建一個新的計算圖,用于高階梯度計算。
默認值為 False,如果需要計算二階或更高階梯度,需設置為 True。 - only_inputs:
是否只對 inputs 中的張量計算梯度。
默認值為 True,表示只計算 inputs 的梯度。 - allow_unused:
是否允許 inputs 中的某些張量未被 outputs 使用。
默認值為 False,如果某些 inputs 未被 outputs 使用,會拋出錯誤。如果設置為 True,未使用的張量的梯度會返回 None。
返回值:
- 返回一個元組,包含 inputs 中每個張量的梯度值。
- 如果某個輸入張量未被 outputs 使用,且 allow_unused=True,則對應的梯度為 None。
基本用法
import torch # 定義張量并啟用梯度計算
x = torch.tensor(2.0, requires_grad=True)
y = x ** 2 # y = x^2 # 使用 torch.autograd.grad() 計算梯度
grad = torch.autograd.grad(y, x)
print(grad) # 輸出:(4.0,) (dy/dx = 2x, 當 x=2 時,dy/dx=4)
非標量張量的梯度
當目標張量是非標量時,需要提供 grad_outputs 參數:
x = torch.tensor([1.0, 2.0, 3.0], requires_grad=True)
y = x ** 2 # y = [x1^2, x2^2, x3^2] # 指定 grad_outputs 權重
grad_outputs = torch.tensor([1.0, 1.0, 1.0]) # 權重
grad = torch.autograd.grad(y, x, grad_outputs=grad_outputs)
print(grad) # 輸出:(tensor([2.0, 4.0, 6.0]),) (dy/dx = 2x)
高階梯度計算
通過設置 create_graph=True,可以計算高階梯度:
x = torch.tensor(2.0, requires_grad=True)
y = x ** 3 # y = x^3 # 第一次計算梯度
grad = torch.autograd.grad(y, x, create_graph=True)
print(grad) # 輸出:(12.0,) (dy/dx = 3x^2) # 計算二階梯度
grad2 = torch.autograd.grad(grad[0], x)
print(grad2) # 輸出:(6.0,) (d^2y/dx^2 = 6x)
多輸入、多輸出的梯度計算
可以對多個輸入和輸出同時計算梯度:
x = torch.tensor(2.0, requires_grad=True)
z = torch.tensor(3.0, requires_grad=True)
y1 = x ** 2 + z ** 3 # y1 = x^2 + z^3
y2 = x * z # y2 = x * z # 對多個輸入計算梯度
grads = torch.autograd.grad([y1, y2], [x, z], grad_outputs=[torch.tensor(1.0), torch.tensor(1.0)])
print(grads) # 輸出:(7.0, 11.0) (dy1/dx + dy2/dx, dy1/dz + dy2/dz)
未使用的輸入張量
如果某些輸入張量未被目標張量使用,需設置 allow_unused=True:
x = torch.tensor(2.0, requires_grad=True)
z = torch.tensor(3.0, requires_grad=True)
y = x ** 2 # y = x^2 # z 未被 y 使用
grad = torch.autograd.grad(y, [x, z], allow_unused=True)
print(grad) # 輸出:(4.0, None) (dy/dx = 4, z 未被使用,梯度為 None)
保留計算圖
如果需要多次計算梯度,可以設置 retain_graph=True:
x = torch.tensor(2.0, requires_grad=True)
y = x ** 3 # y = x^3 # 第一次計算梯度
grad1 = torch.autograd.grad(y, x, retain_graph=True)
print(grad1) # 輸出:(12.0,) # 第二次計算梯度
grad2 = torch.autograd.grad(y, x)
print(grad2) # 輸出:(12.0,)
與 backward() 的區別
- 梯度存儲:
- torch.autograd.grad() 不會修改張量的 .grad 屬性,而是直接返回梯度值。
- backward() 會將計算的梯度累積到 .grad 屬性中。
- 靈活性:
- torch.autograd.grad() 可以對多個輸入和輸出同時計算梯度,并支持未使用的輸入張量。
- backward() 只能對單個輸出張量進行反向傳播。
- 高階梯度:
- torch.autograd.grad() 支持通過 create_graph=True 計算高階梯度。
- backward() 也支持高階梯度,但需要手動設置 create_graph=True。