Python数模笔记-Sklearn(3)主成分分析

主成分分析(Principal Components Analysis,PCA)是一种数据降维技术,通过正交变换将一组相关性高的变量转换为较少的彼此独立、互不相关的变量,从而减少数据的维数。


1、数据降维

1.1 为什么要进行数据降维?

为什么要进行数据降维?降维的好处是以略低的精度换取问题的简化。

人们在研究问题时,为了全面、准确地反映事物的特征及其发展规律,往往要考虑很多相关指标的变化和影响。尤其在数据挖掘和分析工作中,前期收集数据阶段总是尽量收集能够获得的各种数据,能收尽收,避免遗漏。多变量、大样本的数据为后期的研究和应用提供了丰富的信息,从不同角度反映了问题的特征和信息,但也给数据处理和分析工作带来了很多困难。

为了避免遗漏信息需要获取尽可能多的特征变量,但是过多的变量又加剧了问题的复杂性。由于各种变量都是对同一事物的反映,变量之间经常会存在一定的相关性,这就造成大量的信息重复、重叠,有时会淹没甚至扭曲事物的真正特征与内在规律。因此,我们希望数据分析中涉及的变量较少,而得到的信息量又较多。这就需要通过降维方法,在减少需要分析的变量数量的同时,尽可能多的保留众多原始变量所包含的有效信息。

变量之间具有一定的相关关系,意味着相关变量所反映的信息有一定程度的重叠,就有可能用较少的综合指标聚合、反映众多原始变量所包含的全部信息或主要信息。 因此,需要研究特征变量之间的相关性、相似性,以减少特征变量的数量,便于分析影响系统的主要因素。例如,对学生的评价指标有很多,作业、考勤、活动、奖惩、考试、考核,根据各种指标的关联度和相似性,最终可以聚合为德智体美等几个主要的类别指标反映众多指标中大部分信息。
  
降维方法可以从事物之间错综复杂的关系中找出一些主要因素,从而能有效利用大量统计数据进行定量分析,解释变量之间的内在关系,得到对事物特征及其发展规律的一些深层次的启发。

1.2 常用的降维思想和方法

降维的数学本质是将高维特征空间映射到低维特征空间,有线性映射和非线性映射两类主要方法。

线性映射方法主要有主成分分析(PCA)和线性判别函数(LDA)。主成分分析(PCA)的思想是按均方误差损失最小化原则,将高维原始空间变换到低维特征向量空间。线性判别函数(LDA)的思想是向线性判别超平面的法向量上投影,使得区分度最大(高内聚,低耦合) 。

非线性映射方法主要有:基于核的非线性降维, 将高维向量的内积转换成低维的核函数表示,如核主成分分析(KPCA)、核线性判别函数(KLDA) ;二维化和张量化, 将数据映射到二维空间上,如二维主成分分析(2DPCA)、二维线性判别分析(2DLDA)、二维典型相关分析(2DCCA);流形学习方法, 从高维采样数据中恢复低维流形结构并求出相应的嵌入映射,如等距映射 (ISOMap) , 拉普拉斯特征映射 (LE), 局部线性嵌入 (LPP)。本质上,非线性映射的思想和算法与神经网络是相通的。

此外,还可以通过聚类分析、神经网络方法进行数据降维。

1.3 SKlearn 中的降维分析方法

SKlearn 工具包提供了多种降维分析方法。

  • 主成分分析
    • decomposition.PCA  主成分分析
    • decomposition.IncrementalPCA  增量主成分分析
    • decomposition.KernelPCA  核主成分分析
    • decomposition.SparsePCA  稀疏主成分分析
    • decomposition.MiniBatchSparsePCA  小批量稀疏主成分分析
    • decomposition.TruncatedSVD  截断奇异值分解
  • 字典学习
    • decomposition.DictionaryLearning  字典学习
    • decomposition.MiniBatchDictionaryLearning  小批量字典学习
    • decomposition.dict_learning  字典学习用于矩阵分解
    • decomposition.dict_learning_online  在线字典学习用于矩阵分解
  • 因子分析
    • decomposition.FactorAnalysis  因子分析(FA)
  • 独立成分分析
    • decomposition.FastICA  快速独立成分分析
  • 非负矩阵分解
    • decomposition.NMF  非负矩阵分解
  • 隐式狄利克莱分布
    • decomposition.LatentDirichletAllocation  在线变分贝叶斯算法(隐式狄利克莱分布)

2、主成分分析(PCA)方法

2.1 基本思想和原理

主成分分析是最基础数据降维方法,它只需要特征值分解,就可以对数据进行压缩、去噪,应用十分广泛。

