【Python讲线代】S03E13特征值分解与主成分分析

1.数据降维的需求背景

在研究工作中,我们常常针对我们关注的研究对象,收集大量有关他的特征属性,从而对其进行观测和分析。比如,对一组城市进行研究的时候,我们可以从人口、GDP、面积、年降水量、年平均温度、人均寿命、人均工资、人均受教育年份、性别比例、宗教人口、汽车保有量、人均住房面积等等收集相关数据。这里随手一列就是十几个特征属性,其实就算列出一百个来,也不足为奇。我们收集越多的特征属性就越方便我们全方面的对事物进行细致的研究,对深层次的规律进行探寻。

但是问题来了,随着样本特征属性数量的增多,我们需要分析处理的数据量也是直线上升的,在进行样本聚类、回归等数据分析的过程中,样本的数据维度过大,无疑会使得问题的研究变得愈加复杂。同时,大家很容易能发现一个现象,就是样本的特征属性之间还存在着相关性:比如GDP与汽车保有量之间,人均工资与人均受教育年份、人均寿命之间,都是存在着某种关联的,其实这也增加了问题处理的复杂性。

因此这种现状让我们感觉到,用这么多彼此相关的特征属性去描述一件事物,一方面很复杂,另一方面似乎也显得不是那么有必要。我们希望能在原有基础上减少特征属性的数量。

2.目标:特征减少,损失要小

那么,我们现在就视图来探究这个问题:如何对样本的特征属性进行降维。目标是什么?归结起来有两点:

第一个目标当然是特征维度要变小,不能用那么多的特征属性了。第二个是描述样本的信息损失要尽量少。数据降维,一定伴随着信息的损失,但是如果损失的太多了,自然也就失去了意义。

3.主成分分析法降维的思路

3.1.直接去掉特征?盲目

有读者可能会想了,能不能直接挑选一个特征属性,然后将其去掉,通过这种方法简单的实现数据降维?直觉告诉我们,似乎是不行的。这种方法最为关键的一点就是没有考虑到特征属性之间彼此紧密耦合的相关关系。这样独立的对各个特征属性进行分析,是很盲目的。

那么具体该如何做?我们还是举一个非常直观的例子来说明:

假设我们研究的对象有两个特征属性 $X$ 和 $Y$ ,对 $5$ 个样本进行数据采样的结果如下:

样本1 样本2 样本3 样本4 样本5
$X$ 2 2 4 8 4
$Y$ 2 6 6 8 8

我们的目标是对其降维,只用一维特征来表示每个样本。我们首先将其绘制在二维平面图中进行整体观察,如图1所示:

图1.样本数据的分布

图1.样本数据的分布

在 $5$ 个样本的特征数据分布图中,我们能挖掘出几个重要的规律:

首先,我们来探究这两个特征属性的数据分布和数据相关情况:

代码片段:

import numpy as np
import matplotlib.pyplot as plt

x = [2,2,4,8,4]
y = [2,6,6,8,8]
S = np.vstack((x,y))

print(np.cov(S))

运行结果:

[[ 6.  4.]
 [ 4.  6.]]

结合特征变量 $X$ 和 $Y$ 的图像分布以及我们的观察发现, $5$ 个样本的特征 $X$ 和特征 $Y$ 呈现出正相关性,数据彼此之间存在着影响。

其次,我们如果真要硬来,直接去掉特征 $X$ 或特征 $Y$ 来实现特征降维,可行吗?显然是不行的,如图2所示,如果我们直接去掉特征 $X$,那么样本 $2$ 和样本 $3$,以及样本 $4$ 和样本 $5$,就变得无法区分了。但是实质上,在降维前的原始数据中,他们显然是有明显区别的。直接去掉特征 $Y$ 也是一样,这种简单粗暴的降维方法显然是不可取的,他忽视了数据中的内在结构关系,并且带来了非常明显的信息损失。

图2. 直接进行特征去除会丢失大量信息

图2. 直接进行特征去除会丢失大量信息

3.2.从解除特征之间的相关性入手

我们应该如何调整我们的降维策略?基于上面的现象,直观上而言,思路应该聚焦在这两方面:

