全屏 单页网站,织梦品牌集团公司网站模板(精),凡科建站app,上海800做网站DAY 44 预训练模型 知识点回顾#xff1a; 预训练的概念常见的分类预训练模型图像预训练模型的发展史预训练的策略预训练代码实战#xff1a;resnet18 作业#xff1a; 尝试在cifar10对比如下其他的预训练模型#xff0c;观察差异#xff0c;尽可能和他人选择的不同尝试通… DAY 44 预训练模型 知识点回顾 预训练的概念常见的分类预训练模型图像预训练模型的发展史预训练的策略预训练代码实战resnet18 作业 尝试在cifar10对比如下其他的预训练模型观察差异尽可能和他人选择的不同尝试通过ctrl进入resnet的内部观察残差究竟是什么 选用 DenseNet121预训练模型注意DenseNet121 模型的最后分类层名为classifier而不是 ResNet 中的fc import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms, models
from torch.utils.data import DataLoader
import matplotlib.pyplot as plt
import os
from torchvision.models import resnet18, densenet121, vgg16# 设置中文字体支持
plt.rcParams[font.family] [SimHei]
plt.rcParams[axes.unicode_minus] False # 解决负号显示问题# 检查GPU是否可用
device torch.device(cuda if torch.cuda.is_available() else cpu)
print(f使用设备: {device})# 1. 数据预处理训练集增强测试集标准化
train_transform transforms.Compose([transforms.RandomCrop(32, padding4),transforms.RandomHorizontalFlip(),transforms.ColorJitter(brightness0.2, contrast0.2, saturation0.2, hue0.1),transforms.RandomRotation(15),transforms.ToTensor(),transforms.Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010))
])test_transform transforms.Compose([transforms.ToTensor(),transforms.Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010))
])# 2. 加载CIFAR-10数据集
train_dataset datasets.CIFAR10(root./cifar_data,trainTrue,downloadTrue,transformtrain_transform
)test_dataset datasets.CIFAR10(root./cifar_data,trainFalse,transformtest_transform
)# 3. 创建数据加载器
batch_size 64
train_loader DataLoader(train_dataset, batch_sizebatch_size, shuffleTrue)
test_loader DataLoader(test_dataset, batch_sizebatch_size, shuffleFalse)# 4. 定义DenseNet121模型
def create_densenet121(pretrainedTrue, num_classes10):model models.densenet121(pretrainedpretrained)# 修改最后一层全连接层in_features model.classifier.in_featuresmodel.classifier nn.Linear(in_features, num_classes) # DenseNet121 的最后一层分类器名称是classifierreturn model.to(device)# 5. 冻结/解冻模型层的函数
# 这种设计允许我们在迁移学习中保留预训练模型的特征提取部分卷积层只训练新添加的分类层全连接层。
def freeze_model(model, freezeTrue):冻结或解冻模型的卷积层参数# 冻结/解冻除fc层外的所有参数for name, param in model.named_parameters():if classifier not in name: #排除名称中包含 fc 的参数这些通常是全连接层的参数param.requires_grad not freeze #param.requires_grad是 PyTorch 中控制参数是否参与反向传播和梯度更新的标志# 打印冻结状态frozen_params sum(p.numel() for p in model.parameters() if not p.requires_grad) #统计所有requires_gradFalse的参数数量total_params sum(p.numel() for p in model.parameters())if freeze:print(f已冻结模型卷积层参数 ({frozen_params}/{total_params} 参数))else:print(f已解冻模型所有参数 ({total_params}/{total_params} 参数可训练))return model# 6. 训练函数支持阶段式训练
def train_with_freeze_schedule(model, train_loader, test_loader, criterion, optimizer, scheduler, device, epochs, freeze_epochs5):前freeze_epochs轮冻结卷积层之后解冻所有层进行训练train_loss_history []test_loss_history []train_acc_history []test_acc_history []all_iter_losses []iter_indices []# 初始冻结卷积层if freeze_epochs 0:model freeze_model(model, freezeTrue)for epoch in range(epochs):# 解冻控制在指定轮次后解冻所有层if epoch freeze_epochs:model freeze_model(model, freezeFalse)# 解冻后调整优化器可选optimizer.param_groups[0][lr] 1e-4 # 降低学习率防止过拟合model.train() # 设置为训练模式running_loss 0.0correct_train 0total_train 0for batch_idx, (data, target) in enumerate(train_loader):data, target data.to(device), target.to(device)optimizer.zero_grad()output model(data)loss criterion(output, target)loss.backward()optimizer.step()# 记录Iteration损失iter_loss loss.item()all_iter_losses.append(iter_loss)iter_indices.append(epoch * len(train_loader) batch_idx 1)# 统计训练指标running_loss iter_loss_, predicted output.max(1)total_train target.size(0)correct_train predicted.eq(target).sum().item()# 每100批次打印进度if (batch_idx 1) % 100 0:print(fEpoch {epoch1}/{epochs} | Batch {batch_idx1}/{len(train_loader)} f| 单Batch损失: {iter_loss:.4f})# 计算 epoch 级指标epoch_train_loss running_loss / len(train_loader)epoch_train_acc 100. * correct_train / total_train# 测试阶段model.eval()correct_test 0total_test 0test_loss 0.0with torch.no_grad():for data, target in test_loader:data, target data.to(device), target.to(device)output model(data)test_loss criterion(output, target).item()_, predicted output.max(1)total_test target.size(0)correct_test predicted.eq(target).sum().item()epoch_test_loss test_loss / len(test_loader)epoch_test_acc 100. * correct_test / total_test# 记录历史数据train_loss_history.append(epoch_train_loss)test_loss_history.append(epoch_test_loss)train_acc_history.append(epoch_train_acc)test_acc_history.append(epoch_test_acc)# 更新学习率调度器if scheduler is not None:scheduler.step(epoch_test_loss)# 打印 epoch 结果print(fEpoch {epoch1} 完成 | 训练损失: {epoch_train_loss:.4f} f| 训练准确率: {epoch_train_acc:.2f}% | 测试准确率: {epoch_test_acc:.2f}%)# 绘制损失和准确率曲线plot_iter_losses(all_iter_losses, iter_indices)plot_epoch_metrics(train_acc_history, test_acc_history, train_loss_history, test_loss_history)return epoch_test_acc # 返回最终测试准确率# 7. 绘制Iteration损失曲线
def plot_iter_losses(losses, indices):plt.figure(figsize(10, 4))plt.plot(indices, losses, b-, alpha0.7)plt.xlabel(IterationBatch序号)plt.ylabel(损失值)plt.title(训练过程中的Iteration损失变化)plt.grid(True)plt.show()# 8. 绘制Epoch级指标曲线
def plot_epoch_metrics(train_acc, test_acc, train_loss, test_loss):epochs range(1, len(train_acc) 1)plt.figure(figsize(12, 5))# 准确率曲线plt.subplot(1, 2, 1)plt.plot(epochs, train_acc, b-, label训练准确率)plt.plot(epochs, test_acc, r-, label测试准确率)plt.xlabel(Epoch)plt.ylabel(准确率 (%))plt.title(准确率随Epoch变化)plt.legend()plt.grid(True)# 损失曲线plt.subplot(1, 2, 2)plt.plot(epochs, train_loss, b-, label训练损失)plt.plot(epochs, test_loss, r-, label测试损失)plt.xlabel(Epoch)plt.ylabel(损失值)plt.title(损失值随Epoch变化)plt.legend()plt.grid(True)plt.tight_layout()plt.show()# 主函数训练模型
def main():# 参数设置epochs 40 # 总训练轮次freeze_epochs 5 # 冻结卷积层的轮次learning_rate 1e-3 # 初始学习率weight_decay 1e-4 # 权重衰减# 创建DenseNet121模型加载预训练权重model create_densenet121(pretrainedTrue, num_classes10)# 定义优化器和损失函数optimizer optim.Adam(model.parameters(), lrlearning_rate, weight_decayweight_decay)criterion nn.CrossEntropyLoss()# 定义学习率调度器scheduler optim.lr_scheduler.ReduceLROnPlateau(optimizer, modemin, factor0.5, patience2, verboseTrue)# 开始训练前5轮冻结卷积层之后解冻final_accuracy train_with_freeze_schedule(modelmodel,train_loadertrain_loader,test_loadertest_loader,criterioncriterion,optimizeroptimizer,schedulerscheduler,devicedevice,epochsepochs,freeze_epochsfreeze_epochs)print(f训练完成最终测试准确率: {final_accuracy:.2f}%)# # 保存模型# torch.save(model.state_dict(), resnet18_cifar10_finetuned.pth)# print(模型已保存至: resnet18_cifar10_finetuned.pth)if __name__ __main__:main()