最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

使用PyTorch實(shí)現(xiàn)線性回歸的全面指南

 更新時間:2026年05月19日 08:53:09   作者:獨(dú)隅  
本文是一份全面的PyTorch線性回歸實(shí)戰(zhàn)指南,從理論基礎(chǔ)到代碼實(shí)現(xiàn),從簡單示例到真實(shí)場景應(yīng)用,系統(tǒng)性地講解如何使用PyTorch實(shí)現(xiàn)線性回歸模型,需要的朋友可以參考下

摘要

核心內(nèi)容包括:

  • ? 深入剖析線性回歸的數(shù)學(xué)原理和梯度下降算法
  • ? 兩種實(shí)現(xiàn)方式:從零實(shí)現(xiàn) vs PyTorch高級API
  • ? 完整的數(shù)據(jù)準(zhǔn)備、模型訓(xùn)練、評估流程
  • ? 4個實(shí)戰(zhàn)案例:房價預(yù)測、股票分析、醫(yī)療費(fèi)用、工業(yè)優(yōu)化
  • ? 模型優(yōu)化技巧和超參數(shù)調(diào)優(yōu)指南

適合人群:

  • PyTorch初學(xué)者
  • 機(jī)器學(xué)習(xí)入門者
  • 需要快速上手線性回歸的數(shù)據(jù)分析師
  • 準(zhǔn)備面試的算法工程師

通過本文的學(xué)習(xí),你將掌握使用PyTorch實(shí)現(xiàn)線性回歸的完整技能,并能夠應(yīng)用到實(shí)際項(xiàng)目中。

第1章 線性回歸理論基礎(chǔ)

1.1 為什么用 PyTorch 學(xué)線性回歸?

線性回歸是機(jī)器學(xué)習(xí)入門的必修課,本質(zhì)是通過尋找特征與目標(biāo)值之間的線性關(guān)系來進(jìn)行預(yù)測。而在 PyTorch 中,這個過程被動態(tài)圖機(jī)制簡化——每個環(huán)節(jié)都變得可視化且易于調(diào)試。

雖然線性回歸可以用 scikit-learn 幾行代碼實(shí)現(xiàn),但用 PyTorch 手動構(gòu)建能深入理解神經(jīng)網(wǎng)絡(luò)的基本工作原理,這對后續(xù)學(xué)習(xí)更復(fù)雜模型至關(guān)重要。伊利諾伊大學(xué)的 ECE 364 課程甚至用整整三周(Week 6-8)專門講授線性回歸在 PyTorch 中的實(shí)現(xiàn)及其與數(shù)據(jù)集、數(shù)據(jù)加載器等組件的結(jié)合。

1.2 PyTorch 兩大核心特性

與 NumPy 相比,PyTorch 張量額外具備兩大關(guān)鍵特性:

  • 自動微分:當(dāng)你在 PyTorch 中定義模型時,實(shí)際上在構(gòu)建一個計(jì)算圖——這個圖會記錄所有操作步驟,并在反向傳播時自動計(jì)算梯度
  • GPU 加速:張量可以無縫遷移到 GPU 上進(jìn)行并行計(jì)算,顯著加速訓(xùn)練過程

線性回歸可以使用單層神經(jīng)網(wǎng)絡(luò)來實(shí)現(xiàn),所需要用到的概念和技巧也適用于更復(fù)雜的深度學(xué)習(xí)模型。

1.3 線性回歸的核心概念

線性回歸是機(jī)器學(xué)習(xí)中最基礎(chǔ)、最重要的算法之一,它假設(shè)目標(biāo)變量 y 與輸入特征 x 之間存在線性關(guān)系。

基本公式:

對于單變量線性回歸:

y = w * x + b + ε

對于多變量線性回歸:

y = w?x? + w?x? + ... + w?x? + b + ε

參數(shù)說明:

  • y:預(yù)測的目標(biāo)值(連續(xù)型變量)
  • x?, x?, ..., x?:輸入特征
  • w?, w?, ..., w?:權(quán)重參數(shù),表示各特征對目標(biāo)的影響程度
  • b:偏置項(xiàng)(截距)
  • ε:噪聲項(xiàng),表示模型無法解釋的隨機(jī)誤差

1.4 數(shù)學(xué)原理與公式推導(dǎo)

1.4.1 損失函數(shù)(均方誤差)

線性回歸使用均方誤差(MSE)作為損失函數(shù),衡量預(yù)測值與真實(shí)值之間的差距:

L(w, b) = (1/2n) * Σ(y? - ??)2

為什么要除以2?

  • 為了在求導(dǎo)時抵消平方項(xiàng)的系數(shù)2,使梯度計(jì)算更簡潔
  • 不影響優(yōu)化結(jié)果,因?yàn)檫@只是對損失函數(shù)的縮放

1.4.2 梯度計(jì)算

對損失函數(shù)求偏導(dǎo),得到梯度:

?L/?w? = (1/n) * Σ(?? - y?) * x??
?L/?b = (1/n) * Σ(?? - y?)

1.4.3 梯度下降更新規(guī)則

w? ← w? - α * ?L/?w?
b ← b - α * ?L/?b

其中 α 是學(xué)習(xí)率,控制每次更新的步長。

1.5 損失函數(shù)與優(yōu)化算法

