文章目录
- 引言
- 一、PCA的概念
- 二、PCA的基本数学原理
-
- [2.1 内积与投影](#2.1 内积与投影)
- [2.2 基](#2.2 基)
- [2.3 基变换](#2.3 基变换)
- [2.4 关键问题及优化目标](#2.4 关键问题及优化目标)
- [2.5 方差](#2.5 方差)
- [2.6 协方差](#2.6 协方差)
- [2.7 协方差矩阵](#2.7 协方差矩阵)
- [2.8 协方差矩阵对角化](#2.8 协方差矩阵对角化)
- 三、PCA执行步骤总结
- 四、PCA参数解释
- 五、代码实现
- 六、PCA的优缺点
- 七、总结
引言
在机器学习领域,我们经常会遇到高维数据带来的"维度灾难"问题。随着特征数量的增加,数据稀疏性增强,模型复杂度飙升,计算成本大幅提高。主成分分析(PCA)作为一种经典的降维技术,能够有效解决这些问题。本文将深入浅出地介绍PCA的原理、实现和应用。
一、PCA的概念
主成分分析(Principal Component Analysis,PCA)是一种无监督的线性降维方法,它通过正交变换将一组可能存在相关性的变量转换为一组线性不相关的变量,这些新变量被称为"主成分"。
PCA的核心思想是:
- 将原始高维数据投影到低维子空间
- 保留数据中最重要的变异信息
- 用较少的变量解释原始数据中的大部分信息
二、PCA的基本数学原理
2.1 内积与投影
下面先看一个向量运算:内积。两个维数相同的向量的内积被定义为:
内积运算将两个向量映射为一个实数,其计算方式非常容易理解,但是其意义并不明显,下面我们分析内积的几何意义。假设A和B是两个n维向量,我们知道n维向量可以表示为n维空间中的一条从原点发射的有向线段,为了简单起见,我们假设A和B均为二维向量,则
那么在二维平面中A和B可以用两条从原点出发有向线段表示,如下图:
现在,我们作OA向量和AA'向量,然后我们从A点向B点所在直线引入一条垂线,垂足为A' ,得到A在B上的投影 m=OA'向量,m称为投影向量。假设A与B的夹角为a,则投影的矢量长度为(矢量有方向,标量无方向):
其中
是向量A的模。若假设向量B的模为1,那么就变成了下面公式(也就是上面我们说的投影的矢量长度):
2.2 基
基:也称为基底,是描述、刻画向量空间的的基本工具。
我们经常使用线段终点的点的坐标表示向量,例如下面的向量可以表示为(3,2),不过只有一个(3,2)本身是不能够精确表示一个向量的,我们仔细看一下,这里的坐标(3,2)实际上表示的是向量在x轴上的投影值3,在y轴上的投影值为2。也就是说我们可以这样理解:以x轴和y轴上正方向长度为1的向量为标准,那么一个向量(3,2)实际上是说在x轴投影为3而y轴投影为2,而投影是矢量,可以为负。
所以向量(3,2)可以由这一组基表示:
因此向量(x,y)实际上表示线性组合,以x轴和y轴上正方向长度为1的向量为标准,:
可知,所有二维向量都可以表示为这样的线性组合,此处(1,0)和(0,1)叫做二维空间的一组基。
2.3 基变换
基变换的表示方法很简单,还是拿上面的例子,想一下,将(3,2)变换为新基上的坐标,就是用(3,2)与第一个基做内积运算,作为第一个新的坐标分量,然后用(3,2)与第二个基做内积运算,作为第二个新坐标的分量。
那么其中矩阵的两行分别为两个基,乘以原向量,其结果刚好为新基的坐标,例如(1,(1,1),(2,2),(3,3)想变换到刚才那组基上,则可以变为这样:
于是一组向量的基变换被表示为矩阵的相乘。
一般地,如果我们有M个N维向量,想将其变换为由R个N维向量表示的新空间中,那么首先将R个基按照行组成矩阵A,,然后将向量按照列组成矩阵B,那么两个矩阵的乘积AB就是变换结果,其中AB的第m列为A中的第M列变换后的结果。
数学表示为:
总结来说基变换的含义就是两个矩阵相乘将右边矩阵中的每一列列向量变换到左边矩阵中每一行行向量为基所表示的空间中去。更抽象的说:一个矩阵可以表示为一种线性变换。
2.4 关键问题及优化目标
上面我们讨论了选择不同的基可以对同样一组数据给出不同的表示,而且如果基的数量少于向量的本身的维数,则可以达到降维的效果,但是我们还没有回答最关键的一个问题:如何选择基才是最优的,或者说如何才能最大程度保留原有的信息?
下面我们以一个具体的例子展开,假设我们的数据由五条记录组成,将它们表示为矩阵形式:
其中每一列为一条数据记录,而一行为一个字段,为了后续处理方便,我们首先将每个字段内所有值都减去字段均值,其结果是将每个字段都变为均值为0(这样做的好处后面可以看到)。
我们看上面的数据,第一个字段的均值为2,第二个字段的均值为3,所以变换后:
我们可以看到五条数据在平面直角坐标系内的样子:
那么现在还是回到刚刚的问题:如何选择基才是最优的,或者说如何才能最大程度保留原有的信息?
这个问题实际上是要在二维平面中选择一个方向,将所有数据都投影到这个方向所在的直线上,用投影值表示原始记录,这是一个实际的二维降到一维的问题。
以上图为例,可以看出如果向x轴投影,那么最左边的两个点会重叠在一起,中间的两个点也会重叠在一起,于是本身四个各不相同的二维点投影后只剩下两个不同的值了,这是一种严重的信息丢失,同理,如果向y轴投影最上面的两个点和分布在x轴上的两个点也会重叠,所以看来x和y轴都不是最好的投影选择。我们直观目测,如果向通过第一象限和第三象限的斜线投影,则五个点在投影后还是可以区分的。
下面我们用数学方法表述这个问题。
2.5 方差
从上述来说,我们希望投影后投影值尽可能分散,而这种分散程度,可以用数学上的方差来表述,此处,一个字段的方差可以看做是每个元素与字段均值的差的平方和的均值,即:
由于上面我们已经将每个字段的均值都化0 了,因此方差可以直接用每个元素的平方和除以元素个数表示:
于是上面的问题变为:寻找一个一维基,使得所有数据变换为这个基上的坐标表示后,方差值最大。(对于二维变一维来说)
2.6 协方差
对于上面二维降成一维的问题来说,找到那个使得方差最大的方向就可以了。不过对于更高维,比如三维数据来说,将数据降到二维,寻找的基为方差最大的方向,再次将数据讲到一维,找到的基必然与降到二维的基无限接近,显然这样的维度是没有用的,因此应该有其他约束条件。从直观上讲,让两个字段尽可能表示更多的原始信息,我们是不希望他们之间存在线性相关性,因为相关性意味着两个字段不是完全独立,必然存在重复表示的信息。
数字上可以用两个字段的协方差表示其相关性,协方差的公式为:
由于已经让每个字段均值为0,则:
可以看出,在字段均值为0的情况下,两个字段的协方差简洁的表示为其内积除以元素数m。
当协方差为0时,表示两个字段完全独立,为了让协方差为0,我们选择第二个即时只能在与第一个基正交的方向上选择。因此最终选择的两个方向一定是正交的。
至此,我们得到了降维问题的优化目标:将一组N维向量降维K维(K大于0,小于N),其目标是选择K个单位(模为1)正交基,使得原始数据变换到这组基上后,各字段两两间协方差为0,而字段的方差则尽可能大(在正交的约束下,取最大的k个方差)。
2.7 协方差矩阵
假设我们有a,b两个字段,组成矩阵 X :
然后我们用X乘以X的转置,并乘上系数1/m:
这时候我们会发现,这个矩阵对角线上的两个元素分别是两个字段的方差,而其他元素是a和b的协方差,两者被统一到了一个矩阵的。
2.8 协方差矩阵对角化
设原始数据矩阵X对于的协方差矩阵为C,而P是一组基按行组成的矩阵,设Y=PX,则Y为X对P做基变换后的数据,设Y的协方差矩阵为D,我们推导一下D与C的关系:
此时,优化目标变成了寻找一个矩阵P,满足PCPT是一个对角矩阵,并且对角元素按照从大到小依次排列,那么P的前K行就是要寻找的基,用P的前K行组成的矩阵乘以X就使得X从N维降到了K维并满足上述优化条件。
由上文知道,协方差矩阵C是一个对称矩阵,在线性代数上,实对称矩阵有一系列非常好的性质:
- 实对称矩阵不同特征值对应的特征向量必然正交。
- 设特征向量 λ 重数为r,则必然存在r个线性无关的特征向量对应于 λ,因此可以将这r个特征向量单位正交化。
有上面两条可知,一个n行n列的实对称矩阵一定可以找到n个单位正交特征向量,设这n个特征向量为e1, e2, ...en,我们将其按照列组成矩阵:

则对协方差矩阵C有如下结论:
其中 Λ 为对称矩阵,其对角元素为各特征向量对应的特征值(可能有重复)。到这里,我们发现我们已经找到了需要的矩阵P:
P是协方差矩阵的特征向量单位化后按照行排列出的矩阵,其中每一行都是C的一个特征向量。
三、PCA执行步骤总结
求解步骤:
- 将原始数据按列组成n行m列矩阵X
- 将X的每一行(代表一个属性字段)进行零均值化(去平均值),即减去这一行的均值
- 求出协方差矩阵 C= 1/mXXT
- 求出协方差矩阵的特征值及对应的特征向量
- 将特征向量按对应特征值大小从上到下按行排列成矩阵,取前k行组成矩阵P(保留最大的k各特征向量)
- Y=PX 即为降维到K维后的数据
四、PCA参数解释
python
from sklearn.decomposition import PCA
从sklearn.decomposition导入PCA函数
python
PCA(n_components=None, copy=True, whiten=False, svd_solver='auto', tol=0.0, iterated_power='auto', random_state=None)
- n_components
功能:决定PCA算法应该保留的主成分数量。 取值: 整数k:表示保留前k个主成分。
小数(0,1]之间的数:表示保留的主成分的方差百分比,例如0.9表示保留90%的方差。 如果设置为None(默认值),则保留所有主成分。 - copy
功能:是否在运行算法时,将原始训练数据复制一份。 取值: True(默认值):复制数据,以免修改原始数据。
False:直接在原始数据上进行计算。 - whiten
功能:决定是否对数据进行白化处理。
取值:
True:对数据进行白化,即对每个特征进行归一化,使得每个特征的方差都为1。在某些应用中,白化可以提高数据的可解释性。
False(默认值):不进行白化。 - svd_solver
功能:决定使用的SVD(奇异值分解)求解器的类型。
取值:
'auto'(默认值):根据输入数据的大小和特征数量自动选择最合适的求解器。
'full':使用传统的SVD方法,适用于较小的数据集。
'arpack':使用scipy库中的稀疏SVD实现,适用于大型数据集。
'randomized':使用一种随机算法来加快SVD的计算速度,适用于大型数据集且主成分数目较少的情况。 - tol
功能:决定奇异值分解的收敛容差。
取值:默认为0.0,表示使用默认的收敛容差。较小的值会产生更精确的结果,但也会增加计算时间。 - iterated_power
功能:决定幂迭代方法的迭代次数。
取值:默认为'auto',表示使用一种启发式方法选择迭代次数。通常不需要手动调整这个参数。 - random_state
功能:决定随机数生成的种子
取值:如果设置为None,则随机生成器使用当前系统时间作为种子
设置为整数,则使用该整数作为随机数生成器的种子
五、代码实现
python
from sklearn.decomposition import PCA
import pandas as pd
from sklearn.model_selection import train_test_split
data = pd.read_csv(r"./creditcard.csv")
# 数据划分
X = data.iloc[:,:-1]
y = data.iloc[:,-1]
pca = PCA(n_components=0.90) ## 实例化PCA对象
pca.fit(X) ##进行训练不需要传入y
print('特征所占百分比:{}'.format(sum(pca.explained_variance_ratio_)))
print(pca.explained_variance_ratio_)
print('PCA降维后数据:')
new_x = pca.transform(X)
print(new_x) #数据X在主成分空间中的表示。具体来说,这个方法将数据X从原始特征空间转入
x_train,x_test,y_train,y_test = \
train_test_split(X,y,test_size=0.5,random_state=0)
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import cross_val_score #交叉验证的函数
# 交叉验证选择较优惩罚因子
lr = LogisticRegression(penalty='l2')
lr.fit(x_train,y_train)
from sklearn import metrics
train_predicted = lr.predict(x_train) #自测
print(metrics.classification_report(y_train,train_predicted))
# cm_plot(y_train,train_predicted).show()
#预测结果
test_predicted = lr.predict(x_test) #小的数据集进行测试
print(metrics.classification_report(y_test,test_predicted)) #绘制混淆矩阵
# cm_plot(y_test,test_predicted).show() #小的数据集的报告
六、PCA的优缺点
优点:
- 计算方法简单,容易实现
- 可以减少指标筛选的工作量
- 消除变量间的多重共线性
- 在一定程度上能减少噪声数据
缺点:
- 特征必须是连续型变量
- 无法解释降维后的数据是是什么
- 贡献率小的成分有可能更重要
七、总结
PCA作为一种经典且强大的降维工具,在机器学习领域有着广泛的应用。理解其数学原理和实现细节,能够帮助我们在实际项目中更好地使用它。需要注意的是,PCA并非适用于所有场景,在使用前应该仔细评估数据特性和需求,选择最合适的降维方法。
希望本文能帮助您掌握PCA的核心概念和应用技巧!