热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

用PCA方法进行数据降维

在进行数据分析时,我们往往会遇到多维数据,多维数据在处理时由于维度较大计算起来非常麻烦,这时我们需要对数据进行降维。而在所有降维方法中&#

在进行数据分析时,我们往往会遇到多维数据,多维数据在处理时由于维度较大计算起来非常麻烦,这时我们需要对数据进行降维。而在所有降维方法中,PCA是我们最常用的方法之一,其在使用时可以消除指标间的相互影响,同时也不用考虑数据的分布,而且降维效果非常明显,所以PCA可以在绝大多数情况下使用。而本文就是用python来解释一下如何用PCA方法进行降维。

首先对PCA进行一下简介。PCA全称是principal components analysis,即主成分分析。假设对某一事物的研究设计p个指标,分别用X1、X2、......、Xp表示,这p个指标构成的p维随机向量为X=(X1, X2, ..., Xp)’,设X的均值为μ,协方差矩阵为Σ。对X进行线性变换,可以形成新的综合变量,用Y表示,也就是说新的变量可以由原来的变量线性表示,即满足图1中的关系。

图1. PCA原理

由于这个线性变换是任意的,所以可以得到不同的Y。为了取得理想的效果,我们希望Yi=(ui)’X的方差尽可能大且Yi之间相互独立。所以我们将线性变换约束在下面的条件之内:

(1)(ui)’(ui)=1 (i=1, 2, 3, ..., p)

(2)Yi与Yj相互无关(i不等于j,i, j=1, 2, 3, ..., p)

(3)Y1是X1、X2、...、Xp的一切满足条件(1)的线性组合中方差最大者,Y2是与Y1不相关的X1、X2、...、Xp所有线性组合中方差最大者,......,Yp是与Y1、Y2、...、Y(p-1)不相关的X1、X2、...、Xp的所有线性组合中方差最大者。

基于以上三条原则确定的综合变量Y1、Y2、...、Yp分别称为原始变量的第一、第二...第p个主成分。各综合变量在总方差中所占的比重依次递减。在实际运用中,我们往往选取方差最大的几个主成分,就达到了降维的目的。

下面就用python代码结合实际例子来说明一下PCA的具体用法。在这里我们要说明一下本次使用的数据集,该数据集是Iris Flower Dataset,即著名的鸢尾花数据集。该数据集只有5个维度(其中我们主要用到前4个维度),样本量也只有150个,整个数据集比较轻便,非常适合做数据展示。

首先导入需要的库。

import numpy as np 
import pandas as pd 
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.decomposition import PCA

接下来读取相关数据集,这个数据集位于seaborn库当中。前8行数据如图2所示。

data = sns.load_dataset('iris')
data.head(8)

图2. 数据集样例

然后对数据做一个简单的处理,看一下各个维度之间的相关关系。所得结果如图3和图4所示。

values = data.iloc[:, :4] #读取前4列数据
correlation = values.corr() #列与列之间的相关系数
fig, ax = plt.subplots(figsize=(12, 10))
sns.heatmap(correlation, annot=True, annot_kws={'size':16}, cmap='Reds', square=True, ax=ax) #热力图
sns.pairplot(data, hue='species') #散点关系图

图3. 各维度之间的相关系数热力图

图4. 各维度之间的散点关系图

从图中可以大致看出,sepal_length和petal_length与petal_width都有较强的相关性,而petal_length和petal_width的相关性最强,达到0.96。下面我们来用PCA具体来分析一下该数据集,首先先看看该数据在选取4个主成分下的情况,这时候其主成分的数量和原数据的维度数相等。其结果如图5所示。

pca = PCA(n_components=4) #选取4个主成分
pc = pca.fit_transform(values) #对原数据进行pca处理
print("explained variance ratio: %s" % pca.explained_variance_ratio_) #输出各个主成分所占的比例
plt.plot(range(1, 5), np.cumsum(pca.explained_variance_ratio_)) #绘制主成分累积比例图
plt.scatter(range(1,5),np.cumsum(pca.explained_variance_ratio_))
plt.xlim(0, 5)
plt.ylim(0.9, 1.02)
plt.xlabel("number of components")
plt.ylabel("cumulative explained variance");

图5. 各主成分累加结果

我们可以看到pca.explained_variance_ratio_的结果是[0.92461872 0.05306648 0.01710261 0.00521218],而图5中也显示前两个主成分之和就已经接近所有主成分的98%,所以在只考虑前两个主成分的情况下,我们就能够将数据的损失控制在很小的范围内。这里我们就只用前两个主成分来做分析。接下来我们就只用前两个主成分来分析原数据,将两个主成分的数据转换成dataframe格式,然后再加上一列原数据中species的数据,代码如下,结果如图6所示。