1.5.1 常見損失函數(shù)對比

損失函數(shù)公式適用場景
MSE(1/2n)Σ(y-?)²回歸問題,對異常值敏感
MAE(1/n)Σy-?
Huber分段函數(shù)回歸問題,平衡MSE和MAE

1.5.2 優(yōu)化算法對比

優(yōu)化器特點(diǎn)適用場景
SGD簡單直接,需要手動調(diào)學(xué)習(xí)率小數(shù)據(jù)集,簡單模型
SGD with Momentum加入動量,加速收斂一般場景
Adam自適應(yīng)學(xué)習(xí)率,收斂快大多數(shù)場景
RMSprop適合非平穩(wěn)目標(biāo)RNN等

第2章 PyTorch框架入門

2.1 PyTorch核心特性

  • 動態(tài)計(jì)算圖:運(yùn)行時構(gòu)建計(jì)算圖,調(diào)試方便
  • Pythonic:API設(shè)計(jì)符合Python習(xí)慣
  • GPU加速:無縫支持CUDA,加速計(jì)算
  • 自動求導(dǎo):自動計(jì)算梯度,簡化實(shí)現(xiàn)

2.2 環(huán)境配置與安裝

# 創(chuàng)建虛擬環(huán)境
python -m venv pytorch_env
source pytorch_env/bin/activate  # Linux/Mac
# pytorch_env\Scripts\activate  # Windows
# 安裝PyTorch(CPU版本)
pip install torch torchvision torchaudio
# 安裝PyTorch(GPU版本,CUDA 11.8)
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118
# 安裝其他依賴
pip install numpy pandas matplotlib seaborn jupyter

2.3 張量操作基礎(chǔ)

import torch

# 創(chuàng)建張量
x = torch.tensor([1.0, 2.0, 3.0])  # 從列表創(chuàng)建
y = torch.zeros(3)                 # 零張量
z = torch.ones(2, 3)               # 全1張量
a = torch.randn(2, 2)              # 標(biāo)準(zhǔn)正態(tài)分布

# 張量屬性
print(f"形狀: {x.shape}")
print(f"數(shù)據(jù)類型: {x.dtype}")
print(f"設(shè)備: {x.device}")

# 基本運(yùn)算
x = torch.tensor([1.0, 2.0, 3.0])
y = torch.tensor([4.0, 5.0, 6.0])
print(f"加法: {x + y}")
print(f"乘法: {x * y}")
print(f"點(diǎn)積: {torch.dot(x, y)}")

# 矩陣運(yùn)算
A = torch.randn(3, 2)
B = torch.randn(2, 4)
C = torch.matmul(A, B)  # 矩陣乘法
print(f"矩陣乘法結(jié)果形狀: {C.shape}")

第3章 從零實(shí)現(xiàn)線性回歸

3.1 數(shù)據(jù)生成與準(zhǔn)備

import torch
import numpy as np

# 設(shè)置隨機(jī)種子,確??蓮?fù)現(xiàn)
torch.manual_seed(42)
np.random.seed(42)

# 定義真實(shí)的模型參數(shù)
true_w = torch.tensor([[2.0], [-3.4]])  # 真實(shí)權(quán)重
true_b = 4.2                            # 真實(shí)偏置

# 生成數(shù)據(jù)
num_examples = 1000  # 樣本數(shù)量
num_inputs = 2       # 特征數(shù)量

# 從標(biāo)準(zhǔn)正態(tài)分布中隨機(jī)生成輸入特征
X = torch.normal(0, 1, (num_examples, num_inputs))

# 根據(jù)真實(shí)公式計(jì)算標(biāo)簽,并加入噪聲
noise = torch.normal(0, 0.01, (num_examples, 1))
y = torch.matmul(X, true_w) + true_b + noise

print(f"數(shù)據(jù)集形狀: X={X.shape}, y={y.shape}")
print(f"前3個樣本:\n{X[:3]}")
print(f"對應(yīng)標(biāo)簽:\n{y[:3]}")

3.2 模型參數(shù)初始化

# 初始化權(quán)重 w,從均值為0,標(biāo)準(zhǔn)差為0.01的正態(tài)分布中采樣
w = torch.normal(0, 0.01, size=(num_inputs, 1), requires_grad=True)

# 初始化偏置 b 為 0
b = torch.zeros(1, requires_grad=True)

print(f"初始權(quán)重 w:\n{w}")
print(f"初始偏置 b: ")
print(f"w 需要梯度: {w.requires_grad}")
print(f"b 需要梯度: {b.requires_grad}")

關(guān)鍵點(diǎn):

  • requires_grad=True 告訴 PyTorch 這些參數(shù)需要計(jì)算梯度
  • 權(quán)重通常用小的隨機(jī)數(shù)初始化,避免對稱性問題
  • 偏置可以初始化為0

3.3 前向傳播與損失計(jì)算

def linreg(X, w, b):
    """線性回歸模型的前向傳播"""
    return torch.matmul(X, w) + b

def squared_loss(y_hat, y):
    """均方損失函數(shù)"""
    # 將 y 的形狀調(diào)整為和 y_hat 一致
    return (y_hat - y.reshape(y_hat.shape)) ** 2 / 2

# 測試前向傳播
y_hat = linreg(X[:5], w, b)
print(f"預(yù)測值:\n{y_hat}")

