从零开始:使用 PyTorch 构建深度学习网络

从零开始:使用 PyTorch 构建深度学习网络

目录

  1. [PyTorch 简介](#PyTorch 简介)
  2. 环境配置
  3. [PyTorch 基础](#PyTorch 基础)
  4. 构建神经网络
  5. 训练模型
  6. 评估与测试
  7. 案例实战:手写数字识别
  8. 进阶技巧
  9. 常见问题解答

PyTorch 简介

PyTorch 是一个开源的深度学习框架,由 Facebook(现在的 Meta)的人工智能研究团队开发。它以其动态计算图和简洁的 API 而受到广泛欢迎,尤其在学术研究领域。与其他深度学习框架相比,PyTorch 的特点是直观、灵活且易于调试。

为什么选择 PyTorch?

  • Python 友好:PyTorch 的设计理念非常符合 Python 的编程风格,如果你熟悉 NumPy,学习 PyTorch 将会非常顺利。
  • 动态计算图:不同于 TensorFlow 1.x 的静态图,PyTorch 使用动态计算图,这意味着你可以在运行时修改网络结构,使调试和实验更加方便。
  • 强大的社区支持:庞大的用户基础和丰富的学习资源。
  • 良好的生态系统:包括计算机视觉(torchvision)、自然语言处理(transformers)、音频处理(torchaudio)等领域的专用库。
  • 现代化 API:PyTorch 2.0+ 提供了编译器优化、更好的性能和更简洁的 API。

环境配置

开始使用 PyTorch 前,需要先配置环境。以下是基本步骤:

安装 PyTorch

推荐使用 Anaconda 或 Miniconda 创建虚拟环境:

bash 复制代码
# 创建虚拟环境
conda create -n pytorch_env python=3.11
# 激活环境
conda activate pytorch_env
# 安装 PyTorch(CPU 版本)
conda install pytorch torchvision torchaudio cpuonly -c pytorch

如果你有 NVIDIA GPU,可以安装支持 CUDA 的版本:

bash 复制代码
# 安装支持 CUDA 的 PyTorch
conda install pytorch torchvision torchaudio pytorch-cuda=12.1 -c pytorch -c nvidia

你也可以使用 pip 安装最新版本:

bash 复制代码
# CPU 版本
pip install torch torchvision torchaudio

# GPU 版本 (CUDA 12.1)
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121

验证安装

创建一个简单的 Python 脚本来验证 PyTorch 是否正确安装:

python 复制代码
import torch

# 打印 PyTorch 版本
print(f"PyTorch 版本: {torch.__version__}")

# 检查 GPU 是否可用
print(f"GPU 是否可用: {torch.cuda.is_available()}")
if torch.cuda.is_available():
    print(f"GPU 名称: {torch.cuda.get_device_name(0)}")
    
# 检查 MPS(适用于 Apple Silicon)
print(f"MPS 是否可用: {getattr(torch, 'has_mps', False)}")

PyTorch 基础

在构建神经网络前,先了解 PyTorch 的核心概念。

张量(Tensor)

张量是 PyTorch 中的基本数据结构,类似于 NumPy 的多维数组,但可以在 GPU 上运行计算。

python 复制代码
import torch

# 创建张量
x = torch.tensor([[1, 2], [3, 4]])
print(x)
print(f"Shape: {x.shape}")
print(f"Data type: {x.dtype}")

# 创建特定类型的张量
x_float = torch.tensor([[1, 2], [3, 4]], dtype=torch.float32)
print(x_float)

# 常用的张量创建函数
zeros = torch.zeros(2, 3)
ones = torch.ones(2, 3)
rand = torch.rand(2, 3)  # 均匀分布 [0,1)
randn = torch.randn(2, 3)  # 标准正态分布

print(f"Zeros:\n{zeros}")
print(f"Ones:\n{ones}")
print(f"Random (uniform):\n{rand}")
print(f"Random (normal):\n{randn}")

张量运算

PyTorch 提供了丰富的张量运算函数:

python 复制代码
import torch

# 创建两个张量
a = torch.tensor([[1, 2], [3, 4]], dtype=torch.float32)
b = torch.tensor([[5, 6], [7, 8]], dtype=torch.float32)

# 基本算术运算
print(f"a + b = \n{a + b}")
print(f"a - b = \n{a - b}")
print(f"a * b = \n{a * b}")  # 元素级乘法
print(f"a / b = \n{a / b}")

# 矩阵乘法
print(f"矩阵乘法 a @ b = \n{a @ b}")
# 或使用 torch.matmul
print(f"torch.matmul(a, b) = \n{torch.matmul(a, b)}")

# 其他常用运算
print(f"Sum: {a.sum()}")
print(f"Mean: {a.mean()}")
print(f"Max: {a.max()}")
print(f"Min: {a.min()}")

自动微分

PyTorch 的核心功能之一是自动计算梯度,这是深度学习训练的基础:

python 复制代码
import torch

# 创建需要梯度的张量
x = torch.tensor([[1., 2.], [3., 4.]], requires_grad=True)
print(x)

# 进行一些操作
y = x * 2
z = y.sum()
print(f"z = {z}")

# 反向传播计算梯度
z.backward()

# 查看 x 的梯度
print(f"梯度 dz/dx = \n{x.grad}")  # 应该全是 2

构建神经网络

PyTorch 提供了 nn 模块,包含构建神经网络所需的各种组件。

线性层与激活函数

最基本的神经网络由线性层和激活函数组成:

python 复制代码
import torch
import torch.nn as nn

# 定义一个简单的全连接层
linear = nn.Linear(in_features=10, out_features=5)

# 创建输入数据(批量大小为3,每个样本有10个特征)
x = torch.randn(3, 10)

# 前向传播
output = linear(x)
print(f"输入形状: {x.shape}")
print(f"输出形状: {output.shape}")

# 激活函数
relu = nn.ReLU()
sigmoid = nn.Sigmoid()
tanh = nn.Tanh()

# 应用激活函数
print(f"ReLU: {relu(output)}")
print(f"Sigmoid: {sigmoid(output)}")
print(f"Tanh: {tanh(output)}")

定义神经网络类

在 PyTorch 中,神经网络通常通过继承 nn.Module 类来定义:

python 复制代码
import torch
import torch.nn as nn

class SimpleNN(nn.Module):
    def __init__(self, input_size, hidden_size, output_size):
        super(SimpleNN, 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

# 创建网络实例
input_size = 10
hidden_size = 20
output_size = 5
model = SimpleNN(input_size, hidden_size, output_size)

# 打印模型结构
print(model)

# 创建一个输入样本
x = torch.randn(1, input_size)
# 前向传播
output = model(x)
print(f"输出: {output}")

使用 PyTorch 2.x 的新特性

PyTorch 2.x 引入了一些强大的新特性,比如 torch.compile,可以显著提高模型性能:

python 复制代码
import torch
import torch.nn as nn

class ModernNN(nn.Module):
    def __init__(self, input_size, hidden_size, output_size):
        super().__init__()
        # 使用 Sequential 简化网络定义
        self.network = nn.Sequential(
            nn.Linear(input_size, hidden_size),
            nn.ReLU(),
            nn.Linear(hidden_size, hidden_size // 2),
            nn.ReLU(),
            nn.Linear(hidden_size // 2, output_size)
        )
    
    def forward(self, x):
        return self.network(x)

# 创建网络实例
model = ModernNN(input_size=10, hidden_size=32, output_size=5)

# 使用 torch.compile 加速模型(PyTorch 2.0+ 新特性)
# 在生产环境运行速度提升可达 2x 或更多
if hasattr(torch, 'compile'):
    model = torch.compile(model)

# 输入数据
x = torch.randn(100, 10)  # 批量大小为100的输入

# 使用 @torch.inference_mode 可以在推理时降低内存使用
@torch.inference_mode()
def predict(model, x):
    return model(x)

# 调用推理函数    
outputs = predict(model, x)
print(f"输出形状: {outputs.shape}")

训练模型

训练神经网络涉及多个步骤:数据准备、定义损失函数、优化器配置和训练循环。

数据加载与预处理

PyTorch 提供了 DatasetDataLoader 类来简化数据处理:

python 复制代码
import torch
from torch.utils.data import Dataset, DataLoader
import numpy as np

# 创建一个简单的数据集类
class SimpleDataset(Dataset):
    def __init__(self, size, input_dim, output_dim):
        # 生成随机数据
        self.x = torch.randn(size, input_dim)
        # 生成随机标签(分类问题)
        self.y = torch.randint(0, output_dim, (size,))
        
    def __len__(self):
        return len(self.x)
    
    def __getitem__(self, idx):
        return self.x[idx], self.y[idx]

# 创建数据集实例
dataset = SimpleDataset(size=1000, input_dim=10, output_dim=5)

# 创建数据加载器
dataloader = DataLoader(dataset, batch_size=32, shuffle=True)

# 查看一个批次的数据
for inputs, labels in dataloader:
    print(f"Inputs shape: {inputs.shape}")
    print(f"Labels shape: {labels.shape}")
    break  # 只查看第一个批次

损失函数与优化器

选择合适的损失函数和优化器对模型训练至关重要:

python 复制代码
import torch
import torch.nn as nn
import torch.optim as optim

# 假设我们已经定义了模型
model = SimpleNN(input_size=10, hidden_size=20, output_size=5)

# 定义损失函数(交叉熵损失,适用于分类问题)
criterion = nn.CrossEntropyLoss()

# 定义优化器(随机梯度下降)
optimizer = optim.SGD(model.parameters(), lr=0.01)

# 其他常用优化器
# Adam 优化器
optimizer_adam = optim.Adam(model.parameters(), lr=0.001)
# RMSprop 优化器
optimizer_rmsprop = optim.RMSprop(model.parameters(), lr=0.001)

训练循环

下面是一个完整的训练循环示例:

python 复制代码
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader

# 假设我们已经定义了模型、数据集和数据加载器
model = SimpleNN(input_size=10, hidden_size=20, output_size=5)
dataloader = DataLoader(dataset, batch_size=32, shuffle=True)

# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)

# 训练参数
num_epochs = 10
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model.to(device)

# 训练循环
for epoch in range(num_epochs):
    running_loss = 0.0
    
    for inputs, labels in dataloader:
        # 将数据移到设备(CPU/GPU)
        inputs, labels = inputs.to(device), labels.to(device)
        
        # 清零梯度
        optimizer.zero_grad()
        
        # 前向传播
        outputs = model(inputs)
        
        # 计算损失
        loss = criterion(outputs, labels)
        
        # 反向传播
        loss.backward()
        
        # 更新参数
        optimizer.step()
        
        # 累加损失
        running_loss += loss.item()
    
    # 打印每个 epoch 的平均损失
    epoch_loss = running_loss / len(dataloader)
    print(f"Epoch {epoch+1}/{num_epochs}, Loss: {epoch_loss:.4f}")

print("训练完成!")

评估与测试

训练后,需要评估模型在测试数据上的性能:

python 复制代码
import torch

# 切换到评估模式
model.eval()

# 创建测试数据集和数据加载器
test_dataset = SimpleDataset(size=200, input_dim=10, output_dim=5)
test_loader = DataLoader(test_dataset, batch_size=32)

# 在测试数据上评估
correct = 0
total = 0

# 不计算梯度
with torch.no_grad():
    for inputs, labels in test_loader:
        inputs, labels = inputs.to(device), labels.to(device)
        
        # 前向传播
        outputs = model(inputs)
        
        # 获取预测结果
        _, predicted = torch.max(outputs.data, 1)
        
        # 统计正确预测的数量
        total += labels.size(0)
        correct += (predicted == labels).sum().item()

# 计算准确率
accuracy = 100 * correct / total
print(f"测试集准确率: {accuracy:.2f}%")

# 返回训练模式
model.train()

案例实战:手写数字识别

下面将使用 MNIST 数据集实现一个完整的手写数字识别模型,并应用 PyTorch 的现代特性。

导入必要的库

python 复制代码
import torch
import torch.nn as nn
import torch.optim as optim
import torchvision
import torchvision.transforms as transforms
from torch.utils.data import DataLoader
import torch.nn.functional as F
from torch.cuda.amp import GradScaler, autocast  # 用于混合精度训练

准备数据

python 复制代码
# 数据预处理
transform = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize((0.1307,), (0.3081,))
])

# 下载 MNIST 数据集
train_dataset = torchvision.datasets.MNIST(
    root='./data', 
    train=True, 
    transform=transform,
    download=True
)

test_dataset = torchvision.datasets.MNIST(
    root='./data', 
    train=False, 
    transform=transform,
    download=True
)

# 创建数据加载器,使用新的 PyTorch 2.x 的 persistent workers 特性提高数据加载效率
train_loader = DataLoader(
    train_dataset, 
    batch_size=128,  # 更大的批次大小
    shuffle=True,
    num_workers=4,  # 多进程加载
    persistent_workers=True,  # 保持工作进程活跃,减少启动开销
    pin_memory=True  # 使用固定内存提高GPU传输速度
)

test_loader = DataLoader(
    test_dataset, 
    batch_size=1000, 
    shuffle=False,
    num_workers=4,
    persistent_workers=True,
    pin_memory=True
)

定义现代化的 CNN 模型

python 复制代码
class ModernMNISTModel(nn.Module):
    def __init__(self):
        super().__init__()
        # 使用更现代的网络架构
        self.features = nn.Sequential(
            nn.Conv2d(1, 32, kernel_size=3, padding=1),
            nn.BatchNorm2d(32),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=2, stride=2),
            
            nn.Conv2d(32, 64, kernel_size=3, padding=1),
            nn.BatchNorm2d(64),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=2, stride=2),
            
            nn.Conv2d(64, 128, kernel_size=3, padding=1),
            nn.BatchNorm2d(128),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=2, stride=2, padding=1)  # 确保尺寸正确
        )
        
        self.classifier = nn.Sequential(
            nn.AdaptiveAvgPool2d((1, 1)),  # 自适应池化到固定尺寸
            nn.Flatten(),
            nn.Linear(128, 64),
            nn.ReLU(inplace=True),
            nn.Dropout(0.5),
            nn.Linear(64, 10)
        )
    
    def forward(self, x):
        x = self.features(x)
        x = self.classifier(x)
        return x

