可解释性与积分梯度 Integrated Gradients

  • 积分梯度是一种神经网络可解释性方法
  • 此方法首先在论文《Gradients of Counterfactuals》中提出,后来 《Axiomatic Attribution for Deep Networks》再次介绍了它,这已经是2016~2017年间的工作了
  • 此方法已得到较多应用,但是也有一些反对者表示其给出的结果对于积分路径敏感,不能给出唯一确切的结果,因此存在争议

1. 可解释性

  • 事实上,很多论文中对于可解释性的定义都不太一样,或者直接对避而不谈,这导致可解释性成为一个大而模糊的领域。一般概念上,可解释性就是我们想要知道模型对未见样本 x \pmb{x} x 给出预测 y ^ = f ( x ) \hat{y} = f(\pmb{x}) y^=f(x) 的原因。有些模型本身就是可解释的,比如线性回归、决策树、朴素贝叶斯等;有些模型则很困难解释,比如神经网络

  • 可解释性总体可以分为 “事前可解释性” 和 “事后可解释性

    • 事前(ante-hoc)可解释性:指通过训练结构简单、可解释性好的模型或将可解释性结合到具体的模型结构中的自解释模型使模型本身具备可解释能力。
    • 事后(post-hoc)可解释性:指通过开发可解释性技术解释已训练好的机器学习模型。根据解释目标和解释对象的不同,post-hoc可解释性又可分为全局可解释性(global interpretability)和局部可解释性(local interpretability)。全局可解释性旨在帮助人们理解复杂模型背后的整体逻辑以及内部的工作机制,局部可解释性旨在帮助人们理解机器学习模型针对每一个输入样本的决策过程和决策依据。

    其中事后可解释性又分为 “全局可解释性” 和 “局部可解释性”

    1. 全局可解释性:一般指模型告诉我们它眼中各类标签对应的样本应该具有什么样的特征。具体来说,可以利用可理解的规则集合对模型生成可解释的符号描述;或从难解释模型中提取一个可解释模型;又或者我们把模型结果定住,反向找哪些输入能使得结果最显著,从而获取机器眼中某类对象的总体特征(对象甚至可以是抽象的概念)。下图是神经网络模型中代表 “happy” 和 “serious” 的图像特征(更多相关图像见 OpenAI Microscope
      在这里插入图片描述在这里插入图片描述
    2. 局部可解释性:一般以输入样本为导向,试图分析某个输入样本的每一维特征对模型最终决策结果的贡献。经典的局部解释方法包括敏感性分析解释、局部近似解释、梯度反向传播解释、特征反演解释以及类激活映射解释等
  • 下图给出可解释方法的粗略分类,更多详细说明,请参考:机器学习的可解释性(总结)
    在这里插入图片描述

2. 积分梯度

  • 本方法思想来自 “事后可解释性 - 局部解释 - 敏感性解释”,有趣的一点在于其给出的解释可以组成一个线性模型,因此其属于 “事后可解释性 - 局部解释 - 局部近似方法”

2.1 梯度饱和问题

  • 先说明一下 “敏感性解释” 的思想。我们知道每个样本由多个特征组成,记作 x = { x 1 , x 2 , . . . , x n } \pmb{x} = \{x_1,x_2,...,x_n\} x={x1,x2,...,xn},这里特征的选取是多种多样的

    1. 对于传统ML方法,特征通常是直接给定的。比如西瓜书例子中,西瓜的 “色泽”、“敲声”…
    2. 在CV领域,特征可以是图像中的一个像素、一块区域…
    3. 在NLP领域,特征可以是句子中的一个单词、一个词组…
  • 现在想要知道某个特征对做预测的重要程度,最简单的想法就是修改它的值或直接拿掉它,看看预测结果变化有多大,变化越大就越重要。看下面这个图像分类任务的例子,在测试图片的任意位置贴一个固定大小的灰色方块,看看方块贴各个位置时对于预测结果的影响,把综合结果显示为热力图(越偏蓝影响越大),如图可见这种方法找到的关键特征是比较合理的
    在这里插入图片描述
    这个方法中,方块的大小和颜色都是需要调整的超参数,而且解释结果对于这些超参数是敏感的

  • 上面这个方法显然有些粗糙了,为了得到更精确的结果,做两个改动

    1. 方格尺寸缩小到一个像素
    2. 评估重要程度时,对某个方块(像素)施加微小扰动 △ x \triangle x x,观察结果变化 △ y \triangle y y,以 ∣ △ y △ x ∣ |\frac{\triangle y}{\triangle x}| xy 作为重要程度。假设某图像预测标签为 y k y_k yk,那么第 n n n 个像素 x n x_n xn 的重要程度为梯度 ∣ ∂ y k ∂ x n ∣ |\frac{\partial y_k}{\partial x_n}| xnyk

    让越重要的像素越亮,这样就能绘制出一张显示了关键区域的 saliency map,可见也是比较合理的
    在这里插入图片描述

  • 梯度饱和 gradient saturation 是上述 gradient based 方法的一个重要问题。假设我们要判读某张图片是否为大象的图片,显然鼻子长度是一个重要的指标。但是对于已经有长鼻子的大象来说,对其鼻子长度增长或缩短一点对于预测结果而言已经意义不大了。设模型为 f f f,输入图像为 x = { x 1 , x 2 , . . . , x n } \pmb{x} =\{x_1,x_2,...,x_n\} x={x1,x2,...,xn},鼻子是第 i i i 个属性 x i x_i xi,如下图所示
    在这里插入图片描述
    纵轴是模型将图像分类为大象的概率 f ( x ) f(\pmb{x}) f(x) ,横轴是大象鼻子长度,黄色线代表随着鼻子长度增大,分类为大象的概率不断上升并收敛到1;蓝色线为黄色线的梯度 ∂ f ( x ) ∂ x i \frac{\partial f(\mathbf{x})}{\partial x_i} xif(x)。可见,当黄线处于饱和区,其对应的梯度接近于 0,如果只看梯度,这种情况下会得出鼻子长度无关紧要的错误结论

2.2 积分梯度

  • 积分梯度法的思想很简单,既然鼻子太长时梯度饱和了,那我就从当前长度开始减短,每减短一点求一次梯度,直到减短到某个称为baseline的最小值(确保在非饱和区,这里设为鼻子长度为0),最后把所有梯度全部加起来就好了,当然这个求和还要乘上一个间隔 △ x i \triangle x_i xi,否则无限细分后求和会变成 ∞ \infin 。简单说,就是要用微元法求上图中蓝色线和横轴围成的面积。设baseline图像中的鼻子长度为0,记为 x ′ = { x 1 ′ , x 2 ′ , . . . , x n ′ } \pmb{x}' =\{x_1',x_2',...,x_n'\} x={x1,x2,...,xn},线性插值数为 m m m,则特征 x i x_i xi 的重要性为
    ϕ i I G ( f , x , x ′ ) = ∑ k = 0 m ∂ f ( x ′ + k n ( x − x ′ ) ) ∂ x i △ x i = ∑ k = 0 m ∂ f ( x ′ + k n ( x − x ′ ) ) ∂ x i 1 n ( x i − x i ′ ) \begin{aligned} \phi_i^{IG}(f,\pmb{x},\pmb{x}') &= \sum_{k=0}^{m}\frac{\partial f(\pmb{x}'+\frac{k}{n}(\pmb{x}-\pmb{x}'))}{\partial x_i}\triangle x_i \\ &= \sum_{k=0}^{m}\frac{\partial f(\pmb{x}'+\frac{k}{n}(\pmb{x}-\pmb{x}'))}{\partial x_i}\frac{1}{n}(x_i-x_i')\\ \end{aligned} ϕiIG(f,x,x)=k=0mxif(x+nk(xx))xi=k=0mxif(x+nk(xx))n1(xixi) 再取个极限 lim ⁡ m → ∞ \lim_{m\to \infin} limm,上式就变成了积分形式
    ϕ i I G ( f , x , x ′ ) = ∫ 0 1 δ f ( x ′ + α ( x − x ′ ) ) δ x i d α ( x i − x i ′ ) = ( x i − x i ′ ) ∫ 0 1 δ f ( x ′ + α ( x − x ′ ) ) δ x i d α \begin{aligned} \phi_i^{IG}(f,\pmb{x},\pmb{x}') &= \int_0^1\frac{\delta f(\pmb{x}'+\alpha(\pmb{x}-\pmb{x}'))}{\delta x_i}d\alpha(x_i-x_i') \\ &= (x_i-x_i') \int_0^1\frac{\delta f(\pmb{x}'+\alpha(\pmb{x}-\pmb{x}'))}{\delta x_i}d\alpha \end{aligned} ϕiIG(f,x,x)=01δxiδf(x+α(xx))dα(xixi)=(xixi)01δxiδf(x+α(xx))dα 注意,虽然通常和上面一样选择 γ ( α ) = x ′ + k m ( x − x ′ ) \gamma(\alpha) = \pmb{x}'+\frac{k}{m}(\pmb{x}-\pmb{x}') γ(α)=x+mk(xx) 的线性插值作为插值路径,但实际上可选的插值路径并不唯一,因此这个积分是一个泛函,相应的偏导数也变成变分形式。近年有文章说明选择不同的插值路径时,求出的积分梯度结果也可能不同,导致此方法的有效性出现争议
  • 我们上面的操作本质是在求 x \pmb{x} x x ′ \pmb{x}' x 之间梯度曲线(蓝色线)围成的面积,因此它代表着 x \pmb{x} x x ′ \pmb{x}' x 间的差(类似速度和距离的关系),即 f ( x i ) − f ( x i ′ ) = ϕ i I G ( f , x , x ′ ) f(x_i)-f(x_i') = \phi_i^{IG}(f,\pmb{x},\pmb{x}') f(xi)f(xi)=ϕiIG(f,x,x),此式对每一维特征都成立,因此积分梯度具有完备性(Completeness),即
    f ( x ) − f ( x ′ ) = ∑ i ϕ i I G ( f , x , x ′ ) = ϕ I G ( f , x , x ′ ) f(\pmb{x})-f(\pmb{x}') = \sum_i \phi_i^{IG}(f,\pmb{x},\pmb{x}') =\boldsymbol{\phi}^{IG}(f,\pmb{x},\pmb{x}') f(x)f(x)=iϕiIG(f,x,x)=ϕIG(f,x,x) 更重要的是,设 θ i ( f , x , x ′ ) = ∫ 0 1 δ f ( x ′ + α ( x − x ′ ) ) δ x i d α \theta_i (f,\pmb{x},\pmb{x}')= \int_0^1\frac{\delta f(\mathbf{x}'+\alpha(\mathbf{x}-\mathbf{x}'))}{\delta x_i}d\alpha θi(f,x,x)=01δxiδf(x+α(xx))dα,有
    f ( x ) − f ( x ′ ) = ϕ I G ( f , x , x ′ ) = < ( x − x ′ ) , θ ( f , x , x ′ ) > f(\pmb{x})-f(\pmb{x}') = \boldsymbol{\phi}^{IG}(f,\pmb{x},\pmb{x}') =\big< (\pmb{x}-\pmb{x}'),\boldsymbol{\theta}(f,\pmb{x},\pmb{x}')\big> f(x)f(x)=ϕIG(f,x,x)=(xx),θ(f,x,x)
    因此,任意样本相对于 Baseline 的相对重要程度,可以由特征之差 x − x ′ \pmb{x}-\pmb{x}' xx 和变分路径积分结果 θ ( f , x , x ′ ) \boldsymbol{\theta} (f,\pmb{x},\pmb{x}') θ(f,x,x) 线性表示,相当于是找了一个线性模型对样本 x \pmb{x} x 的预测进行了解释。因此前面提到积分梯度也属于 “事后可解释性 - 局部解释 - 局部近似方法”

3. 参考

  1. 机器学习的可解释性(总结)
  2. [distill] Visualizing the Impact of Feature Attribution Baselines (这一篇distill文章给出了很多可视化,另外深入讨论了Baseline的选择问题)
  3. 李宏毅课程
  4. 积分梯度 – 神经网络可解释性的另一种方法(这一篇和我的思路差不多,但我觉得他没讲清楚。另外评论区有人提出了关于此方法的争议)
  5. 积分梯度:一种新颖的神经网络可视化方法(这一篇写的不错,如果说我是从前往后说明,这篇就是从后往前说明,两个角度可以结合着看)
  • 27
    点赞
  • 69
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论
这里提供一个使用Integrated Gradients方法来解释神经网络分类决策的示例。Integrated Gradients是一种用于理解深度学习模型决策过程的方法,其通过计算模型输出值相对于输入变量的梯度,并在整个梯度路径上对输入进行积分,从而得到每个输入变量的重要性得分。 在这个示例中,我们使用一个预训练的简单的MNIST分类器来演示Integrated Gradients的应用。首先,我们需要定义一个计算模型输出的函数: ```python import tensorflow as tf import numpy as np # 加载MNIST数据集 (x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data() x_train, x_test = x_train / 255.0, x_test / 255.0 # 加载预训练的MNIST分类器模型 model = tf.keras.models.load_model('path/to/pretrained/mnist_classifier.h5') # 定义计算模型输出的函数 def predict_fn(x): return model.predict(np.array([x])) ``` 接下来,我们定义一个计算Integrated Gradients的函数: ```python def integrated_gradients( input_image, predict_fn, baseline=None, num_steps=50, num_runs=10 ): """ 计算输入图像的Integrated Gradients :param input_image: 输入图像 :param predict_fn: 计算模型输出的函数 :param baseline: 基准图像 :param num_steps: 积分步数 :param num_runs: 重复计算次数 :return: 输入图像的Integrated Gradients """ # 基准图像 if baseline is None: baseline = np.zeros_like(input_image) # 梯度路径上的权重 alphas = np.linspace(0, 1, num_steps)[:, np.newaxis, np.newaxis, np.newaxis].astype(np.float32) # 重复计算 ig_scores = [] for _ in range(num_runs): # 计算积分路径上的图像 inputs = [baseline + (input_image - baseline) * alpha for alpha in alphas] # 计算每个积分路径上的梯度 grads = [] for i in range(num_steps): with tf.GradientTape() as tape: tape.watch(inputs[i]) preds = predict_fn(inputs[i]) grads.append(tape.gradient(preds, inputs[i])[0]) # 计算Integrated Gradients ig = np.average(grads, axis=0) * (input_image - baseline) ig_scores.append(ig) return np.average(ig_scores, axis=0) ``` 最后,我们可以使用这个函数来计算输入图像的Integrated Gradients,并可视化每个像素的重要性得分: ```python import matplotlib.pyplot as plt # 选择一个输入图像 image = x_test[0] # 计算Integrated Gradients ig = integrated_gradients(image, predict_fn) # 可视化每个像素的重要性得分 plt.imshow(ig.squeeze(), cmap='gray') plt.show() ``` 这样,我们就可以得到每个像素的重要性得分,以解释模型对该图像的分类决策。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

云端FFF

所有博文免费阅读,求打赏鼓励~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值