# 測試損失計(jì)算
loss = squared_loss(y_hat, y[:5])
print(f"損失值:\n{loss}")
print(f"平均損失: {loss.mean()}")

3.4 反向傳播與參數(shù)更新

def sgd(params, lr, batch_size):
    """
    小批量隨機(jī)梯度下降優(yōu)化器
    
    參數(shù):
        params: 需要更新的參數(shù)列表,如 [w, b]
        lr: 學(xué)習(xí)率
        batch_size: 批量大小
    """
    with torch.no_grad():  # 更新參數(shù)時,不需要記錄梯度
        for param in params:
            # 梯度下降更新公式
            param -= lr * param.grad / batch_size
            # 更新后,手動將梯度清零
            param.grad.zero_()

# 示例:假設(shè)我們有梯度
w.grad = torch.tensor([[0.1], [0.2]])
b.grad = torch.tensor([0.05])
lr = 0.03

print(f"更新前 w: {w.flatten()}")
print(f"更新前 b: {b.item()}")

sgd([w, b], lr, 10)

print(f"更新后 w: {w.flatten()}")
print(f"更新后 b: {b.item()}")

3.5 完整訓(xùn)練循環(huán)

import random

def data_iter(batch_size, features, labels):
    """
    生成小批量數(shù)據(jù)的迭代器
    """
    num_examples = len(features)
    indices = list(range(num_examples))
    random.shuffle(indices)  # 打亂樣本順序
    
    for i in range(0, num_examples, batch_size):
        batch_indices = torch.tensor(
            indices[i: min(i + batch_size, num_examples)]
        )
        yield features[batch_indices], labels[batch_indices]

# 超參數(shù)設(shè)置
lr = 0.03        # 學(xué)習(xí)率
num_epochs = 5   # 訓(xùn)練輪數(shù)
batch_size = 10  # 批量大小

# 重新初始化參數(shù)
w = torch.normal(0, 0.01, size=(num_inputs, 1), requires_grad=True)
b = torch.zeros(1, requires_grad=True)

# 開始訓(xùn)練
print("=" * 60)
print("開始訓(xùn)練線性回歸模型...")
print("=" * 60)

for epoch in range(num_epochs):
    for X_batch, y_batch in data_iter(batch_size, X, y):
        # 1. 前向傳播:計(jì)算預(yù)測值
        y_hat = linreg(X_batch, w, b)
        
        # 2. 計(jì)算損失
        loss = squared_loss(y_hat, y_batch).mean()
        
        # 3. 反向傳播:計(jì)算梯度
        loss.backward()
        
        # 4. 更新參數(shù)
        sgd([w, b], lr, batch_size)
    
    # 每個epoch結(jié)束后,計(jì)算在整個數(shù)據(jù)集上的平均損失
    with torch.no_grad():
        train_loss = squared_loss(linreg(X, w, b), y).mean()
        print(f'Epoch {epoch + 1}/{num_epochs}, Loss: {train_loss:.6f}')

# 訓(xùn)練結(jié)束,查看學(xué)習(xí)到的參數(shù)
print("\n" + "=" * 60)
print("訓(xùn)練完成!模型參數(shù)對比:")
print("=" * 60)
print(f'真實(shí)的權(quán)重 w: {true_w.flatten().numpy()}')
print(f'學(xué)到的權(quán)重 w: {w.detach().flatten().numpy()}')
print(f'權(quán)重誤差: {((w - true_w).abs() / true_w.abs()).mean().item():.4%}')
print()
print(f'真實(shí)的偏置 b: {true_b:.4f}')
print(f'學(xué)到的偏置 b: {b.item():.4f}')
print(f'偏置誤差: {abs(b.item() - true_b) / abs(true_b):.4%}')

輸出示例:

============================================================
開始訓(xùn)練線性回歸模型...
============================================================
Epoch 1/5, Loss: 0.042567
Epoch 2/5, Loss: 0.000152
Epoch 3/5, Loss: 0.000058
Epoch 4/5, Loss: 0.000051
Epoch 5/5, Loss: 0.000050

============================================================
訓(xùn)練完成!模型參數(shù)對比:
============================================================
真實(shí)的權(quán)重 w: [ 2.  -3.4]
學(xué)到的權(quán)重 w: [ 1.9998 -3.3995]
權(quán)重誤差: 0.0123%
真實(shí)的偏置 b: 4.2000
學(xué)到的偏置 b: 4.1998
偏置誤差: 0.0048%

第4章 PyTorch高級API實(shí)現(xiàn)

4.1 nn.Module模型定義

import torch.nn as nn

class LinearRegressionModel(nn.Module):
    def __init__(self, input_dim):
        super(LinearRegressionModel, self).__init__()
        # 定義線性層
        self.linear = nn.Linear(input_dim, 1)
    
    def forward(self, x):
        # 前向傳播
        return self.linear(x)

# 創(chuàng)建模型
model = LinearRegressionModel(num_inputs)
print(model)
print(f"\n模型參數(shù):")
for name, param in model.named_parameters():
    print(f"  {name}: {param.shape}")

輸出:

LinearRegressionModel(
  (linear): Linear(in_features=2, out_features=1, bias=True)
)

