You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在CNN模型中冻结卷积层内部分参数而非整层全部参数?

CNN单层内部分参数冻结的实现方法

不需要整层冻结的时候,核心逻辑非常直接:深度学习框架只会对开启了梯度计算的参数执行更新,你只要给不需要更新的那部分参数关掉梯度,再让优化器只更新开了梯度的参数就行,完全不需要改训练循环的逻辑。

就拿你说的「10个卷积filter只更新5个、冻结剩余5个」的场景,用最常用的PyTorch实现的话步骤非常少:

  • 先定位到目标卷积层的权重张量:卷积层权重的维度顺序是[filter总数, 输入通道数, 卷积核高, 卷积核宽],第一维正好对应你说的10个filter。
  • 先确保整层权重的梯度计算是打开的,再把你要冻结的那5个filter对应的权重切片,单独把这部分的requires_grad设为False,如果卷积层带偏置参数,对应位置的偏置也要同步关掉梯度。
  • 初始化优化器的时候,不要直接传入全模型参数,先筛选一遍所有requires_grad=True的参数传给优化器,这步是避免冻结失效的关键。

具体可运行的示例代码如下:

import torch
import torch.nn as nn

class DemoCNN(nn.Module):
    def __init__(self):
        super().__init__()
        # 目标卷积层:共10个3x3的filter,输入通道为3
        self.target_conv = nn.Conv2d(in_channels=3, out_channels=10, kernel_size=3)
        self.cls_head = nn.Linear(10, 2)

    def forward(self, x):
        x = self.target_conv(x)
        x = x.mean(dim=[2,3]) # 全局平均池化
        return self.cls_head(x)

model = DemoCNN()

# ========== 核心冻结逻辑 ==========
# 冻结第5-9号共5个filter,只更新0-4号的5个filter
# 先打开整层权重的梯度,避免之前的配置干扰
model.target_conv.weight.requires_grad = True
# 给后5个filter的权重关掉梯度
model.target_conv.weight[5:, :, :, :].requires_grad = False
# 同步处理对应位置的偏置
if model.target_conv.bias is not None:
    model.target_conv.bias.requires_grad = True
    model.target_conv.bias[5:].requires_grad = False

# 优化器只传入需要更新的参数
trainable_params = filter(lambda p: p.requires_grad, model.parameters())
optimizer = torch.optim.SGD(trainable_params, lr=1e-3, momentum=0.9)

# 后续正常写训练循环即可,反向传播时冻结的5个filter不会计算梯度,参数值会保持初始状态完全不变

几个容易踩的坑提前说:

  • 不要上来就给整层设requires_grad=False,一旦整层梯度被关掉,你再单独开切片部分的梯度是不生效的。
  • 梯度开关的设置一定要放在优化器初始化之前,要是先初始化优化器再改requires_grad,优化器的参数列表里还是会包含冻结的参数,会导致冻结失效。
  • 如果用TensorFlow/Keras实现逻辑完全一致,只要在前向传播时把要冻结的权重切片用tf.stop_gradient()包裹,就能阻止对应部分的参数更新。

内容的提问来源于stack exchange,提问作者ZeroorOne

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.03 02:48:27