主成分分析的目的是减少数据集变量数量,同时要保留尽可能多的特征信息;方法是通过正交变换将原始变量组转换为数量较少的彼此独立的特征变量,从而减少数据集的维数。

主成分分析方法的思想是,将高维特征(n维)映射到低维空间(k维)上,新的低维特征是在原有的高维特征基础上通过线性组合而重构的,并具有相互正交的特性,即为主成分。

通过正交变换构造彼此正交的新的特征向量,这些特征向量组成了新的特征空间。将特征向量按特征值排序后,样本数据集中所包含的全部方差,大部分就包含在前几个特征向量中,其后的特征向量所含的方差很小。因此,可以只保留前 k个特征向量,而忽略其它的特征向量,实现对数据特征的降维处理。

主成分分析方法得到的主成分变量具有几个特点:(1)每个主成分变量都是原始变量的线性组合;(2)主成分的数目大大少于原始变量的数目;(3)主成分保留了原始变量的绝大多数信息;(4)各主成分变量之间彼此相互独立。

2.2 算法步骤

主成分分析的基本步骤是:对原始数据归一化处理后求协方差矩阵,再对协方差矩阵求特征向量和特征值;对特征向量按特征值大小排序后,依次选取特征向量,直到选择的特征向量的方差占比满足要求为止。

算法的基本流程如下:

  • (1)归一化处理,数据减去平均值;
  • (2)通过特征值分解,计算协方差矩阵;
  • (3)计算协方差矩阵的特征值和特征向量;
  • (4)将特征值从大到小排序;
  • (5)依次选取特征值最大的k个特征向量作为主成分,直到其累计方差贡献率达到要求;
  • (6)将原始数据映射到选取的主成分空间,得到降维后的数据。

在算法实现的过程中,SKlearn 工具包针对实际问题的特殊性,又发展了各种改进算法,例如:

  • 增量主成分分析:针对大型数据集,为了解决内存限制问题,将数据分成多批,通过增量方式逐步调用主成分分析算法,最终完成整个数据集的降维。
  • 核主成分分析:针对线性不可分的数据集,使用非线性的核函数把样本空间映射到线性可分的高维空间,然后在这个高维空间进行主成分分析。
  • 稀疏主成分分析:针对主成分分析结果解释性弱的问题,通过提取最能重建数据的稀疏分量, 凸显主成分中的主要组成部分,容易解释哪些原始变量导致了样本之间的差异。

2.3 优点和缺点

主成分分析方法的主要优点是:
  1)仅以方差衡量信息量,不受数据集以外的因素影响; 
  2)各主成分之间正交,可消除原始数据各变量之间的相互影响;
  3)方法简单,易于实现。

主成分分析方法的主要缺点是:
  1)各个主成分的含义具有模糊,解释性弱,通常只有信息量而无实际含义;
  2)在样本非正态分布时得到的主成分不是最优的,因此特殊情况下方差小的成分也可能含有重要信息。


3、SKlearn 中的主成分分析(PCA) 方法

3.1 PCA 算法(decomposition.PCA)

sklearn.decomposition.PCA 类是 PCA算法的具体实现,官网介绍详见:https://scikit-learn.org/stable/modules/decomposition.html#principal-component-analysis-pca

sklearn.decomposition.PCA(n_components=None, copy=True, whiten=False)

class sklearn.decomposition.PCA(n_components=None, *, copy=True, whiten=False, svd_solver='auto', tol=0.0, iterated_power='auto', random_state=None)

PCA 类的主要参数:

  • n_components: int,float  n 为正整数,指保留主成分的维数;n 为 (0,1] 范围的实数时,表示主成分的方差和所占的最小阈值。
  • whiten:bool, default=False  是否对降维后的主成分变量进行归一化。默认值 False。
  • svd_solver:{‘auto’, ‘full’, ‘arpack’, ‘randomized’}  指定奇异值分解SVD的算法。'full' 调用 scipy库的 SVD;'arpack'调用scipy库的 sparse SVD;'randomized' SKlearn的SVD,适用于数据量大、变量维度多、主成分维数低的场景。默认值 'auto'。

PCA 类的主要属性:

  • components_:   方差最大的 n-components 个主成分
  • explained_variance_:  各个主成分的方差值
  • explained_variance_ratio_:  各个主成分的方差值占主成分方差和的比例

