PaddleClas/docs/zh_CN/faq_series/faq_2021_s2.md

27 KiB
Raw Blame History

PaddleClas 相关常见问题汇总 - 2021 第2季

写在前面

  • 我们收集整理了开源以来在issues和用户群中的常见问题并且给出了简要解答旨在为广大用户提供一些参考也希望帮助大家少走一些弯路。

  • 图像分类、识别、检索领域大佬众多,模型和论文更新速度也很快,本文档回答主要依赖有限的项目实践,难免挂一漏万,如有遗漏和不足,也希望有识之士帮忙补充和修正,万分感谢。

目录

近期更新

Q2.1.7: 在训练时,出现如下报错信息:ERROR: Unexpected segmentation fault encountered in DataLoader workers.,如何排查解决问题呢?

A:尝试将训练配置文件中的字段 num_workers 设置为 0;尝试将训练配置文件中的字段 batch_size 调小一些;检查数据集格式和配置文件中的数据集路径是否正确。

Q2.1.8: 如何在训练时使用 MixupCutmix

A

  • Mixup 的使用方法请参考 MixupCuxmix 请参考 Cuxmix

  • 在使用 MixupCutmix 时,需要注意:

    • 配置文件中的 Loss.Tranin.CELoss 需要修改为 Loss.Tranin.MixCELoss,可参考 MixCELoss
    • 使用 MixupCutmix 做训练时无法计算训练的精度Acc指标因此需要在配置文件中取消 Metric.Train.TopkAcc 字段,可参考 Metric.Train.TopkAcc

Q2.1.9: 训练配置yaml文件中字段 Global.pretrain_modelGlobal.checkpoints 分别用于配置什么呢?

A

  • 当需要 fine-tune 时,可以通过字段 Global.pretrain_model 配置预训练模型权重文件的路径,预训练模型权重文件后缀名通常为 .pdparams
  • 在训练过程中训练程序会自动保存每个epoch结束时的断点信息包括优化器信息 .pdopt 和模型权重信息 .pdparams。在训练过程意外中断等情况下,需要恢复训练时,可以通过字段 Global.checkpoints 配置训练过程中保存的断点信息文件,例如通过配置 checkpoints: ./output/ResNet18/epoch_18 即可恢复18epoch训练结束时的断点信息PaddleClas将自动加载 epoch_18.pdoptepoch_18.pdparams从19epoch继续训练。

Q2.6.3: 如何将模型转为 ONNX 格式?

APaddle支持两种转ONNX格式模型的方式且依赖于 paddle2onnx 工具,首先需要安装 paddle2onnx

pip install paddle2onnx
  • 从 inference model 转为 ONNX 格式模型:

    以动态图导出的 combined 格式 inference model包含 .pdmodel.pdiparams 两个文件)为例,使用以下命令进行模型格式转换:

    paddle2onnx --model_dir ${model_path}  --model_filename  ${model_path}/inference.pdmodel --params_filename ${model_path}/inference.pdiparams --save_file ${save_path}/model.onnx --enable_onnx_checker True
    

    上述命令中:

    • model_dir:该参数下需要包含 .pdmodel.pdiparams 两个文件;
    • model_filename:该参数用于指定参数 model_dir 下的 .pdmodel 文件路径;
    • params_filename:该参数用于指定参数 model_dir 下的 .pdiparams 文件路径;
    • save_file:该参数用于指定转换后的模型保存目录路径。

    关于静态图导出的非 combined 格式的 inference model通常包含文件 __model__ 和多个参数文件)转换模型格式,以及更多参数说明请参考 paddle2onnx 官方文档 paddle2onnx

  • 直接从模型组网代码导出ONNX格式模型

    以动态图模型组网代码为例,模型类为继承于 paddle.nn.Layer 的子类,代码如下所示:

    import paddle
    from paddle.static import InputSpec
    
    class SimpleNet(paddle.nn.Layer):
        def __init__(self):
            pass
        def forward(self, x):
            pass
    
    net = SimpleNet()
    x_spec = InputSpec(shape=[None, 3, 224, 224], dtype='float32', name='x')
    paddle.onnx.export(layer=net, path="./SimpleNet", input_spec=[x_spec])
    

    其中:

    • InputSpec() 函数用于描述模型输入的签名信息,包括输入数据的 shapetypename(可省略);
    • paddle.onnx.export() 函数需要指定模型组网对象 net,导出模型的保存路径 save_path,模型的输入数据描述 input_spec

    需要注意,paddlepaddle 版本需大于 2.0.0。关于 paddle.onnx.export() 函数的更多参数说明请参考paddle.onnx.export