模型參數(shù):
  linear.weight: torch.Size([1, 2])
  linear.bias: torch.Size([1])

4.2 內(nèi)置損失函數(shù)與優(yōu)化器

# 定義損失函數(shù)
criterion = nn.MSELoss()

# 定義優(yōu)化器
optimizer = torch.optim.SGD(model.parameters(), lr=0.03)

# 訓(xùn)練循環(huán)
num_epochs = 5
for epoch in range(num_epochs):
    for X_batch, y_batch in data_iter(batch_size, X, y):
        # 前向傳播
        y_pred = model(X_batch)
        
        # 計(jì)算損失
        loss = criterion(y_pred, y_batch)
        
        # 反向傳播
        optimizer.zero_grad()  # 梯度清零
        loss.backward()        # 計(jì)算梯度
        
        # 更新參數(shù)
        optimizer.step()
    
    # 打印訓(xùn)練進(jìn)度
    if (epoch + 1) % 1 == 0:
        with torch.no_grad():
            y_pred = model(X)
            epoch_loss = criterion(y_pred, y).item()
            print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {epoch_loss:.6f}')

# 查看學(xué)習(xí)到的參數(shù)
print("\n學(xué)到的參數(shù):")
print(f"w: {model.linear.weight.data.numpy()}")
print(f"b: {model.linear.bias.item()}")

4.3 DataLoader數(shù)據(jù)加載器

from torch.utils.data import TensorDataset, DataLoader

# 創(chuàng)建數(shù)據(jù)集
dataset = TensorDataset(X, y)

# 創(chuàng)建數(shù)據(jù)加載器
data_loader = DataLoader(
    dataset=dataset,
    batch_size=batch_size,
    shuffle=True,      # 每個epoch打亂數(shù)據(jù)
    num_workers=0      # 數(shù)據(jù)加載的子進(jìn)程數(shù)
)

# 使用 DataLoader 訓(xùn)練
model = LinearRegressionModel(num_inputs)
criterion = nn.MSELoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.01)

for epoch in range(num_epochs):
    for X_batch, y_batch in data_loader:
        y_pred = model(X_batch)
        loss = criterion(y_pred, y_batch)
        
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
    
    if (epoch + 1) % 1 == 0:
        with torch.no_grad():
            y_pred = model(X)
            epoch_loss = criterion(y_pred, y).item()
            print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {epoch_loss:.6f}')

4.4 訓(xùn)練過程可視化

import matplotlib.pyplot as plt

# 記錄訓(xùn)練過程
train_losses = []
model = LinearRegressionModel(num_inputs)
criterion = nn.MSELoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.01)

for epoch in range(20):
    epoch_loss = 0
    for X_batch, y_batch in data_loader:
        y_pred = model(X_batch)
        loss = criterion(y_pred, y_batch)
        
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        
        epoch_loss += loss.item()
    
    avg_loss = epoch_loss / len(data_loader)
    train_losses.append(avg_loss)

# 繪制損失曲線
plt.figure(figsize=(10, 6))
plt.plot(range(1, len(train_losses) + 1), train_losses, marker='o')
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.title('Training Loss Curve')
plt.grid(True)
plt.savefig('training_loss.png', dpi=300, bbox_inches='tight')
plt.show()

# 預(yù)測結(jié)果可視化
with torch.no_grad():
    y_pred = model(X).numpy()
    
plt.figure(figsize=(10, 6))
plt.scatter(y.numpy(), y_pred, alpha=0.5)
plt.plot([y.min(), y.max()], [y.min(), y.max()], 'r--')
plt.xlabel('True Values')
plt.ylabel('Predictions')
plt.title('True vs Predicted Values')
plt.grid(True)
plt.savefig('predictions.png', dpi=300, bbox_inches='tight')
plt.show()

第5章 實(shí)戰(zhàn)應(yīng)用案例

5.1 房價預(yù)測項(xiàng)目

import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import mean_squared_error, r2_score

# 生成模擬房價數(shù)據(jù)
np.random.seed(42)
n_samples = 1000

data = {
    'area': np.random.uniform(50, 200, n_samples),        # 面積
    'rooms': np.random.randint(1, 6, n_samples),          # 房間數(shù)
    'age': np.random.uniform(0, 30, n_samples),           # 房齡
    'distance_to_center': np.random.uniform(1, 20, n_samples)  # 距離市中心
}

# 生成價格
data['price'] = (
    1.5 * data['area'] +          # 面積系數(shù)
    10 * data['rooms'] +          # 房間數(shù)系數(shù)
    -0.8 * data['age'] +          # 房齡系數(shù)
    -2 * data['distance_to_center'] +  # 距離系數(shù)
    50 +                          # 基礎(chǔ)價格
    np.random.normal(0, 20, n_samples)  # 噪聲
)

df = pd.DataFrame(data)

# 特征和標(biāo)簽
X = df[['area', 'rooms', 'age', 'distance_to_center']].values
y = df['price'].values.reshape(-1, 1)

# 劃分訓(xùn)練集和測試集
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42
)

# 特征標(biāo)準(zhǔn)化
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)

# 轉(zhuǎn)換為PyTorch張量
X_train_tensor = torch.FloatTensor(X_train_scaled)
y_train_tensor = torch.FloatTensor(y_train)
X_test_tensor = torch.FloatTensor(X_test_scaled)
y_test_tensor = torch.FloatTensor(y_test)

