# 图像分类常见问题汇总 - 2021 第1季


## 目录
* [第1期](#第1期)(2021.01.05)

<a name="第1期"></a>
## 第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%，更多的对比实验可以参考：[图像分类迁移学习教程](../application/transfer_learning.md)。


### 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上运行，这可以进一步加速预测过程。

更多的预测部署加速技巧，也欢迎大家补充。
