← 返回首页
🤖

PyTorch基础详解

📂 ai ⏱ 4 min 798 words

PyTorch基础详解

PyTorch是Facebook开发的深度学习框架,以动态计算图和Pythonic设计著称。

PyTorch基础

张量操作

import torch
import numpy as np
import matplotlib.pyplot as plt

# 创建张量
x = torch.tensor([1, 2, 3, 4, 5])
print(f"一维张量: {x}")
print(f"张量形状: {x.shape}")
print(f"数据类型: {x.dtype}")

# 创建二维张量
y = torch.tensor([[1, 2, 3], [4, 5, 6]])
print(f"\n二维张量:\n{y}")
print(f"张量形状: {y.shape}")

# 创建特殊张量
zeros = torch.zeros(3, 3)
ones = torch.ones(2, 4)
rand_tensor = torch.randn(3, 3)

print(f"\n零张量:\n{zeros}")
print(f"\n随机张量:\n{rand_tensor}")

张量运算

# 基本运算
a = torch.tensor([1, 2, 3, 4])
b = torch.tensor([5, 6, 7, 8])

print(f"加法: {a + b}")
print(f"减法: {a - b}")
print(f"乘法: {a * b}")
print(f"除法: {a / b}")
print(f"幂运算: {a ** 2}")

# 数学函数
print(f"\n平方根: {torch.sqrt(a.float())}")
print(f"指数: {torch.exp(a.float())}")
print(f"对数: {torch.log(a.float())}")
print(f"正弦: {torch.sin(a.float())}")

# 聚合函数
print(f"\n求和: {torch.sum(a)}")
print(f"均值: {torch.mean(a.float())}")
print(f"最大值: {torch.max(a)}")
print(f"最小值: {torch.min(a)}")

自动微分

# 自动微分(Autograd)
x = torch.tensor([2.0, 3.0], requires_grad=True)
y = x ** 2 + 2 * x + 1

print(f"输入 x: {x}")
print(f"输出 y: {y}")

# 反向传播
y.sum().backward()

print(f"梯度 dy/dx: {x.grad}")

神经网络构建

使用nn.Module

import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader, TensorDataset

# 定义神经网络
class SimpleNet(nn.Module):
    def __init__(self, input_size, hidden_size, output_size):
        super(SimpleNet, 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 = SimpleNet(input_size=10, hidden_size=20, output_size=2)
print(f"模型结构:\n{model}")

# 打印模型参数
print(f"\n模型参数:")
for name, param in model.named_parameters():
    print(f"{name}: {param.shape}")

训练循环

# 生成示例数据
np.random.seed(42)
X = np.random.randn(1000, 10).astype(np.float32)
y = np.random.randint(0, 2, 1000)

# 转换为PyTorch张量
X_tensor = torch.FloatTensor(X)
y_tensor = torch.LongTensor(y)

# 划分数据集
X_train, X_test = X_tensor[:800], X_tensor[800:]
y_train, y_test = y_tensor[:800], y_tensor[800:]

# 创建数据加载器
train_dataset = TensorDataset(X_train, y_train)
train_loader = DataLoader(dataset=train_dataset, batch_size=32, shuffle=True)

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

# 训练模型
print("\n训练神经网络:")
for epoch in range(10):
    model.train()
    running_loss = 0.0
    correct = 0
    total = 0
    
    for batch_X, batch_y in train_loader:
        # 前向传播
        outputs = model(batch_X)
        loss = criterion(outputs, batch_y)
        
        # 反向传播和优化
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        
        # 统计
        running_loss += loss.item()
        _, predicted = torch.max(outputs.data, 1)
        total += batch_y.size(0)
        correct += (predicted == batch_y).sum().item()
    
    # 打印统计信息
    train_accuracy = 100 * correct / total
    print(f'Epoch [{epoch+1}/10], Loss: {running_loss/len(train_loader):.4f}, '
          f'训练准确率: {train_accuracy:.2f}%')

# 测试模型
model.eval()
with torch.no_grad():
    test_outputs = model(X_test)
    _, predicted = torch.max(test_outputs.data, 1)
    test_accuracy = 100 * (predicted == y_test).sum().item() / y_test.size(0)
    print(f'\n测试准确率: {test_accuracy:.2f}%')

常用层和模块

卷积层

# 卷积层
conv_layer = nn.Conv2d(in_channels=1, out_channels=16, kernel_size=3, stride=1, padding=1)
print(f"卷积层参数: {conv_layer.weight.shape}")

# 池化层
pool_layer = nn.MaxPool2d(kernel_size=2, stride=2)

# 示例
x = torch.randn(1, 1, 28, 28)  # 批次大小, 通道数, 高度, 宽度
x = conv_layer(x)
print(f"卷积后形状: {x.shape}")
x = pool_layer(x)
print(f"池化后形状: {x.shape}")

循环层

# LSTM层
lstm_layer = nn.LSTM(input_size=10, hidden_size=20, num_layers=2, batch_first=True)
print(f"LSTM参数: {sum(p.numel() for p in lstm_layer.parameters()):,}")

# 示例
x = torch.randn(32, 15, 10)  # 批次大小, 序列长度, 输入特征
output, (h_n, c_n) = lstm_layer(x)
print(f"输出形状: {output.shape}")
print(f"隐藏状态形状: {h_n.shape}")

嵌入层

# 嵌入层
vocab_size = 1000
embed_size = 64
embedding = nn.Embedding(vocab_size, embed_size)
print(f"嵌入层参数: {embedding.weight.shape}")

# 示例
x = torch.randint(0, vocab_size, (32, 20))  # 批次大小, 序列长度
output = embedding(x)
print(f"嵌入后形状: {output.shape}")

保存和加载模型

模型持久化

# 保存模型
torch.save(model.state_dict(), 'model.pth')
print("模型已保存")

# 加载模型
loaded_model = SimpleNet(input_size=10, hidden_size=20, output_size=2)
loaded_model.load_state_dict(torch.load('model.pth'))
loaded_model.eval()
print("模型已加载")

# 验证加载的模型
with torch.no_grad():
    test_output = loaded_model(X_test[:5])
    print(f"加载模型的预测: {test_output}")

完整保存

# 保存完整模型
torch.save({
    'model_state_dict': model.state_dict(),
    'optimizer_state_dict': optimizer.state_dict(),
    'epoch': 10,
    'loss': 0.5,
}, 'checkpoint.pth')

# 加载完整模型
checkpoint = torch.load('checkpoint.pth')
model.load_state_dict(checkpoint['model_state_dict'])
optimizer.load_state_dict(checkpoint['optimizer_state_dict'])
epoch = checkpoint['epoch']
loss = checkpoint['loss']

print(f"加载的epoch: {epoch}")
print(f"加载的损失: {loss}")

GPU加速

CUDA支持

# 检查CUDA是否可用
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"使用设备: {device}")