# 創(chuàng)建數(shù)據(jù)加載器
train_dataset = TensorDataset(X_train_tensor, y_train_tensor)
train_loader = DataLoader(dataset=train_dataset, batch_size=32, shuffle=True)

# 定義模型
class HousePriceModel(nn.Module):
    def __init__(self, input_dim):
        super(HousePriceModel, self).__init__()
        self.linear = nn.Linear(input_dim, 1)
    
    def forward(self, x):
        return self.linear(x)

model = HousePriceModel(X_train_scaled.shape[1])
criterion = nn.MSELoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.01)

# 訓(xùn)練
num_epochs = 100
for epoch in range(num_epochs):
    for X_batch, y_batch in train_loader:
        y_pred = model(X_batch)
        loss = criterion(y_pred, y_batch)
        
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

# 評估
model.eval()
with torch.no_grad():
    y_pred_train = model(X_train_tensor).numpy()
    y_pred_test = model(X_test_tensor).numpy()
    
    train_rmse = np.sqrt(mean_squared_error(y_train, y_pred_train))
    test_rmse = np.sqrt(mean_squared_error(y_test, y_pred_test))
    train_r2 = r2_score(y_train, y_pred_train)
    test_r2 = r2_score(y_test, y_pred_test)
    
    print(f"訓(xùn)練集 RMSE: {train_rmse:.2f} (萬元)")
    print(f"測試集 RMSE: {test_rmse:.2f} (萬元)")
    print(f"訓(xùn)練集 R2: {train_r2:.4f}")
    print(f"測試集 R2: {test_r2:.4f}")

5.2 股票趨勢分析

# 模擬股票數(shù)據(jù)
dates = pd.date_range('2023-01-01', periods=365, freq='D')
np.random.seed(42)

stock_data = {
    'date': dates,
    'open': np.random.uniform(100, 150, 365),
    'high': np.random.uniform(105, 155, 365),
    'low': np.random.uniform(95, 145, 365),
    'volume': np.random.uniform(1000000, 5000000, 365),
    'close': np.random.uniform(100, 150, 365) + np.random.normal(0, 2, 365)
}

stock_df = pd.DataFrame(stock_data)
stock_df['return'] = stock_df['close'].pct_change()  # 日收益率
stock_df = stock_df.dropna()

print("股票數(shù)據(jù)示例:")
print(stock_df.head())
print(f"\n數(shù)據(jù)集形狀: {stock_df.shape}")

5.3 醫(yī)療費(fèi)用預(yù)測

# 模擬醫(yī)療數(shù)據(jù)
n_patients = 1000
medical_data = {
    'age': np.random.randint(18, 80, n_patients),
    'bmi': np.random.uniform(18, 40, n_patients),
    'smoker': np.random.choice([0, 1], n_patients, p=[0.8, 0.2]),
    'children': np.random.randint(0, 5, n_patients),
    'charges': (
        200 * medical_data['age'] +
        300 * medical_data['bmi'] +
        10000 * medical_data['smoker'] +
        500 * medical_data['children'] +
        np.random.normal(0, 2000, n_patients)
    )
}

medical_df = pd.DataFrame(medical_data)

print("醫(yī)療數(shù)據(jù)統(tǒng)計(jì):")
print(f"吸煙者平均費(fèi)用: {medical_df[medical_df['smoker']==1]['charges'].mean():.2f}")
print(f"非吸煙者平均費(fèi)用: {medical_df[medical_df['smoker']==0]['charges'].mean():.2f}")
print(f"費(fèi)用標(biāo)準(zhǔn)差: {medical_df['charges'].std():.2f}")

5.4 工業(yè)生產(chǎn)優(yōu)化

# 模擬生產(chǎn)數(shù)據(jù)
n_samples = 500
production_data = {
    'temperature': np.random.uniform(150, 250, n_samples),
    'pressure': np.random.uniform(5, 15, n_samples),
    'time': np.random.uniform(10, 60, n_samples),
    'speed': np.random.uniform(50, 150, n_samples),
    'quality': (
        0.3 * production_data['temperature'] +
        0.5 * production_data['pressure'] +
        0.2 * production_data['time'] -
        0.1 * production_data['speed'] +
        50 + np.random.normal(0, 5, n_samples)
    )
}

prod_df = pd.DataFrame(production_data)

# 找出最優(yōu)參數(shù)組合
optimal_params = {
    'temperature': prod_df.loc[prod_df['quality'].idxmax(), 'temperature'],
    'pressure': prod_df.loc[prod_df['quality'].idxmax(), 'pressure'],
    'time': prod_df.loc[prod_df['quality'].idxmax(), 'time'],
    'speed': prod_df.loc[prod_df['quality'].idxmax(), 'speed'],
    'quality': prod_df['quality'].max()
}

print("最優(yōu)生產(chǎn)參數(shù):")
for k, v in optimal_params.items():
    print(f"  {k}: {v:.2f}")

第6章 模型優(yōu)化與調(diào)參

6.1 學(xué)習(xí)率調(diào)優(yōu)策略

# 不同學(xué)習(xí)率對比
learning_rates = [0.001, 0.01, 0.03, 0.1, 0.3]
results = {}

