\u200E
极简主义!几行代码助力你快速分析模型的神器来啦
发布日期:2021-09-15T11:59:26.000+0000 浏览量:1277次




PPMA(Paddle Model Analysis)是一个基于飞桨实现的一个模型分析小工具,它以极简主义为特色,高度封装了飞桨代码以便让大家用最少的代码来完成模型的分析,目前所支持的功能有ImageNet精度验证、可视化图片Top5预测类别、测试模型Params、Throughput、类激活图可视化(CAM)、测试时数据增强(TTA)等,在这里你可以用最少三行代码来实现想要的功能。



其中ImageNet精度验证在计算Top5准确率上用了飞桨的API(paddle.metric.Accuracy),减少了代码的编写。类激活图可视化CAM迁移了pytorch-grad-cam项目,同时参考了飞桨InterpretDL库的几行代码(这里推荐一下IntepretDL,它是基于飞桨的可解释性算法库,不仅包含可视化算法,还能从数据集和训练过程的角度去解释模型),测试时数据增强TTA迁移了ttach项目,用飞桨代码进行高阶封装。




设计思路






【为什么设计】


图像分类作为CV的基础任务,在ImageNet上训练的权重能更好迁移到下游任务,比如目标检测、语义分割等。所以分析基于ImageNet上训练的模型有助于我们能更好了解掌握模型的优劣,正是基于此,本项目简洁封装了飞桨基础代码,以便用户能用至少三行代码来完成对模型的分析。




【怎么设计】


目前有很多优秀的库拥有着简洁易用的体验,比如fastai、keras、scikit-learn,以及飞桨自家的PaddleHapi,这些都是对复杂的代码进行封装,大大降低了用户上手难度以及用户学习成本,同时高度的封装带来的是灵活性、自定义性的下降,如何去权衡这两个矛盾是一个需要思考的问题。


在尝试体验上述工具后,总结了对于一个工具是否简洁易用需要看以下两点:

  1. 命名的艺术

对函数的命名是一个需要推敲磨打的技术活,一方面函数命名尽量简单直观,做到用户自然记忆不需要查函数名,这就要求尽量命名短,单词意思尽量贴合使用场景。一方面又要避免与用户变量命名习惯冲突,比如"img"这个命名很常见,大多数用来表示一张图片,故命名函数时尽可能避开它,这能降低因为命名问题造成的error。



  1. API的设计

高度封装以及灵活性是一对矛盾。比如具有高度封装的Keras,其灵活性和自定义性没有Pytorch那么好。在本项目(模型分析)上,因为我们只是针对具体任务进行分析,其自定义性需求并不是那么高,我们可以适当提高封装性,同时支持更多的默认参数,用户可以通过修改默认参数来完成特定需求,比如CAM增加自定义标签(默认是网络输出的标签)查看相应激活图。





如何使用




AI Studio在线运行本项目:

https://aistudio.baidu.com/aistudio/projectdetail/2143665

  1. 安装PPMA
pip install ppma
  1. ImageNet精度验证

完整的ImageNet数据集有1400多万张图片,涵盖2万多类别,它是目前深度学习图像领域应用的最多的一个领域,关于图像分类、定位、检测等研究工作大多基于此数据集展开。但通常我们说的ImageNet指的是目前常用的是ISLVRC 2012(ImageNet Large Scale Visual Recognition Challenge)比赛用的子数据集。


训练集:1,281,167张图片+标签

验证集:50,000张图片+标签

测试集:100,000张图片,


它是图像分类任务的试金石,基于此数据训练一个很不错的分类网络,可以良好迁移到下游任务比如检测、分割,可以说这个数据集极大推动了计算机视觉的发展。


"ImageNet改变了AI领域人们对数据集的认识,人们真正开始意识到它在研究中的地位,就像算法一样重要",李飞飞教授说。


所以,当我们用ILSVRC2012训练好模型后,或者通过Pytorch、Tensorflow进行模型转换以及权重转换后,我们需要对该模型进行精度验证从而了解这个分类网络的性能。


先准备数据集结构如下,数据集已上传AI Studio:

https://aistudio.baidu.com/aistudio/datasetdetail/96753


data/ILSVRC2012
    ├─ ILSVRC2012_val_00000001.JPEG
    ├─ ILSVRC2012_val_00000002.JPEG
    ├─ ILSVRC2012_val_00000003.JPEG
    ├─ ...
    ├─ ILSVRC2012_val_00050000.JPEG
    └─ val.txt   # target


准备好数据集后,运行以下代码

   
     
import ppma
import paddle

model = paddle.vision.models.resnet50(pretrained=True)    # 可以替换自己的模型
data_path = "data/ILSVRC2012"                             # 数据路径

ppma.imagenet.val(model, data_path)                     # 进行验证


可以看见,我们只需要三行代码,即可完成对ImageNet数据集的验证


  1. 测试图片 Top5 类别

基于ImageNet数据集,我们可以对一张图片进行分类,利用PPMA可以快速得到图像分类前5个最可能的分类结果以及相应的精度


import ppma
import paddle

img_path = 'test.jpg'                                    # 图片路径
model = paddle.vision.models.resnet50(pretrained=True)   # 可以替换自己的模型

ppma.imagenet.test_img(model, img_path)


在这个示例中我们只需要准备图像路径和模型,一键放入函数里面,无过多的冗余,简单直观,输入效果如下


测试图片:


