機器學習的原理基本上就是擬合訓練資料,於是我們會使用具有許多未知參數的模型來進行擬合,達到預測新資料的效果。而擬合過程中,會使用損失函數(loss function)來計算與資料的誤差,接著使用微積分中的鏈鎖法則(chain rule)來反向傳播 (有關微積分的鏈鎖法則及偏微分,可以觀看這篇文章 AI調用基礎微積分-多維空間的偏微分 )
匯入Pytorch
首先,在建置模型以前,你很可能需要先下載及匯入好以下模型/插件
import os
import torch
from torch import nn
from torch.utils.data import DataLoader
from torchvision import datasets, transforms
接著指定GPU進行訓練
device = (
"cuda"
if torch.cuda.is_available()
else "mps"
if torch.backends.mps.is_available()
else "cpu"
)
device
完成以後,可以根據你的需求,建立nn模型或自己寫一個
自己寫
自己寫的話擁有更高的彈性,不過更需要相關經驗
以下是使用 Python 表示上述三種線性模型的示例:
- 簡單線性回歸模型:
def simple_linear_regression(x, w, b):
return w * x + b
# 例子
x = 2
w = 3
b = 1
result = simple_linear_regression(x, w, b)
print("Simple Linear Regression Result:", result)
- 多變量線性回歸模型:
def multivariate_linear_regression(x, w, b):
return sum(w_i * x_i for w_i, x_i in zip(w, x)) + b
# 例子
x = [2, 3, 4] # 三個自變量
w = [1, 2, 3] # 對應的權重
b = 1
result = multivariate_linear_regression(x, w, b)
print("Multivariate Linear Regression Result:", result)
- 邏輯回歸模型:
import numpy as np
def logistic_regression(x, w, b):
z = np.dot(w, x) + b
return 1 / (1 + np.exp(-z))
# 例子
x = np.array([1, 2, 3]) # 特徵向量
w = np.array([0.5, 0.8, -0.2]) # 權重向量
b = -1
result = logistic_regression(x, w, b)
print("Logistic Regression Result:", result)
nn模型
如果你使用 PyTorch 這樣的深度學習框架,你可以使用其內置的 nn.Module
類來定義線性模型。以下是使用 PyTorch 中的 nn.Linear
來實現這三種模型的示例:
- 簡單線性回歸模型:
import torch
import torch.nn as nn
class SimpleLinearRegression(nn.Module):
def __init__(self, input_size):
super(SimpleLinearRegression, self).__init__()
self.linear = nn.Linear(input_size, 1)
def forward(self, x):
return self.linear(x)
# 例子
model = SimpleLinearRegression(input_size=1)
x = torch.tensor([[2.0]]) # 輸入張量
result = model(x)
print("Simple Linear Regression Result:", result.item())
- 多變量線性回歸模型:
class MultivariateLinearRegression(nn.Module):
def __init__(self, input_size):
super(MultivariateLinearRegression, self).__init__()
self.linear = nn.Linear(input_size, 1)
def forward(self, x):
return self.linear(x)
# 例子
model = MultivariateLinearRegression(input_size=3)
x = torch.tensor([[2.0, 3.0, 4.0]]) # 多變量輸入張量
result = model(x)
print("Multivariate Linear Regression Result:", result.item())
- 邏輯回歸模型:
class LogisticRegression(nn.Module):
def __init__(self, input_size):
super(LogisticRegression, self).__init__()
self.linear = nn.Linear(input_size, 1)
def forward(self, x):
return torch.sigmoid(self.linear(x))
# 例子
model = LogisticRegression(input_size=3)
x = torch.tensor([[1.0, 2.0, 3.0]]) # 特徵張量
result = model(x)
print("Logistic Regression Result:", result.item())
有關tf.Keras使用nn模型做MNIST的實例,可以看這篇文章 Keras 教學 3 – CNN 卷積層、池化層、展平層、密集層、丟棄層
訓練程式
我們做一個實例,使用隨機生成的數據來訓練模型,以預測一個自變量與一個因變量之間的線性關係。
import torch
import torch.nn as nn
import numpy as np
import matplotlib.pyplot as plt
# 生成訓練數據
np.random.seed(0)
X = np.random.rand(100, 1) * 10 # 100個樣本的自變量
y = 2 * X + 1 + np.random.randn(100, 1) # 對應的因變量,加入了隨機噪聲
# 將數據轉換為 PyTorch 張量
X_tensor = torch.from_numpy(X).float()
y_tensor = torch.from_numpy(y).float()
# 定義簡單線性回歸模型
class SimpleLinearRegression(nn.Module):
def __init__(self):
super(SimpleLinearRegression, self).__init__()
self.linear = nn.Linear(1, 1) # 單變量線性回歸,一個自變量對應一個因變量
def forward(self, x):
return self.linear(x)
# 初始化模型
model = SimpleLinearRegression()
# 定義損失函數
criterion = nn.MSELoss()
# 定義優化器
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
# 訓練模型
num_epochs = 1000
for epoch in range(num_epochs):
# 前向傳播
outputs = model(X_tensor)
loss = criterion(outputs, y_tensor)
# 反向傳播與優化
optimizer.zero_grad()
loss.backward()
optimizer.step()
if (epoch+1) % 100 == 0:
print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {loss.item():.4f}')
# 繪製訓練數據與模型預測的關係
predicted = model(X_tensor).detach().numpy()
plt.scatter(X, y, label='Original data')
plt.plot(X, predicted, label='Fitted line', color='red')
plt.legend()
plt.show()
這個示例程式會生成一個簡單的數據集,然後使用梯度下降來訓練一個簡單的線性回歸模型。在每個訓練周期中,它都會計算損失並更新模型的參數,最後將原始數據和模型預測的結果繪製成圖表。
輸出如下,看起來它很好的找到了趨勢
學習率設置不當
如果我們把學習率調高一點,調到0.035輸出如下
可以看到它直接變得數值超不穩定甚至梯度爆炸了,所以尋找正確學習率的經驗在AI領域可是非常重要的
SGD隨機梯度下降與反向傳播
當使用隨機梯度下降(SGD)等優化算法時,正規化是一個重要的技術,用於防止過度擬合(overfitting)。過度擬合發生在模型在訓練數據上表現很好,但在測試數據上表現很差的情況下。正規化的目標是限制模型的複雜度,從而使其更好地泛化到未見過的數據。
常見的正規化技術包括 L1 正規化和 L2 正規化:
- L1 正規化:通過在損失函數中添加權重的絕對值的總和來實現。它的目標是促使模型權重變得稀疏,從而可以選擇最重要的特徵。
- L2 正規化:通過在損失函數中添加權重的平方和來實現。它的目標是使權重值變得較小,防止權重過大。
L2 正規化的示例如下:
import torch
import torch.nn as nn
import numpy as np
# 生成訓練數據
np.random.seed(0)
X = np.random.rand(100, 1) * 10 # 100個樣本的自變量
y = 2 * X + 1 + np.random.randn(100, 1) # 對應的因變量,加入了隨機噪聲
# 將數據轉換為 PyTorch 張量
X_tensor = torch.from_numpy(X).float()
y_tensor = torch.from_numpy(y).float()
# 定義簡單線性回歸模型
class SimpleLinearRegression(nn.Module):
def __init__(self):
super(SimpleLinearRegression, self).__init__()
self.linear = nn.Linear(1, 1) # 單變量線性回歸,一個自變量對應一個因變量
def forward(self, x):
return self.linear(x)
# 初始化模型
model = SimpleLinearRegression()
# 定義損失函數(包括 L2 正規化)
criterion = nn.MSELoss()
lambda_value = 0.01 # 正規化參數
optimizer = torch.optim.SGD(model.parameters(), lr=0.01, weight_decay=lambda_value)
# 訓練模型
num_epochs = 1000
for epoch in range(num_epochs):
# 前向傳播
outputs = model(X_tensor)
loss = criterion(outputs, y_tensor)
# 反向傳播與優化
optimizer.zero_grad()
loss.backward()
optimizer.step()
if (epoch+1) % 100 == 0:
print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {loss.item():.4f}')
我們將正規化參數 lambda_value
設置為 0.01,並在優化器的 weight_decay
參數中使用它。因此將 L2 正規化項添加到優化過程中,限制模型權重的大小,防止過擬合。
說了這麼多,您應該可以開始試著建置自己的模型了,開始一起預測尚未探索的領域,如金融、股票、生科,等待您的研究