# 创建模型实例
model = ModernMNISTModel()

# 使用 torch.compile 编译模型(PyTorch 2.0+)
if hasattr(torch, 'compile'):
    model = torch.compile(model)

训练与评估完整流程(带混合精度训练)

python 复制代码
# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = optim.AdamW(model.parameters(), lr=0.001, weight_decay=1e-4)  # 使用 AdamW 替代 Adam
scheduler = torch.optim.lr_scheduler.OneCycleLR(  # 使用 OneCycleLR 调度器
    optimizer, 
    max_lr=0.005, 
    epochs=10, 
    steps_per_epoch=len(train_loader)
)

# 设备配置
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model.to(device)

# 混合精度训练
scaler = GradScaler()

# 训练参数
num_epochs = 10

# 训练循环
for epoch in range(num_epochs):
    model.train()  # 设置为训练模式
    running_loss = 0.0
    
    for i, (images, labels) in enumerate(train_loader):
        images, labels = images.to(device), labels.to(device)
        
        # 清零梯度
        optimizer.zero_grad()
        
        # 使用混合精度训练
        with autocast():
            # 前向传播
            outputs = model(images)
            loss = criterion(outputs, labels)
        
        # 反向传播和优化
        scaler.scale(loss).backward()
        scaler.step(optimizer)
        scaler.update()
        
        # 更新学习率
        scheduler.step()
        
        running_loss += loss.item()
        
        # 每100批次打印统计信息
        if (i+1) % 100 == 0:
            print(f'Epoch [{epoch+1}/{num_epochs}], Step [{i+1}/{len(train_loader)}], Loss: {loss.item():.4f}, LR: {scheduler.get_last_lr()[0]:.6f}')
    
    # 测试模型
    model.eval()  # 设置为评估模式
    with torch.no_grad():
        correct = 0
        total = 0
        for images, labels in test_loader:
            images, labels = images.to(device), labels.to(device)
            
            # 使用 torch.inference_mode() 优化推理
            with torch.inference_mode():
                outputs = model(images)
                _, predicted = torch.max(outputs.data, 1)
            
            total += labels.size(0)
            correct += (predicted == labels).sum().item()
        
        print(f'Epoch [{epoch+1}/{num_epochs}], 测试准确率: {100 * correct / total:.2f}%')