模型预测:

  1. 测试模型 Param、Throughput

一个模型除了精度指标之外,还有参数量(Params)、吞吐量(Throughput)等,以下是如何对于模型进行检测参数量和吞吐量(测试Throughput时候,前几轮因为不稳定要进行warmup,这里设置10iter)

import ppma
import paddle

model = paddle.vision.models.resnet50()   # 可以替换自己的模型

# Params -- depend model
param = ppma.tools.param(model)
print('Params:{:,}'.format(param))

# Thoughtout -- depend model and resolution
ppma.tools.throughput(model, image_size=224)



  1. CAM (Class Activation Mapping)

深度学习的可解释一直是讨论的热点,尤其是在分类和检测等视觉性任务,我们要了解网络学到了什么知识以及哪些没有学习,这就用到了CAM。它可用于定位图像中与类别相关的区域,可视化以此来观察分类的高响应是否落在目标的核心部位上,CAM的具体原理如下。


PPMA基于热门的开源项目进行复现,对代码进行了更高的封装,并提供了基于CAM的GradCAM、GradCAM++、XGradCAM三种可视化方法,使用方法如下所示。

import paddle
import matplotlib.pyplot as plt
from ppma import cam

img_path = 'img1.jpg'                                      # 图片路径
model = paddle.vision.models.resnet18(pretrained=True)     # 模型定义
target_layer = model.layer4[-1]                            # 提取模型某层的激活图
cam_extractor = cam.GradCAMPlusPlus(model, target_layer)   # 支持 GradCAM、XGradCAM、GradCAM++

# 提取激活图
# label设置为None,默认标签用该网络的ImageNet top1类别
activation_map = cam_extractor(img_path, label=None)   
plt.imshow(activation_map)
plt.axis('off')
plt.show()

# 与原图融合
cam_image = cam.overlay(img_path, activation_map)   
plt.imshow(cam_image)
plt.axis('off')
plt.show()


CAM里面有两个很重要的参数,分别是target_layer、label,target_layer是提取网络某个层梯度作为激活,不同的网络结构提取的层不同,对于CNN网络,大部分是在网络最后的avgpool层之前,而label是待测试的标签,默认为None,即用网络的预测标签,也可以自己设置图片的标签以此来看模型是否学习到该学习的地方。



特别说明:预计下一版本的飞桨会改进获取模型内部梯度的方式,计算梯度的效率会大幅提高,到时候对更大型的CNN网络以及ViT、MLP等前沿模型会提供更好的支持,敬请关注!于此同时,这里推荐一个基于飞桨的可解释性算法库InterpretDL,目前已集成十余种不同的可解释性算法。除了可视化算法,InterpretDL还能从数据集和训练过程的角度去解释模型,推荐大家去使用。

  1. TTA (Test Time Augmentation)

TTA,测试时间数据增强,是在模型测试时对数据进行增强以达到提升模型性能的一种Trick。


与数据增强对训练集的方式类似,测试时间数据增强的目的是对测试图像进行不同方式的修改。因此,我们将向训练好的模型展示几次增强后的图像,而不是只展示一次常规的、"干净的 "图像。然后,我们将对每张相应图像的预测进行平均,并将其作为模型的最终预测结果。



本项目基于热门开源项目做了简化,提升了易用性,使用如下:

import paddle
import ppma
import ppma.tta as tta

model = paddle.vision.resnet18(pretrained=True)
model_tta = tta.ClassTTA(model, tta.aliases.hflip_transform())   # 生成 TTA 模型

ppma.imagenet.val(model_tta, "data/ILSVRC2012")


我们可以看到只加了一个翻转增强,就能让ResNet18精度涨了0.8%




参考资料


https://image-net.org/
https://towardsdatascience.com/test-time-augmentation-tta-and-how-to-perform-it-with-keras-4ac19b67fb4d
https://github.com/qubvel/ttach
https://github.com/jacobgil/pytorch-grad-cam
Grad-CAM: Visual Explanations from Deep Networks via Gradient-based Localization Ramprasaath R. Selvaraju, Michael Cogswell, Abhishek Das, Ramakrishna Vedantam, Devi Parikh, Dhruv Batra
Grad-CAM++: Improved Visual Explanations for Deep Convolutional Networks Aditya Chattopadhyay, Anirban Sarkar, Prantik Howlader, Vineeth N Balasubramanian
https://github.com/PaddlePaddle/InterpretDL


InterpretDL:基于飞桨的模型可解释性算法开源库,目前集成了十余种主流的可解释性算法。InterpretDL遵循『Plug-and-Play』的设计理念,用户无需修改模型;所有算法使用统一API接口,方便用户快速上手;并对每种算法提供单独的教程与解析,帮助用户理解、选择合适的算法。


如果您想详细了解更多InterpretDL的相关内容,大家可以直接前往Github地址获得完整开源项目代码,记得Star收藏支持一下哦:

https://github.com/PaddlePaddle/InterpretDL




长按下方二维码立即

Star

更多信息:

  1. 飞桨官方QQ群:793866180

  2. 飞桨官网网址:

    www.paddlepaddle.org.cn/

  3. 飞桨开源框架项目地址:

    GitHub:

    github.com/PaddlePaddle/Paddle 
    Gitee:

    gitee.com/paddlepaddle/Paddle

  4. 欢迎在飞桨论坛讨论交流~~

    http://discuss.paddlepaddle.org.cn