Gadzan

PCA主成分分析

泛滥成灾的特征维度

维度灾难

维数灾难(Curse of Dimensionality,也可以直接翻译为“维度诅咒”)是一种在分析或组织高维(通常是几百维或者更高维度)数据时会遇到的现象。既然叫灾难或者诅咒,可见不是好现象。

这个说法,最早是由理查德 · 贝尔曼(Richard E. Bellman)——美国应用数学家,同时也是动态规划算法创始人——提出来的。

他是在思考动态优化的过程中发现了这件事:当数据维度增加时,由于向量空间体积呈指数级增加,会遇到许多在低维数据中很难出现的问题。比如:

$100$个平均分布的点能把一个一维的单位区间均分为$100$份,也就是说$100$个均匀分布的采样点就可以在一维的单位空间里形成精度为$0.01$的采样。

而要在二维的单位空间里形成同样密度的采样,就需要$10000$个点;三维需要$1000000$个点;十维空间则需要$10^{20}$个采样点……

那要是1000维呢?所需采样数根本就是天文数字,现实当中,我们怎么可能去找那么多样本数据?

以上是当年理查德 · 贝尔曼举的例子。

数据稀疏

其实这个问题反过来想更直接。

在现实生活中,无论我们是做统计分析还是机器学习,能获得的样本的数量(至少是量级)是相对固定的,毕竟现实数据都有其获取成本。

同样数量的样本,如果我们只选取一维特征,那么这些样本在特征空间中的密度肯定会比在二维、三维或者更高维度空间中大得多。

下图这个例子显示了20个样本,分别在一维、二维和三维空间中的分布:

而到了真正的高维,将稀疏到什么程度,可以想象。

数据稀疏对于任何要求有统计学意义的方法而言(无论是概率统计、数据挖掘,还是机器学习)都是一个问题。

一般而言,为了获得在统计学上可靠的结果,用来支撑这一结果的数据量随着特征维数的提高而呈指数级增长。

数据稀疏对机器学习的影响

数据稀疏对于机器学习的影响尤其大。

  • 首先,机器学习本身就是建立在统计学习之上的。

  • 其次,在机器学习中有大量模型依据样本之间的相似度来对其进行判断,而往往样本的相似度由其在特征空间的相互距离决定,这就使得样本密度直接影响了样本属性。

  • 此外,维度的增多还直接导致了对于计算能力需求的增大,从而在实践中对机器学习算法造成影响。

机器学习中,有时会出现这样的情况:在训练样本固定的情况下,特征维数增加到某一个临界点后,继续增加反而会导致模型的预测能力减小——这叫做休斯现象(Hughes Phenomenon,以其发现者 G. Hughes 命名)。

降低数据维度

降低维度的可能

虽然很多时候,“维数灾难”会被研究人员当作不处理高维数据的借口,但学术界对这一现象一直在进行研究。

由于本征维度的存在,众多降维方法的有效性得到了证明——也就是说,应用这些降维方法处理过的数据,虽然特征维度下降了,却没有丢失掉主要的属性信息。

注意:本征维度(Intrinsic Dimension)原本是信号处理中的概念。

信号的本征维度描述了需要用来表示信号的变量数量。对于含有 $N$ 个变量的信号而言,它的本征维度为 $M$,$M$ 满足 $0 \leqslant M \leqslant N$。

本征维度指出,许多高维数据集可以通过削减维度降至低维空间,而不必丢失重要信息。

降维度方法

机器学习领域里讲的降维是指:采用某种映射方法,将原本高维空间中的数据样本映射到低维空间中。

降维的本质是学习一个映射函数 $y=f( x)$,其中 $x$ 表示原始的高维数据,$y$ 表示映射后的低维数据。

之所以降维后的数据能够不丧失主要信息,是因为原本的高维数据中包含了冗余信息和噪音,通过降维,我们减少了冗余,过滤了噪声,从而保留了有效的特征属性,甚至是提高了数据的精度——这当然是我们希望的情况。

降维算法多种多样,比较常用的有:PCA(Principal Component Analysis,主成分分析)、LDA(Linear Discriminant Analysis,线性判别分析)、LLE(Locally linear embedding,局部线性嵌入)、Laplacian Eigenmaps (拉普拉斯特征映射)等。

还有一些机器学习模型和方法,比如随机森林/决策树,聚类等,也可以用作降维的手段。