PCA 类的主要方法:

  • fit(X,y=None)  表示用数据 X 训练PCA模型
    fit() 是scikit-learn中的通用方法,实现训练、拟合的步骤。PCA是无监督学习,y=None。
  • fit_transform(X)  表示用数据 X 训练PCA模型,并返回降维后的数据
  • transform(X)  将数据 X 转换成降维后的数据,用训练好的 PCA模型对新的数据集进行降维。
  • inverse_transform()  将降维后的数据转换成原始数据

3.2 decomposition.PCA 使用例程

from sklearn.decomposition import PCA  # 导入 sklearn.decomposition.PCA 类
import numpy as np

X = np.array([[-1, -1], [-2, -1], [-3, -2], [1, 1], [2, 1], [3, 2]])
modelPCA = PCA(n_components=2)  # 建立模型,设定保留主成分数 K=2
modelPCA.fit(X)  # 用数据集 X 训练 模型 modelPCA
print(modelPCA.n_components_)  # 返回 PCA 模型保留的主成份个数
# 2
print(modelPCA.explained_variance_ratio_)  # 返回 PCA 模型各主成份占比
# [0.9924 0.0075]  # print 显示结果
print(modelPCA.singular_values_) # 返回 PCA 模型各主成份的奇异值
# [6.3006 0.5498]  # print 显示分类结果

X = np.array([[-1, -1], [-2, -1], [-3, -2], [1, 1], [2, 1], [3, 2]])
modelPCA2 = PCA(n_components=0.9) # 建立模型,设定主成份方差占比 0.9
# 用数据集 X 训练 模型 modelPCA2,并返回降维后的数据
Xtrans = modelPCA2.fit_transform(X)
print(modelPCA2.n_components_)  # 返回 PCA 模型保留的主成份个数
# 1
print(modelPCA2.explained_variance_ratio_)  # 返回 PCA 模型各主成份占比
# [0.9924]  # print 显示结果
print(modelPCA2.singular_values_)  # 返回 PCA 模型各主成份占比
# [6.3006]  # print 显示结果
print(Xtrans)  # 返回降维后的数据 Xtrans
# [[1.3834], [2.2219], [3.6053], [-1.3834], [-2.2219], [-3.6053]]

注意:建立模型时,PCA(n_components=2) 中的 n_components为正整数,表示设定保留的主成份维数为 2;PCA(n_components=0.9) 中的 n_components 为 (0,1] 的小数,表示并不直接设定保留的主成份维数,而是设定保留的主成份应满足其方差和占比 >0.9。

3.3 改进算法:增量主成分分析(decomposition.IncrementalPCA)

对于样本集巨大的问题,例如样本量大于 10万、特征变量大于100,PCA 算法耗费的内存很大,甚至无法处理。   
  class sklearn.decomposition.IncrementalPCA 类是增量主成分分析算法的具体实现,官网介绍详见:https://scikit-learn.org/stable/modules/generated/sklearn.decomposition.IncrementalPCA.html#sklearn.decomposit

class sklearn.decomposition.IncrementalPCA(n_components=None, *, whiten=False, copy=True, batch_size=None)

主要参数:
inverse_transform()  将降维后的数据转换成原始数据

IncrementalPCA 的使用例程如下:

# Demo of sklearn.decomposition.IncrementalPCA

from sklearn.datasets import load_digits
from sklearn.decomposition import IncrementalPCA, PCA
from scipy import sparse

X, _ = load_digits(return_X_y=True)
print(type(X))  # <class 'numpy.ndarray'>
print(X.shape)      # (1797, 64)

modelPCA = PCA(n_components=6)  # 建立模型,设定保留主成分数 K=6
modelPCA.fit(X)  # 用数据集 X 训练 模型 modelPCA
print(modelPCA.n_components_)  # 返回 PCA 模型保留的主成份个数
# 6
print(modelPCA.explained_variance_ratio_)  # 返回 PCA 模型各主成份占比
# [0.1489 0.1362 0.1179 0.0841 0.0578 0.0492]
print(sum(modelPCA.explained_variance_ratio_))  # 返回 PCA 模型各主成份占比
# 0.5941
print(modelPCA.singular_values_) # 返回 PCA 模型各主成份的奇异值
# [567.0066  542.2518 504.6306 426.1177 353.3350 325.8204]

