PyTorch 作為主流深度學習框架,提供豐富的功能與彈性的設計,讓開發者能更有效率地建構和訓練模型。本文將深入探討 PyTorch 的核心概念,並以建構神經網路模型的流程為主軸,逐步講解每個環節的實務技巧。
在 PyTorch 中,Tensor
和 Autograd
機制是進行深度學習的基本。Tensor
類別似 NumPy 的多維陣列,用於儲存和運算資料,而 Autograd
則負責自動計算梯度,簡化模型訓練的過程。理解這兩個核心概念對於使用 PyTorch 至關重要。
PyTorch 基礎:Tensor 與 Autograd
Tensor
是 PyTorch 中的核心資料結構,用於儲存和處理多維資料。而 Autograd
機制則能自動計算 Tensor
運算的梯度,這對於神經網路的訓練至關重要,因為我們需要梯度來更新模型的引數。
import torch
# 建立一個 Tensor 並設定 requires_grad=True 以追蹤梯度
x = torch.tensor([[1., 2.], [3., 4.]], requires_grad=True)
# 進行一些運算
y = x * 2
z = y.mean()
# 計算梯度
z.backward()
# 顯示 x 的梯度
print(x.grad)
內容解密
- 我們建立了一個 2x2 的
Tensor
x,並設定requires_grad=True
,這讓 PyTorch 追蹤 x 的所有運算,以便之後計算梯度。 - 接著,我們進行了兩個運算:
y = x * 2
和z = y.mean()
。 z.backward()
啟動反向傳播,計算 z 對 x 的梯度。- 最後,
print(x.grad)
顯示 x 的梯度。
圖表翻譯
graph LR A[x] --> B[y = x * 2] B --> C[z = y.mean()] C --> D[z.backward()]
- 此圖展示了計算流程:從 x 開始,經過乘法運算得到 y,再計算平均值得到 z,最後進行反向傳播計算梯度。
模型建構與層級設計
在 PyTorch 中,我們使用 nn.Module
來定義模型和層。模型通常由多個層組成,每個層執行特定的運算,例如線性變換、卷積、啟用函式等。
import torch.nn as nn
class MyModel(nn.Module):
def __init__(self, input_size, hidden_size, output_size):
super().__init__()
self.linear1 = nn.Linear(input_size, hidden_size)
self.relu = nn.ReLU()
self.linear2 = nn.Linear(hidden_size, output_size)
def forward(self, x):
x = self.linear1(x)
x = self.relu(x)
x = self.linear2(x)
return x
內容解密
MyModel
繼承自nn.Module
,表示它是一個 PyTorch 模型。__init__
方法初始化了模型的層:兩個線性層 (nn.Linear
) 和一個 ReLU 啟用函式 (nn.ReLU
)。forward
方法定義了模型的前向傳播邏輯。
圖表翻譯
graph LR A[輸入 x] --> B(Linear 1) B --> C(ReLU) C --> D(Linear 2) D --> E[輸出]
- 此圖展示了
MyModel
的前向傳播流程:輸入 x 經過兩個線性層和一個 ReLU 啟用函式,最終得到輸出。
損失函式與最佳化器
損失函式用於衡量模型預測與真實值之間的差異,而最佳化器則負責根據損失函式的梯度更新模型的引數。
import torch.optim as optim
# 建立模型例項
model = MyModel(input_size=10, hidden_size=20, output_size=5)
# 定義損失函式和最佳化器
criterion = nn.MSELoss()
optimizer = optim.Adam(model.parameters(), lr=0.01)
內容解密
criterion = nn.MSELoss()
建立了一個均方誤差損失函式。optimizer = optim.Adam(model.parameters(), lr=0.01)
建立了一個 Adam 最佳化器,學習率設定為 0.01。
圖表翻譯
graph LR A[模型引數] --> B{計算損失} B --> C[計算梯度] C --> D[更新引數]
- 此圖展示了模型訓練的流程:計算損失、計算梯度、更新引數。
模型訓練流程
模型訓練的流程通常包含以下步驟:前向傳播、計算損失、反向傳播、更新引數。
# 訓練迴圈
for epoch in range(num_epochs):
# 前向傳播
outputs = model(inputs)
loss = criterion(outputs, targets)
# 反向傳播和最佳化
optimizer.zero_grad() # 清零梯度
loss.backward() # 計算梯度
optimizer.step() # 更新引數
內容解密
- 在每個 epoch 中,我們先進行前向傳播,計算模型的輸出和損失。
- 接著,我們使用
optimizer.zero_grad()
清零梯度,然後使用loss.backward()
計算梯度,最後使用optimizer.step()
更新模型的引數。
圖表翻譯
graph LR A[輸入資料] --> B{前向傳播} B --> C{計算損失} C --> D{反向傳播} D --> E{更新引數}
- 此圖展示了模型訓練的流程:輸入資料、前向傳播、計算損失、反向傳播、更新引數。
結語
本文介紹了 PyTorch 的核心概念和實務技巧,包括 Tensor、Autograd、模型建構、層級設計、損失函式、最佳化器設定以及模型訓練流程。透過這些技巧,讀者可以更有效率地使用 PyTorch 建構和訓練深度學習模型。在實務應用上,PyTorch 的彈性和豐富的功能使其成為深度學習開發的利器。
圖表翻譯
下面是 LSTMNode 的圖表:
graph LR X_in -->|輸入|> Input_Gate H_in -->|隱藏狀態|> Input_Gate Input_Gate -->|輸入門|> Cell_State Cell_State -->|細胞狀態|> Forget_Gate Forget_Gate -->|忘記門|> Cell_State Cell_State -->|細胞狀態|> Output_Gate Output_Gate -->|輸出門|> Hidden_State Hidden_State -->|隱藏狀態|> Output
這個圖表展示了 LSTMNode 的前向傳播過程,包括輸入門、忘記門、細胞狀態和輸出門的計算。
長短期記憶單元(LSTM)節點的實作
長短期記憶(LSTM)是一種特殊的迴圈神經網路(RNN),用於處理序列資料。它的設計目的是為了克服傳統RNN的梯度消失問題,從而能夠學習到長距離的依賴關係。
LSTM 節點的結構
一個LSTM節點由多個門控元件組成,包括輸入門、遺忘門、細胞狀態和輸出門。這些門控元件共同控制著細胞狀態的更新和輸出的計算。
LSTM 節點的前向傳播
LSTM節點的前向傳播可以透過以下步驟實作:
- 輸入門: 計算輸入門的啟用值,決定哪些新資訊被新增到細胞狀態中。
- 遺忘門: 計算遺忘門的啟用值,決定哪些舊資訊被遺忘。
- 細胞狀態更新: 更新細胞狀態,根據輸入門和遺忘門的啟用值。
- 輸出門: 計算輸出門的啟用值,決定哪些資訊被輸出。
實作LSTM節點的Python程式碼
import numpy as np
class LSTMNode:
def __init__(self, input_size, hidden_size, output_size):
self.input_size = input_size
self.hidden_size = hidden_size
self.output_size = output_size
self.Z = np.random.rand(input_size, hidden_size)
self.W_f = np.random.rand(hidden_size, hidden_size)
self.B_f = np.random.rand(hidden_size)
def forward(self, X_in, H_in, C_in, params_dict):
'''
前向傳播
'''
self.X_in = X_in
self.C_in = C_in
self.f_int = np.dot(self.Z, params_dict['W_f']['value']) + params_dict['B_f']['value']
#... 其他門控元件的計算...
return self.X_out, self.H, self.C
# 示例用法
lstm_node = LSTMNode(10, 20, 30)
X_in = np.random.rand(1, 10)
H_in = np.random.rand(1, 20)
C_in = np.random.rand(1, 20)
params_dict = {'W_f': {'value': np.random.rand(20, 20)}, 'B_f': {'value': np.random.rand(20)}}
X_out, H, C = lstm_node.forward(X_in, H_in, C_in, params_dict)
print(X_out.shape, H.shape, C.shape)
LSTM 神經網路之隱藏狀態與記憶單元更新
在長短期記憶(LSTM)神經網路中,隱藏狀態和記憶單元的更新是非常重要的步驟。以下是這些步驟的詳細解釋:
1. Forget Gate(遺忘門)
首先,我們需要計算遺忘門的輸出。遺忘門的輸出是根據前一時間步的隱藏狀態和當前輸入之間的點積,以及權重矩陣和偏差項之間的點積。
self.f_int = np.dot(self.Z, params_dict['W_f']['value']) + params_dict['B_f']['value']
self.f = sigmoid(self.f_int)
2. Input Gate(輸入門)
接下來,我們需要計算輸入門的輸出。輸入門的輸出是根據前一時間步的隱藏狀態和當前輸入之間的點積,以及權重矩陣和偏差項之間的點積。
self.i_int = np.dot(self.Z, params_dict['W_i']['value']) + params_dict['B_i']['value']
self.i = sigmoid(self.i_int)
3. Cell State(記憶單元)
然後,我們需要計算記憶單元的更新值。記憶單元的更新值是根據前一時間步的記憶單元、輸入門的輸出和遺忘門的輸出之間的運算。
self.C_bar_int = np.dot(self.Z, params_dict['W_c']['value']) + params_dict['B_c']['value']
self.C_bar = tanh(self.C_bar_int)
self.C_out = self.f * self.C_in + self.i * self.C_bar
4. Output Gate(輸出門)
最後,我們需要計算輸出門的輸出。輸出門的輸出是根據前一時間步的隱藏狀態和當前輸入之間的點積,以及權重矩陣和偏差項之間的點積。
self.o_int = np.dot(self.Z, params_dict['W_o']['value']) + params_dict['B_o']['value']
self.o = sigmoid(self.o_int)
內容解密
上述程式碼實作了LSTM神經網路中隱藏狀態和記憶單元的更新。其中,self.f
、self.i
、self.C_bar
和self.o
分別代表遺忘門、輸入門、記憶單元和輸出門的輸出。這些值是根據前一時間步的隱藏狀態和當前輸入之間的點積,以及權重矩陣和偏差項之間的點積計算而得。
圖表翻譯
以下是LSTM神經網路中隱藏狀態和記憶單元更新的流程圖:
flowchart TD A[前一時間步隱藏狀態] --> B[遺忘門] B --> C[輸入門] C --> D[記憶單元更新] D --> E[輸出門] E --> F[最終輸出]
這個流程圖展示了LSTM神經網路中隱藏狀態和記憶單元更新的過程。其中,遺忘門、輸入門、記憶單元更新和輸出門是LSTM神經網路中的四個重要組成部分。
使用 PyTorch 進行深度學習
PyTorch 是一個流行的深度學習框架,提供了強大的工具和功能來進行神經網路的建構和訓練。在這篇文章中,我們將探討 PyTorch 的基礎知識和使用方法。
Tensor 和 Autograd
PyTorch 的核心是 Tensor 和 Autograd。Tensor 是一個多維陣列,可以用來表示神經網路的輸入、輸出和引數。Autograd 是 PyTorch 的自動微分系統,可以自動計算 Tensor 之間的梯度。
import torch
# 建立一個 Tensor
a = torch.tensor([[3., 3.], [3., 3.]], requires_grad=True)
# 進行計算
b = a * 4
c = b + 3
d = a + 2
e = c * d
# 計算梯度
e_sum = e.sum()
e_sum.backward()
# 印出梯度
print(a.grad)
Model、Layer、Optimizer 和 Loss
PyTorch 的 Model、Layer、Optimizer 和 Loss 是四個重要的概念。
- Model:代表神經網路的模型,可以包含多個 Layer。
- Layer:代表神經網路中的單一層,可以是全連線層、卷積層等。
- Optimizer:代表最佳化器,可以用來更新模型的引數。
- Loss:代表損失函式,可以用來評估模型的效能。
import torch
import torch.nn as nn
# 定義模型
class MyModel(nn.Module):
def __init__(self):
super(MyModel, self).__init__()
self.fc1 = nn.Linear(5, 10) # input layer (5) -> hidden layer (10)
self.fc2 = nn.Linear(10, 5) # hidden layer (10) -> output layer (5)
def forward(self, x):
x = torch.relu(self.fc1(x)) # activation function for hidden layer
x = self.fc2(x)
return x
# 建立模型、最佳化器和損失函式
model = MyModel()
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
loss_fn = nn.MSELoss()
# 進行訓練
for epoch in range(100):
# 前向傳播
inputs = torch.randn(100, 5)
labels = torch.randn(100, 5)
outputs = model(inputs)
loss = loss_fn(outputs, labels)
# 反向傳播
optimizer.zero_grad()
loss.backward()
optimizer.step()
# 印出損失
print('epoch {}: loss = {:.4f}'.format(epoch+1, loss.item()))
第7章:使用PyTorch的神經網路函式庫
PyTorch是一個強大的深度學習框架,提供了豐富的工具和函式庫來建構和訓練神經網路。在這一章中,我們將探討如何使用PyTorch的神經網路函式庫來建立和訓練模型。
PyTorch的層和模型
在PyTorch中,層和模型都是從torch.nn.Module
類別繼承而來的。層是神經網路中的基本單元,負責執行特定的運算,例如全連線層、卷積層等。模型則是多個層的組合,代表著整個神經網路。
以下是PyTorch層和模型的基本結構:
import torch
import torch.nn as nn
class PyTorchLayer(nn.Module):
def __init__(self):
super().__init__()
def forward(self, x: torch.Tensor, inference: bool = False) -> torch.Tensor:
raise NotImplementedError()
class PyTorchModel(nn.Module):
def __init__(self):
super().__init__()
def forward(self, x: torch.Tensor, inference: bool = False) -> torch.Tensor:
raise NotImplementedError()
在上述程式碼中,PyTorchLayer
和PyTorchModel
都是從torch.nn.Module
類別繼承而來的,且都實作了__init__
和forward
方法。
推理模式
在訓練神經網路時,我們需要根據不同的模式(訓練或推理)調整模型的行為。PyTorch提供了一個方便的方式來切換模型的模式,即使用eval()
方法。
def inference_mode(m: nn.Module):
m.eval()
#...
if inference:
self.apply(inference_mode)
在上述程式碼中,我們定義了一個inference_mode
函式,該函式呼叫模型的eval()
方法。然後,在模型的forward
方法中,我們根據inference
旗標呼叫inference_mode
函式。
實作DenseLayer
現在,我們可以開始實作DenseLayer了。DenseLayer是一種全連線層,負責執行線性變換和啟用函式。
class DenseLayer(PyTorchLayer):
def __init__(self, input_size: int, neurons: int, dropout: float = 1.0, activation: nn.Module = None):
super().__init__()
self.linear = nn.Linear(input_size, neurons)
self.activation = activation
if dropout < 1.0:
self.dropout = nn.Dropout(1 - dropout)
def forward(self, x: torch.Tensor, inference: bool = False) -> torch.Tensor:
#...
在上述程式碼中,我們定義了DenseLayer類別,該類別繼承自PyTorchLayer。DenseLayer的__init__
方法初始化了線性變換層、啟用函式和dropout層。forward
方法則執行線性變換、啟用函式和dropout操作。
內容解密
DenseLayer
類別繼承自PyTorchLayer
,表示它是一種全連線層。__init__
方法初始化了線性變換層、啟用函式和dropout層。forward
方法執行線性變換、啟用函式和dropout操作。
圖表翻譯
graph LR A[輸入] --> B[線性變換] B --> C[啟用函式] C --> D[dropout] D --> E[輸出]
- 圖表表示DenseLayer的運算流程:輸入 -> 線性變換 -> 啟用函式 -> dropout -> 輸出。
PyTorch中的神經網路層實作
在PyTorch中,神經網路層可以透過nn.Module
類別來實作。下面是一個簡單的神經網路層實作例子:
import torch
import torch.nn as nn
class DenseLayer(nn.Module):
def __init__(self, input_size, output_size, activation=None, dropout=0.0):
super(DenseLayer, self).__init__()
self.linear = nn.Linear(input_size, output_size)
self.activation = activation
self.dropout = nn.Dropout(dropout)
def forward(self, x):
x = self.linear(x)
if self.activation:
x = self.activation(x)
if hasattr(self, "dropout"):
x = self.dropout(x)
return x
在這個例子中,DenseLayer
類別繼承自nn.Module
,並定義了一個密集連線層(Dense Layer)。該層包含一個線性變換(Linear Transformation)和一個啟用函式(Activation Function),以及一個dropout層。
實作波士頓房屋價格預測模型
使用上述的DenseLayer
類別,可以實作一個簡單的波士頓房屋價格預測模型。下面是模型的實作程式碼:
class HousePricesModel(nn.Module):
def __init__(self, hidden_size=13, hidden_dropout=0.0):
super(HousePricesModel, self).__init__()
self.dense1 = DenseLayer(13, hidden_size, activation=nn.Sigmoid(), dropout=hidden_dropout)
self.dense2 = DenseLayer(hidden_size, 1)
def forward(self, x):
assert x.dim() == 2
assert x.shape[1] == 13
x = self.dense1(x)
x = self.dense2(x)
return x
在這個例子中,HousePricesModel
類別繼承自nn.Module
,並定義了一個具有兩個密集連線層的神經網路模型。第一個層使用Sigmoid啟用函式,第二個層輸出預測值。
使用PyTorch的自動梯度計算
PyTorch提供了自動梯度計算的功能,可以自動計算模型引數的梯度。下面是使用PyTorch自動梯度計算的例子:
# 建立模型例項
model = HousePricesModel()
# 建立輸入張量
x = torch.randn(1, 13)
# 計算輸出
output = model(x)
# 計算損失
loss = torch.mean((output - torch.randn(1, 1)) ** 2)
# 自動計算梯度
loss.backward()
在這個例子中,使用PyTorch的自動梯度計算功能,可以自動計算模型引數的梯度。這樣可以簡化模型訓練的過程。
PyTorch模型建立與最佳化器設定
PyTorch是一個強大的深度學習框架,提供了多種工具和功能來幫助使用者建立和訓練神經網路模型。下面是建立一個簡單的PyTorch模型和設定最佳化器的步驟:
深度學習模型建構與訓練:PyTorch實戰
PyTorch 作為一個廣泛使用的深度學習框架,提供豐富的工具和功能,簡化了神經網路的建構和訓練流程。本文將深入探討如何運用 PyTorch 建立和訓練深度學習模型,並結合實際案例進行說明。
張量與自動微分
PyTorch 的核心概念是張量 (Tensor) 和自動微分 (Autograd)。張量是一種多維陣列,用於表示神經網路的輸入、輸出和引數。Autograd 則能自動計算張量之間的梯度,簡化了反向傳播的過程。
import torch
# 建立一個張量,並設定 requires_grad=True 以追蹤梯度
x = torch.tensor([[1., 2.], [3., 4.]], requires_grad=True)
# 進行運算
y = x * 2
z = y.mean()
# 計算梯度
z.backward()
# 顯示 x 的梯度
print(x.grad)
內容解密
- 首先,我們建立一個張量
x
並設定requires_grad=True
,使其能夠追蹤梯度。 - 接著,進行一系列運算,得到最終結果
z
。 - 呼叫
z.backward()
啟動反向傳播,計算z
對x
的梯度。 - 最後,
x.grad
儲存了x
的梯度。
圖表翻譯
graph LR X[張量 x] --> Y{x * 2} Y --> Z((y.mean())) Z --> G[計算梯度]
此圖示展示了計算流程:從張量 x
開始,經過乘法運算得到 y
,再經平均值運算得到 z
,最後計算 z
對 x
的梯度。
模型、層、最佳化器與損失函式
建構神經網路模型涉及幾個關鍵組成:
- 模型 (Model): 代表整個神經網路架構,由多個層組成。
- 層 (Layer): 神經網路的基本單元,例如線性層、卷積層等,負責執行特定運算。
- 最佳化器 (Optimizer): 負責更新模型引數,例如 SGD、Adam 等。
- 損失函式 (Loss): 評估模型預測與真實值之間的差異,常用於指導模型訓練。
import torch.nn as nn
import torch.optim as optim
# 定義一個簡單的模型
class SimpleModel(nn.Module):
def __init__(self, input_size, hidden_size, output_size):
super(SimpleModel, self).__init__()
self.fc1 = nn.Linear(input_size, hidden_size)
self.relu = nn.ReLU()
self.fc2 = nn.Linear(hidden_size, output_size)
def forward(self, x):
x = self.fc1(x)
x = self.relu(x)
x = self.fc2(x)
return x
# 建立模型例項、最佳化器和損失函式
model = SimpleModel(input_size=10, hidden_size=20, output_size=5)
optimizer = optim.Adam(model.parameters(), lr=0.001)
loss_fn = nn.MSELoss()
# 訓練迴圈 (示意)
for epoch in range(100):
# ... 前向傳播、計算損失、反向傳播、更新引數 ...
pass
內容解密
SimpleModel
繼承自nn.Module
,定義了包含兩個線性層和一個 ReLU 啟用函式的模型。forward
方法定義了模型的前向傳播邏輯。- 使用
optim.Adam
建立最佳化器,並使用nn.MSELoss
作為損失函式。
圖表翻譯
graph LR I[輸入] --> FC1[線性層 1] FC1 --> ReLU[ReLU 啟用函式] ReLU --> FC2[線性層 2] FC2 --> O[輸出]
此圖示展現了 SimpleModel
的資料流向:輸入經過兩個線性層和一個 ReLU 啟用函式後得到輸出。
波士頓房價預測模型實作
以下展示如何使用 PyTorch 建立一個波士頓房價預測模型:
import torch.nn as nn
class BostonHousingModel(nn.Module):
def __init__(self, input_size=13, hidden_size=32):
super().__init__()
self.fc1 = nn.Linear(input_size, hidden_size)
self.relu = nn.ReLU()
self.fc2 = nn.Linear(hidden_size, 1)
def forward(self, x):
x = self.fc1(x)
x = self.relu(x)
x = self.fc2(x)
return x
# 建立模型例項
model = BostonHousingModel()
# 輸入範例 (13 個特徵)
input_data = torch.randn(1, 13)
# 進行預測
predictions = model(input_data)
print(predictions)
內容解密
此模型包含兩個線性層和一個 ReLU 啟用函式。輸入資料包含 13 個特徵,模型輸出房價的預測值。
圖表翻譯
graph LR Input[輸入 (13 特徵)] --> FC1[線性層 1] FC1 --> ReLU[ReLU] ReLU --> FC2[線性層 2] FC2 --> Output[輸出 (房價預測)]
此圖示說明瞭波士頓房價預測模型的資料流程:輸入經過兩個線性層和 ReLU 啟用函式後,輸出房價預測值。
PyTorch 提供了簡潔而強大的工具,讓開發者能輕鬆建構和訓練深度學習模型。從張量和自動微分到模型、層、最佳化器和損失函式,PyTorch 的設計理念著重於靈活性和效率。透過理解這些核心概念,並結合實際案例的練習,開發者可以更有效地運用 PyTorch 解決各種深度學習問題。隨著深度學習技術的持續發展,PyTorch 也將持續演進,提供更豐富的功能和更優異的效能,賦能更多創新應用。對於臺灣的開發者而言,掌握 PyTorch 將有助於提升自身的技術競爭力,並在全球深度學習領域佔有一席之地。