# 保存模型
torch.save({
    'model_state_dict': model.state_dict(),
    'optimizer_state_dict': optimizer.state_dict(),
    'epoch': num_epochs
}, 'mnist_model_modern.pth')

print("模型已保存!")

# 测试推理性能
import time

model.eval()
test_images, test_labels = next(iter(test_loader))
test_images = test_images.to(device)

# 预热
with torch.inference_mode():
    for _ in range(10):
        _ = model(test_images[:10])

# 计时
start_time = time.time()
with torch.inference_mode():
    for _ in range(50):
        _ = model(test_images)
end_time = time.time()

print(f"推理性能: {50 * len(test_images) / (end_time - start_time):.2f} 图像/秒")

进阶技巧

掌握了基础知识后,这里介绍一些提高模型性能的进阶技巧和 PyTorch 的现代特性。

学习率调整

随着训练的进行,适当调整学习率可以帮助模型更好地收敛:

python 复制代码
from torch.optim.lr_scheduler import StepLR, ReduceLROnPlateau, CosineAnnealingLR

# 每10个 epoch 将学习率乘以 gamma
scheduler = StepLR(optimizer, step_size=10, gamma=0.1)

# 当验证损失不再下降时减小学习率
scheduler = ReduceLROnPlateau(optimizer, mode='min', factor=0.1, patience=5)