# let the fit function itself divide the data into batches
Xsparse = sparse.csr_matrix(X)  # 压缩稀疏矩阵,并非 IPCA 的必要步骤
print(type(Xsparse))  # <class 'scipy.sparse.csr.csr_matrix'>
print(Xsparse.shape)  # (1797, 64)
modelIPCA = IncrementalPCA(n_components=6, batch_size=200)
modelIPCA.fit(Xsparse)  # 训练模型 modelIPCA
print(modelIPCA.n_components_)  # 返回 PCA 模型保留的主成份个数
# 6
print(modelIPCA.explained_variance_ratio_)  # 返回 PCA 模型各主成份占比
# [0.1486 0.1357 0.1176 0.0838 0.0571 0.0409]
print(sum(modelIPCA.explained_variance_ratio_))  # 返回 PCA 模型各主成份占比
# 0.5838
print(modelIPCA.singular_values_) # 返回 PCA 模型各主成份的奇异值
#[566.4544 541.334 504.0643 425.3197 351.1096 297.0412]

本例程调用了 SKlearn内置的数据集 .datasets.load_digits,并给出了 PCA 算法与 IPCA 算法的对比,两种算法的结果非常接近,说明 IPCA 的性能降低很小。

3.4 改进算法:核主成分分析(decomposition.KernelPCA)

对于线性不可分的数据集,使用非线性的核函数可以把样本空间映射到线性可分的高维空间,然后在这个高维空间进行主成分分析。

class sklearn.decomposition.KernelPCA 类是算法的具体实现,官网介绍详见:https://scikit-learn.org/stable/modules/generated/sklearn.decomposition.KernelPCA.html#sklearn.decomposition.KernelPCA

class sklearn.decomposition.KernelPCA(n_components=None, *, kernel='linear', gamma=None, degree=3, coef0=1, kernel_params=None, alpha=1.0, fit_inverse_transform=False, eigen_solver='auto', tol=0, max_iter=None, remove_zero_eig=False, random_state=None, copy_X=True, n_jobs=None)

KernelPCA 的使用例程如下:

# Demo of sklearn.decomposition.KernelPCA

from sklearn.datasets import load_iris
from sklearn.decomposition import KernelPCA, PCA
import matplotlib.pyplot as plt
import numpy as np

X, y = load_iris(return_X_y=True)
print(type(X))  # <class 'numpy.ndarray'>

modelPCA = PCA(n_components=2)  # 建立模型,设定保留主成分数 K=2
Xpca = modelPCA.fit_transform(X)  # 用数据集 X 训练 模型 modelKPCA

modelKpcaP = KernelPCA(n_components=2, kernel='poly') # 建立模型,核函数:多项式
XkpcaP = modelKpcaP.fit_transform(X)  # 用数据集 X 训练 模型 modelKPCA

modelKpcaR = KernelPCA(n_components=2, kernel='rbf') # 建立模型,核函数:径向基函数
XkpcaR = modelKpcaR.fit_transform(X)  # 用数据集 X 训练 模型 modelKPCA

modelKpcaS = KernelPCA(n_components=2, kernel='cosine') # 建立模型,核函数:余弦函数
XkpcaS = modelKpcaS.fit_transform(X)  # 用数据集 X 训练 模型 modelKPCA

fig = plt.figure(figsize=(8,6))
ax1 = fig.add_subplot(2,2,1)
ax2 = fig.add_subplot(2,2,2)
ax3 = fig.add_subplot(2,2,3)
ax4 = fig.add_subplot(2,2,4)
for label in np.unique(y):
    position = y == label
    ax1.scatter(Xpca[position, 0], Xpca[position, 1], label='target=%d' % label)
    ax1.set_title('PCA')
    ax2.scatter(XkpcaP[position, 0], XkpcaP[position, 1], label='target=%d' % label)
    ax2.set_title('kernel= Poly')
    ax3.scatter(XkpcaR[position, 0], XkpcaR[position, 1], label='target=%d' % label)
    ax3.set_title('kernel= Rbf')
    ax4.scatter(XkpcaS[position, 0], XkpcaS[position, 1], label='target=%d' % label)
    ax4.set_title('kernel= Cosine')
plt.suptitle("KernalPCA")
plt.show()

本例程调用了 SKlearn内置的数据集 .datasets.load_iris,并给出了 PCA 算法与 3种核函数的KernelPCA 算法的对比,结果如下图所示。不同算法的降维后映射到二维平面的结果有差异,进一步的讨论已经超出本文的内容。

Sklearn_07.png

版权说明:
本文内容及例程为作者原创,并非转载书籍或网络内容。
本文中案例问题来自:
1 SciKit-learn 官网:https://scikit-learn.org/stable/index.html

YouCans 原创作品
Copyright 2021 YouCans, XUPT
Crated:2021-05-10

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,772评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,458评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,610评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,640评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,657评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,590评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,962评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,631评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,870评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,611评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,704评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,386评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,969评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,944评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,179评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,742评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,440评论 2 342

推荐阅读更多精彩内容