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

基于InsightFace的自定义数据集迁移学习:过拟合/欠拟合问题求助

问题描述
  • 基于InsightFace框架,使用ArcFace Torch的glint360k_cosface_r100_fp16_0.1模型做迁移学习,在自定义数据集上遭遇欠拟合/过拟合问题
  • 数据集细节:127个个体,每人7张不同角度图像(正面、左右3/4视角、上下视角、左右侧脸),共889张图
  • 初始划分:按文件夹级80%训练/20%验证(每人5张训练、2张验证),因单个体数据量不足导致欠拟合
  • 尝试先做数据增强再划分,出现过拟合,推测模型记忆增强图特征而非泛化
  • 附实现思路伪代码,请求指出问题并提供指导

实现思路伪代码

BEGIN

# ---- 环境配置 ----
设置CUDA和OpenCV路径
配置PyTorch内存分配参数

# ---- 导入依赖库 ----
导入所需库(Torch、NumPy、OpenCV、InsightFace等)

# ---- 定义FaceDataset类 ----
类 FaceDataset:
    初始化数据集目录、变换操作、缓存
    如果缓存存在:
        从缓存加载数据集
    否则:
        初始化InsightFace人脸检测模型
        遍历数据集目录
        对每个图像文件夹:
            对每张图像:
                检测人脸
                如果检测到人脸:
                    裁剪并缩放到(112,112)
                    存入数据集
        将数据集保存到缓存
    
    函数 _detect_face(image):
        读取图像
        转换为RGB格式
        用InsightFace检测人脸
        如果检测到人脸:
            裁剪、缩放后返回人脸图像
        否则:
            返回None

    函数 __getitem__(index):
        返回图像和标签

    函数 __len__():
        返回样本数量

# ---- 定义FaceRecognitionModel类 ----
类 FaceRecognitionModel:
    初始化ResNet50骨干网络
    冻结底层,微调上层
    添加带Dropout的全连接分类头
    函数 forward(input):
        输入通过骨干网络
        输入通过分类头
        返回输出

# ---- 定义训练函数 ----
函数 train_model(model, train_loader, val_loader, criterion, optimizer, scheduler, num_epochs):
    初始化指标存储
    设置早停阈值
    
    遍历每个epoch:
        如果处于预热阶段:
            调整学习率
        
        # ---- 训练阶段 ----
        设置模型为训练模式
        遍历每个batch:
            加载输入图像和标签
            计算预测结果
            计算损失
            反向传播并更新权重

        # ---- 验证阶段 ----
        设置模型为评估模式
        遍历每个batch:
            计算预测结果
            计算验证损失
        根据验证损失更新学习率调度器
        检查早停条件

    返回最优模型

# ---- 定义数据划分函数 ----
函数 split_data():
    从文件名提取人物身份
    使用GroupShuffleSplit避免身份泄露
    返回训练和验证索引

# ---- 定义数据增强函数 ----
函数 get_transforms():
    返回图像增强流水线(翻转、缩放、归一化)

# ---- 定义ONNX导出函数 ----
函数 export_to_onnx(model, save_path):
    将PyTorch模型转换为ONNX格式
    验证转换结果
    返回ONNX模型

# ---- 主函数 ----
函数 main():
    设置数据集路径、缓存目录、日志路径
    初始化启用缓存的数据集
    划分数据集,确保训练/验证集个体不重叠
    应用数据增强
    创建训练/验证数据加载器
    
    # ---- 模型初始化 ----
    加载ResNet50骨干网络
    初始化FaceRecognitionModel
    设置损失函数、优化器、学习率调度器
    
    # ---- 训练模型 ----
    调用train_model()
    
    # ---- 导出训练好的模型 ----
    调用export_to_onnx()

    打印 "训练完成!"

# ---- 运行主函数 ----
如果 __name__ == "__main__":
    调用main()

END

核心问题分析与优化方案

1. 数据集划分逻辑问题

  • 初始划分欠拟合根源:每人仅5张训练图,对于R100这类大模型来说数据量严重不足,无法学到足够的个体特征差异
  • 增强后过拟合原因:先增强再划分导致同一原始图的增强版同时出现在训练/验证集,属于数据泄露,模型看似表现好实则未泛化

优化方案:

  • 先按个体做严格划分:80%个体(101个)用于训练,20%个体(26个)用于验证,彻底避免身份泄露
  • 训练集内部做实时动态增强,增强仅作用于训练样本,验证集保留原始数据,杜绝泄露

2. 模型设置问题

  • 伪代码用ResNet50替代原模型的R100骨干,浪费预训练权重的特征学习优势
  • 冻结策略笼统:预训练模型底层已学到通用人脸特征,直接冻结无法适配自定义数据集的角度差异;全量微调又易过拟合
  • 分类头设计不合理:普通全连接层不适合人脸识别任务,Dropout比例偏低

优化方案:

  • 直接加载预训练的glint360k_cosface_r100_fp16_0.1完整模型,而非重新初始化ResNet50
  • 采用分层解冻策略:先冻结前70%骨干层,仅微调后30%骨干层和分类头;训练3-5个epoch后,解冻前50%层,学习率调低10倍继续训练
  • 替换分类头为ArcFace原生ArcMarginProduct,配合CosFace损失;Dropout比例调高至0.5增强正则化

3. 数据增强问题

  • 现有增强力度不足,仅覆盖翻转、缩放,无法弥补小数据集的角度差异;提前增强缓存的方式会固定增强模式,缺乏多样性

优化方案:

  • 训练阶段实时应用组合增强:
    • 几何变换:随机水平翻转、±15°小角度旋转、人脸区域随机裁剪
    • 像素变换:随机亮度/对比度调整、低强度高斯噪声
  • 验证集仅做归一化和Resize,不做任何增强
  • 使用Albumentations库实现增强,针对性适配人脸图像

4. 训练流程问题

  • 预热阶段逻辑模糊,缺乏明确的学习率递增策略
  • 验证仅计算损失,未评估人脸识别核心指标(余弦相似度匹配准确率、FRR/FAR等),无法准确判断泛化能力
  • 早停仅依赖验证损失,易被噪声干扰

优化方案:

  • 学习率预热:前2个epoch采用线性递增(从1e-6到1e-4),后续用余弦退火调度器
  • 验证阶段补充计算:训练/验证集的余弦相似度匹配准确率,绘制损失、准确率曲线直观监控拟合状态
  • 早停条件结合验证损失与准确率:连续3个epoch损失上升且准确率下降时停止训练
  • 添加1e-4的权重衰减(L2正则化),抑制过拟合

5. 预处理问题

  • 仅裁剪缩放未做人脸对齐,预训练模型基于对齐人脸训练,未对齐会严重影响特征提取效果
  • 未处理多人脸样本,可能引入错误标签

优化方案:

  • 人脸检测后添加关键点对齐步骤:用InsightFace检测5个关键点,将人脸对齐到标准位置后再缩放到(112,112)
  • 预处理时过滤无脸、多脸的无效样本
  • 缓存对齐后的人脸图像,确保训练数据一致性

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 18:56:07