谈谈机器学习模型的可解释性

深度学习一直被认为是一个黑盒子,可是试图对模型的理解仍然是很是必要的。先从一个例子来讲明解释神经网络的重要性:古代一个小镇上的一匹马可以作数学题,好比给它一个题目 2+3 ,它踏马蹄 5 下后就会停下,这匹马被当地称做神马汉斯。后来人们发现,汉斯其实并不会作数学题,它经过观察主人的反应来判断何时停下。所以当一个训练好的网络模型根据输入来输出他的答案时,有时候虽然也能获得正确的结果,可是咱们更多时候还须要知道网络输出这个结果的缘由,这样可以帮助咱们来判断模型获得的这个结果是否可靠。进一步地,咱们能够凭借解释的结果来进一步优化咱们的模型,而不只仅是从结果层面来进行约束git

在以前的一篇研究中,网络可以准确地将一幅大熊猫地图片识别为大熊猫,可是当这张图片混有必定的噪声时,网络识别的结果是长臂猿。因而可知,网络有时候只能根据数据集和损失函数来优化它的拟合过程,可是网络具体作出决定依靠的是图像的哪些特征则很难进行判断。就像考试的目的是为了让学生更好地掌握书本知识,而后取得高分,每每咱们会经过题海战术来更方便快捷地总结出题规律,能达到更好的效果,这显然与素质教育的本质背道而驰。github

笔者曾在2021年CVPR上发表过一篇关于图像去噪的文章,里面提到了“提升神经网络的可解释性”,最近在面试中常常被问到相关的问题,可是我回答的老是不能令面试官满意,直到真正了解到针对神经网络可解释性的文章,我才明白其中的区别:面试

  1. 咱们文章的可解释性是针对在网络设计时网络结构,模块等都是经验性地选取,所以咱们根据传统的算法进行理论推导,而后使用神经网络的拟合能力对理论进行建模,完成整个网络的设计过程;
  2. 而本篇文章提到的可解释性是对网络输出结果的缘由进行讨论,试图解释网络输出结果的缘由,来帮助咱们判断模型获得的结果是否可靠。

Local Explanation主要解释作出决定的缘由,好比一张图片模型输出是猫,那么local explanation的目的就是解释为何它以为这张图片是猫?很容易想到关于Attention机制的一些研究,经过 Attention 机制可以给特征赋予不一样的空间和通道权重,从而使网络更加剧视重要信息。一般在解释Attention的效果时,会采用 Salience Map 来表示。以下图所示:算法

在 Salience Map 中,较亮的部分表明对网络影响最重要的区域。好比在分类任务中,判断是不是猴子网络主要感兴趣的区域确实是猴子,而不是其余的内容。所以,Salience Map 就至关于网络作出决定所给出的理由。那么 Salience Map 是怎么得出来的呢?

想象一下:若是我对图片的某个区域作干扰,那么若是干扰后影响了网络的判断结果,证实该干扰区域在网络作出判断时是重要的,反之则不重要。数学描述为:对于输入 \(X = [x_{1},x_{2},...x_{n}]\),其中 \(x_{i}\) 表明了每一个输入,对于图片而言就是每一个像素点。若是判断 \(x_{i}\) 对输出 \(y\) 的影响,那么能够给 \(x_{i}\) 增长一个扰动 \(\Delta x_{i}\),相应地输出结果的变化量为 \(\Delta y\),因而 \(x_{i}\) 的重要程度就能够描述为:网络

\[\dfrac{\Delta y}{\Delta x_{i}} = \dfrac{\partial y}{ \partial x_{i}} \]

计算 Salience Map 的PyTorch代码以下:函数

def compute_saliency_maps(X, y, model):
    """
    X表示图片, y表示分类结果, model表示使用的与训练好的分类模型
    输出为salience map: A Tensor of shape (N, H, W)
    """
    # 确保model是test模式
    model.eval()
    # 确保X是须要gradient
    X.requires_grad_()
    saliency = None
    logits = model.forward(X)
    logits.backward(torch.FloatTensor([1.]))  # 计算梯度
    saliency = abs(X.grad.data)  # 返回X的梯度绝对值大小
    saliency, _ = torch.max(saliency, dim=1)
    return saliency.squeeze()

输出结果以下:学习

可是 Salience Map 会存在一些问题,好比判断一个动物是不是大象,长鼻子是其中一个很是明显的特征,可是当鼻子长到必定程度时,再增长鼻子的长度丝绝不会改变网络的判断结果,此时鼻子的长度对网络判断的贡献就很小。

除了 Salience Map 外,类激活的热力图也能够显示原始图片的不一样区域对某个CNN输出结果的 “贡献” 程度,以下图所示:优化

类激活的热力图在文献 "Grad-CAM: visual explanations from deep networks via gradient-based localization" 首次被提出,方法能够总结为:给定一张输入图像,对于一个卷积层的输出特征图,用类别相对于通道的梯度对这个特征图中的每一个通道进行加权。直观上来看,理解这个技巧的一种方法是,你是用 “每一个通道对类别的重要程度” 对 “输入图像对不一样通道的激活强度” 的空间图进行加权,从而获得了 “输入图像对类别的激活强度” 的空间图。参考代码连接:https://github.com/jacobgil/pytorch-grad-cam

其实对于神经网络而言,它所看到的只是一堆数据而已,经过损失函数可使模型将这一堆数据映射为咱们想要的值,其实人是没法真正理解机器想的是什么的,这些只是想找一些合理的方法来将机器想的内容合理化为人们所指望的那个样子而已。因此对一些新入门的朋友而言,没必要过度纠结于神经网络究竟是怎么实现特定的功能的,就像一位大佬说过:The question of whether machines could think was “about as relevant as the question of whether Submarines Can Swim. 我的理解就是:思考和游泳都是人类具备的属性,目的可以帮助咱们解决事情或者可以在水里生存,可是反过来不必定成立,解决事情或者在水里生存不必定非要是咱们人类具备的属性,机器也能拥有这些,可是他们在以什么样的方式进行工做,咱们不得而知,讨论这个问题也就没什么意义,咱们只须要关心结果是不是咱们所须要的就好了。ui

相关文章
相关标签/搜索