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

为何小数据集上微调MLP后测试精度与预训练模型一致?

问题:MLP微调后性能无变化的原因及代码修正

我基于6k样本训练了一个简单MLP模型,测试集精度达96.80%,保存权重为model_weights.pth。随后用50个样本(finetune_loader)微调模型,但微调后测试集精度与预训练时完全一致,输出概率也无变化。相关代码如下:

模型定义

class MLP(nn.Module):
    def __init__(self,input_dim=92, hidden_dim = 150, num_classes=2):
        super().__init__()
        self.input_dim = input_dim
        self.num_classes = num_classes
        self.hidden_dim = hidden_dim
        #self.softmax = nn.Softmax(dim=1)

        self.layers = nn.Sequential(
            nn.Linear(self.input_dim, self.hidden_dim),
            nn.ReLU(),
            nn.Linear(self.hidden_dim, self.hidden_dim),
            nn.ReLU(),
            nn.Linear(self.hidden_dim, self.hidden_dim),
            nn.ReLU(),
            nn.Linear(self.hidden_dim, self.num_classes),

        )

    def forward(self, x):
        x = self.layers(x)
        return x

预训练超参数与模型初始化

num_epoch = 300   # 200e3//len(train_loader)
learning_rate = 1e-3
batch_size = 64
device = torch.device("cuda")
SEED = 42
torch.manual_seed(42)

model = MLP(input_dim=input_dim, hidden_dim=hidden_dim, num_classes=num_classes).to(device)
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate, weight_decay=1e-4)
criterion = nn.CrossEntropyLoss()

微调代码

model_finetune = MLP()
model_finetune.load_state_dict(torch.load('model_weights.pth'))
model_finetune.to(device)
model_finetune.train()
# train the network
for t in tqdm(range(num_epoch)):
  for i, data in enumerate(finetune_loader, 0):
    #def closure():
      # Get and prepare inputs
      inputs, targets = data
      inputs, targets = inputs.float(), targets.long()
      inputs, targets = inputs.to(device), targets.to(device)
      
      # Zero the gradients
      optimizer.zero_grad()
      # Perform forward pass
      outputs = model_finetune(inputs)
      # Compute loss
      loss = criterion(outputs, targets)
      # Perform backward pass
      loss.backward()
      #return loss
      optimizer.step()     # a

model_finetune.eval()
with torch.no_grad():
    outputs2 = model_finetune(test_data)
    #predicted_labels = outputs.squeeze().tolist()

    _, preds = torch.max(outputs2, 1)
    prediction_test = np.array(preds.cpu())
    accuracy_test_finetune = accuracy_score(y_test, prediction_test)
    accuracy_test_finetune
    
    Output: 0.9680851063829787

核心问题:优化器绑定对象错误

你的微调代码存在致命错误:使用的optimizer是预训练时绑定原model参数的优化器,而非微调模型model_finetune的参数。这意味着optimizer.step()更新的是原模型的权重,而非你加载的微调模型,导致model_finetune的权重完全没被修改,性能自然和预训练时一致。

修正方案

1. 重新初始化优化器,绑定微调模型参数

在微调部分,必须为model_finetune单独创建优化器,且建议使用更小的学习率(避免破坏预训练的有效权重):

model_finetune = MLP()
model_finetune.load_state_dict(torch.load('model_weights.pth'))
model_finetune.to(device)
model_finetune.train()

# 关键:为微调模型重新创建优化器
optimizer = torch.optim.Adam(model_finetune.parameters(), lr=1e-4, weight_decay=1e-4)
criterion = nn.CrossEntropyLoss()  # 若预训练时已定义,可复用,但建议显式声明避免混淆

# train the network
for t in tqdm(range(num_epoch)):
    running_loss = 0.0
    for i, data in enumerate(finetune_loader, 0):
        inputs, targets = data
        inputs, targets = inputs.float(), targets.long()
        inputs, targets = inputs.to(device), targets.to(device)
        
        optimizer.zero_grad()  # 清空当前模型的梯度
        outputs = model_finetune(inputs)
        loss = criterion(outputs, targets)
        loss.backward()  # 计算微调模型的梯度
        optimizer.step()  # 更新微调模型的权重
        
        running_loss += loss.item()
    # 打印损失确认训练进程
    print(f"Epoch {t+1}, Loss: {running_loss/len(finetune_loader):.4f}")

2. 额外注意事项

  • 学习率设置:微调时学习率通常比预训练小1-2个数量级(比如从1e-3改为1e-4),防止预训练学到的特征被破坏。
  • 数据验证:确认finetune_loader加载的50个样本标签正确、数据格式与预训练一致,且已转移到指定设备(GPU)。
  • 训练状态验证:通过打印每轮损失值,观察损失是否下降,确认训练确实在更新模型权重。

内容的提问来源于stack exchange,提问作者S.EB

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 18:40:40