读这篇文章之间欢迎各位先阅读我之前写过的线性降维的文章。这篇文章应该也是属于Unsupervised Learning的内容的。
Neighbor Embedding
Manifold Learning(流形学习)
在实际的数据中,很可能会存在这一种分布:
左边这个分布可以看成原先在二维平面上的分布硬塞到一个三维空间之中。
那么如果我们直接对三维空间的这个分布计算欧氏距离的话,很可能是行不通的!如果是在比较接近的点(例如图中我用黄色箭头标记出来的点)那么计算欧式距离进行比较还是可以表明它们之间的接近程度的。但是如果在我标注出来的红色的点,因此它们在三维空间中将原来的二维平面进行了扭曲,因此很可能比较欧氏距离并不能够象征它们之间的相似度。这个想法可以用地球在类似,如果在地球上很接近的两个点那么计算直线距离当然是可以的;但是如果在很遥远的两个点,由于三维空间内的扭曲性,那么计算直线距离就不行了。
那么我们如果能够将该三维空间下的曲面展开成二维空间中分布(如右图),那么我们可以发现它们的分布就很容易进行划分,计算欧氏距离也就能够象征相似程度了,这也能够为我们的下游任务提供更多的便利。
下面就来介绍几种能够完成非线性降维的方法
Locally Linear Embedding(LLE)
当前我们拥有以下样本,那么对于其中的某一个样本\(x^i\)来说,其各个邻居为\(x^j\),那么它和各个邻居之间的“关系”为\(w_{ij}\),如下图所示:
那么这个关系的确定是认为\(x^i\)可以由各个邻居\(x^j\)经过线性变换组合而成,即:
而假设经过降维之后\(x^i\)对应为\(z^i\),其需要满足的条件为降维后各个z之间的关系要保持不变,即:
那么采用这一种类似方法的好处在于即使你不知道原来样本x应该怎么表示,只要你能够知道如何计算它们之间的关系,你就仍然可以完成降维。
而这个方法需要注意的是要调节选择的邻居数目,适合的数目才能够带来够好的效果:
T-distributed Stochastic Neighbor Embedding(t-SNE)
前面提及的各个算法虽然都限制了在原来维度中相接近的点,降维之后也要相接近,但是都没有限制在原来维度中不接近的点,降维之后也要分割开来,因此例如LLE会出现以下情形,即不同类别的点也都挤在了一起:
那么t-SNE的处理方法就较为不同,具体如下:
- 对于原来的数据x和我们想要降维而成的数据z
- 在原来的维度空间中对每个样本计算相似度\(S(x^i,x^j)\)(计算的方法可自行选择),再将该相似度转为分布,即\(P(x^j \mid x^i)=\frac{S(x^i,x^j)}{\sum_{k\neq i}S(x^i,x^k)}\)
- 在降维而得到的空间也做相似计算,即\(S'(z^i,z^j)\)和\(Q(z^j\mid z^i)=\frac{S'(z^i,z^j)}{\sum_{k\neq i}S'(z^i,z^k)}\)
- 而求解方法就是找到一组z,使得分布P和分布Q能够更加接近,相当于最小化这两个分布的KL散度,即\(L=\sum_{i}KL(P(*\mid x^i)\mid \mid Q(*\mid z^i))\)
t-SNE在选择相似度的度量函数的时候有一个很奇妙的地方,其选择为:
因为按照我们正常的逻辑应该是在x中选择什么样的度量指标,在z上就选择一样的度量指标,但t-SNE这样选择的理由,我们需要通过这两个函数的曲线来说明:
- 首先,因为我们在进行降维的时候是希望两个分布越接近越好,也就是说x降到z之后它们的S是越接近越好,因此在降维的时候应该是在某一点的x直接进行水平方向的平移(保持S不变)找到对应的z
- 其次,我们可以看到上面两个橙色的点和两个蓝色的点,从橙色的点降维到蓝色的点之后两个点之间的距离会变大,也就是说如果原来在x中的两个点很接近,那么降维之后的点距离被拉开的程度是不严重的;但如果在x中两个点本身就有一定的距离,由于z的函数曲线下降的很慢,因此降维后这个距离就会被拉开很严重
因此t-SNE的分类结果大致如下:
Deep Generative Model
费曼曾经说过:What I cannot create, I do not understand.
那么这句话用在当前的机器学习之中也同样适用:因为当前的机器学习虽然可以做到完成分辨的任务,例如分辨出猫和狗,但如果有一天机器可以自己“创造”出一张猫的图像,那么也许机器才能够对猫这个名词的概念有更深的了解。而“创造”就是生成模型的任务。因此本节主要是对当前生成模型的研究进行介绍。
PixelRNN
如果对RNN没有了解且有兴趣地可以看我这篇文章,如果不阅读的话也是可以看得懂接下来PiexlRNN的具体流程的。
假设我们要创造一张\(3\times 3\)的图像,那么我们可以训练一个神经网络,它可以不断接受已经创造出来的像素点对应的向量,然后输出下一个像素点应该对应的向量,如下图所示:
你可能会好奇为什么每一次输入的个数都不一样,其实这是RNN的特性决定的,它可以处理输入不同个数向量的情况。
那么李宏毅老师也将这个想法用来创造一些神奇宝贝,但是在训练的时候发现了以下需要注意的地方,我觉得这些点能够让我们在以后的某些工作中受到启发:
- 一个像素点的数值是表示为一个RGB三个通道的,而因为神经网络在输出的时候通常会经过一个激活函数(例如Sigmord),而这会导致各个通道的数值一般都很少出现为0或者为1的极端情况,都是聚集在中间。而由于图像的性质如果三个通道的数值都集中在中间那么就会使得像素呈现较重的灰色。要产生鲜艳的颜色就必须某些通道接近1,其他通道接近0。对于这个问题的解决方法就是不输出通道值,将每个像素点用一个one-hat-vector来表示,其中每一个维度代表一种常见的鲜艳的颜色
- 但这样又有一个问题就是颜色太多了会导致这个向量很长,那么解决方法是将相似的颜色进行聚类,统一成一种颜色来表示,最终表示为160多种颜色。
做出来的效果如下图:
Variational Auto-encoder(VAE)
What is VAE
VAE是在Auto-encoder进行了改进。首先先介绍在结构和训练过程上的改进:
- 在结构上,VAE的En输出不只是一个Embedding,而是输出两个向量\(M,\sigma\),然后再从标准正态分布中产生一个向量\(E\),接下来的操作就是图中生成向量\(C\)的操作了,然后再将C放入De之中还原出输入
- 在训练上,VAE不仅仅要求还原出来的输出要跟输入尽可能接近,还需要最小化右下角的式子
因此训练完成之后就可以将VAE的De取出来做生成任务。
Why VAE
为什么Auto-encoder不够,而需要改进的VAE呢?我们通过下面这个例子来进行解释。
假设Auto-encoder做的事情是下面的,将月亮的图片变成Code,再还原成月亮的图片,那么如果在满月和半月对应的Code之间选择一个点,进行还原的话,是否还原出来的图片也会像是满月和半月之间的月亮呢?不会!因为Auto-encoder只学习了对应的满月和半月两个点的转换,中间的转换并没有学习,因此转换出来很难想象是什么东西。
但对于VAE来说,它不仅仅是对满月和半月这两个点来进行学习,它还加入了一定的噪声,同时学习过程之中还要求加入噪声之后也要还原出原来的图片,因此在满月的Code对应的点的附近就都能够还原出满月。而如果满月的噪声的范围和半月的噪声的范围有交集,在这个交集之中因为VAE既学习了要像满月,也学习了要像半月,因此真的有可能就会在该点Code上还原出一张介于满月和半月之间的图片。
那再让我们回头来看VAE是如何改进Auto-encoder就可以理解中间各个向量的含义了:
其中向量\(M\)就可以认为是原始的Code,而向量\(E\)可以认为是噪声,那么\(exp(\sigma)\)向量就可以认为是控制原始向量和噪声之间的一个超参数的度量,那么就得到了向量C。
而对于VAE来说训练时仅仅要求输入和输出类似是不够的,因为这样会导致向量\(exp(\sigma)\)取接近于0,从而来导致噪声几乎没有,那这样就可以做到输入输出很接近,因此还需要加上的限制就是下面的式子:
其中前两项可以简单理解为限制它不会让噪声直接失去掉,第三项则是类似于正则化的思想。
我们也可以从另外一个角度来进行分析,假设我们把Code的取值看成具有一定的分布:
其中在一些能够还原出比较像宝可梦图片的Code的取值上就具有较多的概率,而如果还原出来的图像不正常那么就具有较小的概率,那如果我们能够估计出来这个分布就可以通过采样来产生宝可梦了。因此对于分布的概率需要介绍下面的混合高斯分布。
对于一般的混合高斯分布来说,其中具有的高斯分布的数量是固定的,即:
可以看到其表达式是采用求和的形式。那么从这种高斯分布中进行采样的步骤就是先产生一个正整数代表从哪一个高斯分布进行采样,之后再在对应的高斯分布中采样即可。
但有另外一种混合高斯分布其含有的高斯分布的数量可以认为是无限的,且每一个高斯分布都有其对应的均值和方差。那么我们如何来表示这种混合高斯分布,或者说我们如何从这种高斯分布中进行取样呢?
具体做法为:首先先从一个标准正态分布中取样得到一个向量z,再将这个向量z通过计算均值的函数和通过计算方差的函数,算出应该对应的高斯分布的均值和方差,然后再在这个高斯分布中进行采样得到x。那么就有需要注意的点:
- 首先这个计算均值和方差的韩式应该怎么确定?这部分是根据实际场景来的,更可以认为是一个神经网络也是行得通的。
- 总体的混合高斯分布的表示应该为:\(P(x)=\int_zP(z)P(x\mid z)dz\)
那么一般情况并不是我们拥有这样的混合高斯函数让我们从中进行采样,而是我们已经有了样本数据集,我们假设它符合混合高斯的分布,然后我们需要推导出这个混合高斯分布的式子(实际上也就是推导出那个对z产生对应均值和方差的神经网络)。那么计算的方法为:
其实也就是微调那个神经网络的参数,通过梯度下降来实现:
那么现在就来进行推导:
- 首先我们需要另外一个分布\(q(z\mid x)\),它表示给定样本x,它将会产生对应的均值和方差,然后z再从这个均值和方差对应的高斯分布中进行采样,即:
- 那么我们对之前的式子进行一定的推导与变换:
注意这里的\(q(z\mid x)\)可以是任何分布是因为后面的积分会将其积分成1,而最下面的这一项我们可以认为是\(logP(x)\)的下界,因此我们现在的目标就更换为:
- 将这个下界的表达式进行整理得到:
因此我们要最大化上面这两项
- 那么第一项就相当于最小化它们的散度,而最小化散度经过推导也就是最小化下面这个式子:
- 而最大化第二项我们也可以进行写成:
就可以认为是从\(q(z\mid x)\)中取样得到一个z,然后我们要让\(logP(x\mid z)\)最大,那么这也就是Auto-encoder所做的事情:
结合我们前面说到的两个分布都可以用神经网络来描述就可以理解了。那么这两者的结合,就是VAE的loss函数了
Problem of VAE
VAE有一个很严重的问题就是它永远只是在学习怎么产生一张图片能够和原始数据的图像越来越接近,它始终没有学习如何产生能够以假乱真的图片,或者说它只懂得了尽可能地模仿训练集的图像,例如下面的例子:
假设我们对输入和输出的相似度的计算是使用展开成向量然后计算平方差,那么上图的例子中两个不同的问题虽然都是存在一个像素点的不同,这在我们计算平方差的时候是一样的,但时在实际的图像上是很不一样的。因此如果能够像GAN一样学习如何欺骗过辨别器,那就可以产生很好的效果。
GAN
对于GAN的介绍可以看我这篇文章。