# 余弦退火学习率(在深度学习中表现优异)
scheduler = CosineAnnealingLR(optimizer, T_max=10)

# 在训练循环中使用
for epoch in range(num_epochs):
    # 训练代码...
    
    # 更新学习率(取决于scheduler类型)
    if isinstance(scheduler, ReduceLROnPlateau):
        scheduler.step(val_loss)
    else:
        scheduler.step()

早停法(Early Stopping)

当模型在验证集上的性能不再提升时,停止训练可以防止过拟合:

python 复制代码
best_val_loss = float('inf')
patience = 5
counter = 0
best_model_path = 'best_model.pth'

for epoch in range(num_epochs):
    # 训练代码...
    
    # 计算验证损失
    val_loss = validate(model, val_loader, criterion)
    
    # 更新最佳损失和检查早停
    if val_loss < best_val_loss:
        best_val_loss = val_loss
        counter = 0
        # 保存最佳模型
        torch.save({
            'model_state_dict': model.state_dict(),
            'optimizer_state_dict': optimizer.state_dict(),
            'epoch': epoch,
            'loss': val_loss,
        }, best_model_path)
        print(f"保存最佳模型,验证损失: {val_loss:.4f}")
    else:
        counter += 1
        if counter >= patience:
            print(f"Early stopping at epoch {epoch+1}")
            break