for lr in learning_rates:
    model = LinearRegressionModel(num_inputs)
    optimizer = torch.optim.SGD(model.parameters(), lr=lr)
    criterion = nn.MSELoss()
    
    losses = []
    for epoch in range(20):
        epoch_loss = 0
        for X_batch, y_batch in data_loader:
            y_pred = model(X_batch)
            loss = criterion(y_pred, y_batch)
            
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()
            
            epoch_loss += loss.item()
        
        losses.append(epoch_loss / len(data_loader))
    
    results[lr] = losses[-1]  # 記錄最終損失

print("不同學(xué)習(xí)率的最終損失:")
for lr, loss in results.items():
    print(f"  lr={lr:.3f}: {loss:.6f}")

6.2 批量大小選擇

batch_sizes = [4, 8, 16, 32, 64, 128]
results = {}

for bs in batch_sizes:
    data_loader = DataLoader(dataset=dataset, batch_size=bs, shuffle=True)
    model = LinearRegressionModel(num_inputs)
    optimizer = torch.optim.Adam(model.parameters(), lr=0.01)
    criterion = nn.MSELoss()
    
    for epoch in range(10):
        for X_batch, y_batch in data_loader:
            y_pred = model(X_batch)
            loss = criterion(y_pred, y_batch)
            
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()
    
    with torch.no_grad():
        final_loss = criterion(model(X), y).item()
        results[bs] = final_loss

print("不同批量大小的最終損失:")
for bs, loss in results.items():
    print(f"  batch_size={bs}: {loss:.6f}")

6.3 正則化技術(shù)

# L2正則化(權(quán)重衰減)
model = LinearRegressionModel(num_inputs)
optimizer = torch.optim.SGD(
    model.parameters(), 
    lr=0.01, 
    weight_decay=0.01  # L2正則化系數(shù)
)
criterion = nn.MSELoss()

# 訓(xùn)練
for epoch in range(20):
    for X_batch, y_batch in data_loader:
        y_pred = model(X_batch)
        loss = criterion(y_pred, y_batch)
        
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

print("L2正則化后的權(quán)重:")
print(f"w: {model.linear.weight.data.numpy()}")
print(f"權(quán)重范數(shù): {torch.norm(model.linear.weight).item():.4f}")

6.4 早停與模型保存

# 早停實(shí)現(xiàn)
class EarlyStopping:
    def __init__(self, patience=5, min_delta=0.001):
        self.patience = patience
        self.min_delta = min_delta
        self.counter = 0
        self.best_loss = None
        self.early_stop = False
    
    def __call__(self, val_loss):
        if self.best_loss is None:
            self.best_loss = val_loss
        elif val_loss > self.best_loss - self.min_delta:
            self.counter += 1
            if self.counter >= self.patience:
                self.early_stop = True
        else:
            self.best_loss = val_loss
            self.counter = 0
        
        return self.early_stop

# 模型保存與加載
model = LinearRegressionModel(num_inputs)
torch.save(model.state_dict(), 'linear_model.pth')

# 加載模型
model_loaded = LinearRegressionModel(num_inputs)
model_loaded.load_state_dict(torch.load('linear_model.pth'))
model_loaded.eval()

第7章 常見問題與解決方案

問題解決方案
損失不下降增大學(xué)習(xí)率或檢查數(shù)據(jù)是否標(biāo)準(zhǔn)化
損失震蕩劇烈減小學(xué)習(xí)率
梯度為 NaN學(xué)習(xí)率過大導(dǎo)致梯度爆炸,降低學(xué)習(xí)率
訓(xùn)練集和測試集差距大過擬合,增加數(shù)據(jù)量或添加正則化
忘記 zero_grad()每次迭代前必須調(diào)用 optimizer.zero_grad()
GPU 不可用檢查 CUDA 版本與 PyTorch 版本是否匹配

7.1 損失不下降

問題: 訓(xùn)練過程中損失值保持不變或震蕩

解決方案:

# 1. 檢查學(xué)習(xí)率是否合適
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)  # 嘗試更小的學(xué)習(xí)率

# 2. 檢查數(shù)據(jù)是否標(biāo)準(zhǔn)化
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)

# 3. 檢查梯度是否正常
for name, param in model.named_parameters():
    print(f"{name} gradient norm: {param.grad.norm().item()}")

7.2 過擬合問題

問題: 訓(xùn)練集表現(xiàn)好,測試集表現(xiàn)差

解決方案:

# 1. 使用正則化
optimizer = torch.optim.SGD(model.parameters(), lr=0.01, weight_decay=0.01)

# 2. 增加數(shù)據(jù)
# 3. 減少模型復(fù)雜度
# 4. 使用早停
early_stopping = EarlyStopping(patience=5)

7.3 GPU加速

# 檢查GPU可用性
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"使用設(shè)備: {device}")

# 將模型和數(shù)據(jù)移動到GPU
model = model.to(device)
X = X.to(device)
y = y.to(device)

# 訓(xùn)練時同樣在GPU上
for X_batch, y_batch in data_loader:
    X_batch = X_batch.to(device)
    y_batch = y_batch.to(device)
    
    y_pred = model(X_batch)
    loss = criterion(y_pred, y_batch)
    
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

總結(jié)