# 移动模型到GPU
model.to(device)

# 移动数据到GPU
X_train_gpu = X_train.to(device)
y_train_gpu = y_train.to(device)

# 训练(自动使用GPU)
model.train()
for batch_X, batch_y in train_loader:
    batch_X = batch_X.to(device)
    batch_y = batch_y.to(device)
    
    outputs = model(batch_X)
    loss = criterion(outputs, batch_y)
    
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

实际应用

完整的图像分类项目

import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms
from torch.utils.data import DataLoader

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

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

train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=1000, shuffle=False)

# 定义CNN模型
class MNISTNet(nn.Module):
    def __init__(self):
        super(MNISTNet, self).__init__()
        self.conv1 = nn.Conv2d(1, 32, 3, 1)
        self.conv2 = nn.Conv2d(32, 64, 3, 1)
        self.dropout1 = nn.Dropout(0.25)
        self.dropout2 = nn.Dropout(0.5)
        self.fc1 = nn.Linear(9216, 128)
        self.fc2 = nn.Linear(128, 10)
    
    def forward(self, x):
        x = self.conv1(x)
        x = torch.relu(x)
        x = self.conv2(x)
        x = torch.relu(x)
        x = torch.max_pool2d(x, 2)
        x = self.dropout1(x)
        x = torch.flatten(x, 1)
        x = self.fc1(x)
        x = torch.relu(x)
        x = self.dropout2(x)
        x = self.fc2(x)
        return torch.log_softmax(x, dim=1)

# 创建模型
model = MNISTNet().to(device)

# 定义优化器
optimizer = optim.Adam(model.parameters(), lr=0.001)

# 训练函数
def train(model, device, train_loader, optimizer, epoch):
    model.train()
    for batch_idx, (data, target) in enumerate(train_loader):
        data, target = data.to(device), target.to(device)
        optimizer.zero_grad()
        output = model(data)
        loss = nn.functional.nll_loss(output, target)
        loss.backward()
        optimizer.step()
        if batch_idx % 100 == 0:
            print(f'Train Epoch: {epoch} [{batch_idx * len(data)}/{len(train_loader.dataset)} '
                  f'({100. * batch_idx / len(train_loader):.0f}%)]\tLoss: {loss.item():.6f}')

# 测试函数
def test(model, device, test_loader):
    model.eval()
    test_loss = 0
    correct = 0
    with torch.no_grad():
        for data, target in test_loader:
            data, target = data.to(device), target.to(device)
            output = model(data)
            test_loss += nn.functional.nll_loss(output, target, reduction='sum').item()
            pred = output.argmax(dim=1, keepdim=True)
            correct += pred.eq(target.view_as(pred)).sum().item()
    
    test_loss /= len(test_loader.dataset)
    print(f'\nTest set: Average loss: {test_loss:.4f}, '
          f'Accuracy: {correct}/{len(test_loader.dataset)} '
          f'({100. * correct / len(test_loader.dataset):.2f}%)\n')

# 训练模型
print("训练MNIST分类器:")
for epoch in range(1, 6):
    train(model, device, train_loader, optimizer, epoch)
    test(model, device, test_loader)

PyTorch最佳实践

  1. 使用nn.Module:组织模型结构
  2. 数据加载器:使用DataLoader管理数据
  3. GPU加速:充分利用CUDA加速
  4. 模型保存:定期保存检查点
  5. 调试技巧:使用print和torch.no_grad()调试

PyTorch是深度学习研究和应用的主流框架,掌握PyTorch对于构建和训练神经网络至关重要。