使用预训练模型与迁移学习

对于复杂任务,使用预训练模型可以大幅提高性能,PyTorch 2.x 提供了更简洁的 API:

python 复制代码
import torch
import torchvision.models as models

# 使用新的 API 加载预训练模型
# weights 参数代替了旧的 pretrained=True
resnet = models.resnet50(weights=models.ResNet50_Weights.IMAGENET1K_V2)

# 冻结预训练层
for param in resnet.parameters():
    param.requires_grad = False

# 替换最后的全连接层,适应新任务
num_features = resnet.fc.in_features
resnet.fc = torch.nn.Linear(num_features, num_classes)  # 只训练这一层

# 也可以使用 HuggingFace 获取最新的预训练模型
# pip install transformers
from transformers import AutoImageProcessor, AutoModelForImageClassification

# 加载预训练的视觉模型
processor = AutoImageProcessor.from_pretrained("microsoft/resnet-50")
model = AutoModelForImageClassification.from_pretrained("microsoft/resnet-50")

# 加载并预处理图像
from PIL import Image
import requests

url = "http://images.cocodataset.org/val2017/000000039769.jpg"
image = Image.open(requests.get(url, stream=True).raw)
inputs = processor(images=image, return_tensors="pt")

# 使用模型进行推理
with torch.no_grad():
    outputs = model(**inputs)
    logits = outputs.logits

