Day44 Python打卡训练营
知识点回顾:
1. 预训练的概念
2. 常见的分类预训练模型
3. 图像预训练模型的发展史
4. 预训练的策略
5. 预训练代码实战:resnet18
作业:
1. 尝试在cifar10对比如下其他的预训练模型,观察差异,尽可能和他人选择的不同
2. 尝试通过ctrl进入resnet的内部,观察残差究竟是什么
一、预训练的概念
我们之前在训练中发现,准确率最开始随着epoch的增加而增加。随着循环的更新,参数在不断发生更新。
所以参数的初始值对训练结果有很大的影响:
- 如果最开始的初始值比较好,后续训练轮数就会少很多
- 很有可能陷入局部最优值,不同的初始值可能导致陷入不同的局部最优值
所以很自然的想到,如果最开始能有比较好的参数,即可能导致未来训练次数少,也可能导致未来训练避免陷入局部最优解的问题。这就引入了一个概念,即预训练模型。
如果别人在某些和我们目标数据类似的大规模数据集上做过训练,我们可以用他的训练参数来初始化我们的模型,这样我们的模型就比较容易收敛。
为了帮助你们理解,这里提出几个自问自答的问题。
- 那为什么要选择类似任务的数据集预训练的模型参数呢?
因为任务差不多,他提取特征的能力才有用,如果任务相差太大,他的特征提取能力就没那么好。 所以本质预训练就是拿别人已经具备的通用特征提取能力来接着强化能力使之更加适应我们的数据集和任务。
- 为什么要求预训练模型是在大规模数据集上训练的,小规模不行么? 因为提取的是通用特征,所以如果数据集数据少、尺寸小,就很难支撑复杂任务学习通用的数据特征。比如你是一个物理的博士,让你去做小学数学题,很快就能上手;但是你是一个小学数学速算高手,让你做物理博士的课题,就很困难。所以预训练模型一般就挺强的。
我们把用预训练模型的参数,然后接着在自己数据集上训练来调整该参数的过程叫做微调,这种思想叫做迁移学习。把预训练的过程叫做上游任务,把微调的过程叫做下游任务。
现在再来看下之前一直用的cifar10数据集,他是不是就很明显不适合作为预训练数据集?
- 规模过小:仅 10 万张图像,且尺寸小(32x32),无法支撑复杂模型学习通用视觉特征;
- 类别单一:仅 10 类(飞机、汽车等),泛化能力有限;
二、 经典的预训练模型
2.1 CNN架构预训练模型
2.2 Transformer类预训练模型
适用于较大尺图像(如224x224),在CIFAR10上需上采样图像尺寸或调整Patch大小。
2.3 自监督预训练模型
无需人工标注,通过 pretext task(如掩码图像重建)学习特征,适合数据稀缺场景。
三、常见的分类预训练模型介绍
3.1 预训练模型的发展史
上图的层数,代表该模型不同的版本resnet有resnet18、resnet50、resnet152;efficientnet有efficientnet-b0、efficientnet-b1、efficientnet-b2、efficientnet-b3、efficientnet-b4等
其中ImageNet Top - 5 准确率是图像分类任务里的一种评估指标 ,用于衡量模型在 ImageNet 数据集上的分类性能,模型对图像进行分类预测,输出所有类别(共 1000 类 )的概率,取概率排名前五的类别,只要这五个类别里包含人工标注的正确类别,就算预测正确。
模型架构演进关键点总结
- 深度突破:从LeNet的7层到ResNet152的152层,残差连接解决了深度网络的训练难题。 ----没上过我复试班cv部分的自行去了解下什么叫做残差连接,很重要!
- 计算效率:GoogLeNet(Inception)和MobileNet通过结构优化,在保持精度的同时大幅降低参数量。
-
预训练模型使用建议
- 特征复用:DenseNet的密集连接设计使模型能更好地利用浅层特征,适合小数据集。
- 自动化设计:EfficientNet使用神经架构搜索(NAS)自动寻找最优网络配置,开创了AutoML在CNN中的应用。
这些模型的预训练权重均可通过主流框架(如PyTorch的
torchvision.models
、Keras的applications
模块)直接加载,便于快速迁移到新任务。总结:CNN 架构发展脉络
- 早期探索(1990s-2010s):LeNet 验证 CNN 可行性,但受限于计算和数据。
- 深度学习复兴(2012-2015):AlexNet、VGGNet、GoogLeNet 通过加深网络和结构创新突破性能。
- 超深网络时代(2015 年后):ResNet 解决退化问题,开启残差连接范式,后续模型围绕效率(MobileNet)、特征复用(DenseNet)、多分支结构(Inception)等方向优化。
-
3.1 预训练模型的训练策略
那么什么模型会被选为预训练模型呢?比如一些调参后表现很好的cnn神经网络(固定的神经元个数+固定的层数等)。
所以调用预训练模型做微调,本质就是 用这些固定的结构+之前训练好的参数 接着训练
所以需要找到预训练的模型结构并且加载模型参数
相较于之前用自己定义的模型有以下几个注意点
- 需要调用预训练模型和加载权重
- 需要resize 图片让其可以适配模型
- 需要修改最后的全连接层以适应数据集
-
其中,训练过程中,为了不破坏最开始的特征提取器的参数,最开始往往先冻结住特征提取器的参数,然后训练全连接层,大约在5-10个epoch后解冻训练。
主要做特征提取的部分叫做backbone骨干网络;负责融合提取的特征的部分叫做Featue Pyramid Network(FPN);负责输出的预测部分的叫做Head。
首先复用下之前的代码
import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pyplot as plt# 设置中文字体支持 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, padding=4),transforms.RandomHorizontalFlip(),transforms.ColorJitter(brightness=0.2, contrast=0.2, saturation=0.2, hue=0.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='./data',train=True,download=True,transform=train_transform )test_dataset = datasets.CIFAR10(root='./data',train=False,transform=test_transform )# 3. 创建数据加载器(可调整batch_size) batch_size = 64 train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True) test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False)# 4. 训练函数(支持学习率调度器) def train(model, train_loader, test_loader, criterion, optimizer, scheduler, device, epochs):model.train() # 设置为训练模式train_loss_history = []test_loss_history = []train_acc_history = []test_acc_history = []all_iter_losses = []iter_indices = []for epoch in range(epochs):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(f"Epoch {epoch+1}/{epochs} | Batch {batch_idx+1}/{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(f"Epoch {epoch+1} 完成 | 训练损失: {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 # 返回最终测试准确率# 5. 绘制Iteration损失曲线 def plot_iter_losses(losses, indices):plt.figure(figsize=(10, 4))plt.plot(indices, losses, 'b-', alpha=0.7)plt.xlabel('Iteration(Batch序号)')plt.ylabel('损失值')plt.title('训练过程中的Iteration损失变化')plt.grid(True)plt.show()# 6. 绘制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()
使用设备: cuda Files already downloaded and verified
# 导入ResNet模型 from torchvision.models import resnet18# 定义ResNet18模型(支持预训练权重加载) def create_resnet18(pretrained=True, num_classes=10):# 加载预训练模型(ImageNet权重)model = resnet18(pretrained=pretrained)# 修改最后一层全连接层,适配CIFAR-10的10分类任务in_features = model.fc.in_featuresmodel.fc = nn.Linear(in_features, num_classes)# 将模型转移到指定设备(CPU/GPU)model = model.to(device)return model # 创建ResNet18模型(加载ImageNet预训练权重,不进行微调) model = create_resnet18(pretrained=True, num_classes=10) model.eval() # 设置为推理模式# 测试单张图片(示例) from torchvision import utils# 从测试数据集中获取一张图片 dataiter = iter(test_loader) images, labels = dataiter.next() images = images[:1].to(device) # 取第1张图片# 前向传播 with torch.no_grad():outputs = model(images)_, predicted = torch.max(outputs.data, 1)# 显示图片和预测结果 plt.imshow(utils.make_grid(images.cpu(), normalize=True).permute(1, 2, 0)) plt.title(f"预测类别: {predicted.item()}") plt.axis('off') plt.show()
-
在 CIFAR-10 数据集 中,类别标签是固定的 10 个,分别对应:
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# 设置中文字体支持 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, padding=4),transforms.RandomHorizontalFlip(),transforms.ColorJitter(brightness=0.2, contrast=0.2, saturation=0.2, hue=0.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='./data',train=True,download=True,transform=train_transform )test_dataset = datasets.CIFAR10(root='./data',train=False,transform=test_transform )# 3. 创建数据加载器 batch_size = 64 train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True) test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False)# 4. 定义ResNet18模型 def create_resnet18(pretrained=True, num_classes=10):model = models.resnet18(pretrained=pretrained)# 修改最后一层全连接层in_features = model.fc.in_featuresmodel.fc = nn.Linear(in_features, num_classes)return model.to(device)# 5. 冻结/解冻模型层的函数 def freeze_model(model, freeze=True):"""冻结或解冻模型的卷积层参数"""# 冻结/解冻除fc层外的所有参数for name, param in model.named_parameters():if 'fc' not in name:param.requires_grad = not freeze# 打印冻结状态frozen_params = sum(p.numel() for p in model.parameters() if not p.requires_grad)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_epochs=5):"""前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, freeze=True)for epoch in range(epochs):# 解冻控制:在指定轮次后解冻所有层if epoch == freeze_epochs:model = freeze_model(model, freeze=False)# 解冻后调整优化器(可选)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(f"Epoch {epoch+1}/{epochs} | Batch {batch_idx+1}/{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(f"Epoch {epoch+1} 完成 | 训练损失: {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-', alpha=0.7)plt.xlabel('Iteration(Batch序号)')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 # 权重衰减# 创建ResNet18模型(加载预训练权重)model = create_resnet18(pretrained=True, num_classes=10)# 定义优化器和损失函数optimizer = optim.Adam(model.parameters(), lr=learning_rate, weight_decay=weight_decay)criterion = nn.CrossEntropyLoss()# 定义学习率调度器scheduler = optim.lr_scheduler.ReduceLROnPlateau(optimizer, mode='min', factor=0.5, patience=2, verbose=True)# 开始训练(前5轮冻结卷积层,之后解冻)final_accuracy = train_with_freeze_schedule(model=model,train_loader=train_loader,test_loader=test_loader,criterion=criterion,optimizer=optimizer,scheduler=scheduler,device=device,epochs=epochs,freeze_epochs=freeze_epochs)print(f"训练完成!最终测试准确率: {final_accuracy:.2f}%")# # 保存模型# torch.save(model.state_dict(), 'resnet18_cifar10_finetuned.pth')# print("模型已保存至: resnet18_cifar10_finetuned.pth")if __name__ == "__main__":main()
使用设备: cuda Files already downloaded and verified 已冻结模型卷积层参数 (11176512/11181642 参数) Epoch 1/40 | Batch 100/782 | 单Batch损失: 2.2746 Epoch 1/40 | Batch 200/782 | 单Batch损失: 2.0283 Epoch 1/40 | Batch 300/782 | 单Batch损失: 1.7735 Epoch 1/40 | Batch 400/782 | 单Batch损失: 1.9917 Epoch 1/40 | Batch 500/782 | 单Batch损失: 1.6662 Epoch 1/40 | Batch 600/782 | 单Batch损失: 1.8309 Epoch 1/40 | Batch 700/782 | 单Batch损失: 1.7485 Epoch 1 完成 | 训练损失: 1.9633 | 训练准确率: 29.96% | 测试准确率: 32.28% Epoch 2/40 | Batch 100/782 | 单Batch损失: 1.9622 Epoch 2/40 | Batch 200/782 | 单Batch损失: 1.9096 Epoch 2/40 | Batch 300/782 | 单Batch损失: 1.9117 Epoch 2/40 | Batch 400/782 | 单Batch损失: 1.6654 Epoch 2/40 | Batch 500/782 | 单Batch损失: 1.8214 Epoch 2/40 | Batch 600/782 | 单Batch损失: 2.0345 Epoch 2/40 | Batch 700/782 | 单Batch损失: 2.1190 Epoch 2 完成 | 训练损失: 1.8675 | 训练准确率: 33.81% | 测试准确率: 32.79% Epoch 3/40 | Batch 100/782 | 单Batch损失: 1.7294 Epoch 3/40 | Batch 200/782 | 单Batch损失: 1.8884 Epoch 3/40 | Batch 300/782 | 单Batch损失: 2.0095 Epoch 3/40 | Batch 400/782 | 单Batch损失: 1.7234 Epoch 3/40 | Batch 500/782 | 单Batch损失: 1.8481 Epoch 3/40 | Batch 600/782 | 单Batch损失: 1.8441 Epoch 3/40 | Batch 700/782 | 单Batch损失: 2.0066 Epoch 3 完成 | 训练损失: 1.8540 | 训练准确率: 34.40% | 测试准确率: 34.65% Epoch 4/40 | Batch 100/782 | 单Batch损失: 1.9432 Epoch 4/40 | Batch 200/782 | 单Batch损失: 1.6196 Epoch 4/40 | Batch 300/782 | 单Batch损失: 1.7874 Epoch 4/40 | Batch 400/782 | 单Batch损失: 1.8416 Epoch 4/40 | Batch 500/782 | 单Batch损失: 1.9233 Epoch 4/40 | Batch 600/782 | 单Batch损失: 1.7665 Epoch 4/40 | Batch 700/782 | 单Batch损失: 1.9478 Epoch 4 完成 | 训练损失: 1.8512 | 训练准确率: 34.39% | 测试准确率: 34.35% Epoch 5/40 | Batch 100/782 | 单Batch损失: 2.0171 Epoch 5/40 | Batch 200/782 | 单Batch损失: 1.7849 Epoch 5/40 | Batch 300/782 | 单Batch损失: 1.8292 Epoch 5/40 | Batch 400/782 | 单Batch损失: 1.9803 Epoch 5/40 | Batch 500/782 | 单Batch损失: 1.6365 Epoch 5/40 | Batch 600/782 | 单Batch损失: 1.9088 Epoch 5/40 | Batch 700/782 | 单Batch损失: 1.8456 Epoch 5 完成 | 训练损失: 1.8486 | 训练准确率: 34.38% | 测试准确率: 34.29% 已解冻模型所有参数 (11181642/11181642 参数可训练) Epoch 6/40 | Batch 100/782 | 单Batch损失: 1.4501 Epoch 6/40 | Batch 200/782 | 单Batch损失: 0.9866 Epoch 6/40 | Batch 300/782 | 单Batch损失: 1.3025 Epoch 6/40 | Batch 400/782 | 单Batch损失: 1.1481 Epoch 6/40 | Batch 500/782 | 单Batch损失: 1.2977 Epoch 6/40 | Batch 600/782 | 单Batch损失: 1.1055 Epoch 6/40 | Batch 700/782 | 单Batch损失: 1.0491 Epoch 6 完成 | 训练损失: 1.2998 | 训练准确率: 54.22% | 测试准确率: 67.23% Epoch 7/40 | Batch 100/782 | 单Batch损失: 1.1548 Epoch 7/40 | Batch 200/782 | 单Batch损失: 0.9465 Epoch 7/40 | Batch 300/782 | 单Batch损失: 0.9650 Epoch 7/40 | Batch 400/782 | 单Batch损失: 0.6820 Epoch 7/40 | Batch 500/782 | 单Batch损失: 0.8018 Epoch 7/40 | Batch 600/782 | 单Batch损失: 0.9235 Epoch 7/40 | Batch 700/782 | 单Batch损失: 0.9785 Epoch 7 完成 | 训练损失: 0.9831 | 训练准确率: 65.82% | 测试准确率: 73.35% Epoch 8/40 | Batch 100/782 | 单Batch损失: 1.0422 Epoch 8/40 | Batch 200/782 | 单Batch损失: 0.8977 Epoch 8/40 | Batch 300/782 | 单Batch损失: 0.9675 Epoch 8/40 | Batch 400/782 | 单Batch损失: 0.7166 Epoch 8/40 | Batch 500/782 | 单Batch损失: 0.8461 Epoch 8/40 | Batch 600/782 | 单Batch损失: 0.9074 Epoch 8/40 | Batch 700/782 | 单Batch损失: 0.6013 Epoch 8 完成 | 训练损失: 0.8601 | 训练准确率: 69.97% | 测试准确率: 76.02% Epoch 9/40 | Batch 100/782 | 单Batch损失: 0.7530 Epoch 9/40 | Batch 200/782 | 单Batch损失: 1.2476 Epoch 9/40 | Batch 300/782 | 单Batch损失: 0.8363 Epoch 9/40 | Batch 400/782 | 单Batch损失: 0.7913 Epoch 9/40 | Batch 500/782 | 单Batch损失: 0.5406 Epoch 9/40 | Batch 600/782 | 单Batch损失: 0.8790 Epoch 9/40 | Batch 700/782 | 单Batch损失: 0.8013 Epoch 9 完成 | 训练损失: 0.7942 | 训练准确率: 72.51% | 测试准确率: 78.50% Epoch 10/40 | Batch 100/782 | 单Batch损失: 0.6242 Epoch 10/40 | Batch 200/782 | 单Batch损失: 0.7985 Epoch 10/40 | Batch 300/782 | 单Batch损失: 0.8187 Epoch 10/40 | Batch 400/782 | 单Batch损失: 0.8442 Epoch 10/40 | Batch 500/782 | 单Batch损失: 0.7636 Epoch 10/40 | Batch 600/782 | 单Batch损失: 0.6356 Epoch 10/40 | Batch 700/782 | 单Batch损失: 0.7811 Epoch 10 完成 | 训练损失: 0.7466 | 训练准确率: 74.18% | 测试准确率: 80.30% Epoch 11/40 | Batch 100/782 | 单Batch损失: 0.5778 Epoch 11/40 | Batch 200/782 | 单Batch损失: 0.6424 Epoch 11/40 | Batch 300/782 | 单Batch损失: 0.6740 Epoch 11/40 | Batch 400/782 | 单Batch损失: 0.6944 Epoch 11/40 | Batch 500/782 | 单Batch损失: 0.8197 Epoch 11/40 | Batch 600/782 | 单Batch损失: 0.7754 Epoch 11/40 | Batch 700/782 | 单Batch损失: 0.6164 Epoch 11 完成 | 训练损失: 0.7096 | 训练准确率: 75.35% | 测试准确率: 80.29% Epoch 12/40 | Batch 100/782 | 单Batch损失: 0.6795 Epoch 12/40 | Batch 200/782 | 单Batch损失: 0.5132 Epoch 12/40 | Batch 300/782 | 单Batch损失: 0.5526 Epoch 12/40 | Batch 400/782 | 单Batch损失: 0.5981 Epoch 12/40 | Batch 500/782 | 单Batch损失: 0.6312 Epoch 12/40 | Batch 600/782 | 单Batch损失: 0.5807 Epoch 12/40 | Batch 700/782 | 单Batch损失: 0.8097 Epoch 12 完成 | 训练损失: 0.6747 | 训练准确率: 76.43% | 测试准确率: 80.95% Epoch 13/40 | Batch 100/782 | 单Batch损失: 0.5757 Epoch 13/40 | Batch 200/782 | 单Batch损失: 0.5791 Epoch 13/40 | Batch 300/782 | 单Batch损失: 0.5037 Epoch 13/40 | Batch 400/782 | 单Batch损失: 0.7592 Epoch 13/40 | Batch 500/782 | 单Batch损失: 0.8742 Epoch 13/40 | Batch 600/782 | 单Batch损失: 0.7225 Epoch 13/40 | Batch 700/782 | 单Batch损失: 0.6084 Epoch 13 完成 | 训练损失: 0.6451 | 训练准确率: 77.64% | 测试准确率: 81.31% Epoch 14/40 | Batch 100/782 | 单Batch损失: 0.6919 Epoch 14/40 | Batch 200/782 | 单Batch损失: 0.5774 Epoch 14/40 | Batch 300/782 | 单Batch损失: 0.5386 Epoch 14/40 | Batch 400/782 | 单Batch损失: 0.7253 Epoch 14/40 | Batch 500/782 | 单Batch损失: 0.4620 Epoch 14/40 | Batch 600/782 | 单Batch损失: 0.6363 Epoch 14/40 | Batch 700/782 | 单Batch损失: 0.4766 Epoch 14 完成 | 训练损失: 0.6262 | 训练准确率: 78.27% | 测试准确率: 81.57% Epoch 15/40 | Batch 100/782 | 单Batch损失: 0.5209 Epoch 15/40 | Batch 200/782 | 单Batch损失: 0.7623 Epoch 15/40 | Batch 300/782 | 单Batch损失: 0.5972 Epoch 15/40 | Batch 400/782 | 单Batch损失: 0.5153 Epoch 15/40 | Batch 500/782 | 单Batch损失: 0.4694 Epoch 15/40 | Batch 600/782 | 单Batch损失: 0.6652 Epoch 15/40 | Batch 700/782 | 单Batch损失: 0.8098 Epoch 15 完成 | 训练损失: 0.6035 | 训练准确率: 78.94% | 测试准确率: 82.69% Epoch 16/40 | Batch 100/782 | 单Batch损失: 0.3695 Epoch 16/40 | Batch 200/782 | 单Batch损失: 0.5164 Epoch 16/40 | Batch 300/782 | 单Batch损失: 0.4680 Epoch 16/40 | Batch 400/782 | 单Batch损失: 0.7711 Epoch 16/40 | Batch 500/782 | 单Batch损失: 0.5883 Epoch 16/40 | Batch 600/782 | 单Batch损失: 0.3142 Epoch 16/40 | Batch 700/782 | 单Batch损失: 0.5261 Epoch 16 完成 | 训练损失: 0.5852 | 训练准确率: 79.62% | 测试准确率: 82.86% Epoch 17/40 | Batch 100/782 | 单Batch损失: 0.6548 Epoch 17/40 | Batch 200/782 | 单Batch损失: 0.8322 Epoch 17/40 | Batch 300/782 | 单Batch损失: 0.5157 Epoch 17/40 | Batch 400/782 | 单Batch损失: 0.4902 Epoch 17/40 | Batch 500/782 | 单Batch损失: 0.9218 Epoch 17/40 | Batch 600/782 | 单Batch损失: 0.6169 Epoch 17/40 | Batch 700/782 | 单Batch损失: 0.3676 Epoch 17 完成 | 训练损失: 0.5620 | 训练准确率: 80.46% | 测试准确率: 83.46% Epoch 18/40 | Batch 100/782 | 单Batch损失: 0.5617 Epoch 18/40 | Batch 200/782 | 单Batch损失: 0.5368 Epoch 18/40 | Batch 300/782 | 单Batch损失: 0.3711 Epoch 18/40 | Batch 400/782 | 单Batch损失: 0.6305 Epoch 18/40 | Batch 500/782 | 单Batch损失: 0.8022 Epoch 18/40 | Batch 600/782 | 单Batch损失: 0.3864 Epoch 18/40 | Batch 700/782 | 单Batch损失: 0.3906 Epoch 18 完成 | 训练损失: 0.5511 | 训练准确率: 80.82% | 测试准确率: 83.58% Epoch 19/40 | Batch 100/782 | 单Batch损失: 0.5529 Epoch 19/40 | Batch 200/782 | 单Batch损失: 0.5140 Epoch 19/40 | Batch 300/782 | 单Batch损失: 0.5248 Epoch 19/40 | Batch 400/782 | 单Batch损失: 0.5481 Epoch 19/40 | Batch 500/782 | 单Batch损失: 0.5130 Epoch 19/40 | Batch 600/782 | 单Batch损失: 0.5096 Epoch 19/40 | Batch 700/782 | 单Batch损失: 0.4920 Epoch 19 完成 | 训练损失: 0.5346 | 训练准确率: 81.38% | 测试准确率: 83.39% Epoch 20/40 | Batch 100/782 | 单Batch损失: 0.4986 Epoch 20/40 | Batch 200/782 | 单Batch损失: 0.4441 Epoch 20/40 | Batch 300/782 | 单Batch损失: 0.5545 Epoch 20/40 | Batch 400/782 | 单Batch损失: 0.6198 Epoch 20/40 | Batch 500/782 | 单Batch损失: 0.6450 Epoch 20/40 | Batch 600/782 | 单Batch损失: 0.7414 Epoch 20/40 | Batch 700/782 | 单Batch损失: 0.5779 Epoch 20 完成 | 训练损失: 0.5207 | 训练准确率: 81.76% | 测试准确率: 83.81% Epoch 21/40 | Batch 100/782 | 单Batch损失: 0.6586 Epoch 21/40 | Batch 200/782 | 单Batch损失: 0.4860 Epoch 21/40 | Batch 300/782 | 单Batch损失: 0.6694 Epoch 21/40 | Batch 400/782 | 单Batch损失: 0.7057 Epoch 21/40 | Batch 500/782 | 单Batch损失: 0.5195 Epoch 21/40 | Batch 600/782 | 单Batch损失: 0.6519 Epoch 21/40 | Batch 700/782 | 单Batch损失: 0.4956 Epoch 21 完成 | 训练损失: 0.5018 | 训练准确率: 82.49% | 测试准确率: 83.52% Epoch 22/40 | Batch 100/782 | 单Batch损失: 0.6390 Epoch 22/40 | Batch 200/782 | 单Batch损失: 0.4532 Epoch 22/40 | Batch 300/782 | 单Batch损失: 0.4574 Epoch 22/40 | Batch 400/782 | 单Batch损失: 0.7280 Epoch 22/40 | Batch 500/782 | 单Batch损失: 0.5452 Epoch 22/40 | Batch 600/782 | 单Batch损失: 0.5946 Epoch 22/40 | Batch 700/782 | 单Batch损失: 0.5525 Epoch 22 完成 | 训练损失: 0.4916 | 训练准确率: 82.60% | 测试准确率: 84.31% Epoch 23/40 | Batch 100/782 | 单Batch损失: 0.4012 Epoch 23/40 | Batch 200/782 | 单Batch损失: 0.3825 Epoch 23/40 | Batch 300/782 | 单Batch损失: 0.4821 Epoch 23/40 | Batch 400/782 | 单Batch损失: 0.4401 Epoch 23/40 | Batch 500/782 | 单Batch损失: 0.4588 Epoch 23/40 | Batch 600/782 | 单Batch损失: 0.4711 Epoch 23/40 | Batch 700/782 | 单Batch损失: 0.6688 Epoch 23 完成 | 训练损失: 0.4769 | 训练准确率: 83.42% | 测试准确率: 84.67% Epoch 24/40 | Batch 100/782 | 单Batch损失: 0.3449 Epoch 24/40 | Batch 200/782 | 单Batch损失: 0.5792 Epoch 24/40 | Batch 300/782 | 单Batch损失: 0.4305 Epoch 24/40 | Batch 400/782 | 单Batch损失: 0.3993 Epoch 24/40 | Batch 500/782 | 单Batch损失: 0.3771 Epoch 24/40 | Batch 600/782 | 单Batch损失: 0.4710 Epoch 24/40 | Batch 700/782 | 单Batch损失: 0.3654 Epoch 24 完成 | 训练损失: 0.4715 | 训练准确率: 83.58% | 测试准确率: 84.01% Epoch 25/40 | Batch 100/782 | 单Batch损失: 0.4161 Epoch 25/40 | Batch 200/782 | 单Batch损失: 0.4130 Epoch 25/40 | Batch 300/782 | 单Batch损失: 0.3507 Epoch 25/40 | Batch 400/782 | 单Batch损失: 0.5175 Epoch 25/40 | Batch 500/782 | 单Batch损失: 0.3962 Epoch 25/40 | Batch 600/782 | 单Batch损失: 0.5365 Epoch 25/40 | Batch 700/782 | 单Batch损失: 0.5413 Epoch 25 完成 | 训练损失: 0.4591 | 训练准确率: 83.95% | 测试准确率: 84.44% Epoch 26/40 | Batch 100/782 | 单Batch损失: 0.4219 Epoch 26/40 | Batch 200/782 | 单Batch损失: 0.4298 Epoch 26/40 | Batch 300/782 | 单Batch损失: 0.3857 Epoch 26/40 | Batch 400/782 | 单Batch损失: 0.4982 Epoch 26/40 | Batch 500/782 | 单Batch损失: 0.5355 Epoch 26/40 | Batch 600/782 | 单Batch损失: 0.3574 Epoch 26/40 | Batch 700/782 | 单Batch损失: 0.3226 Epoch 26 完成 | 训练损失: 0.4541 | 训练准确率: 83.97% | 测试准确率: 84.71% Epoch 27/40 | Batch 100/782 | 单Batch损失: 0.3924 Epoch 27/40 | Batch 200/782 | 单Batch损失: 0.4315 Epoch 27/40 | Batch 300/782 | 单Batch损失: 0.3559 Epoch 27/40 | Batch 400/782 | 单Batch损失: 0.6344 Epoch 27/40 | Batch 500/782 | 单Batch损失: 0.3476 Epoch 27/40 | Batch 600/782 | 单Batch损失: 0.3715 Epoch 27/40 | Batch 700/782 | 单Batch损失: 0.5282 Epoch 27 完成 | 训练损失: 0.4372 | 训练准确率: 84.86% | 测试准确率: 84.43% Epoch 28/40 | Batch 100/782 | 单Batch损失: 0.5050 Epoch 28/40 | Batch 200/782 | 单Batch损失: 0.4678 Epoch 28/40 | Batch 300/782 | 单Batch损失: 0.4039 Epoch 28/40 | Batch 400/782 | 单Batch损失: 0.4929 Epoch 28/40 | Batch 500/782 | 单Batch损失: 0.4750 Epoch 28/40 | Batch 600/782 | 单Batch损失: 0.5359 Epoch 28/40 | Batch 700/782 | 单Batch损失: 0.5022 Epoch 28 完成 | 训练损失: 0.4326 | 训练准确率: 84.84% | 测试准确率: 84.66% Epoch 29/40 | Batch 100/782 | 单Batch损失: 0.3526 Epoch 29/40 | Batch 200/782 | 单Batch损失: 0.3220 Epoch 29/40 | Batch 300/782 | 单Batch损失: 0.4290 Epoch 29/40 | Batch 400/782 | 单Batch损失: 0.3962 Epoch 29/40 | Batch 500/782 | 单Batch损失: 0.5649 Epoch 29/40 | Batch 600/782 | 单Batch损失: 0.4467 Epoch 29/40 | Batch 700/782 | 单Batch损失: 0.4557 Epoch 29: reducing learning rate of group 0 to 5.0000e-05. Epoch 29 完成 | 训练损失: 0.4220 | 训练准确率: 85.19% | 测试准确率: 85.04% Epoch 30/40 | Batch 100/782 | 单Batch损失: 0.4535 Epoch 30/40 | Batch 200/782 | 单Batch损失: 0.3584 Epoch 30/40 | Batch 300/782 | 单Batch损失: 0.5184 Epoch 30/40 | Batch 400/782 | 单Batch损失: 0.3496 Epoch 30/40 | Batch 500/782 | 单Batch损失: 0.3999 Epoch 30/40 | Batch 600/782 | 单Batch损失: 0.6774 Epoch 30/40 | Batch 700/782 | 单Batch损失: 0.4407 Epoch 30 完成 | 训练损失: 0.3837 | 训练准确率: 86.47% | 测试准确率: 85.75% Epoch 31/40 | Batch 100/782 | 单Batch损失: 0.3535 Epoch 31/40 | Batch 200/782 | 单Batch损失: 0.1690 Epoch 31/40 | Batch 300/782 | 单Batch损失: 0.2427 Epoch 31/40 | Batch 400/782 | 单Batch损失: 0.2824 Epoch 31/40 | Batch 500/782 | 单Batch损失: 0.3223 Epoch 31/40 | Batch 600/782 | 单Batch损失: 0.3366 Epoch 31/40 | Batch 700/782 | 单Batch损失: 0.3447 Epoch 31 完成 | 训练损失: 0.3608 | 训练准确率: 87.33% | 测试准确率: 85.59% Epoch 32/40 | Batch 100/782 | 单Batch损失: 0.3180 Epoch 32/40 | Batch 200/782 | 单Batch损失: 0.3460 Epoch 32/40 | Batch 300/782 | 单Batch损失: 0.2582 Epoch 32/40 | Batch 400/782 | 单Batch损失: 0.3221 Epoch 32/40 | Batch 500/782 | 单Batch损失: 0.3611 Epoch 32/40 | Batch 600/782 | 单Batch损失: 0.3356 Epoch 32/40 | Batch 700/782 | 单Batch损失: 0.2092 Epoch 32 完成 | 训练损失: 0.3546 | 训练准确率: 87.42% | 测试准确率: 86.22% Epoch 33/40 | Batch 100/782 | 单Batch损失: 0.2492 Epoch 33/40 | Batch 200/782 | 单Batch损失: 0.6831 Epoch 33/40 | Batch 300/782 | 单Batch损失: 0.3228 Epoch 33/40 | Batch 400/782 | 单Batch损失: 0.3360 Epoch 33/40 | Batch 500/782 | 单Batch损失: 0.4186 Epoch 33/40 | Batch 600/782 | 单Batch损失: 0.4582 Epoch 33/40 | Batch 700/782 | 单Batch损失: 0.2431 Epoch 33 完成 | 训练损失: 0.3448 | 训练准确率: 87.80% | 测试准确率: 86.03% Epoch 34/40 | Batch 100/782 | 单Batch损失: 0.3151 Epoch 34/40 | Batch 200/782 | 单Batch损失: 0.3402 Epoch 34/40 | Batch 300/782 | 单Batch损失: 0.3575 Epoch 34/40 | Batch 400/782 | 单Batch损失: 0.4508 Epoch 34/40 | Batch 500/782 | 单Batch损失: 0.3518 Epoch 34/40 | Batch 600/782 | 单Batch损失: 0.2904 Epoch 34/40 | Batch 700/782 | 单Batch损失: 0.4845 Epoch 34 完成 | 训练损失: 0.3363 | 训练准确率: 88.06% | 测试准确率: 86.03% Epoch 35/40 | Batch 100/782 | 单Batch损失: 0.3098 Epoch 35/40 | Batch 200/782 | 单Batch损失: 0.4241 Epoch 35/40 | Batch 300/782 | 单Batch损失: 0.2464 Epoch 35/40 | Batch 400/782 | 单Batch损失: 0.2701 Epoch 35/40 | Batch 500/782 | 单Batch损失: 0.4191 Epoch 35/40 | Batch 600/782 | 单Batch损失: 0.3869 Epoch 35/40 | Batch 700/782 | 单Batch损失: 0.3189 Epoch 35 完成 | 训练损失: 0.3301 | 训练准确率: 88.38% | 测试准确率: 85.86% Epoch 36/40 | Batch 100/782 | 单Batch损失: 0.3671 Epoch 36/40 | Batch 200/782 | 单Batch损失: 0.2216 Epoch 36/40 | Batch 300/782 | 单Batch损失: 0.1238 Epoch 36/40 | Batch 400/782 | 单Batch损失: 0.2974 Epoch 36/40 | Batch 500/782 | 单Batch损失: 0.2941 Epoch 36/40 | Batch 600/782 | 单Batch损失: 0.4725 Epoch 36/40 | Batch 700/782 | 单Batch损失: 0.2895 Epoch 36: reducing learning rate of group 0 to 2.5000e-05. Epoch 36 完成 | 训练损失: 0.3219 | 训练准确率: 88.55% | 测试准确率: 85.69% Epoch 37/40 | Batch 100/782 | 单Batch损失: 0.2448 Epoch 37/40 | Batch 200/782 | 单Batch损失: 0.1732 Epoch 37/40 | Batch 300/782 | 单Batch损失: 0.2051 Epoch 37/40 | Batch 400/782 | 单Batch损失: 0.2676 Epoch 37/40 | Batch 500/782 | 单Batch损失: 0.4176 Epoch 37/40 | Batch 600/782 | 单Batch损失: 0.3213 Epoch 37/40 | Batch 700/782 | 单Batch损失: 0.2074 Epoch 37 完成 | 训练损失: 0.2986 | 训练准确率: 89.29% | 测试准确率: 85.93% Epoch 38/40 | Batch 100/782 | 单Batch损失: 0.2360 Epoch 38/40 | Batch 200/782 | 单Batch损失: 0.1479 Epoch 38/40 | Batch 300/782 | 单Batch损失: 0.3533 Epoch 38/40 | Batch 400/782 | 单Batch损失: 0.5048 Epoch 38/40 | Batch 500/782 | 单Batch损失: 0.1659 Epoch 38/40 | Batch 600/782 | 单Batch损失: 0.3273 Epoch 38/40 | Batch 700/782 | 单Batch损失: 0.2075 Epoch 38 完成 | 训练损失: 0.2927 | 训练准确率: 89.52% | 测试准确率: 86.18% Epoch 39/40 | Batch 100/782 | 单Batch损失: 0.2367 Epoch 39/40 | Batch 200/782 | 单Batch损失: 0.2999 Epoch 39/40 | Batch 300/782 | 单Batch损失: 0.1458 Epoch 39/40 | Batch 400/782 | 单Batch损失: 0.2884 Epoch 39/40 | Batch 500/782 | 单Batch损失: 0.3936 Epoch 39/40 | Batch 600/782 | 单Batch损失: 0.1809 Epoch 39/40 | Batch 700/782 | 单Batch损失: 0.3922 Epoch 39: reducing learning rate of group 0 to 1.2500e-05. Epoch 39 完成 | 训练损失: 0.2861 | 训练准确率: 89.81% | 测试准确率: 86.32% Epoch 40/40 | Batch 100/782 | 单Batch损失: 0.2916 Epoch 40/40 | Batch 200/782 | 单Batch损失: 0.2238 Epoch 40/40 | Batch 300/782 | 单Batch损失: 0.2087 Epoch 40/40 | Batch 400/782 | 单Batch损失: 0.1997 Epoch 40/40 | Batch 500/782 | 单Batch损失: 0.3312 Epoch 40/40 | Batch 600/782 | 单Batch损失: 0.4169 Epoch 40/40 | Batch 700/782 | 单Batch损失: 0.1733 Epoch 40 完成 | 训练损失: 0.2713 | 训练准确率: 90.29% | 测试准确率: 86.30%
训练完成!最终测试准确率: 86.30%
几个明显的现象
- 解冻后几个epoch即可达到之前cnn训练20轮的效果,这是预训练的优势
- 由于训练集用了 RandomCrop(随机裁剪)、RandomHorizontalFlip(随机水平翻转)、ColorJitter(颜色抖动)等数据增强操作,这会让训练时模型看到的图片有更多 “干扰” 或变形。比如一张汽车图片,训练时可能被裁剪成只显示局部、颜色也有变化,模型学习难度更高;而测试集是标准的、没增强的图片,模型预测相对轻松,就可能出现训练集准确率暂时低于测试集的情况,尤其在训练前期增强对模型影响更明显。随着训练推进,模型适应增强后会缓解。
- 最后收敛后的效果超过非预训练模型的80%,大幅提升
- @浙大疏锦行