基于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
相关产品推荐
相关产品推荐

