Press "Enter" to skip to content

HSIC简介:一个有意思的判断相关性的思路

前段时间

在机器之心看到这样的一个推送 彻底解决梯度爆炸问题,新方法不用反向传播也能训练 ResNet
,当然,媒体的标题党作风我们暂且无视,主要看内容即可。机器之心的这篇文章,介绍的是论文
The HSIC Bottleneck: Deep Learning without Back-Propagation

 
的成果,里边提出了一种通过 HSIC Bottleneck 来训练神经网络的算法。

 

 

论文链接:

https://arxiv.org/pdf/1908.01580.pdf

 

坦白说,这篇论文笔者还没有看明白,因为对笔者来说里边的新概念有点多了。不过论文中的“HSIC”这个概念引起了笔者的兴趣。经过学习,终于基本地理解了这个 HSIC 的含义和来龙去脉,于是就有了本文,试图给出 HSIC 的一个尽可能通俗(但可能不严谨)的理解。

 

背景

 

HSIC 全称“ Hilbert-Schmidt independence criterion
”,中文可以叫做“希尔伯特-施密特独立性指标”吧,跟互信息一样,它也可以用来衡量两个变量之间的独立性。

 

度量相关

 

我们知道,互信息的基本形式是:

 

 

如果 I(X,Y)=0 那幺就说明 p(x,y)≡p(x)p(y),也就是两个变量是相互独立的,否则是相关的。但
这一项意味着我们要用某种方式对概率密度进行估计。

 

HSIC 的作用跟互信息类似,但是跟互信息不一样的是,它不需要估计两个变量的概率密度,而是直接转化为采样的形式。

 

长期关注笔者文章的读者都知道,“互信息”是在笔者文章中经常出现的概念,我们可以用互信息做新词发现(比如《基于切分的新词发现》
[1]

),也可以用互信息做无监督学习(比如深度学习的互信息:无监督提取特征),互信息的重要性可见一斑。如果说有一个指标可以取代互信息、比互信息还方便,那肯定是笔者必须去学习的对象了。

 

问题定义

 

一般来说,我们将问题定义为:

 

有数据 (x1, y1), (x2, y2), … , (xn, yn) ∼ p(x, y) ,判断 p(x, y) 是否恒等于 p(x), p(y),即 x, y 是否独立。

 

严格来讲,如果是对于连续变量,这里的“恒等于”指的是“几乎处处等于”,但我们这里不严格声明这一点。为了描述的规范,这里设 x∈X , y∈Y ,而 f(x), g(y)∈R。注意 x, y 可能是两个含义完全不一样的变量,比如 x 可能是“星期一”, y 可能是“上班”,p(x, y) 就是“ 今天是星期一,且今天要上班
”的概率。鉴于此, X , Y 可能是两个完全不一样的域。

 

基本的思路是去计算互信息 (1) ,但很多问题中我们都无法很好地估计概率或概率密度。一种可能的方案是转化为对偶问题,用类似对抗的思路去学习互信息(infomax 的思路),但这种方法可能会不稳定,而且受到采样方案的影响。最好的方案就是能有一个类似“相关系数”的指标,让我们可以显式地计算和优化这个指标。

 

HSIC 就是冲着这个目标而来的。

 

HSIC

 

这里我们尽可能清晰地引入 HSIC 的概念。然而,“尽可能清晰”不等价于篇幅尽可能短,事实上,下面的篇幅依然会比较长,而且有不少数学公式,但是相对于标准教程里边一上来就引入希尔伯特空间、再生核、各种算子等做法,这里的介绍应该算是对很多不了解相关概念的读者来说都是友好的了。

 

基本思想

 

HSIC 留意到:

 

p(x,y)≡p(x)p(y) 当且仅当对于任意的 f,g,下式都等于 0:

 

 

这个结论显然不难理解。有意思的是,等号右边是采样的形式,也就是说我们 将这个指标转化为了采样的形式,避免了直接估算概率密度。

 

这样一来,我们就有一个判断独立性的方法:选取“足够多”的 f,g,然后计算:

 

 

看与 0 的接近程度;反过来,如果在优化问题中,我们希望特征 x,y 尽可能相互独立,那幺我们就可以将加入到损失函数中。

 

抽丝剥茧

 

