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

为何训练数据为gen(x)、验证数据为x时,分类器训练Loss降但验证效果差?

问题描述

我构建了一个分类器SimpleModel:

  • 当使用input=torch.randn(100,1)、label=(input>0时为1,否则为0)训练时,分类器训练效果良好,验证准确率接近1。
  • 但当使用input=gen(torch.randn(100,1))、label=(input>0时为1,否则为0)(其中gen()为自定义生成模型)训练时,分类器训练效果不佳:train loss下降,但验证准确率始终未提升,最终约为0.5,同时validation loss上升。

相关代码

import torch
from torch import nn
from torch import optim
import matplotlib.pyplot as plt

class SimpleModel(nn.Module):
    def __init__(self):
        super(SimpleModel, self).__init__()
        self.linear1=nn.Linear(1,1)
        self.sigmoid=nn.Sigmoid()
    def forward(self,x):
        x=self.linear1(x)
        x=self.sigmoid(x)
        return x

class Gen(nn.Module):
    def __init__(self):
        super(Gen, self).__init__()
        self.linear1=nn.Linear(1,2)
        self.relu1=nn.ReLU()
        self.linear2=nn.Linear(2,1)
        
        
    def forward(self,x):
        x=self.linear1(x)
        x=self.relu1(x)
        x=self.linear2(x)      
        return x
model=SimpleModel()
gen=Gen()
criterion = nn.BCELoss()
optimizer = optim.Adam(model.parameters(), lr=0.0001)
loss_history=[]
val_loss_history=[]
acc_history=[]
val_acc_history=[]

for step in range(10000):
    z=torch.randn(100,1)
    
    x=gen(z)
    label=(x>0).float().reshape(-1,1)
    out=model(x)
    loss=criterion(out,label)
    
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()
    acc=(out.round()==label).float().mean()
    
    val_x=torch.randn(100,1)
    val_label=(val_x>0).float().reshape(-1,1)    
    val_out=model(val_x)
    val_loss=criterion(val_out,val_label)
    val_acc=(val_out.round()==val_label).float().mean()
    
    print(loss.item(), acc.item(), val_loss.item(), val_acc.item())
    
    loss_history.append(loss.item())
    val_loss_history.append(val_loss.item())
    acc_history.append(acc.item())
    val_acc_history.append(val_acc.item())

plt.figure()
plt.plot(loss_history, label="train loss")
plt.plot(val_loss_history, label="validation loss")
plt.legend()

训练效果对比

  • 正常训练效果:
    正常训练效果
  • 使用gen数据训练效果:
    使用gen数据训练效果
问题原因分析

1. 训练集与验证集分布完全脱节

训练数据是gen(z)的输出,验证数据是直接的torch.randn(100,1),两者分布完全不同:

  • 原始torch.randn是对称的标准正态分布,正负样本均衡。
  • Gen模型的ReLU层会把线性变换后的负数值全部置0,再经过第二层线性变换后,输出x的分布会严重偏移,大概率出现正负样本失衡,甚至大部分样本集中在单侧区间。

分类器在这种偏移的训练分布上学到的规律,完全无法适配验证集的标准正态分布,最终只能随机猜测,准确率卡在0.5。

2. 输入与标签的线性关联被破坏

SimpleModel是单层线性+sigmoid模型,只能学习输入到标签的线性决策边界(判断输入是否大于0)。但Gen的ReLU层截断了负向信息,导致gen(z)的输出和原始输入不再是线性关系,甚至不同的z会对应相同的x值(比如多个负数被ReLU置0)。

此时分类器虽然能在训练集上拟合(loss下降),但学到的是Gen输出后的局部规律,完全不适用于验证集的原始分布,导致验证准确率无法提升。

3. 验证任务与训练任务完全不符

训练时分类器的任务是判断gen(z)的输出是否大于0,但验证时却要求它判断torch.randn是否大于0,相当于让模型完成两个完全无关的任务,自然无法得到合理的验证结果。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 18:32:12