Q2.5.4: 在 build 检索底库时,参数 pq_size 应该如何设置?

Apq_size 是PQ检索算法的参数。PQ检索算法可以简单理解为“分层”检索算法pq_size 是每层的“容量”因此该参数的设置会影响检索性能不过在底库总数据量不太大小于10000张的情况下这个参数对性能的影响很小因此对于大多数使用场景而言在构建底库时无需修改该参数。关于PQ检索算法的更多内容可以查看相关论文

精选

1. 理论篇

1.1 PaddleClas基础知识

Q1.1.1 PaddleClas和PaddleDetection区别

APaddleClas是一个兼主体检测、图像分类、图像检索于一体的图像识别repo用于解决大部分图像识别问题用户可以很方便的使用PaddleClas来解决小样本、多类别的图像识别问题。PaddleDetection提供了目标检测、关键点检测、多目标跟踪等能力方便用户定位图像中的感兴趣的点和区域被广泛应用于工业质检、遥感图像检测、无人巡检等项目。

Q1.1.2 PaddleClas 2.2和PaddleClas 2.1完全兼容吗?

APaddleClas2.2相对PaddleClas2.1新增了metric learning模块主体检测模块、向量检索模块。另外也提供了商品识别、车辆识别、logo识别和动漫人物识别等4个场景应用示例。用户可以基于PaddleClas 2.2快速构建图像识别系统。在图像分类模块,二者的使用方法类似,可以参考图像分类示例快速迭代和评估。新增的metric learning模块可以参考metric learning示例。另外新版本暂时还不支持fp16、dali训练也暂时不支持多标签训练这块内容将在不久后支持。

Q1.1.3: Momentum 优化器中的 momentum 参数是什么意思呢?

A: Momentum 优化器是在 SGD 优化器的基础上引入了“动量”的概念。在 SGD 优化器中,在 t+1 时刻,参数 w 的更新可表示为:

w_t+1 = w_t - lr * grad

其中,lr 为学习率,grad 为此时参数 w 的梯度。在引入动量的概念后,参数 w 的更新可表示为:

v_t+1 = m * v_t + lr * grad
w_t+1 = w_t - v_t+1

其中,m 即为动量 momentum,表示累积动量的加权值,一般取 0.9,当取值小于 1 时,则越早期的梯度对当前的影响越小,例如,当动量参数 m0.9 时,在 t 时刻,t-5 的梯度加权值为 0.9 ^ 5 = 0.59049,而 t-2 时刻的梯度加权值为 0.9 ^ 2 = 0.81。因此,太过“久远”的梯度信息对当前的参考意义很小,而“最近”的历史梯度信息对当前影响更大,这也是符合直觉的。

通过引入动量的概念,在参数更新时考虑了历史更新的影响,因此可以加快收敛速度,也改善了 SGD 优化器带来的损失cost、loss震荡问题。

Q1.1.4: PaddleClas 是否有 Fixing the train-test resolution discrepancy 这篇论文的实现呢?

A: 目前 PaddleClas 没有实现。如果需要可以尝试自己修改代码。简单来说该论文所提出的思想是使用较大分辨率作为输入对已经训练好的模型最后的FC层进行fine-tune。具体操作上首先在较低分辨率的数据集上对模型网络进行训练完成训练后对网络除最后的FC层外的其他层的权重设置参数 stop_gradient=True然后使用较大分辨率的输入对网络进行fine-tune训练。

1.2 骨干网络和预训练模型库

1.3 图像分类

Q1.3.1: PaddleClas有提供调整图片亮度对比度饱和度色调等方面的数据增强吗

APaddleClas提供了多种数据增广方式 可分为3类

  1. 图像变换类: AutoAugment, RandAugment;
  2. 图像裁剪类: CutOut、RandErasing、HideAndSeek、GridMask
  3. 图像混叠类Mixup, Cutmix.

其中Randangment提供了多种数据增强方式的随机组合可以满足亮度、对比度、饱和度、色调等多方面的数据增广需求

1.4 通用检测模块

Q1.4.1 主体检测是每次只输出一个主体检测框吗?

A主体检测这块的输出数量是可以通过配置文件配置的。在配置文件中Global.threshold控制检测的阈值小于该阈值的检测框被舍弃Global.max_det_results控制最大返回的结果数这两个参数共同决定了输出检测框的数量。

Q1.4.2 训练主体检测模型的数据是如何选择的?换成更小的模型会有损精度吗?

