`import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader
from torchvision.datasets import CIFAR10
from torchvision.transforms import Compose, ToTensor, Normalize
import matplotlib.pyplot as plt
import numpy as np
1. 数据加载与预处理
transform = Compose([
ToTensor(),
Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010)) # CIFAR-10均值和标准差
])
train_dataset = CIFAR10(root='./data', train=True, download=True, transform=transform)
test_dataset = CIFAR10(root='./data', train=False, download=True, transform=transform)
train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=64, shuffle=False)
2. 定义网络模型(CNN)
class CIFAR10Net(nn.Module):
def init(self):
super(CIFAR10Net, self).init()
self.conv1 = nn.Conv2d(3, 32, 3, padding=1)
self.relu1 = nn.ReLU()
self.conv2 = nn.Conv2d(32, 32, 3, padding=1)
self.relu2 = nn.ReLU()
self.pool1 = nn.MaxPool2d(2, 2)
self.drop1 = nn.Dropout(0.25)
self.conv3 = nn.Conv2d(32, 64, 3, padding=1)self.relu3 = nn.ReLU()self.conv4 = nn.Conv2d(64, 64, 3, padding=1)self.relu4 = nn.ReLU()self.pool2 = nn.MaxPool2d(2, 2)self.drop2 = nn.Dropout(0.25)self.flatten = nn.Flatten()self.fc1 = nn.Linear(64 * 8 * 8, 512)self.relu5 = nn.ReLU()self.drop3 = nn.Dropout(0.5)self.fc2 = nn.Linear(512, 10)def forward(self, x):x = self.conv1(x)x = self.relu1(x)x = self.conv2(x)x = self.relu2(x)x = self.pool1(x)x = self.drop1(x)x = self.conv3(x)x = self.relu3(x)x = self.conv4(x)x = self.relu4(x)x = self.pool2(x)x = self.drop2(x)x = self.flatten(x)x = self.fc1(x)x = self.relu5(x)x = self.drop3(x)x = self.fc2(x)return x
model = CIFAR10Net()
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model.to(device)
3. 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
4. 训练网络
epochs = 20
train_acc_history = []
val_acc_history = []
train_loss_history = []
val_loss_history = []
for epoch in range(epochs):
# 训练阶段
model.train()
running_loss = 0.0
correct = 0
total = 0
for inputs, targets in train_loader:
inputs, targets = inputs.to(device), targets.to(device)
optimizer.zero_grad()
outputs = model(inputs)
loss = criterion(outputs, targets)
loss.backward()
optimizer.step()
running_loss += loss.item()_, predicted = outputs.max(1)total += targets.size(0)correct += predicted.eq(targets).sum().item()train_loss = running_loss / len(train_loader)
train_acc = correct / total
train_loss_history.append(train_loss)
train_acc_history.append(train_acc)# 验证阶段
model.eval()
val_loss = 0.0
val_correct = 0
val_total = 0
with torch.no_grad():for inputs, targets in test_loader:inputs, targets = inputs.to(device), targets.to(device)outputs = model(inputs)loss = criterion(outputs, targets)val_loss += loss.item()_, predicted = outputs.max(1)val_total += targets.size(0)val_correct += predicted.eq(targets).sum().item()val_loss = val_loss / len(test_loader)
val_acc = val_correct / val_total
val_loss_history.append(val_loss)
val_acc_history.append(val_acc)print(f'Epoch {epoch+1}/{epochs} | Train Loss: {train_loss:.3f} | Train Acc: {train_acc:.3f} | Val Loss: {val_loss:.3f} | Val Acc: {val_acc:.3f}')
5. 测试模型精度
model.eval()
test_correct = 0
test_total = 0
with torch.no_grad():
for inputs, targets in test_loader:
inputs, targets = inputs.to(device), targets.to(device)
outputs = model(inputs)
_, predicted = outputs.max(1)
test_total += targets.size(0)
test_correct += predicted.eq(targets).sum().item()
test_acc = test_correct / test_total
print(f'测试集准确率: {test_acc:.3f}')
绘制训练曲线
plt.figure(figsize=(12, 4))
plt.subplot(1, 2, 1)
plt.plot(train_acc_history, label='训练准确率')
plt.plot(val_acc_history, label='验证准确率')
plt.legend()
plt.title('准确率变化')
plt.subplot(1, 2, 2)
plt.plot(train_loss_history, label='训练损失')
plt.plot(val_loss_history, label='验证损失')
plt.legend()
plt.title('损失变化')
plt.show()
可视化部分测试结果
class_names = ['飞机', '汽车', '鸟', '猫', '鹿', '狗', '青蛙', '马', '船', '卡车']
model.eval()
with torch.no_grad():
inputs, targets = next(iter(test_loader))
inputs, targets = inputs.to(device), targets.to(device)
outputs = model(inputs)
_, predicted = outputs.max(1)
plt.figure(figsize=(10, 5))
for i in range(10):plt.subplot(2, 5, i+1)img = inputs[i].cpu().numpy().transpose((1, 2, 0))img = img * np.array([0.2023, 0.1994, 0.2010]) + np.array([0.4914, 0.4822, 0.4465]) # 反归一化img = np.clip(img, 0, 1)plt.imshow(img)plt.title(f'预测: {class_names[predicted[i]]}\n真实: {class_names[targets[i]]}')plt.axis('off')
plt.tight_layout()
plt.show()`