其实的形式已经很好地体现了 HSIC 的判别思想。下面我们就沿着这个思路,继续抽丝剥茧,逐步地走向 HSIC 最终的形式。

 

首先我们把
算一算:

 

 

然后我们用一个技巧:我们知道
,说明了这个期望值的结果跟随机变量的记号没啥关系。所以我们有:

 

 

把其余的项都这样变换,最终我们就可以得到:

 

 

这样一来,每一项都是 f(x1)f(x2)g(x1)g(x2) 的期望,只不过变量的采样分布不一样。

 

特征函数

 

现在的问题是: 要选择哪些 f, g 呢?
怎样才算“足够多”呢?
 

类比向量空间的知识,所有可能的 f(x) 能组成一个向量空间 F,所有的 g(y) 也一样组成一个向量空间 G 。如果能把这两个空间的所有“基底”都遍历一遍,那肯定就够了。那问题就是:如何找到所有的基底呢?

 

这时候“ 核函数
”就登场了。所谓核函数,那就是——呃,其实说起来很复杂,我也不大懂。简单来说,核函数是类似于线性代数中“正定矩阵”的存在,就是一个定义在 X × X 的二元对称函数 K(x1, x2) = K(x2, x1) ,然后我们把一元函数 f(x) 类比为一个向量,那幺:

 

 

就相当于一个矩阵乘以向量的矩阵运算。跟矩阵的特征值和特征向量一样,核函数也能定义特征值和特征函数,满足下述恒等式的一元函数 ψ 就称为这个核函数的特征函数:

 

 

上面的内容都是铺垫的,其严格定义则是属于“ 再生核希尔伯特空间
“范畴。后面我们用到的,实际上是两点性质:

 

1. 核函数的所有特征函数 ψ1,ψ2,…,构成该空间的一组正交基;

 

2. 核函数的所有特征值 α1,α2,…都是正的,且满足:

 

 

HSIC登场

 

经过上述铺垫,HSIC 基本上就可以登场了:

 

首先,假如我们已经有定义在 X×X 的核函数
,那幺我们就可以算出
对应的特征值 α1,α2,… 和特征函数 ψ1,ψ2,…;同样地,有了定义在 Y×Y 的核函数
后,也可以算出对应的特征值 β1,β2,…和特征函数 ϕ1,ϕ2,…。

 

然后,因为特征函数构成了基底,所以在 (3) 中,我们可以把 f,g 换成对应特征函数 ψi,ϕj

 

 

因为所有的特征值都是正的,所以我们还可以用特征值为权重进行加权求和,而不改变的作用:

 

 

现在我们把 (6) 代入到上面去,就得到:

 

 

最后,再利用等式 (9),方括号里边的实际上就是
,于是,HSIC 就登场了:

 

 

这就是我们最重要寻找的度量相关性的指标,它纯粹是采样的形式,而且 KX,KY 都是事先给定的、通常是可微的,因此这就是一个可以明确采样计算、可以直接优化的指标!

 

在实际计算中,我们可选的核函数有很多,比较常用的是:

 

 

其中 σ>0 是一个常数,本文开头提到的论文
The HSIC Bottleneck: Deep Learning without Back-Propagation

也是用这个核函数。不同的核函数效果有点不一样,但是都能保证 HSIC(X,Y)=0⇔p(x,y)≡p(x)p(y) 。

 

矩阵形式

 

最后,我们来推导一下 (13) 在有限样本下的矩阵形式。

 

按照采样求期望的思想,

实际上就是对所有的样本对 (xi,yi) 的结果求平均,而其实就是
将这个平均操作做两次,所以:

 

 

其中

实际上都是 n×n 的对称矩阵,分别记为,那幺上述运算可以写成矩阵乘法
,其中 Tr 表示矩阵的迹。基于同样的思想,第二项实际上就是“所有元素的平均乘以所有元素的平均”,如果非要写成矩阵形式的话,那就是
,其中加粗的 1 表示大小为 n×n 的全 1 矩阵。相应地,最后一项“所有元素平均值的 1/n 的两倍”,即

 

所以,如果用矩阵形式表示 HSIC,那就是:

 

 

这里的 J=I−1/n,而 I 是 n 阶单位矩阵。跟《简述无偏估计和有偏估计》
[2]
一文讨论的类似,这其实是一个有偏估计,而将前面的 1/n 换成 1/(n−1),就得到无偏估计:

 

 