一是,要考虑去除掉特征之间的相关性,想法是创造另一组新的特征来描述样本,并且新的特征必须彼此之间不相关。

二是,在新的彼此无关的特征集中,舍弃掉不重要的特征,保留较少的特征,实现数据的特征维度降维,保持尽量少的信息损失。

4.剖析主成分分析的细节

4.1.构造彼此无关的新特征

首先我们来看第一点,我们尝试用 $2$ 个新的特征来对样本进行描述,那么为了让这两个新特征满足彼此无关的要求,就得让这两个新特征的协方差为 $0$,构成的协方差矩阵是一个对角矩阵。

而目前我们所使用的原始特征 $X$ 和 $Y$ 的协方差不为 $0$,其协方差矩阵是一个普通的对称矩阵。

看到这里,你是不是突然觉得眼前一亮,我们的工作不就是要将当前的对称矩阵变换到对角矩阵么?大的方向的确如此,我们就沿着这个方向,一步一步从头到尾来实施一遍主成分分析 $(PCA)$ 的具体方法。

我们首先回顾一下协方差的定义公式:

$Cov(X,Y)=\frac{1}{n-1}\sum_{1}^{n}{(x_i-\mu)(y_i-v)}$ ,感觉公式还不够简练,我们发现如果变量 $X$ 和变量 $Y$ 的均值为 $0$,那么协方差的式子就会变得更加简单。

这个其实好办,我们将 $X$ 中的每一个变量都减去他们的均值 $\mu$,同样将 $Y$ 中的每一个变量都减去他们的均值 $v$,这样经过零均值化处理后,特征 $X$ 和特征 $Y$ 的平均值都变为了 $0$。很显然,这样的处理并不会改变方差与协方差的值,因为数据的离散程度并未发生改变,同时,从公式的表达上来看也非常清楚。

经过零均值处理后, $X$ 和 $Y$ 的协方差矩阵就可以写作:

$\begin{bmatrix} V[X]&Cov[X,Y]\\Cov[Y,X]&V[Y]\end{bmatrix}$$=\begin{bmatrix}\frac{1}{n-1}\sum_{1}^{n}{x_i^2}&\frac{1}{n-1}\sum_{1}^{n}{x_iy_i}\\\frac{1}{n-1}\sum_{1}^{n}{y_ix_i}&\frac{1}{n-1}\sum_{1}^{n}{y_i^2}\end{bmatrix}$$=\frac{1}{n-1}\begin{bmatrix}\sum_{1}^{n}{x_i^2}&\sum_{1}^{n}{x_iy_i}\\\sum_{1}^{n}{y_ix_i}&\sum_{1}^{n}{y_i^2}\end{bmatrix}$

我们看一下 $\begin{bmatrix}\sum_{1}^{n}{x_i^2}&\sum_{1}^{n}{x_iy_i}\\\sum_{1}^{n}{y_ix_i}&\sum_{1}^{n}{y_i^2}\end{bmatrix}$ 这个矩阵,不难发现他就是零均值化后的样本矩阵 $A=\begin{bmatrix} x_1&x_2&x_3&...&x_n\\y_1&y_2&y_3&...&y_n\end{bmatrix}$ 与自身转置矩阵 $A^T$ 相乘的结果,即:

协方差矩阵 $C=AA^T \Rightarrow$ $\begin{bmatrix}\sum_{1}^{n}{x_i^2}&\sum_{1}^{n}{x_iy_i}\\\sum_{1}^{n}{y_ix_i}&\sum_{1}^{n}{y_i^2}\end{bmatrix}=$$\begin{bmatrix} x_1&x_2&x_3&...&x_n\\y_1&y_2&y_3&...&y_n\end{bmatrix}$$\begin{bmatrix} x_1&y_1\\x_2&y_2\\x_3&y_3\\.&.\\x_n&y_n\end{bmatrix}$。一般而言,$X$ 和 $Y$ 满足线性无关,所以依据我们之前介绍的知识,协方差矩阵 $C$ 是对称的、正定的满秩方阵。