pca1 = PCA(n_components=2) #选取2个主成分
pc1 = pca1.fit_transform(values) 
pc1_df = pd.DataFrame(pc1, columns=['pc_1', 'pc_2'])
pc1_df['species'] = data['species'] #加上一列species
pc1_df.head(8)

图6. 只有两个主成分的数据样例

接下来我们来看一下这两个主成分的组成。

print(pca1.components_)

结果如下。

[[ 0.36138659 -0.08452251  0.85667061  0.3582892 ][ 0.65658877  0.73016143 -0.17337266 -0.07548102]]

用这个结果来验证一下前面的数据。按照图1中的原理来计算,pca1.components_第一行的数据和values第一行数据对应项相乘的和,应该等于pc1_dfpc_1列第一个数据-2.684126,即图6中第一行第一列数据。即有下列代码。

print(np.dot(pca1.components_[0], values.iloc[0]))

按照上式计算,结果是2.8182395066394683。很多人看到这里,认为是不是算错了,其实我们在计算方法上都没有错,只是在这里有一个隐含条件没有满足,就是sklearn在进行PCA计算时,数据要进行“中心化”,即每个数据减去这组数据的平均值,这样做主要是为了后续方便计算。所以我们要把上述代码改为下面这样。

print(np.dot(pca1.components_[0], values.iloc[0]-values.mean(axis=0)))

其得到的结果是-2.684125625969536,这就和前面的-2.684126对应起来了(这里排除小数点精度问题)。接下来就是用我们降维后的数据来作图。我们将原先的数据从4维降为2维,这正好方便绘制二维图,代码如下。结果如图7所示。

setosa = pc1_df[pc1_df['species']=='setosa'] #找出setosa对应的主成分数据
virginica = pc1_df[pc1_df['species']=='virginica']
versicolor = pc1_df[pc1_df['species']=='versicolor']
fig, ax = plt.subplots(figsize=(10, 8))
plt.scatter(setosa['pc_1'], setosa['pc_2'], alpha=0.7, color = 'red', label='Setosa') #绘制Setosa的散点图
plt.scatter(virginica['pc_1'], virginica['pc_2'], alpha=0.7, color = 'green', label='Virginica')
plt.scatter(versicolor['pc_1'], versicolor['pc_2'], alpha=0.7, color = 'blue',  label='Versicolor')
plt.legend(loc='best')
plt.xlabel('principal component 1')
plt.ylabel('principal component 2')

图7 . 降维后的散点图

主成分分析这种方法虽然简单易用,但其也有自身的缺点,比如对降维最终得到数目,不能很好地估计,同时PCA对于维度之间非线性的依赖关系不能得到很好的结果。此外本例中笔者没有对原数据进行标准化,因为标准化可能会损失一定信息,这个问题业界也争论了很长时间,到底是否对数据进行标准化需要根据实际情况来判断,因为本例中各维度之间的数据差异不大,所以笔者并未进行标准化。所以针对PCA的使用,大家还是要根据数据的要求来进行判断。

作者简介:Mort,数据分析爱好者,擅长数据可视化,比较关注机器学习领域,希望能和业内朋友多学习交流。

赞 赏 作 者

Python中文社区作为一个去中心化的全球技术社区,以成为全球20万Python中文开发者的精神部落为愿景,目前覆盖各大主流媒体和协作平台,与阿里、腾讯、百度、微软、亚马逊、开源中国、CSDN等业界知名公司和技术社区建立了广泛的联系,拥有来自十多个国家和地区数万名登记会员,会员来自以工信部、清华大学、北京大学、北京邮电大学、中国人民银行、中科院、中金、华为、BAT、谷歌、微软等为代表的政府机关、科研单位、金融机构以及海内外知名公司,全平台近20万开发者关注。

推荐阅读:

用 Python 进行系统聚类分析

用 Python 对数据进行相关性分析

如何在 matplotlib 中加注释和内嵌图

如何用一行代码让 gevent 爬虫提速 100%

▼点击成为社区会员   喜欢就点个在看吧