# 获取预测结果
predicted_class_idx = logits.argmax(-1).item()
print("预测类别:", model.config.id2label[predicted_class_idx])

PyTorch 2.x 的模型加速与部署

PyTorch 2.x 提供了多种模型优化和部署技术:

使用 TorchScript 和 torch.compile
python 复制代码
import torch

# 定义模型
model = YourModel()
model.eval()

# 使用 torch.compile 加速(PyTorch 2.0+)
optimized_model = torch.compile(
    model, 
    mode='reduce-overhead',  # 可选模式: 'default', 'reduce-overhead', 'max-autotune'
    fullgraph=True
)

# 或使用 TorchScript 导出模型
example_input = torch.randn(1, 3, 224, 224)
scripted_model = torch.jit.script(model)
# 或 traced_model = torch.jit.trace(model, example_input)

# 保存模型用于部署
scripted_model.save("model_scripted.pt")
量化模型以减小尺寸和加速推理
python 复制代码
import torch.quantization

# 准备量化
model.eval()
model.qconfig = torch.quantization.get_default_qconfig('fbgemm')
torch.quantization.prepare(model, inplace=True)

# 校准模型(需要代表性数据)
with torch.no_grad():
    for data, _ in calibration_dataloader:
        model(data)

# 转换到量化模型
torch.quantization.convert(model, inplace=True)

# 保存量化模型
torch.jit.save(torch.jit.script(model), "quantized_model.pt")
分布式训练

PyTorch 提供了多种分布式训练方法,包括数据并行和模型并行:

python 复制代码
import torch.distributed as dist
import torch.multiprocessing as mp
from torch.nn.parallel import DistributedDataParallel as DDP

def setup(rank, world_size):
    # 初始化进程组
    dist.init_process_group("nccl", rank=rank, world_size=world_size)

def train(rank, world_size):
    setup(rank, world_size)
    
    # 创建模型
    model = YourModel().to(rank)
    # 将模型包装为分布式模型
    ddp_model = DDP(model, device_ids=[rank])
    
    # 数据加载器需要修改为分布式
    sampler = torch.utils.data.distributed.DistributedSampler(
        dataset,
        num_replicas=world_size,
        rank=rank
    )
    dataloader = DataLoader(dataset, sampler=sampler, ...)
    
    # 训练循环
    for epoch in range(num_epochs):
        sampler.set_epoch(epoch)  # 确保不同进程看到不同数据
        for data, target in dataloader:
            # 常规训练步骤
            ...

# 启动多进程训练
world_size = torch.cuda.device_count()
mp.spawn(train, args=(world_size,), nprocs=world_size, join=True)

使用现代 PyTorch 特性进行移动设备部署

PyTorch 提供了 TorchMobile 功能,可以将模型部署到移动设备:

python 复制代码
import torch

# 准备模型
model = YourModel()
model.eval()

# 转换为 TorchScript
example_input = torch.rand(1, 3, 224, 224)
traced_model = torch.jit.trace(model, example_input)

# 优化移动设备部署
traced_model_optimized = torch.utils.mobile_optimizer.optimize_for_mobile(traced_model)

# 保存为移动格式
traced_model_optimized.save("model_mobile.pt")