今天我们只讲其中最常用的一种——PCA,主成分分析。

主成分分析(PCA)的原则

PCA 是一种统计学中用于分析、简化数据集的技术,经常用来减少数据的维度数。

PCA 由英国数学家卡尔 · 皮尔逊(Karl Pearson)——他也是皮尔森卡方检验的发明者——在1901年发明的。在统计学领域,PCA 是最简单的用特征分析进行多元统计分布的方法。

我们对于所有降维方法的预期都是:将原始高维空间的样本数据转变为低维“子空间”(Subspace)中的数据,使得子空间中样本密度得以提高,样本间距离计算变得容易,同时又不丧失主要特征信息,至少是不丧失与学习任务有密切关系的那些特征信息。

向量空间都有对应的超平面,而超平面的维度低于其所在空间。

注意:我们之前专门学习过超平面,还记得吗?

那么,如果我们能把一个空间中的样本点映射到它的超平面上去,这样一来,映射后的结果不就只存在于超平面空间(也就是原空间的子空间)了吗?这样,我们就获得了降维的结果。

怎么能够保证超平面中的点不丧失对应原始点的“主成分”呢?

首先,至少要尽量使得原空间中的样本点投影到超平面之后不重叠。否则,有一些样本就“消失”了——这显然不符合我们的预期。

其次,既然做了投影,就一定会丢失一部分信息。直接丢失掉的,就是原空间中样本到达超平面的距离。因此,我们还要尽量使得这个超平面靠近原空间样本点——如果样本点到超平面的距离只有很小的一段,那么映射后它丢失的信息量也相应地会很小。

基于这种想法,我们理想的超平面需要具备这样两个性质:

  • 最大可分性:样本点到这个超平面上的投影尽量能够分开;

  • 最近重构性:样本点到这个超平面的距离尽量近。

PCA 的优化目标

既然已经知道我们要做的是将一个向量空间中的样本投影到具备上述两个性质的超平面里面去。那么根据之前的经验,下一步就是把我们要做的事情转化为形式化优化目标。

我们的优化目标很清晰,就是最大可分性和最近重构性。形式化表达就是用数学式子来表达它(们)。

假设我们有 $n$ 个样本数据,这些样本原本属于一个 $d$ 维空间。

我们先对样本数据做一下中心化,使得 $\sum_i x^{(i)} = 0$。

注意: 数据中心化就是将一个个样本以整体均值为中心移动至原点。比如下图这样:

原空间里的第 $i$ 个样本可以表示为:

$x^{(i)} = (x^{(i)}_1, x^{(i)}_2, ..., x^{(i)}_d) $