推荐阅读
  • 本文由编程笔记#小编为大家整理,主要介绍了logistic回归(线性和非线性)相关的知识,包括线性logistic回归的代码和数据集的分布情况。希望对你有一定的参考价值。 ... [详细]
  • 本文介绍了机器学习手册中关于日期和时区操作的重要性以及其在实际应用中的作用。文章以一个故事为背景,描述了学童们面对老先生的教导时的反应,以及上官如在这个过程中的表现。同时,文章也提到了顾慎为对上官如的恨意以及他们之间的矛盾源于早年的结局。最后,文章强调了日期和时区操作在机器学习中的重要性,并指出了其在实际应用中的作用和意义。 ... [详细]
  • 本文介绍了Python爬虫技术基础篇面向对象高级编程(中)中的多重继承概念。通过继承,子类可以扩展父类的功能。文章以动物类层次的设计为例,讨论了按照不同分类方式设计类层次的复杂性和多重继承的优势。最后给出了哺乳动物和鸟类的设计示例,以及能跑、能飞、宠物类和非宠物类的增加对类数量的影响。 ... [详细]
  • 微软头条实习生分享深度学习自学指南
    本文介绍了一位微软头条实习生自学深度学习的经验分享,包括学习资源推荐、重要基础知识的学习要点等。作者强调了学好Python和数学基础的重要性,并提供了一些建议。 ... [详细]
  • [译]技术公司十年经验的职场生涯回顾
    本文是一位在技术公司工作十年的职场人士对自己职业生涯的总结回顾。她的职业规划与众不同,令人深思又有趣。其中涉及到的内容有机器学习、创新创业以及引用了女性主义者在TED演讲中的部分讲义。文章表达了对职业生涯的愿望和希望,认为人类有能力不断改善自己。 ... [详细]
  • Oracle分析函数first_value()和last_value()的用法及原理
    本文介绍了Oracle分析函数first_value()和last_value()的用法和原理,以及在查询销售记录日期和部门中的应用。通过示例和解释,详细说明了first_value()和last_value()的功能和不同之处。同时,对于last_value()的结果出现不一样的情况进行了解释,并提供了理解last_value()默认统计范围的方法。该文对于使用Oracle分析函数的开发人员和数据库管理员具有参考价值。 ... [详细]
  • 本文介绍了RPC框架Thrift的安装环境变量配置与第一个实例,讲解了RPC的概念以及如何解决跨语言、c++客户端、web服务端、远程调用等需求。Thrift开发方便上手快,性能和稳定性也不错,适合初学者学习和使用。 ... [详细]
  • 拥抱Android Design Support Library新变化(导航视图、悬浮ActionBar)
    转载请注明明桑AndroidAndroid5.0Loollipop作为Android最重要的版本之一,为我们带来了全新的界面风格和设计语言。看起来很受欢迎࿰ ... [详细]
  • 不同优化算法的比较分析及实验验证
    本文介绍了神经网络优化中常用的优化方法,包括学习率调整和梯度估计修正,并通过实验验证了不同优化算法的效果。实验结果表明,Adam算法在综合考虑学习率调整和梯度估计修正方面表现较好。该研究对于优化神经网络的训练过程具有指导意义。 ... [详细]
  • 也就是|小窗_卷积的特征提取与参数计算
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了卷积的特征提取与参数计算相关的知识,希望对你有一定的参考价值。Dense和Conv2D根本区别在于,Den ... [详细]
  • Python瓦片图下载、合并、绘图、标记的代码示例
    本文提供了Python瓦片图下载、合并、绘图、标记的代码示例,包括下载代码、多线程下载、图像处理等功能。通过参考geoserver,使用PIL、cv2、numpy、gdal、osr等库实现了瓦片图的下载、合并、绘图和标记功能。代码示例详细介绍了各个功能的实现方法,供读者参考使用。 ... [详细]
  • 本文讨论了如何使用IF函数从基于有限输入列表的有限输出列表中获取输出,并提出了是否有更快/更有效的执行代码的方法。作者希望了解是否有办法缩短代码,并从自我开发的角度来看是否有更好的方法。提供的代码可以按原样工作,但作者想知道是否有更好的方法来执行这样的任务。 ... [详细]
  • 基于dlib的人脸68特征点提取(眨眼张嘴检测)python版本
    文章目录引言开发环境和库流程设计张嘴和闭眼的检测引言(1)利用Dlib官方训练好的模型“shape_predictor_68_face_landmarks.dat”进行68个点标定 ... [详细]
  • 本文介绍了在Python张量流中使用make_merged_spec()方法合并设备规格对象的方法和语法,以及参数和返回值的说明,并提供了一个示例代码。 ... [详细]
  • 十大经典排序算法动图演示+Python实现
    本文介绍了十大经典排序算法的原理、演示和Python实现。排序算法分为内部排序和外部排序,常见的内部排序算法有插入排序、希尔排序、选择排序、冒泡排序、归并排序、快速排序、堆排序、基数排序等。文章还解释了时间复杂度和稳定性的概念,并提供了相关的名词解释。 ... [详细]
author-avatar
Mickey-洁de妈咪_212
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有