Pytorch教學2 機器學習的原理與模型建置

機器學習的原理基本上就是擬合訓練資料,於是我們會使用具有許多未知參數的模型來進行擬合,達到預測新資料的效果。而擬合過程中,會使用損失函數(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 表示上述三種線性模型的示例:

  1. 簡單線性回歸模型
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)
  1. 多變量線性回歸模型
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)
  1. 邏輯回歸模型
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 來實現這三種模型的示例:

  1. 簡單線性回歸模型
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())
  1. 多變量線性回歸模型
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())
  1. 邏輯回歸模型
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 正規化項添加到優化過程中,限制模型權重的大小,防止過擬合。

說了這麼多,您應該可以開始試著建置自己的模型了,開始一起預測尚未探索的領域,如金融、股票、生科,等待您的研究

Back to Blog pytorch連結

返回頂端