赞
踩
基于实例的解释方法选择数据集的特定实例来解释机器学习模型的行为或解释底层数据分布。
基于实例的解释大多与模型无关,因为它们使任何机器学习模型都更具可解释性。与模型无关方法的区别在于,基于实例的方法通过选择数据集的实例而不是通过创建特征摘要(例如特征重要性或部分依赖性)来解释模型)。
只有当我们能够以人类可理解的方式表示数据实例时,基于实例的解释才有意义。这适用于图像,因为我们可以直接查看它们。一般来说,如果实例的特征值携带更多上下文,则基于实例的方法效果很好,这意味着数据具有结构,就像图像或文本一样。以有意义的方式表示表格数据更具挑战性,因为一个实例可能包含数百或数千个(结构较少的)特征。列出所有特征值来描述一个实例通常是没有用的。如果只有少数几个特征或者我们有办法总结一个实例,它会很好地工作。
基于实例的解释帮助人类构建机器学习模型的心智模型以及机器学习模型已经训练过的数据。它尤其有助于理解复杂的数据分布。但我所说的基于实例的解释是什么意思?我们经常在工作和日常生活中使用它们。让我们从一些例子1开始。
一位医生看到一名患者出现异常咳嗽和轻微发烧。病人的症状让她想起了她多年前有过类似症状的另一个病人。她怀疑她目前的患者可能患有同样的疾病,因此她采集了血液样本来检测这种特定疾病。
一位数据科学家为他的一个客户开展了一个新项目:分析导致键盘生产机器故障的风险因素。数据科学家记得他从事的一个类似项目,并重用了旧项目中的部分代码,因为他认为客户想要相同的分析。
一只小猫坐在燃烧的无人居住的房子的窗台上。消防部门已经到了,其中一名消防员思考了片刻,他是否可以冒险进入大楼去救小猫。他回忆起自己作为消防员生活中的类似案例:缓慢燃烧一段时间的旧木屋往往不稳定,最终倒塌。因为这个案子的相似性,他决定不进去,因为房子倒塌的风险太大了。幸运的是,小猫从窗户跳了出来,安全着陆,没有人在火灾中受到伤害。美满结局。
这些故事说明了我们人类如何通过例子或类比思考。基于实例的解释的蓝图是:事物 B 与事物 A 相似,而 A 导致 Y,所以我预测 B 也会导致 Y。
隐含地,一些机器学习方法是基于实例的。[决策树]](#tree)根据对预测目标很重要的特征中数据点的相似性,将数据划分为节点。
决策树通过查找相似的实例(=在同一终端节点中)并返回这些实例的结果的平均值作为预测来获取新数据实例的预测。
k-最近邻 (knn) 方法明确适用于基于实例的预测。
对于一个新实例,knn 模型定位 k 个最近的邻居(例如,k=3 个最近的实例)并返回这些邻居的结果的平均值作为预测。knn 的预测可以通过返回 k 个邻居来解释,同样,只有当我们有一种好的方法来表示单个实例时,它才有意义。
以下解释方法均基于实例:
作者:Susanne Dandl 和 Christoph Molnar
devtools::load_all()
set.seed(42)
反事实解释以如下形式描述了一种因果情况:“如果
X
X
X 没有发生,
Y
Y
Y 就不会发生”。
例如:“如果我没有喝一口这种热咖啡,我就不会烫到我的舌头”。
事件
Y
Y
Y 是我烧了我的舌头;
因为
X
X
X 是我喝了热咖啡。
反事实思考需要想象一个与观察到的事实相矛盾的假设现实(例如,一个我没有喝过热咖啡的世界),因此得名“反事实”。
与其他动物相比,反事实思考的能力使我们人类如此聪明。
在可解释的机器学习中,反事实解释可用于解释单个实例的预测。
“事件”是一个实例的预测结果,“原因”是该实例的特定特征值,它们输入到模型中并“导致”某个预测。
显示为图表,输入和预测之间的关系非常简单:
特征值导致预测。
即使实际上输入与要预测的结果之间的关系可能不是因果关系,我们也可以将模型的输入视为预测的原因。
鉴于这个简单的图表,很容易看出我们如何模拟反事实来预测机器学习模型:
我们只是在进行预测之前更改实例的特征值,然后分析预测如何变化。
我们对预测以相关方式发生变化的场景感兴趣,例如预测类别的翻转(例如,信用申请被接受或拒绝),或者预测达到某个阈值(例如,癌症的概率达到10%)。
预测的反事实解释描述了将预测更改为预定义输出的特征值的最小变化。
有模型无关和模型特定的反事实解释方法,但在本章中,我们关注仅适用于模型输入和输出(而不是特定模型的内部结构)的模型无关方法。
这些方法在[模型无关章节](#agnostic)中也很熟悉,因为解释可以表示为特征值差异的总结(“改变特征A和B以改变预测”)。
但是反事实解释本身就是一个新的实例,所以它存在于本章中(“从实例X开始,改变A和B得到一个反事实实例”)。
与 原型 不同,反事实不一定是来自训练数据的实际实例,而是可以是特征值的新组合。
在讨论如何创建反事实之前,我想讨论一些反事实的用例以及一个好的反事实解释是什么样的。
在第一个示例中,彼得申请贷款并被(机器学习驱动的)银行软件拒绝。
他想知道为什么他的申请被拒绝,以及如何提高获得贷款的机会。
“为什么”的问题可以表述为反事实:
将预测从拒绝变为批准的特征(收入、信用卡数量、年龄……)的最小变化是什么?
一种可能的答案可能是:
如果彼得每年多赚 10,000 美元,他就会得到贷款。
或者,如果彼得拥有较少的信用卡并且五年前没有拖欠贷款,他就会得到贷款。
彼得永远不会知道拒绝的原因,因为银行对透明度不感兴趣,但那是另一回事了。
在我们的第二个示例中,我们想要解释一个模型,该模型通过反事实解释来预测连续结果。
Anna 想出租她的公寓,但她不确定要收取多少费用,因此她决定训练一个机器学习模型来预测租金。
当然,由于 Anna 是一名数据科学家,这就是她解决问题的方式。
在输入有关大小、位置、是否允许携带宠物等所有详细信息后,模特告诉她可以收取 900 欧元的费用。
她预计 1000 欧元或更多,但她信任她的模型并决定使用公寓的特征值,看看如何提高公寓的价值。
她发现如果该公寓再大
15
m
2
15m^2
15m2,则可以以超过 1000 欧元的价格出租。
有趣但不可操作的知识,因为她无法扩大她的公寓。
最后,通过仅调整她控制下的特征值(内置厨房是/否、允许携带宠物是/否、地板类型等),她发现如果她允许携带宠物并安装隔热效果更好的窗户,她可以收取 1000 欧元。
Anna 直觉地使用反事实来改变结果。
反事实是 人性化的解释,因为它们与当前实例形成对比,并且因为它们是选择性的,这意味着它们通常专注于少数特征变化。
但反事实受到“罗生门效应”的影响。
罗生门是一部日本电影,其中一个武士被谋杀是由不同的人讲述的。
每个故事都同样很好地解释了结果,但故事相互矛盾。
反事实也可能发生同样的情况,因为通常有多种不同的反事实解释。
每个反事实都讲述了如何达到某个结果的不同“故事”。
一个反事实可能会说改变特征 A,另一个反事实可能会说保持 A 不变但改变特征 B,这是矛盾的。
可以通过报告所有反事实解释或通过制定标准来评估反事实并选择最佳解释来解决多重事实的问题。
说到标准,我们如何定义一个好的反事实解释?
首先,反事实解释的用户定义了实例预测中的相关变化(=替代现实)。
一个明显的第一个要求是一个反事实实例尽可能接近地产生预定义的预测。
并不总是可以找到与预定义预测相反的事实。
例如,在具有两个类(稀有类和频繁类)的分类设置中,模型可能总是将实例分类为频繁类。
更改特征值以使预测标签从频繁类翻转到稀有类可能是不可能的。
因此,我们希望放宽反事实的预测必须与预定义结果完全匹配的要求。
在分类示例中,我们可以寻找一个反事实,其中稀有类的预测概率增加到
10
%
10\%
10%,而不是当前的
2
%
2\%
2%。
那么问题是,使预测概率从
2
%
2\%
2% 变为
10
%
10\%
10%(或接近
10
%
10\%
10%)的特征的最小变化是多少?
另一个质量标准是一个反事实应该与关于特征值的实例尽可能相似。
例如,如果我们同时具有离散特征和连续特征,则可以使用曼哈顿距离或高尔距离来测量两个实例之间的距离。
反事实不仅应该接近原始实例,还应该尽可能少地改变特征。
为了衡量这个指标中反事实解释的好坏,我们可以简单地计算变化特征的数量,或者用花哨的数学术语,测量反事实和实际实例之间的
L
0
L_0
L0 范数。
第三,通常需要生成多种不同的反事实解释,以便决策主体可以使用多种可行的方式来产生不同的结果。
例如,继续我们的贷款示例,一种反事实解释可能建议仅将收入翻倍以获得贷款,而另一种反事实解释可能建议转移到附近的城市并增加少量收入以获得贷款。
可以注意到,虽然第一个反事实可能对某些人来说是可能的,但后者可能对其他人来说更可行。
因此,除了为决策主体提供不同的方式来获得期望的结果之外,多样性还使“多样化”的个体能够改变对他们来说方便的特征。
最后一个要求是一个反事实实例应该具有可能的特征值。
对于公寓面积为负数或房间数量设置为 200 的租金示例,生成反事实解释是没有意义的。
如果根据数据的联合分布,反事实很可能就更好了,例如,10 个房间和
20
m
2
20 m^2
20m2 的公寓不应该被视为反事实解释。
理想情况下,如果增加平方米数量,也应该提出增加房间数量。
产生反事实解释的一种简单而幼稚的方法是通过反复试验进行搜索。
这种方法涉及随机更改感兴趣实例的特征值,并在预测到所需输出时停止。
就像安娜试图找到她可以收取更多租金的公寓版本的例子一样。
但是有比试错更好的方法。
首先,我们根据上述标准定义损失函数。
这种损失将感兴趣的实例、反事实和期望的(反事实)结果作为输入。
然后,我们可以找到使用优化算法最小化这种损失的反事实解释。
许多方法都以这种方式进行,但在损失函数和优化方法的定义上有所不同。
在下文中,我们关注其中两个:首先,Wachter 等人的一个。(2017)3,他引入了反事实解释作为解释方法,其次是 Dandl 等人的方法。(2020)4 考虑到上述所有四个标准。
Wachter 等人建议尽量减少以下损失:
L ( x , x ′ , y ′ , λ ) = λ ⋅ ( f ^ ( x ′ ) − y ′ ) 2 + d ( x , x ′ ) L(x,x^\prime,y^\prime,\lambda)=\lambda\cdot(\hat{f}(x^\prime)-y^\prime)^2+d(x,x^\prime) L(x,x′,y′,λ)=λ⋅(f^(x′)−y′)2+d(x,x′)
第一项是模型预测反事实
x
′
x'
x′ 和期望结果
y
′
y'
y′ 之间的二次距离,用户必须提前定义。
第二项是要解释的实例
x
x
x 与反事实
x
′
x'
x′ 之间的距离 d。
损失衡量反事实的预测结果与预定义结果的距离以及反事实与感兴趣的实例的距离。
距离函数 d 定义为使用每个特征的逆中值绝对偏差 (MAD) 加权的曼哈顿距离。
d ( x , x ′ ) = ∑ j = 1 p ∣ x j − x j ′ ∣ M A D j d(x,x^\prime)=\sum_{j=1}^p\frac{|x_j-x^\prime_j|}{MAD_j} d(x,x′)=j=1∑pMADj∣xj−xj′∣
总距离是所有
p
p
p 个特征距离的总和,即实例
x
x
x 和反事实
x
′
x'
x′ 之间的特征值的绝对差值。
特征距离通过特征
j
j
j 在数据集上的绝对偏差中值的倒数来缩放,定义为:
M A D j = median i ∈ { 1 , … , n } ( ∣ x i , j − median l ∈ { 1 , … , n } ( x l , j ) ∣ ) MAD_j=\text{median}_{i\in{}\{1,\ldots,n\}}(|x_{i,j}-\text{median}_{l\in{}\{1,\ldots,n\}}(x_{l,j})|) MADj=mediani∈{1,…,n}(∣xi,j−medianl∈{1,…,n}(xl,j)∣)
向量的中值是向量值的一半较大而另一半较小的值。
MAD 等价于特征的方差,但不是使用均值作为中心并在平方距离上求和,而是使用中值作为中心并在绝对距离上求和。
所提出的距离函数具有优于欧几里得距离的优点:
它对异常值更稳健。
使用 MAD 进行缩放对于使所有功能达到相同的比例是必要的——无论你以平方米还是平方英尺来衡量公寓的大小都无关紧要。
参数
λ
\lambda
λ 平衡预测中的距离(第一项)与特征值中的距离(第二项)。
对于给定的
λ
\lambda
λ,损失被求解并返回一个反事实的
x
′
x'
x′ 。
λ
\lambda
λ的较高值意味着我们更喜欢预测接近预期结果
y
′
y'
y′ 的反事实,较低的值意味着我们更喜欢与特征值中的
x
x
x 非常相似的反事实
x
′
x'
x′ 。
如果
λ
\lambda
λ 非常大,则预测最接近
y
′
y'
y′ 的实例将被选中,无论它离
x
x
x 多远。
最终,用户必须决定如何平衡反事实的预测与期望结果相匹配的要求与反事实与
x
x
x 相似的要求。
该方法的作者建议不要选择
λ
\lambda
λ 的值,而是选择允许反事实实例的预测与
y
′
y'
y′ 相差多远的容差
ϵ
\epsilon
ϵ。
这个约束可以写成:
∣ f ^ ( x ′ ) − y ′ ∣ ≤ ϵ |\hat{f}(x^\prime)-y^\prime|\leq\epsilon ∣f^(x′)−y′∣≤ϵ
为了最小化这个损失函数,可以使用任何合适的优化算法,例如 Nelder-Mead。
如果你可以访问机器学习模型的梯度,则可以使用 ADAM 等基于梯度的方法。
要解释的实例
x
x
x 、所需的输出
y
′
y'
y′ 和容差参数
ϵ
\epsilon
ϵ 必须提前设置。
x’ 的损失函数最小化,并且(局部)最优反事实
x
′
x'
x′ 返回,同时增加
λ
\lambda
λ 直到找到足够接近的解(= 在容差参数内):
arg min x ′ max λ L ( x , x ′ , y ′ , λ ) . \arg\min_{x^\prime}\max_{\lambda}L(x,x^\prime,y^\prime,\lambda). argx′minλmaxL(x,x′,y′,λ).
总的来说,产生反事实的方法很简单:
所提出的方法有一些缺点。
它只考虑第一个和第二个标准而不是最后两个(“产生只有少数特征变化和可能特征值的反事实”)。
d 不喜欢稀疏解决方案,因为将 10 个特征增加 1 将得到与
x
x
x 的距离与将一个特征增加 10 的距离相同。
不现实的特征组合不会受到惩罚。
该方法不能很好地处理具有许多不同级别的分类特征。
该方法的作者建议为分类特征的每个特征值组合分别运行该方法,但是如果你有多个具有许多值的分类特征,这将导致组合爆炸。
例如,具有十个唯一级别的六个分类特征将意味着一百万次运行。
现在让我们看一下克服这些问题的另一种方法。
Dandl等人建议同时最小化四目标损失
L ( x , x ′ , y ′ , X o b s ) = ( o 1 ( f ^ ( x ′ ) , y ′ ) , o 2 ( x , x ′ ) , o 3 ( x , x ′ ) , o 4 ( x ′ , X o b s ) ) L(x,x',y',X^{obs})=\big(o_1(\hat{f}(x'),y'),o_2(x, x'),o_3(x,x'),o_4(x',X^{obs})\big) L(x,x′,y′,Xobs)=(o1(f^(x′),y′),o2(x,x′),o3(x,x′),o4(x′,Xobs))
四个目标
o
1
o_1
o1 到
o
4
o_4
o4 中的每一个都对应于上述四个标准之一。
第一个目标
o
1
o_1
o1 反映了我们的反事实
x
′
x'
x′ 的预测应该尽可能接近我们期望的预测
y
′
y'
y′ 。
因此,我们希望最小化 $ \h at{f}(x’)$ 和
y
′
y'
y′ 之间的距离,这里由曼哈顿度量(
L
1
L_1
L1 norm)计算:
o 1 ( f ^ ( x ′ ) , y ′ ) = { 0 if f ^ ( x ′ ) ∈ y ′ inf y ′ ∈ y ′ ∣ f ^ ( x ′ ) − y ′ ∣ else o_1(\hat{f}(x'),y')={0if ˆf(x′)∈y′infy′∈y′|ˆf(x′)−y′|else o1(f^(x′),y′)={0y′∈y′inf∣f^(x′)−y′∣if f^(x′)∈y′else
第二个目标
o
2
o_2
o2 反映了我们的反事实应该与我们的实例
x
x
x 尽可能相似。
它量化了
x
′
x'
x′ 和
x
x
x 之间的距离
作为高尔距离:
o 2 ( x , x ′ ) = 1 p ∑ j = 1 p δ G ( x j , x j ′ ) o_2(x,x')=\frac{1}{p}\sum_{j=1}^{p}\delta_G(x_j, x'_j) o2(x,x′)=p1j=1∑pδG(xj,xj′)
其中 p 是特征的数量。
$ \delta_G$ 的值取决于
x
j
x_j
xj 的特征类型:
δ G ( x j , x j ′ ) = { 1 R ^ j ∣ x j − x j ′ ∣ if x j numerical I x j ≠ x j ′ if x j categorical \delta_G(x_j,x'_j)={1ˆRj|xj−x′j|if xj numericalIxj≠x′jif xj categorical δG(xj,xj′)={R j1∣xj−xj′∣Ixj=xj′if xj numericalif xj categorical
将数值特征 j j j 的距离除以观察值范围 $ \widehat{R}_j$,为 0 到 1 之间的所有特征缩放 $ \delta_G$。
Gower 距离可以处理数字和分类特征,但不计算改变了多少特征。
因此,我们使用
L
0
L_0
L0 范数计算第三个目标
o
3
o_3
o3 中的特征数量:
o 3 ( x , x ′ ) = ∣ ∣ x − x ′ ∣ ∣ 0 = ∑ j = 1 p I x j ′ ≠ x j . o_3(x,x')=||x-x'||_0=\sum_{j=1}^{p}\mathbb{I}_{x'_j\neq x_j}. o3(x,x′)=∣∣x−x′∣∣0=j=1∑pIxj′=xj.
通过最小化 o 3 o_3 o3 ,我们的目标是我们的第三个标准——稀疏的特征变化。
第四个目标
o
4
o_4
o4 反映了我们的反事实应该具有可能的特征值/组合。
我们可以推断出一个数据点使用训练数据或另一个数据集的“可能性”有多大。
我们将此数据集表示为
X
o
b
s
X^{obs}
Xobs。
作为似然的近似值,
o
4
o_4
o4 测量
x
′
x'
x′ 和最近的观测数据点
x
[
1
]
∈
X
o
b
s
x^{[1]}\in{}X^{obs}
x[1]∈Xobs 之间的平均 Gower 距离:
o 4 ( x ′ , X o b s ) = 1 p ∑ j = 1 p δ G ( x j ′ , x j [ 1 ] ) o_4(x',\textbf{X}^{obs})=\frac{1}{p}\sum_{j=1}^{p}\delta_G(x'_j,x^{[1]}_j) o4(x′,Xobs)=p1j=1∑pδG(xj′,xj[1])
与 Wachter 等人相比,
L
(
x
,
x
′
,
y
′
,
X
o
b
s
)
L(x,x',y',X^{obs})
L(x,x′,y′,Xobs) 没有像
λ
\lambda
λ 这样的平衡/加权项。
我们不想通过将
o
1
o_1
o1、
o
2
o_2
o2、
o
3
o_3
o3 和
o
4
o_4
o4 四个目标合并并加权来将它们合并为一个目标,但我们希望同时优化所有四个项。
我们怎么能做到这一点?
我们使用非支配排序遗传算法 5 或简称 NSGA-II。
NSGA-II 是一种受自然启发的算法,它应用了达尔文的“适者生存”定律。
我们用目标值向量
(
o
1
,
o
2
,
o
3
,
o
4
)
(o_1,o_2,o_3,o_4)
(o1,o2,o3,o4) 来表示反事实的适应度。
反事实的目标值越低,它就越“适合”。
该算法由重复的四个步骤组成,直到满足停止标准,例如,最大迭代/代数。
下图可视化了一代的四个步骤。
在第一代中,一组反事实候选者通过随机改变一些特征来初始化,与我们要解释的实例
x
x
x 相比。
坚持上面的信用示例,一个反事实可能建议将收入增加 30,000 欧元,而另一个建议在过去五年内没有违约并将年龄减少十岁。
所有其他特征值都等于
x
x
x 的值。
然后使用上述四个目标函数评估每个候选人。
其中,我们随机选择了一些候选者,其中更适合的候选者更有可能被选中。
候选者被成对重组,通过平均它们的数值特征值或交叉它们的分类特征来产生与它们相似的孩子。
此外,我们稍微改变孩子的特征值来探索整个特征空间。
从两个结果组中,一个有父母,一个有孩子,我们只想要使用两种排序算法的最好的一半。
非支配排序算法根据候选者的目标值对候选者进行排序。
如果候选者同样优秀,则拥挤距离排序算法根据候选者的多样性对候选者进行排序。
鉴于两种排序算法的排名,我们选择最有希望和/或最多样化的一半候选者。
我们将此集合用于下一代,并从选择、重组和突变过程重新开始。
通过一遍又一遍地重复这些步骤,我们希望能够接近一系列具有低客观价值的有前途的候选人。
从这个集合中,我们可以选择我们最满意的那些,或者我们可以通过突出显示哪些特征以及多久改变一次来总结所有反事实。
以下示例基于 Dandl 等人的信用数据集示例。(2020 年)。
德国信用风险数据集可以在机器学习挑战平台 kaggle.com 上找到。
作者训练了一个支持向量机(具有径向基核)来预测客户具有良好信用风险的概率。
相应的数据集有 522 个完整的观察结果和 9 个包含信用和客户信息的特征。
目标是为具有以下特征值的客户找到反事实解释:
age | sex | job | housing | savings | amount | duration | purpose | |
---|---|---|---|---|---|---|---|---|
58 | f | unskilled | free | little | 6143 | 48 | car |
SVM 以
24.2
%
24.2\%
24.2% 的概率预测该女性具有良好的信用风险。
反事实应该回答如何改变输入特征以获得大于
50
%
50\%
50% 的预测概率?
下表显示了十个最佳反事实:
age | sex | job | amount | duration | o 2 o_2 o2 | o 3 o_3 o3 | o 4 o_4 o4 | f ^ ( x ′ ) \hat{f}(x') f^(x′) |
---|---|---|---|---|---|---|---|---|
skilled | -20 | 0.108 | 2 | 0.036 | 0.501 | |||
skilled | -24 | 0.114 | 2 | 0.029 | 0.525 | |||
skilled | -22 | 0.111 | 2 | 0.033 | 0.513 | |||
-6 | skilled | -24 | 0.126 | 3 | 0.018 | 0.505 | ||
-3 | skilled | -24 | 0.120 | 3 | 0.024 | 0.515 | ||
-1 | skilled | -24 | 0.116 | 3 | 0.027 | 0.522 | ||
-3 | m | -24 | 0.195 | 3 | 0.012 | 0.501 | ||
-6 | m | -25 | 0.202 | 3 | 0.011 | 0.501 | ||
-30 | m | skilled | -24 | 0.285 | 4 | 0.005 | 0.590 | |
-4 | m | -1254 | -24 | 0.204 | 4 | 0.002 | 0.506 |
前五列包含建议的特征更改(仅显示更改的特征),接下来的三列显示目标值( o 1 o_1 o1 在所有情况下都等于 0),最后一列显示预测概率。
所有反事实的预测概率都大于
50
%
50\%
50% ,并且不相互支配。
非支配意味着没有一个反事实在所有目标中的值都小于其他反事实。
我们可以将反事实视为一组权衡解决方案。
他们都建议将持续时间从 48 个月减少到至少 23 个月,其中一些建议女性应该变得熟练而不是不熟练。
一些反事实甚至建议将性别从女性改为男性,这表明该模型存在性别偏见。
这种变化总是伴随着年龄在 1 到 30 岁之间的减少。
我们还可以看到,尽管一些反事实建议对四个特征进行更改,但这些反事实是最接近训练数据的那些。
反事实解释的解释很清楚。
如果实例的特征值根据反事实发生变化,则预测变为预定义的预测。
没有额外的假设,也没有背景魔法。
这也意味着它不像 LIME 之类的方法那么危险,在这种方法中,我们还不清楚我们可以在多大程度上推断本地模型进行解释。
反事实方法创建了一个新实例,但我们也可以通过报告哪些特征值发生了变化来总结反事实。
这为我们提供了报告结果的两种选择。
你可以报告反事实实例或突出显示感兴趣的实例和反事实实例之间更改了哪些特征。
反事实方法不需要访问数据或模型 。
它只需要访问模型的预测功能,例如,它也可以通过 Web API 工作。
这对于由第三方审计或在不披露模型或数据的情况下为用户提供解释的公司很有吸引力。
由于商业秘密或数据保护原因,公司对保护模型和数据感兴趣。
反事实解释在解释模型预测和保护模型所有者的利益之间提供了平衡。
该方法也适用于不使用机器学习的系统。
我们可以为任何接收输入和返回输出的系统创建反事实。
预测公寓租金的系统也可以由手写规则组成,反事实解释仍然有效。
反事实解释方法相对容易实现,因为它本质上是一个损失函数(具有单个或多个目标),可以使用标准优化器库进行优化。
必须考虑一些额外的细节,例如将特征值限制在有意义的范围内(例如,只有正数的公寓大小)。
对于每个实例,你通常会发现多个反事实解释(罗生门效应)。
这很不方便——大多数人更喜欢简单的解释,而不是现实世界的复杂性。
这也是一个实际的挑战。
假设我们为一个实例生成了 23 个反事实解释。
我们是否都报告了他们?
只有最好?
如果它们都相对“好”,但又大不相同怎么办?
必须为每个项目重新回答这些问题。
拥有多个反事实解释也可能是有利的,因为人类可以选择与他们先前的知识相对应的解释。
Dandl 等人的多目标反事实解释方法。在 GitHub 存储库 中实现。
在 Python 包 Alibi 中,作者实现了 简单的反事实方法 以及一个扩展方法,它使用类原型来提高算法输出的可解释性和收敛性6。
Karimi 等人(2020)7 还在 GitHub 存储库 中提供了他们算法 MACE 的 Python 实现。
他们将适当反事实的必要标准转化为逻辑公式,并使用可满足性求解器来找到满足它们的反事实。
Mothilal 等人(2020)8 开发了 DiCE (Diverse Counterfactual Explanation) 以生成基于行列式点过程的多种反事实解释。
DiCE 实现了与模型无关的方法和基于梯度的方法。
另一种搜索反事实的方法是 Laugel 等人的“Growing Spheres”算法。(2017)[^球体]。
他们在论文中没有使用反事实这个词,但方法非常相似。
他们还定义了一个损失函数,该函数支持反事实,特征值的变化尽可能少。
他们建议先在兴趣点周围绘制一个球体,在该球体内采样点,然后检查其中一个采样点是否产生所需的预测,而不是直接优化函数。
然后他们相应地收缩或扩展球体,直到找到(稀疏的)反事实并最终返回。
Ribeiro 等人的锚点。(2018)9 与反事实相反,请参阅关于 Scoped Rules (Anchors) 的章节。
对抗性示例是具有小的、有意的特征扰动的实例,这些扰动会导致机器学习模型做出错误的预测。
我建议先阅读关于 Counterfactual Explanations 的章节,因为它们的概念非常相似。
对抗性示例是反事实示例,旨在欺骗模型,而不是解释它。
为什么我们对对抗样本感兴趣?
它们不只是没有实际相关性的机器学习模型的好奇副产品吗?
答案是明确的“不”。
对抗性示例使机器学习模型容易受到攻击,如下面的场景所示。
一辆自动驾驶汽车因为忽略了停车标志而撞上了另一辆车。
有人在标志上放了一张图片,对于人类来说,这个标志看起来像一个带有一点污垢的停车标志,但在汽车的标志识别软件上却被设计成一个禁止停车标志。
垃圾邮件检测器无法将电子邮件分类为垃圾邮件。
垃圾邮件的设计类似于普通电子邮件,但目的是欺骗收件人。
机器学习驱动的扫描仪在机场扫描行李箱中的武器。
开发了一把刀,通过让系统认为它是一把雨伞来避免被发现。
让我们看一下创建对抗样本的一些方法。
有许多技术可以创建对抗样本。
大多数方法建议最小化对抗性示例和要操作的实例之间的距离,同时将预测转移到期望的(对抗性)结果。
有些方法需要访问模型的梯度,这当然只适用于基于梯度的模型,例如神经网络,其他方法只需要访问预测函数,这使得这些方法与模型无关。
本节中的方法侧重于具有深度神经网络的图像分类器,因为在该领域进行了大量研究,并且对抗性图像的可视化非常具有教育意义。
图像的对抗性示例是具有故意扰动像素的图像,目的是在应用期间欺骗模型。
这些例子令人印象深刻地展示了用于物体识别的深度神经网络是多么容易被看似对人类无害的图像所欺骗。
如果你还没有看过这些示例,你可能会感到惊讶,因为预测的变化对于人类观察者来说是无法理解的。
对抗性示例就像视觉错觉,但对于机器而言。
我的狗有问题
Szegedy等人(2013)10 在他们的作品“Intriguing Properties of Neural Networks”中使用了基于梯度的优化方法来寻找深度神经网络的对抗样本。
这些对抗性示例是通过最小化以下关于 r 的函数来生成的:
l o s s ( f ^ ( x + r ) , l ) + c ⋅ ∣ r ∣ loss(\hat{f}(x+r),l)+c\cdot|r| loss(f^(x+r),l)+c⋅∣r∣
在这个公式中,
x
x
x 是一个图像(表示为像素向量),r 是创建对抗图像的像素变化(x+r 产生一个新图像),l 是期望的结果类,参数 c用于平衡图像之间的距离和预测之间的距离。
第一项是对抗样本的预测结果与期望的类 l 之间的距离,第二项衡量对抗样本与原始图像之间的距离。
这个公式几乎与生成[反事实解释](#counterfactual)的损失函数相同。
r 有额外的约束,因此像素值保持在 0 和 1 之间。
作者建议使用框约束 L-BFGS(一种适用于梯度的优化算法)来解决此优化问题。
受干扰的熊猫:快速梯度标志法
Goodfellow 等人(2014)11 发明了用于生成对抗性图像的快速梯度符号方法。
梯度符号法使用底层模型的梯度来寻找对抗样本。
通过向每个像素添加或减去一个小误差
ϵ
\epsilon
ϵ 来操纵原始图像
x
x
x 。
我们是加还是减
ϵ
\epsilon
ϵ 取决于一个像素的梯度符号是正的还是负的。
在梯度方向上添加错误意味着图像被故意更改,从而导致模型分类失败。
下面的公式描述了快速梯度符号法的核心:
x ′ = x + ϵ ⋅ s i g n ( ▽ x J ( θ , x , y ) ) x^\prime=x+\epsilon\cdot{}sign(\bigtriangledown_x{}J(\theta,x,y)) x′=x+ϵ⋅sign(▽xJ(θ,x,y))
其中
▽
x
J
\bigtriangledown_x{}J
▽xJ是模型损失函数相对于原始输入像素向量x的梯度,y是x的真实标签向量,
θ
\theta
θ是模型参数向量。
从梯度向量(与输入像素的向量一样长)我们只需要符号:
如果像素强度的增加会增加损失(模型产生的误差),则梯度的符号为正(+1),如果像素强度的降低会增加损失,则梯度的符号为负(-1)。
当神经网络以线性方式处理输入像素强度和类别分数之间的关系时,就会出现此漏洞。
特别是,有利于线性的神经网络架构,如 LSTM、maxout 网络、具有 ReLU 激活单元的网络或其他线性机器学习算法(如逻辑回归)容易受到梯度符号方法的影响。
攻击是通过外推进行的。
输入像素强度和类别分数之间的线性导致易受异常值的影响,即模型可以通过将像素值移动到数据分布之外的区域来欺骗。
我希望这些对抗性示例非常特定于给定的神经网络架构。
但事实证明,你可以重用对抗性示例来欺骗具有不同架构的网络,这些网络在同一任务上受过训练。
Goodfellow 等人(2014) 建议在训练数据中添加对抗样本来学习稳健的模型。
水母……不,等等。浴缸:单像素攻击
Goodfellow 及其同事(2014)提出的方法需要改变很多像素,即使只是一点点。
但是如果你只能改变一个像素呢?
你能欺骗机器学习模型吗?
Su 等人(2019) 12 表明,实际上可以通过改变单个像素来欺骗图像分类器。
与反事实类似,单像素攻击寻找一个修改后的示例
x
′
x'
x′ ,该示例接近原始图像
x
x
x ,但将预测更改为对抗性结果。
但是,接近度的定义不同:只有一个像素可以改变。
单像素攻击使用差分进化来找出要更改的像素以及如何更改。
差异进化大致受到物种生物进化的启发。
一群被称为候选解决方案的个体一代一代地重新组合,直到找到解决方案。
每个候选解决方案对像素修改进行编码,并由五个元素的向量表示:
x
x
x 和
y
y
y 坐标以及红色、绿色和蓝色 (RGB) 值。
例如,搜索从 400 个候选解决方案(= 像素修改建议)开始,并使用以下公式从父代创建新一代候选解决方案(子代):
x i ( g + 1 ) = x r 1 ( g ) + F ⋅ ( x r 2 ( g ) − x r 3 ( g ) ) x_{i}(g+1)=x_{r1}(g)+F\cdot(x_{r2}(g)-x_{r3}(g)) xi(g+1)=xr1(g)+F⋅(xr2(g)−xr3(g))
其中每个
x
i
x_i
xi 是候选解的一个元素(
x
x
x 坐标、
y
y
y 坐标、红色、绿色或蓝色),g 是当前代,
F
F
F 是缩放参数(设置为 0.5),r1、r2 和r3 是不同的随机数。
每个新的子候选解决方案又是一个具有五个位置和颜色属性的像素,每个属性都是三个随机父像素的混合。
如果候选解决方案之一是对抗性示例,则停止创建子代,这意味着它被分类为不正确的类,或者如果达到用户指定的最大迭代次数。
一切都是烤面包机:对抗补丁
我最喜欢的方法之一是将对抗性的例子带入物理现实。
Brown 等人(2017)13 设计了一个可打印的标签,可以贴在物体旁边,使它们看起来像用于图像分类器的烤面包机。
出色的工作!
该方法与迄今为止针对对抗性示例提出的方法不同,因为对抗性图像必须非常接近原始图像的限制已被消除。
相反,该方法将图像的一部分完全替换为可以呈现任何形状的补丁。
补丁的图像在不同的背景图像上进行了优化,补丁在图像上的不同位置,有时会移动,有时会变大或变小并旋转,从而使补丁在许多情况下都有效。
最后,这个优化的图像可以被打印出来并用于欺骗野外的图像分类器。
切勿将 3D 打印的乌龟带到枪战中——即使你的计算机认为这是一个好主意:稳健的对抗性示例
下一个方法实际上是为烤面包机添加另一个维度:
Athalye 等人(2017)14 3D 打印了一只乌龟,它被设计成从几乎所有可能的角度对深度神经网络来说看起来像一把步枪。
是的,你没看错。
一个在人类看来像乌龟的物理对象在计算机看来就像是一把步枪!
作者找到了一种在 3D 中为 2D 分类器创建对抗性示例的方法,该分类器对转换具有对抗性,例如旋转海龟、放大等的所有可能性。
当图像旋转或视角改变时,其他方法(例如快速梯度方法)不再起作用。
Athalye 等人(2017)提出了期望转换(EOT)算法,这是一种生成对抗性示例的方法,即使在图像转换时也可以工作。
EOT 背后的主要思想是在许多可能的转换中优化对抗性示例。
在给定可能变换的选定分布的情况下,EOT 不是最小化对抗样本和原始图像之间的距离,而是将两者之间的预期距离保持在某个阈值以下。
变换下的期望距离可以写成:
E t ∼ T [ d ( t ( x ′ ) , t ( x ) ) ] \mathbb{E}_{t\sim{}T}[d(t(x^\prime),t(x))] Et∼T[d(t(x′),t(x))]
其中
x
x
x 是原始图像,t(x) 是转换后的图像(例如旋转),x’ 是对抗样本,t(x’) 是其转换后的版本。
除了处理变换分布之外,EOT 方法还遵循熟悉的模式,将对抗性示例的搜索框架化为优化问题。
我们试图找到一个对抗样本
x
′
x'
x′ ,它在可能的变换 T 的分布中最大化所选类别
y
t
y_t
yt(例如“步枪”)的概率:
arg max x ′ E t ∼ T [ l o g P ( y t ∣ t ( x ′ ) ) ] \arg\max_{x^\prime }\mathbb{E}_{t\sim{}T}[log{}P(y_t|t(x^\prime))] argx′maxEt∼T[logP(yt∣t(x′))]
在对抗性示例 x ′ x' x′ 和原始图像 x x x 之间所有可能的转换的预期距离保持在某个阈值以下的约束下:
E t ∼ T [ d ( t ( x ′ ) , t ( x ) ) ] < ϵ and x ∈ [ 0 , 1 ] d \mathbb{E}_{t\sim{}T}[d(t(x^\prime),t(x))]<\epsilon\quad\text{and}\quad{}x\in[0,1]^d Et∼T[d(t(x′),t(x))]<ϵandx∈[0,1]d
我认为我们应该关注这种方法带来的可能性。
其他方法基于对数字图像的处理。
然而,这些 3D 打印的强大对抗样本可以插入到任何真实场景中,并欺骗计算机对对象进行错误分类。
让我们转过头来:如果有人制造了一把看起来像乌龟的步枪怎么办?
被蒙住眼睛的对手:黑盒攻击
想象以下场景:
我让你可以通过 Web API 访问我出色的图像分类器。
你可以从模型中获得预测,但你无权访问模型参数。
从你的沙发上,你可以发送相应分类的数据和我的服务答案。
大多数对抗性攻击都不适用于这种情况,因为它们需要访问底层深度神经网络的梯度才能找到对抗性示例。
Papernot 及其同事 (2017)15 表明,无需内部模型信息且无需访问训练数据,就可以创建对抗性示例。
这种(几乎)零知识攻击被称为黑盒攻击。
这个怎么运作:
代理模型的目的是逼近黑盒模型的决策边界,但不一定要达到相同的精度。
作者通过攻击在各种云机器学习服务上训练的图像分类器来测试这种方法。
这些服务根据用户上传的图像和标签训练图像分类器。
该软件自动训练模型 - 有时使用用户未知的算法 - 并部署它。
然后分类器对上传的图像进行预测,但无法检查或下载模型本身。
作者能够为各种提供者找到对抗性示例,其中多达
84
%
84\%
84% 的对抗性示例被错误分类。
如果要欺骗的黑盒模型不是神经网络,该方法甚至有效。
这包括没有梯度的机器学习模型,例如决策树。
机器学习处理已知的未知数:从已知分布预测未知数据点。
防御攻击处理未知的未知数:从未知的对抗输入分布中稳健地预测未知数据点。
随着机器学习被集成到越来越多的系统中,例如自动驾驶汽车或医疗设备,它们也成为攻击的切入点。
即使机器学习模型对测试数据集的预测是 100% 正确的,也可以找到对抗样本来欺骗模型。
机器学习模型对网络攻击的防御是网络安全领域的一个新部分。
比吉奥等人(2018)16 对十年来对抗性机器学习的研究进行了很好的回顾,本节以此为基础。
网络安全是一场军备竞赛,攻击者和防御者一次又一次地智取对方。
网络安全有三个黄金法则:1)了解你的对手 2)积极主动,3)保护自己。
不同的应用程序有不同的对手。
试图通过电子邮件骗取他人金钱的人是用户和电子邮件服务提供商的敌对代理人。
提供商想要保护他们的用户,以便他们可以继续使用他们的邮件程序,攻击者想要让人们给他们钱。
了解你的对手意味着了解他们的目标。
假设你不知道这些垃圾邮件发送者的存在,并且电子邮件服务的唯一滥用是发送盗版音乐副本,那么防御将有所不同(例如,扫描附件中的受版权保护的材料,而不是分析文本中的垃圾邮件指标)。
积极主动意味着积极测试和识别系统的弱点。
当你积极尝试用对抗性示例欺骗模型然后防御它们时,你是主动的。
使用解释方法来了解哪些特征很重要以及特征如何影响预测也是了解机器学习模型弱点的主动步骤。
作为数据科学家,你在这个危险的世界中信任你的模型,而无需超越测试数据集的预测能力吗?
你是否分析了模型在不同场景中的行为,确定了最重要的输入,检查了一些示例的预测解释?
你是否尝试过寻找对抗性输入?
机器学习模型的可解释性在网络安全中起着重要作用。
被动,与主动相反,意味着等到系统受到攻击,然后才了解问题并安装一些防御措施。
我们如何保护我们的机器学习系统免受对抗性示例的影响?
一种主动方法是使用对抗性示例对分类器进行迭代再训练,也称为对抗性训练。
其他方法基于博弈论,例如学习特征的不变变换或稳健优化(正则化)。
另一种建议的方法是使用多个分类器而不是一个分类器,并让它们对预测(集成)进行投票,但这并不能保证有效,因为它们都可能遭受类似的对抗性示例的影响。
另一种效果不佳的方法是梯度掩蔽,它通过使用最近邻分类器而不是原始模型来构建没有有用梯度的模型。
我们可以通过攻击者对系统的了解程度来区分攻击类型。
攻击者可能拥有完善的知识(白盒攻击),这意味着他们了解模型的所有信息,例如模型的类型、参数和训练数据;
攻击者可能只知道部分知识(灰盒攻击),这意味着他们可能只知道特征表示和使用的模型类型,但无法访问训练数据或参数;
攻击者可能零知识(黑盒攻击),这意味着他们只能以黑盒方式查询模型,而无法访问训练数据或有关模型参数的信息。
根据信息的级别,攻击者可以使用不同的技术来攻击模型。
正如我们在示例中所见,即使在黑盒情况下也可以创建对抗性示例,因此隐藏有关数据和模型的信息不足以防止攻击。
鉴于攻击者和防御者之间的猫捉老鼠游戏的性质,我们将看到这一领域的大量发展和创新。
想想不断发展的许多不同类型的垃圾邮件。
发明了针对机器学习模型的新攻击方法,并针对这些新攻击提出了新的防御措施。
开发了更强大的攻击来逃避最新的防御等等,无穷无尽。
通过本章,我希望让你对对抗样本问题敏感,只有通过积极研究机器学习模型,我们才能发现和弥补弱点。
原型是代表所有数据的数据实例。
驳议是一组原型不能很好地表示的数据实例。
驳议的目的是与原型一起提供见解,特别是对于原型不能很好地代表的数据点。
原型和驳议可以独立于机器学习模型来描述数据,但它们也可以用于创建可解释的模型或使黑盒模型可解释。
在本章中,我使用“数据点”来指代单个实例,以强调实例也是坐标系中的一个点,其中每个特征都是一个维度。
下图显示了一个模拟的数据分布,其中一些实例被选为原型,一些实例被选为驳议。
小点是数据,大点是驳议,大点是原型。
(手动)选择原型以覆盖数据分布的中心,驳议是没有原型的集群中的点。
原型和驳议总是来自数据的实际实例。
set.seed(1)
dat1 = data.frame(x1 = rnorm(20, mean = 4, sd = 0.3), x2 = rnorm(20, mean = 1, sd = 0.3))
dat2 = data.frame(x1 = rnorm(30, mean = 2, sd = 0.2), x2 = rnorm(30, mean = 2, sd = 0.2))
dat3 = data.frame(x1 = rnorm(40, mean = 3, sd = 0.2), x2 = rnorm(40, mean = 3))
dat4 = data.frame(x1 = rnorm(7, mean = 4, sd = 0.1), x2 = rnorm(7, mean = 2.5, sd = 0.1))
dat = rbind(dat1, dat2, dat3, dat4)
dat$type = "data"
dat$type[c(7, 23, 77)] = "prototype"
dat$type[c(81,95)] = "criticism"
ggplot(dat, aes(x = x1, y = x2)) + geom_point(alpha = 0.7) +
geom_point(data = filter(dat, type!='data'), aes(shape = type), size = 9, alpha = 1, color = "blue") +
scale_shape_manual(breaks = c("prototype", "criticism"), values = c(18, 19))
我手动选择了原型,这不能很好地扩展并且可能导致结果不佳。
有很多方法可以在数据中找到原型。
其中之一是 k-medoids,一种与 k-means 算法相关的聚类算法。
任何返回实际数据点作为聚类中心的聚类算法都有资格选择原型。
但是这些方法中的大多数只找到原型,而没有驳议。
本章介绍 Kim 等人的 MMD 评论家。(2016)2,一种将原型和驳议结合在一个框架中的方法。
MMD-critic 比较数据的分布和所选原型的分布。
这是理解 MMD-critic 方法的中心概念。
MMD-critic 选择最小化两个分布之间差异的原型。
高密度区域的数据点是很好的原型,尤其是当点是从不同的“数据集群”中选择的时候。
来自原型没有很好解释的区域的数据点被选为驳议。
让我们更深入地研究这个理论。
高层的 MMD-critic 程序可以简要概括为:
我们需要一些成分来找到具有 MMD-critic 的数据集的原型和驳议。
作为最基本的成分,我们需要一个内核函数来估计数据密度。
核函数是根据两个数据点的接近程度对它们进行加权的函数。
基于密度估计,我们需要一个度量来告诉我们两个分布有多么不同,以便我们可以确定我们选择的原型的分布是否接近数据分布。
这可以通过测量最大平均差异 (MMD)来解决。
同样基于核函数,我们需要witness function来告诉我们两个分布在特定数据点的不同之处。
使用见证函数,我们可以选择驳议,即原型和数据分布发散的数据点,并且见证函数具有较大的绝对值。
最后一个要素是对好的原型和驳议的搜索策略,可以通过简单的贪婪搜索来解决。
让我们从**最大平均差异 (MMD)**开始,它衡量两个分布之间的差异。
原型的选择创建了原型的密度分布。
我们想评估原型分布是否与数据分布不同。
我们用核密度函数估计两者。
最大平均差异衡量两个分布之间的差异,它是根据两个分布的期望之间的差异的函数空间上的上确界。
全清?
就个人而言,当我看到如何用数据计算某些东西时,我会更好地理解这些概念。
以下公式显示了如何计算平方 MMD 度量 (MMD2):
M M D 2 = 1 m 2 ∑ i , j = 1 m k ( z i , z j ) − 2 m n ∑ i , j = 1 m , n k ( z i , x j ) + 1 n 2 ∑ i , j = 1 n k ( x i , x j ) MMD^2=\frac{1}{m^2}\sum_{i,j=1}^m{}k(z_i,z_j)-\frac{2}{mn}\sum_{i,j=1}^{m,n}k(z_i,x_j)+\frac{1}{n^2}\sum_{i,j=1}^n{}k(x_i,x_j) MMD2=m21i,j=1∑mk(zi,zj)−mn2i,j=1∑m,nk(zi,xj)+n21i,j=1∑nk(xi,xj)
k
k
k 是一个核函数,用于测量两点的相似性,稍后会详细介绍。
m 是原型
z
z
z 的数量,n 是我们原始数据集中数据点
x
x
x 的数量。
原型
z
z
z 是数据点
x
x
x 的选择。
每个点都是多维的,即它可以有多个特征。
MMD-critic 的目标是最小化 MMD2。
MMD2 越接近于零,原型的分布就越适合数据。
将 MMD2 降为零的关键是中间项,它计算原型与所有其他数据点之间的平均接近度(乘以 2)。
如果这个术语加起来是第一项(原型彼此之间的平均接近度)加上最后一项(数据点彼此之间的平均接近度),那么原型完美地解释了数据。
试试如果你使用所有
n
n
n 个数据点作为原型,公式会发生什么。
下图说明了 MMD2 测量。
第一个图显示了具有两个特征的数据点,其中数据密度的估计以阴影背景显示。
其他每个图都显示了不同的原型选择,以及图标题中的 MMD2 度量。
原型是大点,它们的分布显示为等高线。
选择最能覆盖这些场景中数据的原型(左下)具有最低的差异值。
set.seed(42)
n = 40
# create dataset from three gaussians in 2d
dt1 = data.frame(x1 = rnorm(n, mean = 1, sd = 0.1), x2 = rnorm(n, mean = 1, sd = 0.3))
dt2 = data.frame(x1 = rnorm(n, mean = 4, sd = 0.3), x2 = rnorm(n, mean = 2, sd = 0.3))
dt3 = data.frame(x1 = rnorm(n, mean = 3, sd = 0.5), x2 = rnorm(n, mean = 3, sd = 0.3))
dt4 = data.frame(x1 = rnorm(n, mean = 2.6, sd = 0.1), x2 = rnorm(n, mean = 1.7, sd = 0.1))
dt = rbind(dt1, dt2, dt3, dt4)
radial = function(x1, x2, sigma = 1) {
dist = sum((x1 - x2)^2)
exp(-dist/(2*sigma^2))
}
cross.kernel = function(d1, d2) {
kk = c()
for (i in 1:nrow(d1)) {
for (j in 1:nrow(d2)) {
res = radial(d1[i,], d2[j,])
kk = c(kk, res)
}
}
mean(kk)
}
mmd2 = function(d1, d2) {
cross.kernel(d1, d1) - 2 * cross.kernel(d1, d2) + cross.kernel(d2,d2)
}
# create 3 variants of prototypes
pt1 = rbind(dt1[c(1,2),], dt4[1,])
pt2 = rbind(dt1[1,], dt2[3,], dt3[19,])
pt3 = rbind(dt2[3,], dt3[19,])
# create plot with all data and density estimation
p = ggplot(dt, aes(x = x1, y = x2)) +
stat_density_2d(geom = "tile", aes(fill = ..density..), contour = FALSE, alpha = 0.9) +
geom_point() +
scale_fill_gradient2(low = "white", high = "blue", guide = "none") +
scale_x_continuous(limits = c(0, NA)) +
scale_y_continuous(limits = c(0, NA))
# create plot for each prototype
p1 = p + geom_point(data = pt1, color = "red", size = 4) + geom_density_2d(data = pt1, color = "red") +
ggtitle(sprintf("%.3f MMD2", mmd2(dt, pt1)))
p2 = p + geom_point(data = pt2, color = "red", size = 4) +
geom_density_2d(data = pt2, color = "red") +
ggtitle(sprintf("%.3f MMD2", mmd2(dt, pt2)))
p3 = p + geom_point(data = pt3, color = "red", size = 4) +
geom_density_2d(data = pt3, color = "red") +
ggtitle(sprintf("%.3f MMD2", mmd2(dt, pt3)))
# TODO: Add custom legend for prototypes
# overlay mmd measure for each plot
gridExtra::grid.arrange(p, p1, p2, p3, ncol = 2)
核的选择是径向基函数核:
k ( x , x ′ ) = e x p ( − γ ∣ ∣ x − x ′ ∣ ∣ 2 ) k(x,x^\prime)=exp\left(-\gamma||x-x^\prime||^2\right) k(x,x′)=exp(−γ∣∣x−x′∣∣2)
其中
∣
∣
x
x
′
∣
∣
2
||xx'||^2
∣∣xx′∣∣2 是两点之间的欧几里得距离,
γ
\gamma
γ 是缩放参数。
内核的值随着两点之间的距离而减小,范围在零和一之间:
两点相距无限远时为零;
当两点相等时。
我们在一个寻找原型的算法中结合了 MMD2 度量、内核和贪心搜索:
寻找驳议的剩余成分是见证函数,它告诉我们两个密度估计在特定点上的差异有多大。
可以使用以下方法进行估算:
w i t n e s s ( x ) = 1 n ∑ i = 1 n k ( x , x i ) − 1 m ∑ j = 1 m k ( x , z j ) witness(x)=\frac{1}{n}\sum_{i=1}^nk(x,x_i)-\frac{1}{m}\sum_{j=1}^mk(x,z_j) witness(x)=n1i=1∑nk(x,xi)−m1j=1∑mk(x,zj)
对于两个数据集(具有相同的特征),见证函数为你提供了评估点
x
x
x 更适合哪个经验分布的方法。
为了找到驳议,我们在消极和积极的方向上寻找见证函数的极端值。
见证函数中的第一项是点
x
x
x 和数据之间的平均接近度,第二项分别是点
x
x
x 和原型之间的平均接近度。
如果点
x
x
x 的见证函数接近于零,则数据和原型的密度函数接近,这意味着原型的分布类似于点
x
x
x 处的数据分布。
x
x
x 点的负见证函数意味着原型分布高估了数据分布(例如,如果我们选择了一个原型但附近只有很少的数据点);
x
x
x 点的正见证函数意味着原型分布低估了数据分布(例如,如果
x
x
x 周围有很多数据点,但我们没有选择附近的任何原型)。
为了给你更多的直觉,让我们预先使用最低 MMD2 重用绘图中的原型,并显示几个手动选择的点的见证函数。
下图中的标签显示了标记为三角形的各个点的见证函数值。
只有中间的点具有较高的绝对值,因此很适合驳议。
witness = function(x, dist1, dist2, sigma = 1) {
k1 = apply(dist1, 1, function(z) radial(x, z, sigma = sigma))
k2 = apply(dist2, 1, function(z) radial(x, z, sigma = sigma))
mean(k1) - mean(k2)
}
w.points.indices = c(125, 2, 60, 19, 100)
wit.points = dt[w.points.indices,]
wit.points$witness = apply(wit.points, 1, function(x) round(witness(x[c("x1", "x2")], dt, pt2, sigma = 1), 3))
p + geom_point(data = pt2, color = "red") +
geom_density_2d(data = pt2, color = "red") +
ggtitle(sprintf("%.3f MMD2", mmd2(dt, pt2))) +
geom_label(data = wit.points, aes(label = witness), alpha = 0.9, vjust = "top") +
geom_point(data = wit.points, color = "black", shape = 17, size = 4)
见证函数允许我们显式搜索原型没有很好地表示的数据实例。
驳议是见证函数中绝对值高的点。
像原型一样,驳议也是通过贪婪搜索找到的。
但是,我们不是减少整体 MMD2,而是寻找最大化包括见证函数和正则项的成本函数的点。
优化函数中的附加项强制点的多样性,这是必要的,以便点来自不同的集群。
第二步与如何找到原型无关。
我也可以精心挑选一些原型并使用此处描述的程序来学习驳议。
或者原型可以来自任何聚类过程,比如 k-medoids。
这就是MMD驳议理论的重要部分。
还有一个问题:
如何将 MMD-critic 用于可解释的机器学习?
MMD-critic 可以通过三种方式增加可解释性:
通过帮助更好地了解数据分布;
通过建立一个可解释的模型;
通过使黑盒模型可解释。
如果你将 MMD-critic 应用于你的数据以查找原型和驳议,它将提高你对数据的理解,特别是如果你有一个具有边缘情况的复杂数据分布。
但是通过MMD-critic,你可以获得更多!
例如,你可以创建一个可解释的预测模型:所谓的“最近原型模型”。
预测函数定义为:
f ^ ( x ) = a r g m a x i ∈ S k ( x , x i ) \hat{f}(x)=argmax_{i\in{}S}k(x,x_i) f^(x)=argmaxi∈Sk(x,xi)
这意味着我们从原型集合 S 中选择最接近新数据点的原型 i,从某种意义上说,它产生了内核函数的最高值。
原型本身作为预测的解释返回。
此过程具有三个调整参数:
内核类型、内核缩放参数和原型数量。
所有参数都可以在交叉验证循环中进行优化。
在这种方法中没有使用驳议。
作为第三种选择,我们可以使用 MMD-critic 通过检查原型和驳议及其模型预测来使任何机器学习模型在全球范围内都可解释。
程序如下:
这有什么帮助?
还记得 Google 的图像分类器将黑人识别为大猩猩吗?
也许他们应该在部署他们的图像识别模型之前使用这里描述的过程。
仅仅检查模型的性能是不够的,因为如果它是
99
%
99\%
99% 正确的,那么这个问题可能仍然在
1
%
1\%
1% 之内。
标签也可能是错误的!
如果预测有问题,则检查所有训练数据并执行完整性检查可能会发现问题,但这是不可行的。
但是选择——比如说几千个——原型和驳议是可行的,并且可能揭示了数据的问题:
它可能表明缺少深色皮肤的人的图像,这表明数据集中的多样性存在问题。
或者它可以展示一个或多个深色皮肤的人的图像作为原型,或者(可能)作为臭名昭著的“大猩猩”分类的驳议。
我不保证 MMD-critic 肯定会拦截这些错误,但这是一个很好的理智检查。
以下 MMD-critic 示例使用手写数字数据集。
查看实际原型,你可能会注意到每个数字的图像数量不同。
这是因为在整个数据集中搜索了固定数量的原型,而不是每个类的固定数量。
正如预期的那样,原型展示了不同的数字书写方式。
在一项用户研究中,MMD-critic 的作者向参与者提供了图像,他们必须在视觉上与两组图像中的一组图像匹配,每组图像代表两个类别中的一个(例如两个犬种)。
当集合展示原型和驳议**而不是班级的随机图像时,**参与者表现最佳。
你可以自由地选择原型和驳议的数量。
MMD-critic 使用数据的密度估计。
这适用于任何类型的数据和任何类型的机器学习模型。
该算法易于实现。
MMD-critic 在用于提高可解释性的方式上非常灵活。
它可以用来理解复杂的数据分布。
它可用于构建可解释的机器学习模型。
或者它可以阐明黑盒机器学习模型的决策。
发现驳议与原型的选择过程无关。
但是根据 MMD-critic 选择原型是有道理的,因为原型和驳议都是使用比较原型和数据密度的相同方法创建的。
虽然在数学上,原型和驳议的定义不同,但它们的区别是基于截止值(原型的数量)。
假设你选择的原型数量太少而无法覆盖数据分布。
驳议最终会出现在没有得到很好解释的领域。
但是,如果你要添加更多原型,它们最终也会出现在相同的区域中。
任何解释都必须考虑到驳议强烈依赖于现有原型和原型数量的(任意)截止值。
你必须选择原型和驳议的数量。
尽管这可能很好,但它也是一个缺点。
我们实际上需要多少原型和驳议?
越多越好?越少越好吗?
一种解决方案是通过测量人类用于查看图像任务的时间来选择原型和驳议的数量,这取决于特定的应用程序。
只有在使用 MMD-critic 构建分类器时,我们才有办法直接对其进行优化。
一种解决方案可能是在
x
x
x 轴上显示原型数量和在
y
y
y 轴上显示 MMD2 测量值的 screeplot。
我们会选择 MMD2 曲线变平的原型数量。
其他参数是内核的选择和内核缩放参数。
我们有与原型和驳议数量相同的问题:
我们如何选择内核及其缩放参数?
同样,当我们使用 MMD-critic 作为最近的原型分类器时,我们可以调整内核参数。
然而,对于 MMD-critic 的无监督用例,尚不清楚。
(也许我在这里有点苛刻,因为所有无监督的方法都有这个问题。)
它将所有特征作为输入,忽略某些特征可能与预测感兴趣的结果无关这一事实。
一种解决方案是仅使用相关特征,例如图像嵌入而不是原始像素。
只要我们有办法将原始实例投影到仅包含相关信息的表示上,这就会起作用。
有一些可用的代码,但它尚未实现为良好打包和记录的软件。
MMD-critic 的实现可以在 作者 GitHub 存储库 中找到。
最近开发了 MMD-critic 的扩展:Protodash。
作者在他们的 出版物中声称优于 MMD-critic 。
IBM AIX360 工具中提供了 Protodash 实现。
寻找原型的最简单替代方法是 Kaufman 等人的 k-medoids。(1987).17
机器学习模型最终是训练数据的产物,删除一个训练实例会影响生成的模型。
当从训练数据中删除训练实例会显着改变模型的参数或预测时,我们将训练实例称为“有影响的”。
通过识别有影响的训练实例,我们可以“调试”机器学习模型并更好地解释它们的行为和预测。
本章向你展示了两种识别影响实例的方法,即删除诊断和影响函数。
这两种方法都基于稳健的统计数据,这些统计数据提供的统计方法受异常值或违反模型假设的影响较小。
稳健统计还提供了衡量数据估计的稳健程度的方法(例如平均估计或预测模型的权重)。
想象一下,你想估计你所在城市的人的平均收入,并在街上随机询问十个人他们的收入是多少。
除了你的样本可能真的很糟糕之外,你的平均收入估计会受到一个人的影响吗?
要回答这个问题,你可以通过省略个别答案来重新计算平均值,或者通过“影响函数”从数学上推导出平均值如何受到影响。
使用删除方法,我们重新计算平均值十次,每次都省略一张损益表,并测量平均估计值的变化量。
一个大的变化意味着一个实例非常有影响力。
第二种方法通过无限小的权重来增加其中一个人的权重,这对应于统计量或模型的一阶导数的计算。
这种方法也称为“无穷小方法”或“影响函数”。
顺便说一句,答案是你的平均估计值可能会受到单个答案的强烈影响,因为平均值与单个值呈线性关系。
一个更稳健的选择是中位数(一半人赚得更多而另一半人赚得更少的值),因为即使样本中收入最高的人的收入增加十倍,由此产生的中位数也不会改变。
删除诊断和影响函数也可以应用于机器学习模型的参数或预测,以更好地理解它们的行为或解释个体预测。
在我们研究这两种寻找有影响力实例的方法之前,我们将检查异常值和有影响力实例之间的区别。
异常值
异常值是远离数据集中其他实例的实例。
“远”是指到所有其他实例的距离(例如欧几里得距离)非常大。
在新生儿数据集中,体重 6 公斤的新生儿将被视为异常值。
在以支票账户为主的银行账户数据集中,专用贷款账户(负余额大,交易少)将被视为异常值。
下图显示了一维分布的异常值。
set.seed(42)
n = 50
x = rnorm(mean = 1, n = n)
x = c(x, 8)
y = rnorm(mean = x, n = n)
y = c(y, 7.2)
df = data.frame(x, y)
ggplot(df) + geom_histogram(aes(x = x)) + my_theme() +
scale_x_continuous("Feature x") +
scale_y_continuous("count")
异常值可能是有趣的数据点(例如[驳议](#proto)。
当异常值影响模型时,它也是一个有影响的实例。
Outliers can be interesting data points (e.g. criticisms).
When an outlier influences the model it is also an influential instance.
Influential instance
一个有影响的实例是一个数据实例,它的移除对训练的模型有很大的影响。
当使用从训练数据中删除的特定实例重新训练模型时,模型参数或预测的变化越大,该实例的影响力就越大。一个实例对训练模型是否有影响还取决于它对目标
y
y
y 的值。
下图显示了线性回归模型的一个有影响的实例。
df2 = df[-nrow(df),]
df3 = rbind(df2, data.frame(x = 8, y = 0))
df3$regression_model = "with influential instance"
df2$regression_model = "without influential instance"
df.all = rbind(df2, df3)
text.dat = data.frame(x = c(8), y = c(0), lab = c("Influential instance"), regression_model = "with influential instance")
ggplot(df.all, mapping = aes(x = x, y = y, group = regression_model, linetype = regression_model)) +
geom_point(size = 2) +
geom_smooth(method='lm',formula=y~x, se = FALSE, aes(color = regression_model), fullrange = TRUE) +
my_theme() +
geom_label(data = text.dat, aes(label = lab), hjust = 1, nudge_x = -0.2, vjust = 0.3) +
scale_x_continuous("Feature x") +
scale_y_continuous("Target y") +
scale_color_discrete("Model training") +
scale_linetype_discrete("Model training")
为什么有影响力的实例有助于理解模型?
具有影响力的可解释性实例背后的关键思想是将模型参数和预测追溯到一切开始的地方:训练数据。
学习器,即生成机器学习模型的算法,是一个函数,它获取由特征
X
X
X 和目标
y
y
y 组成的训练数据并生成机器学习模型。
例如,决策树的学习器是一种选择分割特征和分割值的算法。
神经网络的学习器使用反向传播来找到最佳权重。
我们询问如果我们在训练过程中从训练数据中删除实例,模型参数或预测将如何变化。
这与其他可解释性方法形成对比,这些方法分析当我们操纵要预测的实例的特征时预测如何变化,例如部分依赖图或特征重要性。
对于有影响的实例,我们不会将模型视为固定的,而是将其视为训练数据的函数。
有影响的实例帮助我们回答有关全局模型行为和个人预测的问题。
哪些是模型参数或总体预测最有影响的实例?
对于特定预测,哪些是最有影响力的实例?
有影响的实例告诉我们模型在哪些实例中可能存在问题,哪些训练实例应该检查错误并给出模型稳健性的印象。
如果单个实例对模型预测和参数有很大影响,我们可能不信任模型。
至少这会让我们进一步调查。
我们如何才能找到有影响力的实例?
我们有两种衡量影响力的方法:
我们的第一个选择是从训练数据中删除实例,在减少的训练数据集上重新训练模型,并观察模型参数或预测的差异(单独或在整个数据集上)。
第二种选择是通过基于模型参数的梯度近似参数变化来提升数据实例的权重。
删除方法更容易理解并激发了权重增加的方法,因此我们从前者开始。
统计学家已经在有影响力的实例领域进行了大量研究,特别是对于(广义)线性回归模型。
当你搜索“有影响的观察”时,第一个搜索结果是关于 DFBETA 和库克距离之类的度量。
DFBETA衡量删除实例对模型参数的影响。
Cook 距离 (Cook, 197718) 衡量删除实例对模型预测的影响。
对于这两种测量方法,我们都必须反复重新训练模型,每次都省略单个实例。
将具有所有实例的模型的参数或预测与具有从训练数据中删除的实例之一的模型的参数或预测进行比较。
DFBETA 定义为:
D F B E T A i = β − β ( − i ) DFBETA_{i}=\beta-\beta^{(-i)} DFBETAi=β−β(−i)
其中
β
\beta
β 是在所有数据实例上训练模型时的权重向量,
b
e
t
a
(
−
i
)
beta^{(-i)}
beta(−i) 是在没有实例
i
i
i 的情况下训练模型时的权重向量。
我会说非常直观。
DFBETA 仅适用于具有权重参数的模型,例如逻辑回归或神经网络,但不适用于决策树、树集成、一些支持向量机等模型。
库克距离是为线性回归模型发明的,并且存在广义线性回归模型的近似值。
训练实例的库克距离定义为当第
i
i
i 个实例从模型训练中移除时,预测结果的平方差的(缩放)总和。
D i = ∑ j = 1 n ( y ^ j − y ^ j ( − i ) ) 2 p ⋅ M S E D_i=\frac{\sum_{j=1}^n(\hat{y}_j-\hat{y}_{j}^{(-i)})^2}{p\cdot{}MSE} Di=p⋅MSE∑j=1n(y^j−y^j(−i))2
其中分子是有和没有第
i
i
i 个实例的模型预测之间的平方差,对数据集求和。
分母是特征数
p
p
p 乘以均方误差。
无论删除哪个实例
i
i
i,所有实例的分母都是相同的。
库克距离告诉我们,当我们从训练中删除第
i
i
i 个实例时,线性模型的预测输出会发生多大的变化。
我们可以将库克距离和 DFBETA 用于任何机器学习模型吗?
DFBETA 需要模型参数,因此此度量仅适用于参数化模型。
库克距离不需要任何模型参数。
有趣的是,库克的距离通常在线性模型和广义线性模型的上下文之外看不到,但是在移除特定实例之前和之后获取模型预测之间的差异的想法是非常普遍的。
库克距离定义的一个问题是 MSE,它对所有类型的预测模型(例如分类)都没有意义。
对模型预测的影响的最简单的影响度量可以写成如下:
Influence ( − i ) = 1 n ∑ j = 1 n ∣ y ^ j − y ^ j ( − i ) ∣ \text{Influence}^{(-i)}=\frac{1}{n}\sum_{j=1}^{n}\left|\hat{y}_j-\hat{y}_{j}^{(-i)}\right| Influence(−i)=n1j=1∑n∣ ∣y^j−y^j(−i)∣ ∣
这个表达式基本上是库克距离的分子,区别是绝对差加起来而不是平方差。
这是我做出的选择,因为它对后面的示例有意义。
删除诊断度量的一般形式包括选择度量(例如预测结果)并计算在所有实例上训练的模型以及实例被删除时的度量差异。
我们可以很容易地分解影响来解释实例 j j j 的预测第 i i i 个训练实例的影响是什么:
Influence j ( − i ) = ∣ y ^ j − y ^ j ( − i ) ∣ \text{Influence}_{j}^{(-i)}=\left|\hat{y}_j-\hat{y}_{j}^{(-i)}\right| Influencej(−i)=∣ ∣y^j−y^j(−i)∣ ∣
这也适用于模型参数的差异或损失的差异。
在下面的示例中,我们将使用这些简单的影响度量。
Deletion diagnostics example
在下面的例子中,我们训练一个支持向量机来预测[宫颈癌](#cervical)给定的风险因素,并测量哪些训练实例对整体和特定预测影响最大。
由于癌症的预测是一个分类问题,我们将影响测量为癌症预测概率的差异。
当实例从模型训练中移除时,如果预测概率在数据集中平均显着增加或减少,则该实例具有影响力。
测量所有rnrow(cervical)
训练实例的影响需要在所有数据上训练一次模型并重新训练它rnrow(cervical)
次(= 训练数据的大小),每个实例都删除一个时间。
#'@param predicted The predicted outcome of a model
#'@param predicted.without The predicted outcome of a model with a data point removed
influence.v = function(predicted, predicted.without) {
predicted - predicted.without
}
influence.matrix = matrix(NA, ncol = nrow(cervical), nrow = nrow(cervical))
lrn = makeLearner("classif.svm", predict.type = "prob")
tsk = makeClassifTask(data = cervical, target = "Biopsy")
mod = train(lrn, tsk)
predicted.orig = getPredictionProbabilities(predict(mod, newdata = cervical))
cs = lapply(1:nrow(cervical), function(to.remove.index) {
mod.2 = train(lrn, tsk, subset = setdiff(1:nrow(cervical), to.remove.index))
predict.removed = getPredictionProbabilities(predict(mod.2, newdata = cervical))
influence.v(predicted.orig, predict.removed)
})
# Column: Removed instance, row: influenced instance
influence.df = data.frame(cs)
influence.df = as.matrix(influence.df)
diag(influence.df) = NA
save(influence.df, predicted.orig, file = influence.matrix.filename)
load(influence.matrix.filename)
df = data.frame(influence = colMeans(abs(influence.df), na.rm = TRUE), id = 1:nrow(cervical))
df = df[order(df$influence, decreasing = TRUE),]
最有影响力的实例的影响度量约为r sprintf("%.2f", abs(df[1,"influence"]))
。
r sprintf('%.2f', abs(df[1,"influence"]))
的影响意味着如果我们删除r df$id[1]
-th 实例,预测概率会改变r sprintf('%.0f', 100 * df[1,"influence"])
平均百分比。
考虑到癌症的平均预测概率是r sprintf('%.1f', 100 *mean(predicted.orig))
% ,这是相当可观的。
所有可能删除的影响测量的平均值是r sprintf('%.1f', 100 * mean(abs(df$influence)))
个百分点。
现在我们知道哪些数据实例对模型影响最大。
这对于调试数据已经很有用了。
有问题的实例吗?
是否存在测量误差?
有影响的实例是第一个应该检查错误的实例,因为它们中的每个错误都会强烈影响模型的预测。
除了模型调试,我们能不能学习一些东西来更好地理解模型?
仅仅打印出最有影响力的前 10 个实例并不是很有用,因为它只是一个包含许多特征的实例表。
所有返回实例作为输出的方法只有在我们有一种很好的方式来表示它们时才有意义。
但是当我们询问时,我们可以更好地理解什么样的实例有影响:
有影响力的实例与无影响力的实例有什么区别?
我们可以将这个问题转化为回归问题,并将实例的影响建模为其特征值的函数。
我们可以从[可解释的机器学习模型](#simple)一章中自由选择任何模型。
对于这个例子,我选择了一个决策树(下图),它表明来自 35 岁及以上女性的数据对支持向量机的影响最大。
在rnrow(cervical)
数据集中的所有女性中,rsum(cervical$Age >= 35)
的年龄均超过 35 岁。
在关于 部分依赖图 的章节中,我们看到 40 岁之后癌症的预测概率急剧增加,并且 特征重要性 也将年龄检测为最重要的特征。
影响分析告诉我们,在预测更高年龄的癌症时,模型变得越来越不稳定。
这本身就是有价值的信息。
这意味着这些实例中的错误会对模型产生很大影响。
第一次影响分析揭示了总体最具影响力的实例。
现在我们选择其中一个实例,即第ri实例,我们希望通过找到最有影响力的训练数据实例来解释预测。
这就像一个反事实的问题:
如果我们在训练过程中省略实例
i
i
i ,实例“ri”的预测将如何变化?
我们对所有实例重复此删除操作。
然后,我们选择在训练中省略时导致实例“ri”的预测发生最大变化的训练实例,并使用它们来解释模型对该实例的预测。
我选择解释预测,例如ri
,因为它是预测癌症概率最高的实例(r sprintf('%.2f', 100 * predict.orig[i])
%),我认为是一个有趣的案例,需要更深入地分析。
例如,我们可以返回前 10 个最有影响力的实例来预测以表格形式打印的第ri实例。
不是很有用,因为我们看不到太多。
同样,通过分析它们的特征来找出影响实例与非影响实例的区别是更有意义的。
我们使用经过训练的决策树来预测给定特征的影响,但实际上我们滥用它只是为了找到结构而不是实际预测某些东西。
下面的决策树显示了哪种训练实例对预测第ri实例的影响最大。
吸烟或已吸烟 18.5 年或更长时间的女性数据实例对“ri”实例的预测有很大影响。
ri
实例背后的女人吸烟了r 颈椎$Smokes..years.[i]
年。
在数据中,r sum(cervical$Smokes..years >= 18.5)
女性 ( r sprintf('%.2f', 100 * mean(cervical$Smokes..years >= 18.5))
%) 吸烟18.5 年或更长。
在收集其中一名女性的吸烟年数时出现的任何错误都会对“ri”实例的预测结果产生巨大影响。
预测中最极端的变化发生在我们删除实例编号r mostest.case.index
时。
据称该患者吸烟了r 颈椎$Smokes..years.[worst.case.index]
年,与决策树的结果一致。
ri
-th 实例的预测概率从r sprintf('%.2f', 100 * predicted.orig[i])
% 变为r sprintf('%.2f', 100 * (predicted. orig[i] - 宫颈癌.200$influence[worst.case.index]))
% 如果我们删除实例r mostest.case.index
!
如果我们仔细看看最有影响力的实例的特征,我们可以看到另一个可能的问题。
资料显示,该女子今年28岁,已吸烟22年。
要么这是一个非常极端的案例,她真的从 6 岁开始吸烟,要么这是一个数据错误。
我倾向于相信后者。
这当然是我们必须质疑数据准确性的情况。
这些示例显示了识别有影响力的实例以调试模型是多么有用。
所提出的方法的一个问题是模型需要为每个训练实例重新训练。
整个重新训练可能会非常缓慢,因为如果你有数千个训练实例,你将不得不重新训练你的模型数千次。
假设模型需要一天的时间来训练,并且你有 1000 个训练实例,那么计算有影响力的实例(没有并行化)将需要将近 3 年的时间。
没有人有时间做这件事。
在本章的其余部分,我将向你展示一种不需要重新训练模型的方法。
你*:我想知道训练实例对特定预测的影响。
研究:你可以删除训练实例,重新训练模型,并测量预测的差异。
你:太好了!但是你有没有一种不需要再培训就可以工作的方法?这需要很多时间。
研究:你是否有一个模型,其损失函数在参数上是可微分的?
你:我用逻辑损失训练了一个神经网络。所以是的。
研究 :然后你可以使用影响函数来近似实例对模型参数和预测的影响。
影响函数是模型参数或预测对训练实例的依赖程度的度量。
该方法不是删除实例,而是将损失中的实例增加一个非常小的步骤。
该方法涉及使用梯度和 Hessian 矩阵来近似当前模型参数的损失。
损失加权类似于删除实例。
你:太好了,这就是我要找的!
Koh 和 Liang (2017)19 建议使用影响函数(一种稳健统计方法)来衡量实例如何影响模型参数或预测。
与删除诊断一样,影响函数将模型参数和预测追溯到负责的训练实例。
但是,该方法不是删除训练实例,而是估计当实例在经验风险(训练数据损失的总和)中加权时模型的变化量。
影响函数的方法需要访问关于模型参数的损失梯度,这仅适用于机器学习模型的子集。
逻辑回归、神经网络和支持向量机符合条件,而随机森林等基于树的方法则没有。
影响函数有助于理解模型行为、调试模型和检测数据集中的错误。
以下部分解释了影响函数背后的直觉和数学。
影响函数背后的数学
影响函数背后的关键思想是通过无限小的步长 ϵ \epsilon ϵ 来增加训练实例的损失,这会产生新的模型参数:
θ ^ ϵ , z = arg min θ ∈ Θ ( 1 − ϵ ) 1 n ∑ i = 1 n L ( z i , θ ) + ϵ L ( z , θ ) \hat{\theta}_{\epsilon,z}=\arg\min_{\theta{}\in\Theta}(1-\epsilon)\frac{1}{n}\sum_{i=1}^n{}L(z_i,\theta)+\epsilon{}L(z,\theta) θ^ϵ,z=argθ∈Θmin(1−ϵ)n1i=1∑nL(zi,θ)+ϵL(z,θ)
其中
θ
\theta
θ 是模型参数向量,
θ
^
ϵ
,
z
\hat{\theta}_{\epsilon,z}
θ^ϵ,z 是将
z
z
z 加权一个非常小的数字
ϵ
\epsilon
ϵ 后的参数向量。
L 是训练模型的损失函数,
z
i
z_i
zi 是训练数据,
z
z
z 是我们想要提升权重以模拟其移除的训练实例。
这个公式背后的直觉是:
如果我们将训练数据中的特定实例
z
i
z_i
zi 提高一点(
ϵ
\epsilon
ϵ)并相应地降低其他数据实例的权重,损失将有多大变化?
优化这个新的组合损失的参数向量是什么样的?
参数的影响函数,即提升训练实例
z
z
z 对参数的影响,可以计算如下。
I up,params ( z ) = d θ ^ ϵ , z d ϵ ∣ ϵ = 0 = − H θ ^ − 1 ∇ θ L ( z , θ ^ ) I_{\text{up,params}}(z)=\left.\frac{d{}\hat{\theta}_{\epsilon,z}}{d\epsilon}\right|_{\epsilon=0}=-H_{\hat{\theta}}^{-1}\nabla_{\theta}L(z,\hat{\theta}) Iup,params(z)=dϵdθ^ϵ,z∣ ∣ϵ=0=−Hθ^−1∇θL(z,θ^)
最后一个表达式
∇
θ
L
(
z
,
θ
^
)
\nabla_{\theta}L(z, \hat{\theta})
∇θL(z,θ^) 是关于加权训练实例参数的损失梯度。
梯度是训练实例损失的变化率。
它告诉我们当我们稍微改变模型参数
θ
^
\hat{\theta}
θ^ 时损失会发生多大的变化。
梯度向量中的正数表示相应模型参数的小幅增加会增加损失,负数表示参数的增加会减少损失。
第一部分
H
θ
^
−
1
H^{-1}_{\hat{\theta}}
Hθ^−1 是逆 Hessian 矩阵(损失关于模型参数的二阶导数)。
Hessian矩阵就是梯度的变化率,或者用loss来表示,它就是loss的变化率。
可以使用以下方法进行估算:
H θ = 1 n ∑ i = 1 n ∇ θ ^ 2 L ( z i , θ ^ ) H_{\theta}=\frac{1}{n}\sum_{i=1}^n\nabla^2_{\hat{\theta}}L(z_i,\hat{\theta}) Hθ=n1i=1∑n∇θ^2L(zi,θ^)
更非正式的:
Hessian 矩阵记录了损失在某个点的弯曲程度。
Hessian 矩阵是一个矩阵而不仅仅是一个向量,因为它描述了损失的曲率,而曲率取决于我们观察的方向。
如果你有很多参数,Hessian 矩阵的实际计算会很耗时。
Koh 和 Liang 提出了一些有效计算的技巧,这超出了本章的范围。
如上式所述,更新模型参数相当于在围绕估计的模型参数形成二次展开后采取单个牛顿步。
这个影响函数公式背后的直觉是什么?
该公式来自于围绕参数
θ
^
\hat{\theta}
θ^ 形成二次展开。
这意味着我们实际上并不知道,或者计算实例
z
z
z 的损失在删除/加权后将如何变化太复杂了。
我们通过在当前模型参数设置下使用有关陡度(=梯度)和曲率(= Hessian 矩阵)的信息来局部近似函数。
使用这种损失近似值,我们可以计算如果我们对实例
z
z
z 进行加权,新参数的大致样子:
θ ^ − z ≈ θ ^ − 1 n I up,params ( z ) \hat{\theta}_{-z}\approx\hat{\theta}-\frac{1}{n}I_{\text{up,params}}(z) θ^−z≈θ^−n1Iup,params(z)
近似参数向量基本上是原始参数减去 z z z 的损失的梯度(因为我们想减少损失)按曲率缩放(= 乘以逆 Hessian 矩阵)并在 n n n 上按 1 缩放,因为那是单个训练实例的权重。
下图显示了增重的工作原理。
x
x
x 轴显示
θ
\theta
θ 参数的值,y 轴显示与加权实例
z
z
z 对应的损失值。
这里的模型参数是一维的,用于演示目的,但实际上它通常是高维的。
我们只将
n
n
n 上的 1 移动到损失改进的方向,例如
z
z
z 。
我们不知道当我们删除
z
z
z 时损失会如何真正改变,但是通过损失的一阶和二阶导数,我们围绕当前模型参数创建了这个二次近似,并假设这就是真实损失的行为方式。
x = seq(from = -1.2, to = 1.2, length.out = 100)
y.fun = function(x) {
-x - 2*x^2 - x^3 + 2 * x^4
}
y = y.fun(x)
expansion = function(x, x0 = 0) {
d1 = function(x) -1 - 2*x - 3 * x^2 + 8 * x^3
d2 = function(x) - 2 - 6 * x + 24 * x^2
y.fun(x0) + d1(x0) * (x - x0) + 0.5 * (x - x0)^2*d2(x0)
}
dat = data.frame(x=x, y=y)
dat$type = "Actual loss"
dat2 = dat
dat2$type = "Quadratic expansion"
dat2$y = expansion(x)
dat3 = rbind(dat, dat2)
#pts = data.frame(x = c(0, 2/6))
ggplot(dat3) +
geom_line(aes(x = x, y = y, group = type, color = type, linetype = type)) +
geom_vline(xintercept = 0, linetype = 2) +
geom_vline(xintercept = 1/2, linetype = 2) +
scale_y_continuous("Loss with upweighted instance z", labels = NULL, breaks = NULL) +
scale_x_continuous("Model parameter", labels = NULL, breaks = NULL) +
geom_point(x = 0, y = expansion(x = 0)) +
geom_label(x = 0, label = expression(hat(theta)), y = expansion(x=0), vjust = 2) +
geom_point(x = 1/2, y = expansion(x = 1/2)) +
geom_label(x = 1/2, y = expansion(x = 1/2), label = expression(hat(theta)[-z]), vjust = 2) +
geom_segment(x = 0, xend=1/2, y=1, yend=1, arrow = arrow(length = unit(0.2, "cm"))) +
geom_label(x = 0.25, y = 1.1, label = expression(-frac(1,n)~I[up~theta](z)), vjust = -0.2) +
my_theme()
我们实际上并不需要计算新的参数,但是我们可以使用影响函数来衡量 z z z 对参数的影响。
当我们增加训练实例
z
z
z 的权重时, 预测如何变化?
我们既可以计算新参数,然后使用新参数化的模型进行预测,也可以直接计算实例
z
z
z 对预测的影响,因为我们可以使用链式法则计算影响:
I u p , l o s s ( z , z t e s t ) = d L ( z t e s t , θ ^ ϵ , z ) d ϵ ∣ ϵ = 0 = ∇ θ L ( z t e s t , θ ^ ) T d θ ^ ϵ , z d ϵ ∣ ϵ = 0 = − ∇ θ L ( z t e s t , θ ^ ) T H θ − 1 ∇ θ L ( z , θ ^ ) Iup,loss(z,ztest)=dL(ztest,ˆθϵ,z)dϵ|ϵ=0=∇θL(ztest,ˆθ)Tdˆθϵ,zdϵ|ϵ=0=−∇θL(ztest,ˆθ)TH−1θ∇θL(z,ˆθ) Iup,loss(z,ztest)=dϵdL(ztest,θ^ϵ,z)∣ ∣ϵ=0=∇θL(ztest,θ^)Tdϵdθ^ϵ,z∣ ∣ϵ=0=−∇θL(ztest,θ^)THθ−1∇θL(z,θ^)
这个等式的第一行意味着我们测量训练实例对某个预测的影响
z
t
e
s
t
z_{test}
ztest 当我们对实例
z
z
z 进行加权并获得新参数
时,测试实例损失的变化
θ
^
ϵ
,
z
\hat{时,测试实例损失的变化\theta}_{\epsilon,z}
时,测试实例损失的变化θ^ϵ,z 。
对于方程的第二行,我们应用了导数的链式法则,得到了测试实例损失对参数的导数乘以
z
z
z 对参数的影响。
在第三行中,我们将表达式替换为参数的影响函数。
第三行第一项
∇
θ
L
(
z
t
e
s
t
,
θ
^
)
T
\nabla_{\theta}L(z_{test},\hat{\theta})^T{}
∇θL(ztest,θ^)T 是测试实例相对于模型参数的梯度.
有一个公式是伟大的,也是科学和准确的展示事物的方式。
但我认为对公式的含义有一些直觉是非常重要的。
I
up,loss
I_{\text{up,loss}}
Iup,loss的公式表明,训练实例
z
z
z 对实例
z
t
e
s
t
z_{test}
ztest 预测的影响函数是“实例对模型参数”乘以“当我们对实例
z
z
z 进行加权时参数的变化量”。
另一种阅读公式的方法:
影响与训练和测试损失的梯度有多大成正比。
训练损失的梯度越高,它对参数的影响就越大,对测试预测的影响也越大。
测试预测的梯度越高,测试实例的影响力越大。
整个构造也可以被视为训练和测试实例之间相似性(由模型学习)的度量。
这就是理论和直觉。
下一节将解释如何应用影响函数。
影响函数的应用
影响函数有很多应用,其中一些已经在本章中介绍过。
了解模型行为
不同的机器学习模型有不同的预测方式。
即使两个模型具有相同的性能,它们从特征进行预测的方式也可能非常不同,因此在不同的场景中会失败。
通过识别有影响的实例来了解模型的特定弱点有助于在你的脑海中形成机器学习模型行为的“心理模型”。
处理域不匹配/调试模型错误
处理域不匹配与更好地理解模型行为密切相关。
域不匹配意味着训练和测试数据的分布不同,这可能导致模型在测试数据上表现不佳。
影响函数可以识别导致错误的训练实例。
假设你已经为接受手术的患者的结果训练了一个预测模型。
所有这些患者都来自同一家医院。
现在你在另一家医院使用该模型,发现它不适用于许多患者。
当然,你假设这两家医院有不同的病人,如果你看他们的数据,你会发现他们在很多特征上是不同的。
但是哪些特征或实例“破坏”了模型?
在这里,有影响力的实例也是回答这个问题的好方法。
你选择其中一名新患者,模型对其做出了错误的预测,找到并分析最有影响力的实例。
例如,这可能表明第二家医院平均有老年患者,而训练数据中最具影响力的实例是第一家医院的少数老年患者,而模型只是缺乏数据来学习很好地预测这个亚组。
结论是,该模型需要针对更多年龄较大的患者进行训练,才能在第二家医院正常工作。
修复训练数据
如果你对可以检查正确性的训练实例的数量有限制,你如何做出有效的选择?
最好的方法是选择最有影响力的实例,因为——根据定义——它们对模型的影响最大。
即使你有一个值明显不正确的实例,如果该实例没有影响并且你只需要预测模型的数据,那么检查有影响的实例是一个更好的选择。
例如,你训练一个模型来预测患者是否应该留在医院或提前出院。
你确实希望确保模型稳健并做出正确的预测,因为错误释放患者可能会产生不良后果。
患者记录可能非常混乱,因此你对数据的质量没有完全的信心。
但是检查患者信息并进行更正可能非常耗时,因为一旦你报告了需要检查的患者,医院实际上需要派人更仔细地查看所选患者的记录,这些记录可能是手写的和躺在一些档案中。
检查患者的数据可能需要一个小时或更长时间。
考虑到这些成本,只检查几个重要的数据实例是有意义的。
最好的方法是选择对预测模型有很大影响的患者。
Koh 和 Liang (2017) 表明,这种类型的选择比随机选择或选择损失最大或错误分类的选择要好得多。
删除诊断和影响函数的方法与 模型无关章节中介绍的主要基于特征扰动的方法非常不同。
查看有影响力的实例强调了训练数据在学习过程中的作用。
这使得影响函数和删除诊断成为机器学习模型的最佳调试工具之一。
在本书介绍的技术中,它们是唯一能够直接帮助识别应检查错误的实例的技术。
删除诊断与模型无关,这意味着该方法可以应用于任何模型。
基于导数的影响函数也可以应用于广泛的模型。
我们可以使用这些方法比较不同的机器学习模型并更好地了解它们的不同行为,而不仅仅是比较预测性能。
我们在本章中没有讨论这个话题,但是通过导数的影响函数也可以用来创建对抗性训练数据。
这些实例以这样的方式被操纵,当模型在那些被操纵的实例上训练时,模型无法正确预测某些测试实例。
与 对抗性示例章节 中的方法不同的是,攻击发生在训练期间,也称为中毒攻击。
如果你有兴趣,请阅读 Koh 和 Liang (2017) 的论文。
对于删除诊断和影响函数,我们考虑了预测的差异,对于影响函数,我们考虑了损失的增加。
但是,真的,该方法可以推广到任何形式的问题:
“当我们删除或增加实例
z
z
z 时……会发生什么?”,你可以在“……”中填写你想要的模型的任何功能。
你可以分析一个训练实例对模型整体损失的影响程度。
你可以分析训练实例对特征重要性的影响程度。
在训练 决策树时,你可以分析训练实例对第一次拆分选择哪个特征的影响程度。
还可以识别有影响力的实例组 [^group-influenceial]。
删除诊断非常计算昂贵,因为它们需要重新训练。
但历史表明,计算机资源在不断增加。
20 年前在资源方面无法想象的计算可以通过你的智能手机轻松执行。
你可以在数秒/分钟内在笔记本电脑上训练具有数千个训练实例和数百个参数的模型。
因此,假设即使在 10 年内使用大型神经网络,删除诊断也不会出现问题,这并不是一个很大的飞跃。
影响函数是删除诊断的一个很好的替代方法,但仅适用于具有关于其参数的二阶可微损失函数的模型,例如神经网络。
它们不适用于基于树的方法,例如随机森林、增强树或决策树。
即使你有带有参数和损失函数的模型,损失也可能无法区分。
但是对于最后一个问题,有一个技巧:
例如,当基础模型使用铰链损失而不是某些可微损失时,请使用可微损失代替计算影响。
损失被影响函数的问题损失的平滑版本所取代,但模型仍然可以使用非平滑损失进行训练。
影响函数只是近似的,因为该方法围绕参数形成二次展开。
近似值可能是错误的,并且实例的影响在移除时实际上更高或更低。
Koh和Liang(2017)通过一些例子表明,通过影响函数计算的影响与删除实例后实际重新训练模型时获得的影响度量接近。
但不能保证近似值总是如此接近。
没有明确的影响衡量标准,我们将其称为有影响或无影响的实例。
按影响对实例进行排序很有用,但如果有方法不仅可以对实例进行排序,而且实际上可以区分有影响的和无影响的,那就太好了。
例如,如果你为测试实例确定前 10 个最有影响力的训练实例,其中一些可能没有影响力,因为例如,只有前 3 个是真正有影响力的。
删除诊断很容易实现。
看看代码我为这个例子写的章节。
对于线性模型和广义线性模型,许多影响度量(例如 Cook 距离)在 R 的stats
包中实现。
Koh 和 Liang 从他们的论文 in a repository中发布了影响函数的 Python 代码。
这太棒了!
不幸的是,它“只是”论文的代码,而不是维护和记录的 Python 模块。
该代码专注于 Tensorflow 库,因此你不能直接将其用于使用其他框架(如 sci-kit learn)的黑盒模型。
Aamodt, Agnar, and Enric Plaza. “Case-based reasoning: Foundational issues, methodological variations, and system approaches.” AI communications 7.1 (1994): 39-59. ↩︎
Kim, Been, Rajiv Khanna, and Oluwasanmi O. Koyejo. “Examples are not enough, learn to criticize! Criticism for interpretability.” Advances in Neural Information Processing Systems (2016). ↩︎ ↩︎
Wachter, Sandra, Brent Mittelstadt, and Chris Russell. “Counterfactual explanations without opening the black box: Automated decisions and the GDPR.” (2017). ↩︎
Dandl, Susanne, Christoph Molnar, Martin Binder, Bernd Bischl. “Multi-objective counterfactual explanations”. In: Bäck T. et al. (eds) Parallel Problem Solving from Nature – PPSN XVI. PPSN 2020. Lecture Notes in Computer Science, vol 12269. Springer, Cham (2020). ↩︎
Deb, Kalyanmoy, Amrit Pratap, Sameer Agarwal and T. Meyarivan, “A fast and elitist multiobjective genetic algorithm: NSGA-II,” in IEEE Transactions on Evolutionary Computation, vol. 6, no. 2, pp. 182-197, (2002). ↩︎
Van Looveren, Arnaud, and Janis Klaise. “Interpretable counterfactual explanations guided by prototypes.” arXiv preprint arXiv:1907.02584 (2019). ↩︎
Karimi, Amir-Hossein, Gilles Barthe, Borja Balle and Isabel Valera. “Model-agnostic counterfactual explanations for consequential decisions.” AISTATS (2020). ↩︎
Mothilal, Ramaravind K., Amit Sharma, and Chenhao Tan. “Explaining machine learning classifiers through diverse counterfactual explanations.” Proceedings of the 2020 Conference on Fairness, Accountability, and Transparency. (2020). ↩︎
Ribeiro, Marco Tulio, Sameer Singh, and Carlos Guestrin. “Anchors: High-precision model-agnostic explanations.” AAAI Conference on Artificial Intelligence (2018). ↩︎
Szegedy, Christian, Wojciech Zaremba, Ilya Sutskever, Joan Bruna, Dumitru Erhan, Ian Goodfellow, and Rob Fergus. “Intriguing properties of neural networks.” arXiv preprint arXiv:1312.6199 (2013). ↩︎
Goodfellow, Ian J., Jonathon Shlens, and Christian Szegedy. “Explaining and harnessing adversarial examples.” arXiv preprint arXiv:1412.6572 (2014). ↩︎
Su, Jiawei, Danilo Vasconcellos Vargas, and Kouichi Sakurai. “One pixel attack for fooling deep neural networks.” IEEE Transactions on Evolutionary Computation (2019). ↩︎
Brown, Tom B., Dandelion Mané, Aurko Roy, Martín Abadi, and Justin Gilmer. “Adversarial patch.” arXiv preprint arXiv:1712.09665 (2017). ↩︎
Athalye, Anish, and Ilya Sutskever. “Synthesizing robust adversarial examples.” arXiv preprint arXiv:1707.07397 (2017). ↩︎
Papernot, Nicolas, et al. “Practical black-box attacks against machine learning.” Proceedings of the 2017 ACM on Asia Conference on Computer and Communications Security. ACM (2017). ↩︎
Biggio, Battista, and Fabio Roli. “Wild Patterns: Ten years after the rise of adversarial machine learning.” Pattern Recognition 84 (2018): 317-331. ↩︎
Kaufman, Leonard, and Peter Rousseeuw. “Clustering by means of medoids”. North-Holland (1987). ↩︎
Cook, R. Dennis. “Detection of influential observation in linear regression.” Technometrics 19.1 (1977): 15-18. ↩︎
Koh, Pang Wei, and Percy Liang. “Understanding black-box predictions via influence functions.” arXiv preprint arXiv:1703.04730 (2017). ↩︎
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。