目錄
1. 自動微分是什么?
1.1 計算圖
1.2?requires_grad?屬性
2. 標量和向量的梯度計算
2.1 標量梯度
2.2 向量梯度
3. 梯度上下文控制
3.1 禁用梯度計算
3.2 累計梯度
4. 梯度下降實戰
4.1 求函數最小值
4.2 線性回歸參數求解
5. 總結
在深度學習中,自動微分是神經網絡訓練的核心機制之一。PyTorch通過torch.autograd
模塊提供了強大的自動微分功能,能夠自動計算張量操作的梯度。今天,我們就來深入探討PyTorch的自動微分機制,并通過一些實戰案例來理解它的原理和應用。
1. 自動微分是什么?
在神經網絡訓練中,我們通常需要計算損失函數對模型參數的梯度,以便通過梯度下降法更新參數,從而最小化損失函數。手動計算梯度是非常繁瑣且容易出錯的,尤其是當網絡結構復雜時。自動微分通過自動構建計算圖并計算梯度,極大地簡化了這一過程。
1.1 計算圖
計算圖是自動微分的核心概念。它是一個有向圖,節點表示張量(Tensor),邊表示張量之間的操作。當我們對張量進行操作時,PyTorch會自動構建一個動態計算圖,并在反向傳播時沿著這個圖計算梯度。


1.2?requires_grad
?屬性
在PyTorch中,每個張量都有一個requires_grad
屬性,用于指定是否需要計算梯度。如果requires_grad=True
,則該張量的所有操作都會被記錄在計算圖中;如果requires_grad=False
,則不會記錄操作,也不會計算梯度。
x = torch.tensor(1.0, requires_grad=True)
y = x ** 2
y.backward()
print(x.grad) # 輸出梯度
2. 標量和向量的梯度計算
2.1 標量梯度
當我們對一個標量進行操作時,可以直接調用backward()
方法來計算梯度。
x = torch.tensor(1.0, requires_grad=True)
y = x ** 2
y.backward()
print(x.grad) # 輸出:tensor(2.)
2.2 向量梯度
對于向量,我們需要提供一個與輸出形狀相同的梯度張量作為backward()
的參數。
x = torch.tensor([1.0, 2.0, 3.0], requires_grad=True)
y = x ** 2
y.backward(torch.tensor([1.0, 1.0, 1.0]))
print(x.grad) # 輸出:tensor([2., 4., 6.])
如果我們將輸出轉換為標量(例如通過求和),則可以直接調用backward()
。
x = torch.tensor([1.0, 2.0, 3.0], requires_grad=True)
y = x ** 2
loss = y.sum()
loss.backward()
print(x.grad) # 輸出:tensor([2., 4., 6.])
3. 梯度上下文控制
在某些情況下,我們可能不需要計算梯度,或者希望控制梯度的計算過程。PyTorch提供了幾種方式來控制梯度計算的上下文。
3.1 禁用梯度計算
使用torch.no_grad()
上下文管理器可以臨時禁用梯度計算。
x = torch.tensor(1.0, requires_grad=True)
with torch.no_grad():y = x ** 2
print(y.requires_grad) # 輸出:False
3.2 累計梯度
默認情況下,多次調用backward()
會累計梯度。如果需要清零梯度,可以使用x.grad.zero_()
。
x = torch.tensor([1.0, 2.0, 3.0], requires_grad=True)
for i in range(3):y = x ** 2loss = y.sum()if x.grad is not None:x.grad.zero_()loss.backward()print(x.grad)
# 輸出:tensor([2., 4., 6.])tensor([2., 4., 6.])tensor([2., 4., 6.])
4. 梯度下降實戰
4.1 求函數最小值
通過梯度下降法,我們可以找到函數的最小值。以下是一個簡單的例子,通過梯度下降法找到函數y = x^2
的最小值。
x = torch.tensor([3.0], requires_grad=True)
lr = 0.1
epochs = 50
for epoch in range(epochs):y = x ** 2if x.grad is not None:x.grad.zero_()y.backward()with torch.no_grad():x -= lr * x.gradprint(f'Epoch {epoch}, x: {x.item()}, y: {y.item()}')
4.2 線性回歸參數求解
我們還可以通過梯度下降法求解線性回歸模型的參數。以下是一個簡單的線性回歸模型,通過梯度下降法求解參數a
和b
。
x = torch.tensor([1, 2, 3, 4, 5], dtype=torch.float)
y = torch.tensor([3, 5, 7, 9, 11], dtype=torch.float)
a = torch.tensor([1.0], requires_grad=True)
b = torch.tensor([1.0], requires_grad=True)
lr = 0.01
epochs = 1000
for epoch in range(epochs):y_pred = a * x + bloss = ((y_pred - y) ** 2).mean()if a.grad is not None and b.grad is not None:a.grad.zero_()b.grad.zero_()loss.backward()with torch.no_grad():a -= lr * a.gradb -= lr * b.gradif (epoch + 1) % 100 == 0:print(f'Epoch {epoch + 1}, Loss: {loss.item()}')
print(f'a: {a.item()}, b: {b.item()}')
5. 總結
通過這篇文章,我們學習了PyTorch的自動微分機制,包括:
-
如何構建計算圖。
-
如何計算標量和向量的梯度。
-
如何控制梯度計算的上下文。
-
如何通過梯度下降法求解函數最小值和線性回歸模型的參數。
自動微分是深度學習的核心技術之一,希望這篇文章能幫助你更好地理解和使用PyTorch的自動微分功能。