# 可以进一步转换为适用于更多平台的格式,如 ONNX
torch.onnx.export(
    model,
    example_input,
    "model.onnx",
    export_params=True,
    opset_version=12,
    do_constant_folding=True,
    input_names=['input'],
    output_names=['output'],
    dynamic_axes={
        'input': {0: 'batch_size'},
        'output': {0: 'batch_size'}
    }
)

常见问题解答

如何处理过拟合?

过拟合是指模型在训练数据上表现良好,但在测试数据上表现不佳。解决方法包括:

  1. 增加数据量:更多样本通常会降低过拟合风险
  2. 数据增强:通过旋转、缩放等变换增加训练数据的多样性
  3. 正则化:使用 L1、L2 正则化或 Dropout
  4. 简化模型:减少模型的复杂度(层数或参数数量)

示例代码(添加 Dropout 和 权重衰减):

python 复制代码
# 添加 Dropout
self.dropout = nn.Dropout(0.5)  # 在网络中间层添加

# 添加权重衰减(L2正则化)
optimizer = optim.Adam(model.parameters(), lr=0.001, weight_decay=1e-4)

GPU 内存不足怎么办?

当模型或数据集过大,GPU 内存不足时:

  1. 减小批量大小:这是最直接的方法
  2. 使用梯度累积:累积多个小批量的梯度后再更新参数
  3. 混合精度训练:使用 float16 代替 float32 进行部分计算

梯度累积示例:

python 复制代码
accumulation_steps = 4  # 累积4个批次
optimizer.zero_grad()

for i, (inputs, labels) in enumerate(dataloader):
    outputs = model(inputs)
    loss = criterion(outputs, labels) / accumulation_steps  # 缩小损失
    loss.backward()
    
    if (i + 1) % accumulation_steps == 0:
        optimizer.step()
        optimizer.zero_grad()

如何解决梯度消失/爆炸问题?

  1. 使用 ReLU 等现代激活函数:避免 Sigmoid 和 Tanh 在饱和区的梯度消失
  2. 批量归一化(Batch Normalization):稳定各层的输入分布
  3. 梯度裁剪:防止梯度爆炸
  4. 合理的权重初始化:如 Xavier 或 He 初始化

梯度裁剪示例:

python 复制代码
torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0)

以上就是 PyTorch 深度学习入门的完整指南。

相关推荐
zeroporn2 分钟前
分别用 语言模型雏形N-Gram 和 文本表示BoW词袋 来实现文本情绪分类
人工智能·语言模型·分类·大模型·n-gram·词袋
云卓SKYDROID18 分钟前
无人机减震模块运行与技术要点分析!
人工智能·无人机·科普·高科技·减震系统
山北雨夜漫步30 分钟前
机器学习 Day18 Support Vector Machine ——最优美的机器学习算法
人工智能·算法·机器学习
正在走向自律33 分钟前
从0到1吃透卷积神经网络(CNN):原理与实战全解析
人工智能·神经网络·cnn
拓端研究室TRL36 分钟前
Python+AI提示词糖尿病预测融合模型:伯努利朴素贝叶斯、逻辑回归、决策树、随机森林、支持向量机SVM应用
人工智能·python·决策树·随机森林·逻辑回归
何双新1 小时前
第8讲、Multi-Head Attention 的核心机制与实现细节
人工智能·transformer
moongoblin1 小时前
协作赋能-1-制造业生产流程重构
大数据·人工智能·经验分享·制造
穿越光年1 小时前
MCP实战:在扣子空间用扣子工作流MCP,一句话生成儿童故事rap视频
人工智能·音视频
Johny_Zhao1 小时前
AI+自动化测试系统方案:网络设备与网络应用智能测试
linux·网络·人工智能·python·网络安全·docker·ai·信息安全·云计算·ansible·shell·cisco·huawei·系统运维·itsm·华三·deepseek
Quieeeet1 小时前
【搭建Node-RED + MQTT Broker实现AI大模型交互】
人工智能·物联网·交互