PyTorch基础详解
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最佳实践
- 使用nn.Module:组织模型结构
- 数据加载器:使用DataLoader管理数据
- GPU加速:充分利用CUDA加速
- 模型保存:定期保存检查点
- 调试技巧:使用print和torch.no_grad()调试
PyTorch是深度学习研究和应用的主流框架,掌握PyTorch对于构建和训练神经网络至关重要。