知识点回顾:
- 传统计算机视觉发展史:LeNet-->AlexNet-->VGGNet-->nceptionNet-->ResNet
之所以说传统,是因为现在主要是针对backbone-neck-head这样的范式做文章
- inception模块和网络
- 特征融合方法阶段性总结:逐元素相加、逐元素相乘、concat通道数增加等
- 感受野与卷积核变体:深入理解不同模块和类的设计初衷
作业:一次稍微有点学术感觉的作业:
- 对inception网络在cifar10上观察精度
- 消融实验:引入残差机制和cbam模块分别进行消融
# 训练函数(语义化重构)
def train_model(network, train_loader, test_loader, loss_func, optimizer, lr_scheduler, device, num_epochs):"""模型训练与评估流程参数:network: 待训练的神经网络train_loader: 训练数据加载器test_loader: 测试数据加载器loss_func: 损失函数optimizer: 优化器lr_scheduler: 学习率调度器device: 计算设备num_epochs: 训练轮数返回:最终测试准确率"""network.train() # 设置训练模式# 初始化指标记录batch_loss_history = [] # 每个batch的损失记录batch_index_history = [] # batch索引记录train_accuracy_history = [] # 每轮训练准确率test_accuracy_history = [] # 每轮测试准确率train_loss_history = [] # 每轮训练损失test_loss_history = [] # 每轮测试损失for epoch in range(num_epochs):epoch_loss = 0.0 # 当前轮次累计损失correct_predictions = 0 # 正确预测数total_samples = 0 # 总样本数# 训练阶段for batch_index, (inputs, labels) in enumerate(train_loader):inputs, labels = inputs.to(device), labels.to(device)# 前向传播与损失计算optimizer.zero_grad()predictions = network(inputs)batch_loss = loss_func(predictions, labels)# 反向传播与参数更新batch_loss.backward()optimizer.step()# 记录损失指标current_loss = batch_loss.item()batch_loss_history.append(current_loss)batch_index_history.append(epoch * len(train_loader) + batch_index + 1)# 统计训练准确率epoch_loss += current_loss_, predicted_labels = predictions.max(1)total_samples += labels.size(0)correct_predictions += predicted_labels.eq(labels).sum().item()# 每100个batch输出进度if (batch_index + 1) % 100 == 0:avg_loss = epoch_loss / (batch_index + 1)print(f'轮次 [{epoch+1}/{num_epochs}] | 批次 [{batch_index+1}/{len(train_loader)}] 'f'| 当前损失: {current_loss:.4f} | 平均损失: {avg_loss:.4f}')# 计算本轮训练指标avg_epoch_loss = epoch_loss / len(train_loader)epoch_train_acc = 100. * correct_predictions / total_samplestrain_accuracy_history.append(epoch_train_acc)train_loss_history.append(avg_epoch_loss)# 评估阶段network.eval() # 设置评估模式test_loss = 0.0correct_test = 0total_test = 0with torch.no_grad(): # 禁用梯度计算for inputs, labels in test_loader:inputs, labels = inputs.to(device), labels.to(device)predictions = network(inputs)test_loss += loss_func(predictions, labels).item()# 统计测试准确率_, predicted = predictions.max(1)total_test += labels.size(0)correct_test += predicted.eq(labels).sum().item()# 计算本轮测试指标avg_test_loss = test_loss / len(test_loader)epoch_test_acc = 100. * correct_test / total_testtest_accuracy_history.append(epoch_test_acc)test_loss_history.append(avg_test_loss)# 更新学习率lr_scheduler.step(avg_test_loss)# 输出本轮结果print(f'轮次 [{epoch+1}/{num_epochs}] 完成 | 'f'训练准确率: {epoch_train_acc:.2f}% | 'f'测试准确率: {epoch_test_acc:.2f}%')# 可视化训练过程visualize_batch_losses(batch_loss_history, batch_index_history)visualize_epoch_metrics(train_accuracy_history, test_accuracy_history, train_loss_history, test_loss_history)return test_accuracy_history[-1] # 返回最终测试准确率# CIFAR-10 类别标签
class_labels = ('飞机', '汽车', '鸟类', '猫咪', '鹿', '狗', '青蛙', '马', '船只', '卡车')# 训练过程可视化函数
def visualize_batch_losses(loss_values, batch_indices):"""绘制每个训练批次的损失变化曲线参数:loss_values: 每个batch的损失值列表batch_indices: 对应的batch索引列表"""plt.figure(figsize=(10, 4))plt.plot(batch_indices, loss_values, 'b-', alpha=0.7, label='批次损失')plt.xlabel('批次序号')plt.ylabel('损失值')plt.title('训练过程中每个批次的损失变化')plt.legend()plt.grid(True)plt.tight_layout()plt.show()def visualize_epoch_metrics(train_acc_history, test_acc_history, train_loss_history, test_loss_history):"""绘制每轮次训练/测试的准确率和损失曲线参数:train_acc_history: 训练准确率历史test_acc_history: 测试准确率历史train_loss_history: 训练损失历史test_loss_history: 测试损失历史"""epochs = range(1, len(train_acc_history) + 1)plt.figure(figsize=(12, 4))# 准确率曲线plt.subplot(1, 2, 1)plt.plot(epochs, train_acc_history, 'b-', label='训练准确率')plt.plot(epochs, test_acc_history, 'r-', label='测试准确率')plt.xlabel('训练轮次
@浙大疏锦行