我们要将它们投影到一个 $d'$ 维的空间,有 $d' < d$。第 $i$ 样本投射到低维空间后表示为 $z^{(i)} = (z^{(i)}_1, z^{(i)}_2, ..., z^{(i)}_{d'} )$。

从 $x^{(i)}$ 到 $z^{(i)}$ 的转换表示为:

$z^{(i)}_{j} = {w_j}^T {x^{(i)}} $ , $i = 1, 2, ..., n$; $j = 1, 2, ..., d'$

上式中,$z^{(i)}_{j}$ 表示 $x^{(i)} $ 在低维坐标系下第 $j$ 维的坐标。

$w_j$ 是一个 $d$ 维的权重向量,$w_j = (w_{j1}, w_{j2}, ..., w_{jd}) $。

如果基于 $z^{(i)} $ 来重构 $x^{(i)} $,令:$\hat{x}^{(i)} = \sum_{j = 1}^{d'} z^{(i)}_{j} w_j$。

$\hat{x}^{(i)}$ 就是原本 $d$ 维空间中的样本点 $x^{(i)} $ 投影到新的 $d'$ 维空间后形成的新样本点在原本 $d$ 维空间中的位置。

比如:下面这个最简单的例子,原空间是一个二维空间($d=2$),把样本 $x$ 映射到一个一维空间里面去,对应的映射点在二维空间中的坐标为 $\hat{x}$,那么 $x$ 和 $\hat{x}$ 之间的距离当然就是 $||\hat{x} - x||_2^2$。

基于最近重构性的优化目标

根据前面说的最近重构性原则,我们要的是所有 $n$ 个样本分别与其基于投影重构的样本点间的距离整体最小

整体距离为:

$\sum_{i=1}^{n} || \hat{x }^{(i)} - x^{(i)} ||_2^2$

我们的目标就是最小化整体距离:

$\min{\sum_{i=1}^{n} || \hat{x }^{(i)} - x^{(i)} ||_2^2}$

因为:

$\sum_{i=1}^{n} || \hat{x }^{(i)} - x^{(i)} ||_2^2 $

$= \sum_{i=1}^{n} ||\sum_{j = 1}^{d'} z^{(i)}_{j} w_j - x^{(i)} ||_2^2 $

$= \sum_{i=1}^{n} {z^{(i)}}^Tz^{(i)} - 2 \sum_{i=1}^{n}{z^{(i)}}^{T}W^{T} x^{(i)} + C$

其中,$C$ 为常数。

$W$ 是一个 $d \times d'$ 的变换矩阵:

$W = (\mathrm{w}_ {kj} = {w}_ {jk}), \ \ j = 1, 2, ..., d', \ \ k = 1,2, ..., d$

它一共有 $d'$ 列,每一列都是一个 $d$ 维的向量 $w_j$。

换言之,$z^{(i)}$ 是原空间中的样本 $x^{(i)}$ 在新的坐标系 $W = (w_1, w_2, ..., w_{d'} )$ 中的坐标向量,于是有:$z^{(i)} = W^T x^{(i)}$。

既然要用 $W$ 来表示坐标系,样本从原空间到新空间又是不同维度空间中点的线性变换。那么我们大可以从一开始就要求 $w_j$ 是标准正交基,也就是有:$||w_j||_2 = 1 $,且 ${w_j}^T{w_l} = 0 $,其中 $j = 1, 2, ..., d', \ \ l = 1, 2, ..., d',\ \ j \ne l $。

回到上面的式子:

$\sum_{i=1}^{n} {z^{(i)}}^Tz^{(i)} - 2 \sum_{i=1}^{n}{z^{(i)}}^{T}W^{T} x^{(i)} \propto -\mathbf {tr}(W^T(\sum_{i=1}^{n}x^{(i)}{x^{(i)}}^T)W)$

注意:$\mathbf {tr}(M)$ 表示方阵 $M$ 的迹,方型矩阵 $M$ 的对角线元素之和称为 $M$ 的迹。

而 $\sum_{i=1}^{n}x^{(i)}{x^{(i)}}^T$ 是 $d \times d$ 的协方差矩阵。

令:$X = (x^{(1)}, x^{(2)}, ..., x^{(n)})$

则:$-\mathbf {tr}(W^T(\sum_{i=1}^{n}x^{(i)}{x^{(i)}}^T)W) = -\mathbf {tr}(W^TXX^TW)$

于是,我们的优化目标就变成了:

$\arg{\min_W {-\mathbf {tr}(W^TXX^TW)}}$

$s.t. W^TW = I$

这里的约束条件是根据 $W$ 的列是标准正交基来的。如果没有这个约束条件,那就相当于目标函数可以任意拉伸投影向量的模,这样是无法给出最优解的。

基于最大可分性的优化目标

如果从最大可分性出发,应该怎么设定我们的优化目标呢?

根据上面一小节我们知道,原空间样本点在新空间的投影为: $z^{(i)} = W^T x^{(i)}$。

既然要让所有样本点投影后尽量分开,那就应该让新空间中投影点的方差尽量大。比如在下图中,原始数据(白点)投影到黑点所在超平面就比投影到红点所在超平面方差大。

投影点的方差是:$\sum_i W^T x^{(i)}{x^{(i)}}^T W$

于是优化目标为:

$\arg{\max_W {\mathbf {tr}(W^TXX^TW)}}$

$s.t. W^TW = I$

如果对目标函数求负,则是:

$\arg{\min_W {-\mathbf {tr}(W^TXX^TW)}}$

$s.t. W^TW = I$

正好与基于最近重构性原则构建的优化目标一致!

PCA 优化算法

已知 PCA 的目标函数是:

$\arg{\min_W {-\mathbf {tr}(W^TXX^TW)}}$

$s.t. W^TW = I$

PCA 的优化算法要做的就是最优化上面这个函数。

算法一

既然优化目标有等式约束条件,那么正好用我们之前学过的拉格朗日乘子法。

我们令:

$L(W) =\mathbf {tr}(W^TXX^TW)+\lambda (W^TW−I) $

然后对 $W$ 求导,并令导函数为$0$可得:$XX^TW = \lambda W$。

这是一个标准的特征方程求解问题,只需要对协方差矩阵 $XX^T$ 进行特征值分解,将求得的特征值排序:$\lambda_1 \geqslant \lambda_2 \geqslant ... \geqslant \lambda_d$,再取前 $d'$ 个特征值对应的特征向量构成 $W=(w_1, w_2, ..., w_{d'} )$ 即可。

这样我们就求出了 $W$,这就是主成分分析的解!

注意:关于矩阵的特征值和特征向量,请参见 《机器学习线性代数常用知识汇总》第4部分。

算法描述如下。

【输入】:

  • $d$ 维空间中 $n$ 个样本数据的集合 $D = \{x^{(1)}, x^{(2)}, ..., x^{(n)} \}$;

  • 低维空间的维数 $d'$ ,这个数值通常由用户指定

【过程】:

  1. 对所有原始样本做中心化:$x^{(i)} := x^{(i)} - \frac{1}{n}\sum_{i=1}^{n} x^{(i)} $;

  2. 计算样本的协方差矩阵:$XX^T$;

  3. 协方差矩阵 $XX^T$ 进行特征值分解;

  4. 取最大的 $d'$ 个特征值对应的特征向量 $w^{(1)}, w^{(2)}, ..., w^{(d')}$。

【输出】:

$W=(w^{(1)}, w^{(2)}, ..., w^{(d')} )$

算法二

上述求解过程可以换一个角度来看。

先对协方差矩阵 $\sum_{i=1}^{n}x^{(i)}{x^{(i)}}^T$ 做特征值分解,取最大特征值对应的特征向量 $w_1$;再对 $\sum_{i=1}^{n}x^{(i)}{x^{(i)}}^T - \lambda_1 w_1w_1^T$ 做特征值分解,取其最大特征值对应的特征向量 $w_2$;以此类推。

因为 $W$ 的各个分量正交,因此 $\sum_{i=1}^{n}x^{(i)}{x^{(i)}}^T = \sum_{j=1}^{d} \lambda_j w_jw_j^T$。

故而解法二和解法一等价。

PCA 的作用

PCA 将 $d$ 维的原始空间数据转换成了$d'$ 维的新空间数据,无疑丧失了部分数据。

根据上面讲的算法我们知道,经过 PCA 后,原样本集协方差矩阵进行特征值分解后,倒数 $(d - d')$ 个特征值对应的特征向量被舍弃了。

因为舍弃了这部分信息,导致的结果是:

  • 样本的采样密度增大——这是降维的首要动机;

  • 最小的那部分特征值所对应的特征向量往往与噪声有关,舍弃它们有降噪的效果。

奇异值分解(Singular Value Decomposition, SVD)

SVD 是线性代数中一种重要的矩阵分解方法,在信号处理、统计学等领域有重要应用。

SVD 的三个矩阵

我们先来看看 SVD 方法本身。

假设 $M$ 是一个 $m\times n$ 阶实矩阵,则存在一个分解使得:

$M_{m \times n} = U_{m \times m} \Sigma_{m \times n} {V^T_{n \times n}}$

其中,$\Sigma$ 是一个 $m \times n$ 的非负实数对角矩阵,$\Sigma$ 对角线上的元素是矩阵 $M$ 的奇异值:

$\Sigma = diag{( \sigma_i)}, \ \ i=1, 2, ..., \min{(m,n)} $

注意:对于一个非负实数 $\sigma$ 而言,仅当存在 $m$ 维的单位向量 $u$ 和 $n$ 维的单位向量 $v$,它们和 $M$ 及 $\sigma$ 有如下关系时:

$Mv = \sigma u \,\text{ 且 } M^{T}u= \sigma v$

我们说 $\sigma$ 是 $M$ 矩阵的奇异值,向量 $u$ 和 $v$ 分别称为 $\sigma$ 的左奇异向量右奇异向量

一个 $m\times n$ 的矩阵至多有 $\min{(m,n)}$ 个不同的奇异值。

$U$ 是一个 $m \times m$ 的酉矩阵,它是一组由 $M$ 的左奇异向量组成的正交基:$U = (u_1, u_2, ..., u_m)$。

它的每一列 $u_i$ 都是 $\Sigma$ 中对应序号的对角值 $\sigma_i$ 关于 $M$ 的左奇异向量。

$V$ 是一个 $n \times n$ 的酉矩阵,它是一组由 $M$ 的右奇异向量组成的正交基:$V = (v_1, v_2, ... v_n)$。

它的每一列 $v_i$ 都是 $\Sigma$ 中对应序号的对角值 $\sigma_i$ 关于$M$的右奇异向量。

何为酉矩阵?

若一个 $n \times n$ 的实数方阵 $U$ 满足 $U^TU= UU^T = I_n$,则 $U$ 称为酉矩阵。

三个矩阵间的关系

我们这样来看:

$M = U\Sigma V^T$

$M^T = {(U\Sigma V^T)}^T = V{\Sigma}^TU^T$

$MM^T = U\Sigma V^TV{\Sigma}^TU^T $

又因为 $U$ 和 $V$ 都是酉矩阵,所以:

$MM^T = U(\Sigma \Sigma^T)U^T$

同理:$M^TM = V(\Sigma^T \Sigma)V^T$。

也就是说 $U$ 的列向量是 $MM^T$ 的特征向量;$V$ 的列向量是 $M^TM$ 的特征向量;而 $\Sigma$ 的对角元素,是 $M$ 的奇异值,也是 $MM^T$ 或者 $M^TM$ 的非零特征值的平方根。

SVD 的计算

SVD 的手动计算过程大致如下:

  1. 计算 $MM^T$ 和 $M^TM$;
  2. 分别计算 $MM^T$ 和 $M^TM$ 的特征向量及其特征值;
  3. 用 $MM^T$ 的特征向量组成 $U$,$M^TM$ 的特征向量组成 $V$;
  4. 对 $MM^T$ 和 $M^TM$ 的非零特征值求平方根,对应上述特征向量的位置,填入 $\Sigma$ 的对角元。

更详细的过程和计算实例还可以参照这里

用 SVD 实现 PCA

所谓降维度,就是按照重要性排列现有特征,舍弃不重要的,保留重要的。

上面讲了 PCA 的算法,很关键的一步就是对协方差矩阵进行特征值分解,不过其实在实践当中,我们通常用对样本矩阵 $X$ 进行奇异值分解来代替这一步。

$X$ 是原空间的样本矩阵,$W$ 是投影矩阵,而 $T$ 是降维后的新样本矩阵,有 $ T= XW$。

我们直接对 $X$ 做 SVD,得到:

$T = XW = U\Sigma W^TW$

因为 $W$ 是标准正交基组成的矩阵,因此:$T =U\Sigma W^TW = U\Sigma$。

我们选矩阵 $U$ 前 $d'$ 列,和 $\Sigma$ 左上角前 $d' \times d'$ 区域内的对角值,也就是前 $d'$ 大的奇异值,然后直接降维:

$T_{d'}=U_{d'}\Sigma_{d'}$

这样做很容易解释其物理意义:样本数据的特征重要性程度既可以用特征值来表征,也可以用奇异值来表征。

动机也很清楚,当然是成本。直接做特征值分解需要先求出协方差矩阵,当样本或特征量大的时候,计算量很大。更遑论对这样复杂的矩阵做特征值分解的难度了。

而对矩阵 $M$ 进行 SVD 时,直接对 $MM^T$ 做特征值分解,要简单得多。

当然 SVD 算法本身也是一个接近 $O(m^3)$(假设 $m>n$)时间复杂度的运算,不过现在 SVD 的并行运算已经被实现,效率也因此提高了不少。

直接用 SVD 降维

除了可以用于 PCA 的实现,SVD 还可以直接用来降维。

在现实应用中,SVD 也确实被作为降维算法大量使用。

有一些应用,直接用眼睛就能看得见。比如:用 SVD 处理图像,减少图片信息量,而又尽量不损失关键信息。

图片是由像素(Pixels)构成的,一般彩色图片的单个像素用三种颜色(Red、Green、Blue)描述,每一个像素点对应一个 RGB 三元值。一张图片可以看作是像素的二维点阵,正好可以对应一个矩阵。那么我们用分别对应 RGB 三种颜色的三个实数矩阵,就可以定义一张图片。

设 $X_R、X_G、X_B$ 是用来表示一张图片的 RGB 数值矩阵,我们对其做 SVD:

$X_R = U_R \Sigma_R V_R^T$

然后我们指定一个参数:$k$,$U_R$ 和 $V_R$ 取前 $k$ 列,形成新的矩阵 $U^k_R$ 和 $V^k_R$,$\Sigma_R$ 取左上 $k \times k$ 的区域,形成新矩阵 $\Sigma^k_R$,然后用它们生成新的矩阵:

$X'_R = U^k_R \Sigma^k_R ({V^k_R})^T $

对 $X_G$ 和 $X_B$ 做同样的事情,最后形成的 $X'_R、X'_G 和 X'_B$ 定义的图片,就是压缩了信息量后的图片。

注意:如此处理后的图片尺寸未变,也就是说 $X'_R、X'_G、 X'_B$ 与原本的 $X_R、X_G、X_B$ 行列数一致,只不过矩阵承载的信息量变小了。

比如,$X_R$ 是一个 $m \times n$ 矩阵,那么 $U_R$ 是 $m \times m$ 矩阵, $\Sigma_R$ 是 $m \times n$ 矩阵, 而 $ V_R^T $ 是 $n \times n$ 矩阵,$U^k_R$ 是 $m \times k$ 矩阵, $\Sigma^k_R$ 是 $k \times k$ 矩阵, 而 $ ({V^k_R})^T $ 是 $k \times n$ 矩阵,它们相乘形成的矩阵仍然是 $m \times n$ 矩阵。

从数学上讲,经过 SVD 重构后的新矩阵,相对于原矩阵秩(Rank)下降了。

SVD & PCA 实例

下面我们来看一个压缩图片信息的例子,比如压缩下面这张图片:

我们将分别尝试 SVD 和 PCA 两种方法。

SVD 压缩图片

我们用 SVD 分解上面这张图片,设不同的 $k$ 值,来看分解后的结果。

下面几个结果的 $k$ 值分别是:$100、50、20 和 5$。

很明显,$k$ 取 $100$ 的时候,损失很小,取 $50$ 的时候还能看清大致内容,到了 $20$ 就模糊得只能看轮廓了,到了 $5$ 则是一片条纹。

代码如下:

import os
import threading

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import sys

def svdImageMatrix(om, k):
    U, S, Vt = np.linalg.svd(om)
    cmping = np.matrix(U[:, :k]) * np.diag(S[:k]) * np.matrix(Vt[:k,:])    
    return cmping

def compressImage(image, k):
    redChannel = image[..., 0]
    greenChannel = image[..., 1]
    blueChannel = image[..., 2]

    cmpRed = svdImageMatrix(redChannel, k)
    cmpGreen = svdImageMatrix(greenChannel, k)
    cmpBlue = svdImageMatrix(blueChannel, k)

    newImage = np.zeros((image.shape[0], image.shape[1], 3), 'uint8')

    newImage[..., 0] = cmpRed
    newImage[..., 1] = cmpGreen
    newImage[..., 2] = cmpBlue

    return newImage

path = 'gadzan.jpg'
img = mpimg.imread(path)

title = "Original Image"
plt.title(title)
plt.imshow(img)
plt.show()

weights = [100, 50, 20, 5]

for k in weights:
    newImg = compressImage(img, k)

    title = " Image after =  %s" %k
    plt.title(title)
    plt.imshow(newImg)
    plt.show()    

    newname = os.path.splitext(path)[0] + '_comp_' + str(k) + '.jpg'
    mpimg.imsave(newname, newImg)

PCA 压缩图片

用 PCA 压缩同一张图片。
我们使用:

from sklearn.decomposition import PCA

过程部分,只要将上面代码中的 svdImageMatrix() 替换为如下 pca() 即可:

def pca(om, cn):

    ipca = PCA(cn).fit(om)
    img_c = ipca.transform(om)

    print img_c.shape
    print np.sum(ipca.explained_variance_ratio_)

    temp = ipca.inverse_transform(img_c)
    print temp.shape

    return temp

cn 对应 sklearn.decomposition.PCAn_components 参数,指的是 PCA 算法中所要保留的主成分个数 n,也就是保留下来的特征个数 n。

我们仍然压缩四次,具体的 cn 值还是 [100, 50, 20, 5]

从运行的结果来看,和 SVD 差不多。

其实好好看看 sklearn.decomposition.PCA 的代码,不难发现,它其实就是用 SVD 实现的。


打赏码

知识共享许可协议 本作品采用知识共享署名 4.0 国际许可协议进行许可。

评论