这就是最终的矩阵形式的 HSIC 公式(注意 J 里边的 1/n 不用换成 1/(n−1))。

 

其它

 

这里先给出一个参考实现,并做一个简单的实验,来验证 HSIC 的有效性,然后在后一节中,我们思考一下 HSIC 可能存在的问题。

 

参考实现

 

假如已知核矩阵
的情况下,HSIC 的计算实现参考如下:

 

import numpy as np

def hsic(Kx, Ky):
    Kxy = np.dot(Kx, Ky)
    n = Kxy.shape[0]
    h = np.trace(Kxy) / n**2 + np.mean(Kx) * np.mean(Ky) - 2 * np.mean(Kxy) / n
return h * n**2 / (n - 1)**2

 

注意这里的实现是根据 (13) 每一项的含义来的,并非根据矩阵形式 (17),事实上矩阵形式 (17) 效率并不高(涉及到三次矩阵乘法)。
下面做一个简单的实验,验证 HSIC 的有效性:

 

# 产生两组独立无关的随机变量
x = np.random.randn(1000)
y = np.random.randn(1000)
Kx = np.expand_dims(x, 0) - np.expand_dims(x, 1)
Kx = np.exp(- Kx**2) # 计算核矩阵
Ky = np.expand_dims(y, 0) - np.expand_dims(y, 1)
Ky = np.exp(- Ky**2) # 计算核矩阵
print(hsic(Kx, Ky)) # 计算HSIC

 

输出结果大概是 0.0002 左右,如果将 x,y 改为:

 

x = np.random.randn(1000)
y = x + 0.1 * np.random.randn(1000)

 

这意味着 x,y 有比较强的相关性,而 HSIC 的结果也表明了这一点,约等于 0.096,比 0.0002 大了两个数量级以上,这表明了 HSIC 确实是有效的(注意,HSIC的输出值一般只有相对比较的意义,其绝对值没有明显含义) 。

 

个人思考

 

显然,由 (13) 给出的 HSIC 的计算结果取决于核函数的选择。不管用哪个核函数,理论上都可以保证:

 

但问题是,当 HSIC(X,Y)>0 时,X,Y 究竟有多相关呢?

 

这就相当依赖核函数选择和原始问题的背景了。从常用核函数 (14) 的形式我们大概可以感知到, 核函数相当于两个样本之间的相似度,问题是什幺样的相似度定义才是真正符合问题背景的,这并没有标准答案,而且通常都是很困难的问题。

 

举个例子,假如 x1,x2,x3 分别代表三张图片,我们知道 ‖x1−x2‖2=0 的话意味着 x1,x2 这两张图片完全一样,但是当 ‖x1−x2‖2,‖x1−x3‖2 都不等于 0 时,我们不能因为 ‖x1−x2‖2<‖x1−x3‖2 就说图片 x2 一定比图片 x3“看起来”更像 x1,因为范数 ‖⋅‖2 不是我们视觉的一个完美的度量。

 

其实笔者认为这是所有核方法的通病,即核方法只能保证当某个指标等于 0 时就是我们的理想追求,但是当这个指标不等于 0 时,这个指标无法很好地度量我们跟理想的差距。良好的度量是要根据具体问题精心设计的,或者根据数据集通过类似 GAN 的方法自动把这个度量学习出来。

 

当然,也不能就此说 HSIC 就没有价值了,HSIC 的价值在于它可以作为辅助目标来优化,就好比我们要训练一个图片自编码器,就算我们用 GAN 的思想,我们也通常会把原图片和重构图片的 MSE 作为辅助 loss 来使用。

 

总结

 

总的来说,本文以一种较为通俗直白的方法介绍了 HSIC 这个概念,介绍过程中涉及到了一些数学内容,但省去了严格的数学定义和论述,尽量只保持了比较核心的部分,私以为这种处理会使得读者更容易接受一些。对于追求严谨的读者,请多多包涵。

 

相关链接

 

[1] https://kexue.fm/archives/3913

 

[2] https://kexue.fm/archives/6747

 

作者丨苏剑林

单位丨追一科技

研究方向丨NLP,神经网络

个人主页丨kexue.fm

 

Be First to Comment

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注