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

PyTorch中冻结除指定层外的大部分层实现微调

模型微调:冻结指定层训练的实现方法

问题描述

我有一个已在数据集上训练完成的模型,修改了最后两层(self.conv_6和self.sigmoid)后,希望进行微调操作:冻结模型中除这两层外的所有层,重新在该数据集上训练模型。模型代码如下:

class model(nn.Module):
def __init__(self, pretrained=False):
    super(model, self).__init__()
    
    self.conv_1 = nn.Conv3d(1024, 1024, kernel_size=(3,1,1), stride=(2,1,1), padding=(1,0,0))
    self.conv_2 = nn.Conv3d(1024, 1024, kernel_size=(3,1,1), stride=(2,1,1), padding=(1,0,0))
    self.conv_3 = nn.Conv3d(1024, 1024, kernel_size=(3,1,1), stride=(2,1,1), padding=(1,0,0))
    self.conv_4 = nn.Conv3d(1024, 1024, kernel_size=(3,1,1), stride=(2,1,1), padding=(1,0,0))
    self.conv_5 = nn.Conv3d(1024, 1024, kernel_size=(3,1,1), stride=(2,1,1), padding=(1,0,0))
    self.conv_6 = nn.Conv3d(1024, 1024, kernel_size=(3,1,1), stride=(2,1,1), padding=(1,0,0))

    
    self.sigmoid = nn.Sigmoid()
    
def forward(self, x):
    
    
    x = self.conv_1(x)
    x = self.conv_2(x)
    x = self.conv_3(x)
    x = self.conv_4(x)
    x = self.conv_5(x)
    
    x = self.conv_6(x)
    y = self.sigmoid(x) 
    return y

解决方案

1. 加载预训练模型并更新最后两层

先加载你已训练好的模型权重,再替换为你修改后的conv_6和sigmoid层。

2. 冻结目标外的所有层

遍历模型参数,将除conv_6和sigmoid之外的所有层参数的requires_grad设为False,这些层在训练时就不会被更新。

3. 配置优化器与训练流程

只把可训练的参数(即conv_6和sigmoid的参数)传入优化器,再执行常规训练循环即可。

完整代码示例:

import torch
import torch.nn as nn

# 复用你定义的模型类
class model(nn.Module):
    def __init__(self, pretrained=False):
        super(model, self).__init__()
        
        self.conv_1 = nn.Conv3d(1024, 1024, kernel_size=(3,1,1), stride=(2,1,1), padding=(1,0,0))
        self.conv_2 = nn.Conv3d(1024, 1024, kernel_size=(3,1,1), stride=(2,1,1), padding=(1,0,0))
        self.conv_3 = nn.Conv3d(1024, 1024, kernel_size=(3,1,1), stride=(2,1,1), padding=(1,0,0))
        self.conv_4 = nn.Conv3d(1024, 1024, kernel_size=(3,1,1), stride=(2,1,1), padding=(1,0,0))
        self.conv_5 = nn.Conv3d(1024, 1024, kernel_size=(3,1,1), stride=(2,1,1), padding=(1,0,0))
        self.conv_6 = nn.Conv3d(1024, 1024, kernel_size=(3,1,1), stride=(2,1,1), padding=(1,0,0))

        self.sigmoid = nn.Sigmoid()
        
    def forward(self, x):
        x = self.conv_1(x)
        x = self.conv_2(x)
        x = self.conv_3(x)
        x = self.conv_4(x)
        x = self.conv_5(x)
        
        x = self.conv_6(x)
        y = self.sigmoid(x) 
        return y

# 加载预训练权重(替换为你的权重文件路径)
my_model = model()
my_model.load_state_dict(torch.load("path/to/your/pretrained_model.pth"))

# 更新最后两层为你修改后的结构(示例中保持原结构,实际按你的修改调整)
my_model.conv_6 = nn.Conv3d(1024, 1024, kernel_size=(3,1,1), stride=(2,1,1), padding=(1,0,0))
my_model.sigmoid = nn.Sigmoid()

# 冻结非目标层
for name, param in my_model.named_parameters():
    if not (name.startswith("conv_6") or name.startswith("sigmoid")):
        param.requires_grad = False

# 仅传入可训练参数到优化器
optimizer = torch.optim.Adam(filter(lambda p: p.requires_grad, my_model.parameters()), lr=1e-4)

# 示例训练循环(根据你的数据集和任务调整)
criterion = nn.BCELoss()  # 二分类任务示例,替换为你的损失函数
epochs = 10
for epoch in range(epochs):
    my_model.train()
    total_loss = 0.0
    for batch_x, batch_y in your_dataloader:  # 替换为你的数据加载器
        optimizer.zero_grad()
        outputs = my_model(batch_x)
        loss = criterion(outputs, batch_y)
        loss.backward()
        optimizer.step()
        total_loss += loss.item()
    print(f"Epoch {epoch+1}, Loss: {total_loss/len(your_dataloader):.4f}")

核心要点

  • 冻结逻辑:requires_grad=False会阻止参数参与梯度计算,确保只有目标层被更新。
  • 优化器效率:用filter筛选可训练参数,避免优化器处理不必要的参数,节省计算资源。
  • 新层默认状态:你修改后的conv_6和sigmoid层参数默认requires_grad=True,会自动参与训练。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 11:28:23