A训练数据是在COCO、Object365、RPC、LogoDet等公开数据集中随机抽取的子集小模型精度可能会有一些损失后续我们也会尝试下更小的检测模型。关于主体检测模型的更多信息请参考主体检测

Q1.4.3: 目前使用的主体检测模型检测在某些场景中会有误检?

A目前的主体检测模型训练时使用了COCO、Object365、RPC、LogoDet等公开数据集如果被检测数据是类似工业质检等于常见类别差异较大的数据需要基于目前的检测模型重新微调训练。

1.5 图像识别模块

Q1.5.1 使用circle loss还需加triplet loss吗?

Acircle loss是统一了样本对学习和分类学习的两种形式,如果是分类学习的形式的话,可以增加triplet loss

Q1.5.2 如果不是识别开源的四个方向的图片,该使用哪个识别模型?

A建议使用商品识别模型一来是因为商品覆盖的范围比较广被识别的图片是商品的概率更大二来是因为商品识别模型的训练数据使用了5万类别的数据泛化能力更好特征会更鲁棒一些。

Q1.5.3 最后使用512维的向量为什么不用1024或者其他维度的呢

A使用维度小的向量为了加快计算在实际使用过程中可能使用128甚至更小。一般来说512的维度已经够大能充分表示特征了。

1.6 检索模块

Q1.6.1 PaddleClas目前使用的Möbius向量检索算法支持类似于faiss的那种index.add()的功能吗? 另外每次构建新的图都要进行train吗这里的train是为了检索加速还是为了构建相似的图

AMobius提供的检索算法是一种基于图的近似最近邻搜索算法目前支持两种距离计算方式inner product和L2 distance. faiss中提供的index.add功能暂时不支持如果需要增加检索库的内容需要从头重新构建新的index. 在每次构建index时检索算法内部执行的操作是一种类似于train的过程不同于faiss提供的train接口我们命名为build, 主要的目的是为了加速检索的速度。

A: QueryGallery 均为数据集配置,其中 Gallery 用于配置底库数据,Query 用于配置验证集。在进行 Eval 时,首先使用模型对 Gallery 底库数据进行前向计算特征向量,特征向量用于构建底库,然后模型对 Query 验证集中的数据进行前向计算特征向量,再与底库计算召回率等指标。

2. 实战篇

2.1 训练与评估共性问题

Q2.1.1 PaddleClas 的train_log文件在哪里?

A:在保存权重的路径中存放了train.log

Q2.1.2 模型训练出nan为什么

A 1.确保正确加载预训练模型, 最简单的加载方式添加参数-o Arch.pretrained=True即可; 2.模型微调时学习率不要太大如设置0.001就好。

Q2.1.3 可以对视频中每一帧画面进行逐帧预测吗?

A可以但目前PaddleClas并不支持视频输入。可以尝试修改一下PaddleClas代码或者预先将视频逐帧转为图像存储再使用PaddleClas进行预测。

Q2.1.4: 数据预处理中,不想对输入数据进行裁剪,该如何设置?或者如何设置剪裁的尺寸。

A: PaddleClas 支持的数据预处理算子可在这里查看:ppcls/data/preprocess/__init__.py,所有支持的算子均可在配置文件中进行配置,配置的算子名称需要和算子类名一致,参数与对应算子类的构造函数参数一致。如不需要对图像裁剪,则可去掉 CropImageRandCropImage,使用 ResizeImage 替换即可可通过其参数设置不同的resize方式 使用 size 参数则直接将图像缩放至固定大小,使用resize_short 参数则会维持图像宽高比进行缩放。设置裁剪尺寸时,可通过 CropImage 算子的 size 参数,或 RandCropImage 算子的 size 参数。

Q2.1.5: PaddlePaddle 安装后,使用报错,无法导入 paddle 下的任何模块import paddle.xxx是为什么呢

A: 首先可以使用以下代码测试 Paddle 是否安装正确:

