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

Fast AI孪生模型训练无提升,准确率始终为50%求助

孪生模型准确率固定50%的问题排查与修复

50%的准确率说明模型完全在随机猜测,核心原因通常是数据配对错误、变换未正确应用、学习率不合理这几个方向,结合你的代码,具体修复点如下:

1. 修复数据变换的应用逻辑

你的after_batch中直接使用*aug_transforms会导致增强无法正确作用于孪生对的两个图像(因为输入是图像tuple,批量变换默认只会处理单个tensor)。需要将变换拆分到after_item阶段,确保每个图像单独应用变换:

dls = tls.dataloaders(
    after_item=[Tuple(Resize(256, method='squash')), Tuple(ToTensor)],
    after_batch=[
        IntToFloatTensor,
        # 对批量中的每个图像单独应用增强
        Tuple(aug_transforms(flip_vert=True, do_flip=True, max_rotate=50, max_warp=0.4, max_zoom=1.3)),
        Normalize.from_stats(*imagenet_stats)
    ],
    bs = 8
)

或者更稳妥的方式是将增强移到after_item,确保每个图像在转为tensor前完成增强:

after_item=[
    Tuple(Resize(256, method='squash')),
    Tuple(aug_transforms(flip_vert=True, do_flip=True, max_rotate=50, max_warp=0.4, max_zoom=1.3)),
    Tuple(ToTensor)
],
after_batch=[IntToFloatTensor, Normalize.from_stats(*imagenet_stats)]

2. 调整学习率

你设置的base_lr=2.51e-5过小,不足以让模型参数更新。建议调整学习率并拆分训练步骤:

# 先单独训练head(冻结encoder)
learn.freeze()
learn.fit_one_cycle(5, lr=1e-3, cbs=[SaveModelCallback(monitor='valid_loss'), EarlyStoppingCallback(monitor='valid_loss', patience=3)])
# 解冻后继续训练
learn.unfreeze()
learn.fit_one_cycle(10, lr=slice(1e-5, 1e-3), cbs=[SaveModelCallback(monitor='valid_loss'), EarlyStoppingCallback(monitor='valid_loss', patience=5)])

3. 验证数据配对的正确性

检查parent_label(f)是否正确获取了图像的类别标签:

# 打印几个样本的标签,确认类别划分正确
for f in files[:5]:
    print(f"文件: {f}, 类别: {parent_label(f)}")

如果parent_label返回的不是正确的类别(比如返回文件名而非父目录名),则SiameseTransform生成的配对样本完全错误,模型无法学习。

4. 检查模型输入的有效性

打印dataloader的一个batch,确认输入形状和标签分布:

batch = dls.one_batch()
x1, x2, y = batch
print(f"x1形状: {x1.shape}, x2形状: {x2.shape}")
print(f"标签分布: {torch.bincount(y)}")

正常情况下,x1和x2的形状应为(bs, 3, 256, 256),标签中0和1的数量应大致相等。

修改后的完整训练函数示例

def train(dataset_path):
    files = get_image_files(dataset_path)
    
    labels = list(set(files.map(parent_label)))
    # 验证标签正确性
    for f in files[:5]:
        print(f"文件: {f}, 类别: {parent_label(f)}")

    encoder = create_body(resnet50(), cut=-2)
    head = create_head(2048*2, 2, ps=0.5)
    model = SiameseModel(encoder, head)

    splits = RandomSplitter()(files)
    tfm = SiameseTransform(files, splits, labels)
    tls = TfmdLists(files, tfm, splits=splits)
    dls = tls.dataloaders(
        after_item=[
            Tuple(Resize(256, method='squash')),
            Tuple(aug_transforms(flip_vert=True, do_flip=True, max_rotate=50, max_warp=0.4, max_zoom=1.3)),
            Tuple(ToTensor)
        ],
        after_batch=[IntToFloatTensor, Normalize.from_stats(*imagenet_stats)],
        bs = 8
    )
    
    # 验证batch有效性
    batch = dls.one_batch()
    x1, x2, y = batch
    print(f"x1形状: {x1.shape}, x2形状: {x2.shape}")
    print(f"标签分布: {torch.bincount(y)}")
    
    torch.cuda.empty_cache()
    learn = Learner(dls, model, loss_func=loss_func, splitter=siamese_splitter, metrics=accuracy)
    # 先单独训练head
    learn.freeze()
    learn.fit_one_cycle(5, lr=1e-3, cbs=[SaveModelCallback(monitor='valid_loss'), EarlyStoppingCallback(monitor='valid_loss', patience=3)])
    # 解冻后继续训练
    learn.unfreeze()
    learn.fit_one_cycle(10, lr=slice(1e-5, 1e-3), cbs=[SaveModelCallback(monitor='valid_loss'), EarlyStoppingCallback(monitor='valid_loss', patience=5)])
    learn.export('siamese1.pkl')

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 16:40:57