在神经网络训练中,**冻结(Freezing)和解冻(Unfreezing)** 是迁移学习中的关键技术,用于控制哪些层参与训练。以下是详细解析:

 

### 冻结/解冻的核心概念

```mermaid

graph LR

A[预训练模型] --> B[冻结大部分层]

B --> C[仅训练新添加层]

C --> D[解冻部分层]

D --> E[微调整个模型]

```

 

### 何时使用冻结/解冻?

| 场景 | 策略 | 目的 |

|------|------|------|

| 小数据集 | 冻结主干+训练新层 | 防止过拟合 |

| 大数据集 | 解冻所有层 | 充分微调 |

| 领域差异大 | 渐进式解冻 | 平稳过渡 |

| 计算资源有限 | 冻结大部分层 | 减少计算量 |

 

### PyTorch实现代码

 

#### 1. 初始冻结(迁移学习标准流程)

```python

from torchvision import models

 

# 加载预训练模型

model = models.resnet18(pretrained=True)

 

# 冻结所有层

for param in model.parameters():

    param.requires_grad = False

 

# 替换最后一层(仅训练该层)

num_ftrs = model.fc.in_features

model.fc = nn.Sequential(

    nn.Linear(num_ftrs, 256),

    nn.ReLU(),

    nn.Dropout(0.5),

    nn.Linear(256, 2) # 猫狗二分类

)

 

# 仅优化最后一层

optimizer = torch.optim.Adam(model.fc.parameters(), lr=0.001)

```

 

#### 2. 渐进式解冻(推荐策略)

```python

# 第一阶段:训练后解冻最后两层

for name, param in model.named_parameters():

    if "layer4" in name or "fc" in name: # ResNet最后残差块

        param.requires_grad = True

 

# 调整优化器包含新解冻层

optimizer = torch.optim.Adam(

    filter(lambda p: p.requires_grad, model.parameters()),

    lr=1e-4, # 更小的学习率

    weight_decay=1e-4

)

 

# 第二阶段:解冻更多层

for name, param in model.named_parameters():

    if "layer3" in name or "layer4" in name or "fc" in name:

        param.requires_grad = True

 

# 再次降低学习率

optimizer.param_groups[0]['lr'] = 5e-5

```

 

### 解冻策略比较

| 策略 | 优点 | 缺点 | 适用场景 |

|------|------|------|----------|

| **全冻结** | 训练快、防过拟合 | 性能上限低 | 小数据集(<1k样本) |

| **全解冻** | 性能潜力大 | 易过拟合、计算量大 | 大数据集(>10k样本) |

| **渐进解冻** | 平衡性能与稳定性 | 需要手动调度 | 中等数据集(1k-10k样本) |

| **选择性解冻** | 针对性强 | 需领域知识 | 特殊任务(如医学影像) |

 

### 最佳实践技巧

 

1. **学习率分层设置**:

   ```python

   optimizer = torch.optim.Adam([

       {'params': model.layer1.parameters(), 'lr': 1e-6},

       {'params': model.layer2.parameters(), 'lr': 5e-6},

       {'params': model.fc.parameters(), 'lr': 1e-4}

   ])

   ```

 

2. **批量归一化层处理**:

   ```python

   # 冻结时固定BN层

   if freeze:

       model.eval() # 固定BN的running_mean/var

   else:

       model.train()

   ```

 

3. **自动化解冻调度**:

   ```python

   def unfreeze_layers(epoch, model):

       if epoch == 5:

           for param in model.layer3.parameters():

               param.requires_grad = True

       if epoch == 10:

           for param in model.layer2.parameters():

               param.requires_grad = True

   ```

 

4. **梯度检查(调试用)**:

   ```python

   for name, param in model.named_parameters():

       if param.requires_grad:

           print(f"层 {name} 正在接收梯度")

   ```

 

### 猫狗分类实战建议

1. **初始阶段(前5轮)**:

   - 冻结所有卷积层

   - 仅训练全连接层

   - 学习率:0.001

 

2. **中期阶段(5-15轮)**:

   - 解冻最后两个残差块(layer4)

   - 学习率:0.0001

   - 添加权重衰减:1e-4

 

3. **后期阶段(>15轮)**:

   - 解冻所有层

   - 学习率:0.00001

   - 使用余弦退火调度器

 

### 效果监控指标

1. **冻结阶段**:

   - 验证准确率应快速上升至70-80%

   - 训练损失稳定下降

 

2. **解冻阶段**:

   - 关注训练/验证损失差距

   - 理想情况:验证损失持续下降

   - 警告信号:验证损失上升 → 立即停止解冻

 

> **关键经验**:在猫狗分类任务中,通常解冻最后1-2个残差块即可获得95%+准确率。全解冻可能仅带来1-2%提升,但显著增加过拟合风险。

 

通过合理使用冻结/解冻策略,可在ImageNet预训练模型基础上,用少量猫狗样本(几百张)达到专业级分类效果,同时避免过拟合。

Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