# 图像分类常见问题汇总 - 2021 第 1 季 ## 目录 * [1. 第 1 期](#1)(2021.01.05) * [2. 第 2 期](#2)(2021.01.14) * [3. 第 3 期](#3)(2020.01.21) * [4. 第 4 期](#4)(2021.01.28) * [5. 第 5 期](#5)(2021.02.03) ## 第 1 期 ### Q1.1: 在模型导出时,发现导出的 inference model 预测精度很低,这块是为什么呢? **A**:可以从以下几个方面排查 * 需要先排查下预训练模型路径是否正确。 * 模型导出时,默认的类别数为 1000,如果预训练模型是自定义的类别数,则在导出的时候需要指定参数 `--class_num=k`,k 是自定义的类别数。 * 可以对比下 `tools/infer/infer.py` 和 `tools/infer/predict.py` 针对相同输入的输出 class id 与 score,如果完全相同,则可能是预训练模型自身的精度很差。 ### Q1.2: 训练样本的类别不均衡,这个该怎么处理呢? **A**:有以下几种比较常用的处理方法。 * 从采样的角度出发的话 * 可以对样本根据类别进行动态采样,每个类别都设置不同的采样概率,保证不同类别的图片在同一个 minibatch 或者同一个 epoch 内,不同类别的训练样本数量基本一致或者符合自己期望的比例。 * 可以使用过采样的方法,对图片数量较少的类别进行过采样。 * 从损失函数的角度出发的话 * 可以使用 OHEM(online hard example miniing)的方法,对根据样本的 loss 进行筛选,筛选出 hard example 用于模型的梯度反传和参数更新。 * 可以使用 Focal loss 的方法,对一些比较容易的样本的 loss 赋予较小的权重,对于难样本的 loss 赋予较大的权重,从而让容易样本的 loss 对网络整体的 loss 有贡献,但是又不会主导 loss。 ### Q1.3 在 docker 中训练的时候,数据路径和配置均没问题,但是一直报错 `SystemError: (Fatal) Blocking queue is killed because the data reader raises an exception`,这是为什么呢? **A**:这可能是因为 docker 中共享内存太小导致的。创建 docker 的时候,`/dev/shm` 的默认大小为 64M,如果使用多进程读取数据,共享内存可能不够,因此需要给 `/dev/shm` 分配更大的空间,在创建 docker 的时候,传入 `--shm-size=8g` 表示给 `/dev/shm` 分配 8G 的空间,一般是够用的。 ### Q1.4 PaddleClas 提供的 10W 类图像分类预训练模型在哪里下载,应该怎么使用呢? **A**:基于 ResNet50_vd, 百度开源了自研的大规模分类预训练模型,其中训练数据为 10 万个类别,4300 万张图片。10 万类预训练模型的下载地址:[下载地址](https://paddle-imagenet-models-name.bj.bcebos.com/ResNet50_vd_10w_pretrained.tar),在这里需要注意的是,该预训练模型没有提供最后的 FC 层参数,因此无法直接拿来预测;但是可以使用它作为预训练模型,在自己的数据集上进行微调。经过验证,该预训练模型相比于基于 ImageNet1k 数据集的 ResNet50_vd 预训练模型,在不同的数据集上均有比较明显的精度收益,最多可达 30%。 ### Q1.5 使用 C++ 进行预测部署的时候怎么进行加速呢? **A**:可以从以下几个方面加速预测过程。 1. 如果是 CPU 预测的话,可以开启 mkldnn 进行预测,同时适当增大运算的线程数(cpu_math_library_num_threads,在 `tools/config.txt` 中),一般设置为 6~10 比较有效。 2. 如果是 GPU 预测的话,在硬件条件允许的情况下,可以开启 TensorRT 预测以及 FP16 预测,这可以进一步加快预测速度。 3. 在内存或者显存足够的情况下,可以增大预测的 batch size。 4. 可以将图像预处理的逻辑(主要设计 resize、crop、normalize 等)放在 GPU 上运行,这可以进一步加速预测过程。 更多的预测部署加速技巧,也欢迎大家补充。 ## 第 2 期 ### Q2.1: PaddleClas 在设置标签的时候必须从 0 开始吗?class_num 必须等于数据集的类别数吗? **A**:在 PaddleClas 中,标签默认是从 0 开始,所以,尽量从 0 开始设置标签,当然,从其他值开始设置也可以,这样会导致设置的 class_num 增大,进而导致分类的 FC 层参数量较大,权重文件会占用更多的存储空间。在数据集类别连续的情况下,设置的 class_num 要等于数据集类别数(当然大于数据集类别数也可以,在很多数据集上甚至可以获得更高的精度,但同样会使 FC 层参数量较大),在数据集类别数不连续的情况下,设置的 class_num 要等于数据集中最大的 class_id+1。 ### Q2.2: 当类别数特别多的时候,最后的 FC 特别大,导致权重文件占用较大的存储空间,该怎么解决? **A**:最终的 FC 的权重是一个大的矩阵,大小为 C*class_num,其中 C 为 FC 前一层的神经单元个数,如 ResNet50 中的 C 为 2048,可以通过降低 C 的值来进一步减小 FC 权重的大小,比如,可以在 GAP 之后加一层维数较小的 FC 层,这样可以大大缩小最终分类层的权重大小。 ### Q2.3: 为什么使用 PaddleClas 在自定义的数据集上训练 ssld 蒸馏没有达到预期? 首先,需要确保 Teacher 模型的精度是否存在问题,其次,需要确保 Student 模型是否成功加载了 ImageNet-1k 的预训练权重以及 Teacher 模型是否成功加载了训练自定义数据集的权重,最后,要确保初次学习率不应太大,至少保证初始学习率不要超过训练 ImageNet-1k 的值。 ### Q2.4: 移动端或嵌入式端上哪些网络具有优势? 建议使用移动端系列的网络,网络详情可以参考[移动端系列网络结构介绍](../models/Mobile.md)。如果任务的速度更重要,可以考虑 MobileNetV3 系列,如果模型大小更重要,可以根据移动端系列网络结构介绍中的 StorageSize-Accuracy 来确定具体的结构。 ### Q2.5: 既然移动端网络非常快,为什么还要使用诸如 ResNet 这样参数量和计算量较大的网络? 不同的网络结构在不同的设备上运行速度优势不同。在移动端,移动端系列的网络比服务器端的网络运行速度更快,但是在服务器端,相同精度下,ResNet 等经过特定优化后的网络具有更大的优势,所以需要根据具体情况来选择具体的网络结构。 ## 第 3 期 ### Q3.1: 双(多)分支结构与 Plain 结构,各自有什么特点? **A**: 以 VGG 为代表的 Plain 网络,发展到以 ResNet 系列(带有残差模块)、Inception 系列(多卷积核并行)为代表的的多分支网络结构,人们发现多分支结构在模型训练阶段更为友好,更大的网络宽度可以带来更强的特征拟合能力,而残差结构则可以避免深度网络梯度消失的问题,但是在推理阶段,带有多分支结构的模型在速度上并无优势,即使多分支结构模型的 FLOPs 要更低,但多分支结构的模型计算密度也更低。例如 VGG16 模型的 FLOPs 远远大于 EfficientNetB3,但是 VGG16 模型的推理速度却显著快于 EfficientNetB3,因此多分支结构在模型训练阶段更为友好,而 Plain 结构模型则更适合于推理阶段,那么以此为出发点,可以在训练阶段使用多分支网络结构,以更大的训练时间成本换取特征拟合能力更强的模型,而在推理阶段,将多分支结构转为 Plain 结构,从而换取更短的推理时间。实现多分支结构到 Plain 结构的转换,可以通过结构重参数化(structural re-parameterization)技术实现。 另外,Plain 结构对于剪枝操作也更为友好。 注:“Plain 结构”与“结构重参数化(structural re-parameterization)技术”出自论文“RepVGG: Making VGG-style ConvNets Great Again”。Plain 结构网络模型指整个网络不存在分支结构,也即网络中第 `i` 层 layer 的输入为第 `i-1` 层 layer 的输出,第 `i` 层 layer 的输出为第 `i+1` 层 layer 的输入。 ### Q3.2: ACNet 的创新点主要在哪里? **A**: ACNet 意为“Asymmetric Convolution Block”,即为非对称卷积模块,该思想出自论文“ACNet: Strengthening the Kernel Skeletons for Powerful CNN via Asymmetric Convolution Blocks”,文章提出了以“ACB”结构的三个 CNN 卷积核为一组,用来在训练阶段替代现有卷积神经网络中的传统方形卷积核。 方形卷积核的尺寸为假设为 `d*d`,即宽、高相等均为 `d`,则用于替换该卷积核的 ACB 结构是尺寸为 `d*d`、`1*d`、`d*1` 的三个卷积核,然后再将三个卷积核的输出直接相加,可以得到与原有方形卷积核相同尺寸的计算结果。 而在训练完成后,将 ACB 结构换回原有的方形卷积核,方形卷积核的参数则为 ACB 结构的三个卷积核的参数直接相加(见 `Q3.4`,因此还是使用与之前相同的模型结构用于推理,ACB 结构只是在训练阶段使用。 在训练中,通过 ACB 结构,模型的网络宽度得到了提高,利用 `1*d`、`d*1` 的两个非对称卷积核提取得到更多的特征用于丰富 `d*d` 卷积核提取的特征图的信息。而在推理阶段,这种设计思想并没有带来额外的参数与计算开销。如下图所示,分别是用于训练阶段和部署推理阶段的卷积核形式。