本文從 PyTorch 的基礎(chǔ)特性出發(fā),系統(tǒng)講解了線性回歸的完整實(shí)現(xiàn)流程——從 nn.Linear 的模型定義、nn.MSELoss 的損失計(jì)算、optim.SGD 的參數(shù)優(yōu)化,到 DataLoader 的批量加載、GPU 加速的部署優(yōu)化、模型的保存與評估。核心要點(diǎn):

  1. PyTorch 三大核心組件nn.Linear(模型)、nn.MSELoss(損失)、optim.SGD(優(yōu)化器)是構(gòu)建任何深度學(xué)習(xí)模型的基石
  2. 訓(xùn)練循環(huán)四步法:前向傳播 → 損失計(jì)算 → 反向傳播 → 參數(shù)更新,是 PyTorch 訓(xùn)練的標(biāo)準(zhǔn)范式
  3. 工程化實(shí)踐:DataLoader 批量加載、訓(xùn)練測試分離、GPU 加速、模型保存加載是實(shí)際項(xiàng)目中不可或缺的技能
  4. 從零到框架的對應(yīng)關(guān)系:理解簡潔 API 背后的實(shí)現(xiàn)邏輯,是掌握深度學(xué)習(xí)的必經(jīng)之路

線性回歸雖簡單,但其中蘊(yùn)含的前向傳播、損失計(jì)算、梯度下降、參數(shù)更新等概念,是所有復(fù)雜深度學(xué)習(xí)模型的基礎(chǔ)。掌握 PyTorch 實(shí)現(xiàn)線性回歸的完整流水線,你將輕松過渡到更復(fù)雜的神經(jīng)網(wǎng)絡(luò)模型。

附錄

附錄A:完整代碼實(shí)現(xiàn)

"""
PyTorch線性回歸完整實(shí)現(xiàn)
"""

import torch
import numpy as np
import random
import matplotlib.pyplot as plt
from torch.utils.data import TensorDataset, DataLoader

# ==================== 1. 數(shù)據(jù)生成 ====================
def generate_data(num_examples=1000, num_inputs=2, seed=42):
    """生成帶噪聲的線性數(shù)據(jù)"""
    torch.manual_seed(seed)
    np.random.seed(seed)
    
    true_w = torch.tensor([[2.0], [-3.4]])
    true_b = 4.2
    
    X = torch.normal(0, 1, (num_examples, num_inputs))
    noise = torch.normal(0, 0.01, (num_examples, 1))
    y = torch.matmul(X, true_w) + true_b + noise
    
    return X, y, true_w, true_b

# ==================== 2. 數(shù)據(jù)迭代器 ====================
def data_iter(batch_size, features, labels):
    """生成小批量數(shù)據(jù)"""
    num_examples = len(features)
    indices = list(range(num_examples))
    random.shuffle(indices)
    
    for i in range(0, num_examples, batch_size):
        batch_indices = torch.tensor(
            indices[i: min(i + batch_size, num_examples)]
        )
        yield features[batch_indices], labels[batch_indices]

# ==================== 3. 模型定義 ====================
def linreg(X, w, b):
    """線性回歸模型"""
    return torch.matmul(X, w) + b

# ==================== 4. 損失函數(shù) ====================
def squared_loss(y_hat, y):
    """均方損失函數(shù)"""
    return (y_hat - y.reshape(y_hat.shape)) ** 2 / 2

# ==================== 5. 優(yōu)化器 ====================
def sgd(params, lr, batch_size):
    """小批量隨機(jī)梯度下降"""
    with torch.no_grad():
        for param in params:
            param -= lr * param.grad / batch_size
            param.grad.zero_()

# ==================== 6. 訓(xùn)練函數(shù) ====================
def train_linear_regression(
    X, y, true_w, true_b,
    lr=0.03, num_epochs=5, batch_size=10
):
    """訓(xùn)練線性回歸模型"""
    num_inputs = X.shape[1]
    
    # 初始化參數(shù)
    w = torch.normal(0, 0.01, size=(num_inputs, 1), requires_grad=True)
    b = torch.zeros(1, requires_grad=True)
    
    losses = []
    
    print("開始訓(xùn)練...")
    print("=" * 60)
    
    for epoch in range(num_epochs):
        for X_batch, y_batch in data_iter(batch_size, X, y):
            # 前向傳播
            y_hat = linreg(X_batch, w, b)
            
            # 計(jì)算損失
            loss = squared_loss(y_hat, y_batch).mean()
            
            # 反向傳播
            loss.backward()
            
            # 更新參數(shù)
            sgd([w, b], lr, batch_size)
        
        # 計(jì)算epoch損失
        with torch.no_grad():
            epoch_loss = squared_loss(linreg(X, w, b), y).mean().item()
            losses.append(epoch_loss)
            print(f'Epoch {epoch + 1}/{num_epochs}, Loss: {epoch_loss:.6f}')
    
    # 評估結(jié)果
    print("\n" + "=" * 60)
    print("訓(xùn)練完成!")
    print("=" * 60)
    print(f'真實(shí)權(quán)重: {true_w.flatten().numpy()}')
    print(f'學(xué)到權(quán)重: {w.detach().flatten().numpy()}')
    print(f'權(quán)重相對誤差: {((w - true_w).abs() / true_w.abs()).mean().item():.4%}')
    print()
    print(f'真實(shí)偏置: {true_b:.4f}')
    print(f'學(xué)到偏置: {b.item():.4f}')
    print(f'偏置相對誤差: {abs(b.item() - true_b) / abs(true_b):.4%}')
    
    return w, b, losses