import paddle
paddle.utils.install_check.run_check(

正确安装时,通常会有如下提示:

PaddlePaddle is installed successfully! Let's start deep learning with PaddlePaddle now.

如未能安装成功,则会有相应问题的提示。 另外在同时安装CPU版本和GPU版本Paddle后由于两个版本存在冲突需要将两个版本全部卸载然后重新安装所需要的版本。

Q2.1.6: 使用PaddleClas训练时如何设置仅保存最优模型不想保存中间模型。

A: PaddleClas在训练过程中会保存/更新以下三类模型:

  1. 最新的模型(latest.pdopt latest.pdparamslatest.pdstates),当训练意外中断时,可使用最新保存的模型恢复训练;
  2. 最优的模型(best_model.pdoptbest_model.pdparamsbest_model.pdstates
  3. 训练过程中一个epoch结束时的断点epoch_xxx.pdoptepoch_xxx.pdparamsepoch_xxx.pdstates)。训练配置文件中 Global.save_interval 字段表示该模型的保存间隔。将该字段设置大于总epochs数则不再保存中间断点模型。

Q2.1.7: 在训练时,出现如下报错信息:ERROR: Unexpected segmentation fault encountered in DataLoader workers.,如何排查解决问题呢?

A:尝试将训练配置文件中的字段 num_workers 设置为 0;尝试将训练配置文件中的字段 batch_size 调小一些;检查数据集格式和配置文件中的数据集路径是否正确。

Q2.1.8: 如何在训练时使用 MixupCutmix

A

  • Mixup 的使用方法请参考 MixupCuxmix 请参考 Cuxmix

  • 在使用 MixupCutmix 时,需要注意:

    • 配置文件中的 Loss.Tranin.CELoss 需要修改为 Loss.Tranin.MixCELoss,可参考 MixCELoss
    • 使用 MixupCutmix 做训练时无法计算训练的精度Acc指标因此需要在配置文件中取消 Metric.Train.TopkAcc 字段,可参考 Metric.Train.TopkAcc

Q2.1.9: 训练配置yaml文件中字段 Global.pretrain_modelGlobal.checkpoints 分别用于配置什么呢?

A

  • 当需要 fine-tune 时,可以通过字段 Global.pretrain_model 配置预训练模型权重文件的路径,预训练模型权重文件后缀名通常为 .pdparams
  • 在训练过程中训练程序会自动保存每个epoch结束时的断点信息包括优化器信息 .pdopt 和模型权重信息 .pdparams。在训练过程意外中断等情况下,需要恢复训练时,可以通过字段 Global.checkpoints 配置训练过程中保存的断点信息文件,例如通过配置 checkpoints: ./output/ResNet18/epoch_18 即可恢复18epoch训练结束时的断点信息PaddleClas将自动加载 epoch_18.pdoptepoch_18.pdparams从19epoch继续训练。

2.2 图像分类

Q2.2.1 SSLD中大模型在500M数据上预训练后蒸馏小模型然后在1M数据上蒸馏finetune小模型

A:步骤如下:

  1. 基于facebook开源的ResNeXt101-32x16d-wsl模型 去蒸馏得到了ResNet50-vd模型;
  2. 用这个ResNet50-vd在500W数据集上去蒸馏MobilNetV3
  3. 考虑到500W的数据集的分布和100W的数据分布不完全一致所以这块在100W上的数据上又finetune了一下精度有微弱的提升。

Q2.2.2 训练SwinTransformerloss出现nan

A训练SwinTransformer时请使用版本大于等于 2.1.1Paddle,并且加载我们提供的预训练模型,学习率也不宜过大。

2.3 通用检测模块

Q2.3.1 为什么有一些图片检测出的结果就是原图?

A:主体检测模型会返回检测框,但事实上为了让后续的识别模型更加准确,在返回检测框的同时也返回了原图。后续会根据原图或者检测框与库中的图片的相似度排序,相似度最高的库中图片的标签即为被识别图片的标签。

Q2.3.2:在直播场景中,需要提供一个直播即时识别画面,能够在延迟几秒内找到特征目标物并用框圈起,这个可以实现吗?

A要达到实时的检测效果需要检测速度达到实时性的要求PP-YOLO是Paddle团队提供的轻量级目标检测模型检测速度和精度达到了很好的平衡可以试试PP-YOLO来做检测. 关于PP-YOLO的使用可以参照PaddleDetection

Q2.3.3: 对于未知的标签加入gallery dataset可以用于后续的分类识别无需训练但是如果前面的检测模型对于未知的标签无法定位检测出来是否还是要训练前面的检测模型

A如果检测模型在自己的数据集上表现不佳需要在自己的检测数据集上再finetune下

2.4 图像识别模块

Q2.4.1: 识别模块预测时报Illegal instruction错?

A:可能是编译生成的库文件与您的环境不兼容,导致程序报错,如果报错,推荐参考向量检索教程重新编译库文件。

Q2.4.2: 识别模型怎么在预训练模型的基础上进行微调训练?

A:识别模型的微调训练和分类模型的微调训练类似,识别模型可以加载商品的预训练模型,训练过程可以参考识别模型训练,后续我们也会持续细化这块的文档。

Q2.4.3: 训练metric learning时每个epoch中无法跑完所有mini-batch为什么

A在训练metric learning时使用的Sampler是DistributedRandomIdentitySampler该Sampler不会采样全部的图片导致会让每一个epoch采样的数据不是所有的数据所以无法跑完显示的mini-batch是正常现象。后续我们会优化下打印的信息尽可能减少给大家带来的困惑。

Q2.4.4: 有些图片没有识别出结果,为什么?

A在配置文件如inference_product.yamlIndexProcess.score_thres中会控制被识别的图片与库中的图片的余弦相似度的最小值。当余弦相似度小于该值时,不会打印结果。您可以根据自己的实际数据调整该值。

2.5 检索模块

Q2.5.1: 添加图片后建索引报assert text_num >= 2错?

A请确保data_file.txt中图片路径和图片名称中间的间隔为单个table而不是空格。

Q2.5.2: 新增底库数据需要重新构建索引吗?

A:这一版需要重新构建索引,未来版本会支持只构建新增图片的索引。

Q2.5.3: Mac重新编译index.so时报错如下clang: error: unsupported option '-fopenmp', 该如何处理?

A:该问题已经解决。可以参照文档重新编译 index.so。

Q2.5.4: 在 build 检索底库时,参数 pq_size 应该如何设置?

Apq_size 是PQ检索算法的参数。PQ检索算法可以简单理解为“分层”检索算法pq_size 是每层的“容量”因此该参数的设置会影响检索性能不过在底库总数据量不太大小于10000张的情况下这个参数对性能的影响很小因此对于大多数使用场景而言在构建底库时无需修改该参数。关于PQ检索算法的更多内容可以查看相关论文

2.6 模型预测部署

Q2.6.1: hub serving方式启动某个模块怎么添加该模块的参数呢

A:具体可以参考hub serving参数

Q2.6.2: 导出inference模型进行预测部署准确率异常为什么呢

A: 该问题通常是由于在导出时未能正确加载模型参数导致的,首先检查模型导出时的日志,是否存在类似下述内容:

UserWarning: Skip loading for ***. *** is not found in the provided dict.

如果存在,则说明模型权重未能加载成功,请进一步检查配置文件中的 Global.pretrained_model 字段,是否正确配置了模型权重文件的路径。模型权重文件后缀名通常为 pdparams,注意在配置该路径时无需填写文件后缀名。

Q2.6.3: 如何将模型转为 ONNX 格式?

APaddle支持两种转ONNX格式模型的方式且依赖于 paddle2onnx 工具,首先需要安装 paddle2onnx

pip install paddle2onnx
  • 从 inference model 转为 ONNX 格式模型:

    以动态图导出的 combined 格式 inference model包含 .pdmodel.pdiparams 两个文件)为例,使用以下命令进行模型格式转换:

    paddle2onnx --model_dir ${model_path}  --model_filename  ${model_path}/inference.pdmodel --params_filename ${model_path}/inference.pdiparams --save_file ${save_path}/model.onnx --enable_onnx_checker True
    

    上述命令中:

    • model_dir:该参数下需要包含 .pdmodel.pdiparams 两个文件;
    • model_filename:该参数用于指定参数 model_dir 下的 .pdmodel 文件路径;
    • params_filename:该参数用于指定参数 model_dir 下的 .pdiparams 文件路径;
    • save_file:该参数用于指定转换后的模型保存目录路径。

    关于静态图导出的非 combined 格式的 inference model通常包含文件 __model__ 和多个参数文件)转换模型格式,以及更多参数说明请参考 paddle2onnx 官方文档 paddle2onnx

  • 直接从模型组网代码导出ONNX格式模型

    以动态图模型组网代码为例,模型类为继承于 paddle.nn.Layer 的子类,代码如下所示:

    import paddle
    from paddle.static import InputSpec
    
    class SimpleNet(paddle.nn.Layer):
        def __init__(self):
            pass
        def forward(self, x):
            pass
    
    net = SimpleNet()
    x_spec = InputSpec(shape=[None, 3, 224, 224], dtype='float32', name='x')
    paddle.onnx.export(layer=net, path="./SimpleNet", input_spec=[x_spec])
    

    其中:

    • InputSpec() 函数用于描述模型输入的签名信息,包括输入数据的 shapetypename(可省略);
    • paddle.onnx.export() 函数需要指定模型组网对象 net,导出模型的保存路径 save_path,模型的输入数据描述 input_spec

    需要注意,paddlepaddle 版本需大于 2.0.0。关于 paddle.onnx.export() 函数的更多参数说明请参考paddle.onnx.export