接下来,我们就想把各样本的特征 $X$ 和特征 $Y$ 的取值用另外一组基来表示,由于要求在新的基下表示的新特征彼此无关,那么必然的,新选择的两个基必须彼此正交。

我们选择一组新的基, $p_1$ 和 $p_2$ ,他们的模长为 $1$,彼此之间满足标准正交,前面我们学过,在此条件下,向量 $a=\begin{bmatrix}x_1\\y_1\end{bmatrix}$ 与向量 $p_i$ 的点积就表示向量 $a$ 在 $p_i$ 方向上的投影,同时由于 $p_i$ 是单位向量,那么点积的结果就代表了基向量 $p_i$ 的坐标。

那么向量 $a$ 在由标准正交向量 $p_1$ 和 $p_2$ 构成的新基底上的坐标即为 $\begin{bmatrix}p_1^Ta\\p_2^Ta\end{bmatrix}$,如果我们令 $P=\begin{bmatrix}p_1^T\\p_2^T\end{bmatrix}$,那么可以进一步将其表示为: $Pa$。

梳理一下这里所做的工作:$A=\begin{bmatrix} x_1&x_2&x_3&...&x_n\\y_1&y_2&y_3&...&y_n\end{bmatrix}$,就是 $n$ 个样本的特征 $X$ 和特征 $Y$ 的原始采样值。而 $PA=\begin{bmatrix} p_1^Ta_1& p_1^Ta_2& p_1^Ta_3&... &p_1^Ta_n\\p_2^Ta_1&p_2^Ta_2&p_2^Ta_3&...&p_2^Ta_n\end{bmatrix}$(其中 $a_i=\begin{bmatrix}x_i\\y_i\end{bmatrix}$)。描述的就是这 $n$ 个样本在新构建的特征下的取值。

此时,我们来实现第一个目标:

即,试图让第一个新特征 $\begin{bmatrix} p_1^Ta_1& p_1^Ta_2&...&p_1^Ta_n\end{bmatrix}$ 和第二个新特征 $\\\begin{bmatrix}p_2^Ta_1&p_2^Ta_2&...&p_2^Ta_n\end{bmatrix}$ 满足线性无关。换句话说,就是要求这两个特征的协方差为 $0$,协方差矩阵是一个对角矩阵。

$D=\frac{1}{n-1}PA(PA)^T=\frac{1}{n-1}PAA^TP^T=\frac{1}{n-1}PCP^T$,这就转化成了我们再熟悉不过的问题了:去寻找让矩阵 $C$ 对角化的 $P$ 矩阵,这里还有一个好的前提条件:$C$ 是对称矩阵、正定矩阵,他保证了矩阵一定能够对角化,且特征值全都为正。

我们在对称矩阵那一节里,得到过这样的结论:对称矩阵一定可以得到由一组标准正交特征向量构成的特征矩阵。即,矩阵 $Q$ 可以表示成:$\begin{bmatrix} q_1&q_2&...&q_n\end{bmatrix}$ , 我们进一步将 $S=Q\Lambda Q^T$ 整理一下,得到 $\Lambda=Q^TSQ$。进行展开得到,$\Lambda=\begin{bmatrix} q_1^T\\q_2^T\\...\\q_n^T\end{bmatrix}S\begin{bmatrix} q_1&q_2&...&q_n\end{bmatrix}$。

上下两个式子进行比对我们就会发现:我们要求的矩阵 $P$,就是 $P=Q^T=\begin{bmatrix} q_1^T\\q_2^T\\...\\q_n^T\end{bmatrix}$,其中 $q_1$ 到 $q_n$ 就是协方差矩阵 $C$ 的 $n$ 个标准正交特征向量。由此,我们再通过 $PA$ 就能计算得出彼此线性无关的新特征。

4.2.结合例子实际操作

那么在这里举的实例中,我们具体来操作一下,首先我们进行零均值化的工作:

代码片段
```
import numpy as np
import matplotlib.pyplot as plt

x = [2,2,4,8,4]
y = [2,6,6,8,8]

x = x - np.mean(x)
y = y - np.mean(y)

S = np.vstack((x,y))

top Created with Sketch.