# ==================== 7. 主函數(shù) ====================
def main():
    # 生成數(shù)據(jù)
    X, y, true_w, true_b = generate_data()
    
    # 訓(xùn)練模型
    w, b, losses = train_linear_regression(X, y, true_w, true_b)
    
    # 可視化損失曲線
    plt.figure(figsize=(10, 6))
    plt.plot(range(1, len(losses) + 1), losses, marker='o')
    plt.xlabel('Epoch')
    plt.ylabel('Loss')
    plt.title('Training Loss Curve')
    plt.grid(True)
    plt.savefig('training_loss.png', dpi=300, bbox_inches='tight')
    plt.show()

if __name__ == "__main__":
    main()

附錄B:API速查表

功能PyTorch API說明
創(chuàng)建張量torch.tensor()從數(shù)據(jù)創(chuàng)建張量
隨機(jī)張量torch.randn()標(biāo)準(zhǔn)正態(tài)分布
線性層nn.Linear()全連接層
MSE損失nn.MSELoss()均方誤差
SGD優(yōu)化器optim.SGD()隨機(jī)梯度下降
Adam優(yōu)化器optim.Adam()自適應(yīng)矩估計(jì)
數(shù)據(jù)加載DataLoader()批量數(shù)據(jù)加載

通過本文,你不僅掌握了線性回歸的理論和實(shí)現(xiàn),更建立了使用PyTorch進(jìn)行深度學(xué)習(xí)開發(fā)的完整技能體系。

以上就是使用PyTorch實(shí)現(xiàn)線性回歸的全面指南的詳細(xì)內(nèi)容,更多關(guān)于PyTorch實(shí)現(xiàn)線性回歸的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Python合并多張圖片成PDF

    Python合并多張圖片成PDF

    最近需要將記的筆記整理成一個pdf進(jìn)行保存,所以就研究了一下如何利用Python代碼將拍下來的照片整個合并成一個pdf,感興趣的可以了解一下
    2021-06-06
  • 在?Python?中如何為對象添加屬性

    在?Python?中如何為對象添加屬性

    在本文中我們將介紹如何在Python中為對象添加屬性,我們還將通過示例介紹如何在Python中更改對象的屬性,本文通過示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2023-06-06
  • 使用py-spy解決scrapy卡死的問題方法

    使用py-spy解決scrapy卡死的問題方法

    這篇文章主要介紹了使用py-spy解決scrapy卡死的問題方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • python如何利用joblib保存訓(xùn)練模型

    python如何利用joblib保存訓(xùn)練模型

    這篇文章主要介紹了python如何利用joblib保存訓(xùn)練模型問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-06-06
  • pycharm 使用anaconda為默認(rèn)環(huán)境的操作

    pycharm 使用anaconda為默認(rèn)環(huán)境的操作

    這篇文章主要介紹了pycharm 使用anaconda為默認(rèn)環(huán)境的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-02-02
  • windows下python 3.6.4安裝配置圖文教程

    windows下python 3.6.4安裝配置圖文教程

    這篇文章主要為大家詳細(xì)介紹了windows下python 3.6.4安裝配置圖文教程,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-08-08
  • python設(shè)置環(huán)境變量路徑實(shí)現(xiàn)過程

    python設(shè)置環(huán)境變量路徑實(shí)現(xiàn)過程

    本文介紹設(shè)置Python路徑的多種方法:臨時設(shè)置(Windows用`set`,Linux/macOS用`export`)、永久設(shè)置(系統(tǒng)屬性或shell配置文件)、動態(tài)修改(`sys.path.append`)、虛擬環(huán)境管理路徑,需注意路徑格式與系統(tǒng)一致,并重啟終端生效
    2025-07-07
  • Python-copy()與deepcopy()區(qū)別詳解

    Python-copy()與deepcopy()區(qū)別詳解

    這篇文章主要介紹了Python-copy()與deepcopy()區(qū)別詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-07-07
  • Python操作SQLite簡明教程

    Python操作SQLite簡明教程

    這篇文章主要介紹了Python操作SQLite簡明教程,簡單明了的入門教程,包含連接、建表、增刪修查等例子,需要的朋友可以參考下
    2014-07-07
  • 基于Python爬取京東雙十一商品價格曲線

    基于Python爬取京東雙十一商品價格曲線

    這篇文章主要介紹了基于Python爬取雙十一商品價格曲線,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-10-10

最新評論

五家渠市| 扎赉特旗| 论坛| 银川市| 曲沃县| 东源县| 惠来县| 漯河市| 正定县| 台湾省| 黎城县| 合川市| 平度市| 大厂| 庄河市| 通河县| 靖远县| 富顺县| 邵阳县| 家居| 监利县| 五指山市| 永修县| 平邑县| 贞丰县| 监利县| 青神县| 新河县| 彰武县| 仙游县| 百色市| 邛崃市| 台湾省| 攀枝花市| 通山县| 琼海市| 西林县| 昌平区| 渭南市| 易门县| 成都市|