AI算法工程师的一些含泪经验(一)
前一段时间一直在优化部署模型...快吐了555。这几天终于来了需求,又要开始重操训练一些新模型了。趁着这次机会总结了下之前的一些训练模型的笔记,可能比较杂,抛砖引玉!当然这是不完全统计的经验,除了训练部分,还有很多部署的坑没有写。
算法工程师50%的时间是和数据打交道,有时候拷贝数据(分别从多个文件夹拷贝到某一文件夹);有时候筛选数据(过滤掉一些质量不好的数据);有时候把数据换个名字、加个前缀(为了后续训练的时候区分数据的特性,比如多尺度、多种图像增强策略)等等,这些工作可能一个月要重复n多次,因此最好总结起来;可以用Python或者shell脚本来处理,或者用jupyter notebook存自己常用的文件处理代码。
如果你不清楚拿到数据的来源和可靠度,可以先用
find ./ -size -1k -exec rm {} \
等命令简单过滤一下,刚才这个命令是扫描1k(或者其他值)以下的损坏图像并删除掉,当然也可以设置其他的参数。很多时候给你的图不一定都是正常的图,最好提前筛一遍,要不然后续处理很麻烦。并不所有的数据都已经有标注信息,如果收集了一批数据要拿去标注,正好公司也有标注人力,可以尝试将这批数据打上预标框让他们再去调整或者补充标框,这样效率更高些。至于预标框怎么打,可以先让模型训练一小批数据,训练个召回率高的小模型,然后预测打框就可以,也可以用一些老模型打框;不过有一个现象比较神奇,标注人员在标注的时候,对于有预标框的数据,标注的质量反而变差了,虽然速度上来了,这是因为大部分标注人员不想调整,这时候需要你好好监督一下,要不然后续模型精度上不去大概率就是数据的问题。
有时候模型的指标不仅仅看准招,当模型给别人提供服务的时候,要看PM那边怎么看待这个模型输出结果在实际场景中的使用效果;对于检测模型最终的输出分数,最终给到使用方的框一般是根据你取得分数阈值来设,设的低一点,那么框就多一点(召回率高),设的高一点,那么框就少一点(准确度高);不同方式不同场景设置不同的阈值有不同的效果,说白了模型效果好坏很大一部分依赖于场景;这个情况在实际项目中其实挺常见的,说白了loss也好, accuracy也好,都是很片面且脆弱的评估指标。与模型结构以及评测的数据分布都有很大关系,具体如何选择模型应该与应用场景强相关。
当模型遇到badcase的时候,简单粗暴地增加模型的容量效果可能并不好;因为这个badcase大概率和场景强相关,这种情况下最好就是收集badcase,可能会有使用你模型的人给你提供badcase,但这种效率比较低,看提供者的心情or紧急程度;你可以直接捞一大批模型使用场景的query然后使用当前模型做检测,收集相应类别置信度比较低的case,然后挑选出来;
测试集很重要,测试集一般不是从训练集中切分出来的,从训练集中切分出来的是验证集;验证集一般用于判断这个模型有没有过拟合、有没有训练走火入魔啦,如果想用验证集来判断模型好坏的话,往往并不能代表模型实际的水平;最好是有测试集,而且测试集是和模型采集批次不同训练模型的时候比较接近实际水平的评价标准;如果没有测试集也可以看训练集的loss大概确定一下,一般来说只要不是demo级别的场景,模型不会轻易过拟合,我们的训练集往往有很重的图像增强策略,每一个epoch可能图像分布都不一样,这时候其实也可以选取模型
model_last
。再强调下,loss和准确率不是完全正比的关系,loss波动很正常,loss低了不一定代表模型的mAP高;相反如果loss变高,模型的精度也不一定差,有可能是loss设的不够好导致部分上升占主导,掩盖了另一部分正常的下降也很正常;相关讨论:https://github.com/thegregyang/LossUpAccUp 和 https://zhihu.com/question/318399418
计算检测模型的mAP,实际中在计算的时候是不考虑目标框分数阈值的,也就是说我们会将所有分数大于0的检测框送去计算mAP;但这里要注意,计算mAP是有max_num也就是最大检测出目标个数,根据任务需求可能是100、可能是500也可能是5000等等,当有这个限制的时候,此时框就需要根据分数来排序,取前100、前500或者前5000的框去计算;最后,如果我们需要可视化结果在图上画框的话,这时候是可以卡阈值的,比如大于0.2分数阈值的要,要不然最终画出来的图会有很多碎框;最后的最后,别忘了NMS!
测试转换后的模型是否正确,一定要保证输入图像的一致;这里的一致指的是输入图像的数值必须一模一样,dif为0才行;一般来说我们输入的模型的图像范围是0-1,通道数一般是彩色也就是RGB,不过需要注意这个彩色是否是假彩色(有时候为了传输节省资源会传灰度图再实际推理的时候变成彩色图,对于某种场景来说,假彩色和真彩色的精度相差不大),输入尺寸也要保持一致,是否需要padding(padding成0或者127或者255,这几种padding方式对结果影响很大)、需要补成32的倍数、或者需要最大边最小边限制,一定要保持一致;对于类别,也需要单独计算;这样测试模型才能够保证正确性。
对于模型来说,如果之后考虑上线。上线的方式很多种:可以pytorch+flask直接docker上线,也可以尝试libtorch上线,也可以TensorRT上线,当然也可以通过自研框架上线…等等等等。如果这个模型追求精度,而且是线下某一时间段跑,并不是实时,可以尝试flask+docker的服务;如果这个模型的实时性很高,在设计模型的时候就要考虑之后的上线,那就需要考虑模型优化以及对应的服务器推理框架了可以尝试TensorRT+triton server;
未完待续...
往期回顾
关注oldpan博客,持续酝酿深度质量文
我是老潘,我们下期见~
打上星标✨不再错过老潘的及时推文
如果觉得有收获,来个点赞加好看