2026/5/20 22:53:11
网站建设
项目流程
网站佣金怎么做分录,做网站的工作怎么样,魏县审批建设的网站,搜索引擎优化的基本原理1. 核心挑战在深度学习实践中#xff0c;我们经常遇到这样的问题#xff1a;如何优化一个已经训练好的模型#xff08;如ResNet18#xff09;#xff1f;直接修改模型结构#xff08;如插入注意力模块#xff09;是否会破坏原有的特征提取能力#xff1f;如何制定训练策…1. 核心挑战在深度学习实践中我们经常遇到这样的问题如何优化一个已经训练好的模型如ResNet18直接修改模型结构如插入注意力模块是否会破坏原有的特征提取能力如何制定训练策略既能利用预训练权重又能让新插入的模块快速学习2. 为什么可以将CBAM插入预训练模型通常认为修改预训练模型的结构会导致权重失效。但在 ResNet 中插入 CBAM 模块是可行的核心原因在于 CBAM 的初始化特性初始状态接近“直通”CBAM 模块的最终输出计算公式为Output Input * Sigmoid(Attention)。在初始化阶段卷积层和全连接层的权重接近于 0导致 Attention 图的值也接近 0。由于Sigmoid(0) 0.5因此在训练初期CBAM 模块的操作近似于Input * 0.5。保留特征结构Input * 0.5仅仅是对特征数值的线性缩放完整保留了特征图的空间结构和相对关系。这保证了下游的预训练层接收到的输入仍然是结构完好的特征而不是混乱的噪声。因此我们可以将 CBAM “无缝注入”到预训练 ResNet 中而不破坏其核心能力。3. 模型架构ResNet18 CBAM我们将 CBAM 模块插入到 ResNet18 的每一个layer残差块组之后。3.1 代码实现import torch import torch.nn as nn from torchvision import models class ResNet18_CBAM(nn.Module): def __init__(self, num_classes10, pretrainedTrue, cbam_ratio16, cbam_kernel7): super().__init__() # 1. 加载预训练ResNet18 self.backbone models.resnet18(pretrainedpretrained) # 2. 修改首层卷积以适应 CIFAR-10 的小尺寸输入 (32x32) # 原版 ResNet 针对 ImageNet (224x224)首层卷积核大且步长为2会导致小图特征丢失 self.backbone.conv1 nn.Conv2d( in_channels3, out_channels64, kernel_size3, stride1, padding1, biasFalse ) self.backbone.maxpool nn.Identity() # 移除 MaxPool 层保留更多空间信息 # 3. 在每个残差块组后添加 CBAM 模块 self.cbam_layer1 CBAM(in_channels64, ratiocbam_ratio, kernel_sizecbam_kernel) self.cbam_layer2 CBAM(in_channels128, ratiocbam_ratio, kernel_sizecbam_kernel) self.cbam_layer3 CBAM(in_channels256, ratiocbam_ratio, kernel_sizecbam_kernel) self.cbam_layer4 CBAM(in_channels512, ratiocbam_ratio, kernel_sizecbam_kernel) # 4. 修改分类头 self.backbone.fc nn.Linear(in_features512, out_featuresnum_classes) def forward(self, x): # Stem 层 x self.backbone.conv1(x) x self.backbone.bn1(x) x self.backbone.relu(x) # Layer 1 CBAM x self.backbone.layer1(x) x self.cbam_layer1(x) # Layer 2 CBAM x self.backbone.layer2(x) x self.cbam_layer2(x) # Layer 3 CBAM x self.backbone.layer3(x) x self.cbam_layer3(x) # Layer 4 CBAM x self.backbone.layer4(x) x self.cbam_layer4(x) # 分类头 x self.backbone.avgpool(x) x torch.flatten(x, 1) x self.backbone.fc(x) return x4. 训练策略三阶段渐进式微调为了平衡“保留预训练知识”和“学习新模块”的需求我们采用了差异化学习率和分阶段解冻的策略。可以将模型看作一个公司团队预训练层ResNet资深专家经验丰富只需微调。新模块CBAM/FC新入职实习生一张白纸需要快速学习。4.1 阶段一预热实习生 (Epoch 1-5)解冻对象仅CBAM模块和分类头 (fc)。冻结对象所有 ResNet 主干层。学习率1e-3(高学习率)。目标让新模块快速学习如何配合预训练特征工作建立初步的分类边界和注意力机制。4.2 阶段二唤醒高层专家 (Epoch 6-20)解冻对象增加解冻layer3和layer4高层卷积。冻结对象conv1,layer1,layer2底层卷积保持冻结。学习率1e-4(中等学习率)。原理高层网络学习“构图和概念”如车轮、猫脸与具体任务强相关需要重新适应 CIFAR-10。而底层网络学习“笔触和纹理”如边缘、颜色是通用的暂时不需要变动。4.3 阶段三全员协同微调 (Epoch 21-50)解冻对象所有层。学习率1e-5(低学习率)。目标进行端到端的全局微调让底层特征也做微小的调整以完美适配新任务。5. 核心训练代码实现上述策略的关键函数def set_trainable_layers(model, trainable_parts): print(f\n--- 解冻以下部分并设为可训练: {trainable_parts}) for name, param in model.named_parameters(): param.requires_grad False # 先默认全冻结 for part in trainable_parts: if part in name: # 如果参数名包含指定部分则解冻 param.requires_grad True break def train_staged_finetuning(model, criterion, train_loader, test_loader, device, epochs): # ... (省略初始化代码) for epoch in range(1, epochs 1): # --- 动态调整策略 --- if epoch 1: print(阶段 1训练注意力模块和分类头) set_trainable_layers(model, [cbam, backbone.fc]) # 只优化 requires_gradTrue 的参数 optimizer optim.Adam(filter(lambda p: p.requires_grad, model.parameters()), lr1e-3) elif epoch 6: print(阶段 2解冻高层卷积层) set_trainable_layers(model, [cbam, backbone.fc, backbone.layer3, backbone.layer4]) optimizer optim.Adam(filter(lambda p: p.requires_grad, model.parameters()), lr1e-4) elif epoch 21: print(阶段 3全局微调) for param in model.parameters(): param.requires_grad True optimizer optim.Adam(model.parameters(), lr1e-5) # ... (后续标准训练与测试循环)6. 实验结果通过这种精细的训练策略模型在 CIFAR-10 数据集上最终达到了90.15%的测试准确率。这证明了CBAM 能够有效增强特征提取能力。分阶段微调策略能够有效防止预训练权重的破坏同时让新模块充分收敛。