随着DeepMind研发的围棋机器人AlphaGo接连击败了世界上的顶尖棋手,人工智能开始得到越来越多的关注。尤其是近年来计算机算力的增长以及可靠数据越来越容易获取,人工智能中的深度学习领域得到了高速发展,深度学习模型在一些任务上的智能可以达到甚至超过人类水平。
但是在光鲜亮丽的面纱之下笼罩着一团迷雾!深度学习模型因其大量的参数、复杂的结构,以及给出的结果难以直接被人们所理解,甚至被诟病为“黑盒模型”。为了能解决这类问题,近期飞桨推出了可解释性算法库InterpretDL,用户可以调用其中的算法来让自己的模型“说人话”。
为什么需要可解释性?
当前,也许有人会说黑盒就黑盒呗,模型效果好就行了吧?其实不然!模型的准确率高只能算是体现数据和推理结果的相关性,但是无法解释因果关系,这种不可解释性可以说将成为深度学习技术应用的“拦路虎”!尤其在金融、法律、医疗、安防等敏感领域,模型的可解释性更是尤为重要!
例如在AI医疗实践中,深度学习模型可以识别医学影像,辅助医生判断肿瘤等疾病,但模型依据哪些位置、什么特征给出了判断的结果?决策的依据是否符合医学知识?如果不能解答这些问题,AI模型很难得到医生的信任。
再如在AI辅助司法过程中,模型根据基本的案情给出了判决结果,这个结果将决定一个人或一群人的命运,在得出这个结果过程中有没有夹杂偏见、歧视等因素?如果无法解释判罚的由来以及合理性,则很容易带来不良社会影响。
此外,这种『黑盒』特性也给模型的研发带来难题。很多模型的准确率可以达到90%以上,其实这种比例已经比我们日常用的一些家电要好很多了,但是家电坏了可以修,例如电扇不转了,可以看看是电机坏了,还是电源问题,这些都可以通过各种工具查出来,然后换个质量好的零件就可以了。
可是模型推理错误了呢?有的视觉模型,仅对输入图片加一点干扰,可能就给出完全错误的结果,究竟是哪个参数或网络层导致的?要知道有的模型参数规模可以说成千上万,甚至更大,怎么查?仅靠“一不怕苦、二不怕累”的精神,盲目的选择数据训练、盲目的修改超参,对深度学习技术发展的推动作用也十分有限,因此深度学习的可解释性是一个急需解决的难题。
飞桨可解释性算法库
InterpretDL
InterpretDL是首个基于飞桨的可解释性算法库,当前0.2.0版本已经上线,对飞桨框架 2.0动态图编程范式做到了全面支持。该版本包含了深度学习领域中多种常见可解释性算法,可以对计算机视觉(CV)、自然语言处理(NLP)和结构化数据(Table)的模型进行解释。那么具体有哪些可以对模型进行解释的算法呢?大体可以被分为三类:基于输入特征的算法、基于模型中间特征的算法和对训练数据解释的算法,下面我们将逐一进行介绍。
基于输入特征的算法
基于输入特征的算法可以解释每个特征在推理中的重要性。其基本原理是通过直接对模型输入进行改动,从而根据得到的梯度或是模型的输出,判断出输入特征的重要程度。对于此类型,InterpretDL支持如下几种算法:
- SmoothGrad:基于最直接的对输入特征算梯度的Gradient算法,SmoothGrad给模型输入随机添加一定程度的噪音,再对其计算梯度,并取几轮计算的平均值,使解释结果更加稳定。
- IntegratedGradients:首先选取一个不含信息的参照物(如全黑图片),随后在参照物与输入的路径上选点计算梯度,最后求平均值。
- Occlusion:遮盖输入的不同部分,随后计算此改变对最终预测值的影响,得到不同部分的重要性。
- LIME:通过对输入进行轻微的扰动,探测黑盒模型的输出发生何种变化,根据这种变化在兴趣点(原始输入)训练一个可解释性模型。
- NormLIME:在一定数量样本的LIME解释基础上,进行归一化计算后得到平均值,以此给出一个全局的解释。
咱们以计算机视觉领域的任务举个例子。如下图所示,我们上述代表性算法中的LIME和SmoothGrad对样例图片的解释。我们可以看到LIME算法是以超像素块为单位进行解释,其中绿色标记块表示对模型预测结果最重要的区域。而SmoothGrad是以像素点为单位的解释,其亮度表示对模型预测结果的贡献度。从两个算法的推理结果看,可谓殊途同归,虽然表示方法不一样,但是都明显的证明了模型在做推理时是“看到”图像中对象的重要特征得出的结果!
此外,LIME算法在自然语言处理领域的情感分类任务中还可以标记出对判断结果有重要贡献的词组,如下图所示,绿色表示正向情感,红色表示负向情感。
基于模型中间特征的算法
此类方法着重于对输入经过模型时的中间特征进行一些操作,最终以热力图的形式展示关键区域。对于此类型,InterpretDL支持如下两种算法:
- GradCAM:对模型的中间层特征图计算梯度,和特征图结合,得到对输入特征的重要性解释。
- ScoreCAM:将中间层特征图与输入结合,根据模型的预测值,对特征图加权得到对模型的解释。
下图中呈现了GradCAM算法对图片中两种标签的解释:
对训练数据解释的算法
这种算法对训练数据中的每一个样本记录相关信息,可以得到不同样本在训练模型过程中扮演的角色,从而进一步理解并调整数据集。InterpretDL支持如下三种对训练数据解释的算法:
- Forgetting Events:通过记录训练过程中样本的预测数据,得到那些经常在上一轮训练预测正确,但在下一轮预测错误的样本,这些样本被认为是模型难以学会的样本。
- Influence Function:对于任一图片,可以计算训练数据中各个样本对此图片预测结果的贡献度,找到对其贡献最大的样本。
- TrainIng Data analYzer:百度自研的训练数据分析算法,通过分析训练过程中模型对样本的预测数据,按样本学习的难易程度划分,找到潜在的错标样本。
咱们同样通过一个例子来展示这种类型算法的解释方式。例如,我们在MNIST数据集上手动错标一些数据,然后使用TrainIng Data analYzer (TIDY)算法,记录样本在训练过程中的特征。如下图所示,其中两类特征可以很好地区分开错标与非错标样本。取左下、中间、以及右上的样本,我们可以发现它们分别对应易学习的样本、难学习的样本,以及错标样本。
通过上面的介绍,我们已经了解了InterpretDL中覆盖三大类的10种可解释性算法,及其中主要算法的效果展示,真的很强大!相信很多小伙伴都想动手来“拷问”下自己的模型了吧,那么InterpretDL好上手吗?
动手实操InterpretDL
其实上手真的很简单,总共三步就可以拿到结果:
- 把模型准备好。
- 把模型加载到可解释性算法中。
- 查看结果!
是不是和“把大象放冰箱”一样简单?具体代码如下所示,运行后即可看到结果。
import interpretdl as it
from paddle.vision.models import resnet50
paddle_model = resnet50(pretrained=True) #获得模型
sg = it.SmoothGradInterpreter(paddle_model, use_cuda=True) #把模型加载到可解释性算法中,这里我们用的是SmoothGrad算法
gradients = sg.interpret(“test.jpg”, visual=True, save_path=None) #展示结果
visualize_grayscale(gradients[0]) #将结果转化为灰度图,展示效果更直观
InterpretDL还在“InterpretDL/tutorials”目录中提供了很多教程,演示了各个算法在CV或NLP任务钟的使用方法和效果,欢迎广大开发者朋友们试用!