我们人类比较容易理解三维以内的信息,在做数据分析挖掘以前,先要对数据集有个浅显的认识,比如统计分布、可视化、相关性等。这里引入了常用降维算法模型原理,对MNIST 784维数据做可视化和结果对比展示,其中的大部分算法可用来减少数据维度,减少特征数,去除噪声干扰信息,压缩数据,降低计算量。公式原理等是引用他人内容,如侵权联系删除。
常用算法列举和特点
算法 | 特点 | MNIST效果 |
1. PCA | 线性降维、运行时间短(1s/3000条) | 极差 |
TSNE | 非线性降维、运行时间短(1452s/70000条) | 一般 |
LargeVis | 非线性降维、运行时间一般(686s/70000条) | 最好 |
UMAP | 非线性降维、运行时间短(16s/4000条) | 较好 |
AUTO_ENCODER | 非线性降维、运行时间一般(135s/65000条) | 一般 |
1. PCA
1.1 算法原理
PCA(Principal Component Analysis),即主成分分析方法,是一种使用最广泛的数据线性降维算法。PCA的主要思想是将n维特征映射到k(其中k<n)维上,这k维是全新的正交特征也被称为主成分,是在原有n维特征的基础上重新构造出来的k维特征。PCA的工作就是从原始的空间中顺序地找一组相互正交的坐标轴,新的坐标轴的选择与数据本身是密切相关的。其中,第一个新坐标轴选择是原始数据中方差最大的方向,第二个新坐标轴选取是与第一个坐标轴正交的平面中使得方差最大的,第三个轴是与第1,2个轴正交的平面中方差最大的。依次类推,可以得到n个这样的坐标轴。(这部分操作类似决策树,先找到一个包含信息最多的切分点,在分离后的结果内找另一个最大的切分点。)通过这种方式获得的新的坐标轴,我们发现,大部分方差都包含在前面k个坐标轴中,后面的坐标轴所含的方差几乎为0。于是,我们可以忽略余下的坐标轴,只保留前面k个含有绝大部分方差的坐标轴。事实上,这相当于只保留包含绝大部分方差的维度特征,而忽略包含方差几乎为0的特征维度,实现对数据特征的降维处理。
1.1.1 协方差
数学定义协方差
提高计算效率我们先将特征均值化变为0,上面公式简化为
可以看到,在字段均值为0的情况下,两个字段的协方差简洁的表示为其内积除以元素数m。
当协方差为0时,表示两个字段完全独立。为了让协方差为0,我们选择第二个基时只能在与第一个基正交的方向上选择。因此最终选择的两个方向一定是正交的。
至此,我们得到了降维问题的优化目标:将一组N维向量降为K维(K大于0,小于N),其目标是选择K个单位(模为1)正交基,使得原始数据变换到这组基上后,各字段两两间协方差为0,而字段的方差则尽可能大(在正交的约束下,取最大的K个方差)。
矩阵是空间里的线性变换,PCA其实为矩阵分解,矩阵分解其实在原空间的子空间中找出线性变换中的主要变化趋势,减少冗余特征和不显著的特征。各维度相关性和噪声可以通过协方差矩阵表示,特征之间协方差为0去除了线性相关,剔除方差比较小的特征代表的噪声。
1.1.2 协方差矩阵
上面我们导出了优化目标,但是这个目标似乎不能直接作为操作指南(或者说算法),因为它只说要什么,但根本没有说怎么做。所以我们要继续在数学上研究计算方案。
我们看到,最终要达到的目的与字段内方差及字段间协方差有密切关系。因此我们希望能将两者统一表示,仔细观察发现,两者均可以表示为内积的形式,而内积又与矩阵相乘密切相关。于是我们来了灵感:
假设我们只有a和b两个字段,那么我们将它们按行组成矩阵X:
然后我们用X乘以X的转置,并乘上系数1/m:
奇迹出现了!这个矩阵对角线上的两个元素分别是两个字段的方差,而其它元素是a和b的协方差。两者被统一到了一个矩阵的。
根据矩阵相乘的运算法则,这个结论很容易被推广到一般情况:
设我们有m个n维数据记录,将其按列排成n乘m的矩阵X,设 ,则C是一个对称矩阵,其对角线分别为各个字段的方差,而第i行j列和j行i列元素相同,表示i和j两个字段的协方差。
1.1.3 协方差矩阵对角化
根据上述推导,我们发现要达到优化目标,等价于将协方差矩阵对角化:即除对角线外的其它元素化为0,并且在对角线上将元素按大小从上到下排列,这样我们就达到了优化目的。这样说可能还不是很明晰,我们进一步看下原矩阵与基变换后矩阵协方差矩阵的关系:
设原始数据矩阵X对应的协方差矩阵为C,而P是一组基按行组成的矩阵,设Y=XP,则Y为X对P做基变换后的数据。设Y的协方差矩阵为D,我们推导一下D与C的关系:
现在事情很明白了!我们要找的P不是别的,而是能让原始协方差矩阵对角化的P。换句话说,优化目标变成了寻找一个矩阵P,满足是一个对角矩阵,并且对角元素按从大到小依次排列,那么P的前K行就是要寻找的基,用P的前K行组成的矩阵乘以X就使得X从N维降到了K维并满足上述优化条件。
至此,我们离“发明”PCA还有仅一步之遥!
现在所有焦点都聚焦在了协方差矩阵对角化问题上,有时,我们真应该感谢数学家的先行,因为矩阵对角化在线性代数领域已经属于被玩烂了的东西,所以这在数学上根本不是问题。
由上文知道,协方差矩阵C是一个是对称矩阵,在线性代数上,实对称矩阵有一系列非常好的性质:
1)实对称矩阵不同特征值对应的特征向量必然正交。
2)设特征向量λ重数为r,则必然存在r个线性无关的特征向量对应于λ,因此可以将这r个特征向量单位正交化。
由上面两条可知,一个n行n列的实对称矩阵一定可以找到n个单位正交特征向量,设这n个特征向量为
我们将其按列组成矩阵:
则对协方差矩阵C有如下结论:
其中Λ为对角矩阵,其对角元素为各特征向量对应的特征值(可能有重复)。
以上结论不再给出严格的数学证明,对证明感兴趣的朋友可以参考线性代数书籍关于“实对称矩阵对角化”的内容。
到这里,我们发现我们已经找到了需要的矩阵P:
P=E
P是协方差矩阵的特征向量单位化后按行排列出的矩阵,其中每一行都是C的一个特征向量。如果设P按照Λ中特征值的从大到小,将特征向量从上到下排列,则用P的前K行组成的矩阵乘以原始数据矩阵X,就得到了我们需要的降维后的数据矩阵Y。
至此我们完成了整个PCA的数学原理讨论。在下面的一节,我们将给出PCA的一个实例。
1.2 算法及实例
为了巩固上面的理论,我们在这一节给出一个具体的PCA实例。
1.2.1 PCA算法
总结一下PCA的算法步骤,设有m条n维数据:
- 将原始数据按列组成m行n列矩阵
- 目标结果是低维数据表示
- 将X的每一行(代表一个属性字段)进行零均值化,即减去这一行的均值
- 求出协方差矩阵
- 求出协方差矩阵的特征值及对应的特征向量
- 将特征向量按对应特征值大小从上到下按行排列成矩阵,取前k行组成矩阵P
- Y=XP即为降维到k维后的数据
1.2.2 代码和结果
import numpy as np
from sklearn.decomposition import PCA
from sklearn.model_selection import train_test_split
from keras.datasets import mnist
(x_train, y_train), (x_test, y_test) = mnist.load_data()
train_data = x_train.reshape((-1, 784))
test_data = x_test.reshape((-1, 784))
data = np.concatenate((train_data, test_data), axis=0)
label = np.concatenate((y_train, y_test), axis=0)
_, x_run, _, y_run = train_test_split(test_data, y_test, test_size = 0.3, random_state=159)
x_run = x_run.astype('float32') / 255.0
pca = PCA(n_components=2)
x_run = pca.fit_transform(x_run)
2. TSNE
2.1 算法原理
t-SNE是由SNE(Stochastic Neighbor