三种方法实现PCA算法(Python)
主成分分析,即Principal Component Analysis(PCA),是多元统计中的重要内容,也广泛应用于机器学习和其它领域。它的主要作用是对高维数据进行降维。PCA把原先的n个特征用数目更少的k个特征取代,新特征是旧特征的线性组合,这些线性组合最大化样本方差,尽量使新的k个特征互不相关。关于PCA的更多介绍,请参考:https://en.wikipedia.org/wiki/Principal_component_analysis.
PCA的主要算法如下:
- 组织数据形式,以便于模型使用;
- 计算样本每个特征的平均值;
- 每个样本数据减去该特征的平均值(归一化处理);
- 求协方差矩阵;
- 找到协方差矩阵的特征值和特征向量;
- 对特征值和特征向量重新排列(特征值从大到小排列);
- 对特征值求取累计贡献率;
- 对累计贡献率按照某个特定比例选取特征向量集的子集合;
- 对原始数据(第三步后)进行转换。
其中协方差矩阵的分解可以通过按对称矩阵的特征向量来,也可以通过分解矩阵的SVD来实现,而在Scikit-learn中,也是采用SVD来实现PCA算法的。关于SVD的介绍及其原理,可以参考:矩阵的奇异值分解(SVD)(理论)。
本文将用三种方法来实现PCA算法,一种是原始算法,即上面所描述的算法过程,具体的计算方法和过程,可以参考:A tutorial on Principal Components Analysis, Lindsay I Smith. 一种是带SVD的原始算法,在Python的Numpy模块中已经实现了SVD算法,并且将特征值从大从小排列,省去了对特征值和特征向量重新排列这一步。最后一种方法是用Python的Scikit-learn模块实现的PCA类直接进行计算,来验证前面两种方法的正确性。
用以上三种方法来实现PCA的完整的Python如下:
import numpy as np
from sklearn.decomposition import PCA
import sys
#returns choosing how many main factors
def index_lst(lst, component=0, rate=0):
#component: numbers of main factors
#rate: rate of sum(main factors)/sum(all factors)
#rate range suggest: (0.8,1)
#if you choose rate parameter, return index = 0 or less than len(lst)
if component and rate:
print('Component and rate must choose only one!')
sys.exit(0)
if not component and not rate:
print('Invalid parameter for numbers of components!')
sys.exit(0)
elif component:
print('Choosing by component, components are %s......'%component)
return component
else:
print('Choosing by rate, rate is %s ......'%rate)
for i in range(1, len(lst)):
if sum(lst[:i])/sum(lst) >= rate:
return i
return 0 def main():
# test data
mat = [[-1,-1,0,2,1],[2,0,0,-1,-1],[2,0,1,1,0]] # simple transform of test data
Mat = np.array(mat, dtype='float64')
print('Before PCA transforMation, data is:\n', Mat)
print('\nMethod 1: PCA by original algorithm:')
p,n = np.shape(Mat) # shape of Mat
t = np.mean(Mat, 0) # mean of each column # substract the mean of each column
for i in range(p):
for j in range(n):
Mat[i,j] = float(Mat[i,j]-t[j]) # covariance Matrix
cov_Mat = np.dot(Mat.T, Mat)/(p-1) # PCA by original algorithm
# eigvalues and eigenvectors of covariance Matrix with eigvalues descending
U,V = np.linalg.eigh(cov_Mat)
# Rearrange the eigenvectors and eigenvalues
U = U[::-1]
for i in range(n):
V[i,:] = V[i,:][::-1]
# choose eigenvalue by component or rate, not both of them euqal to 0
Index = index_lst(U, component=2) # choose how many main factors
if Index:
v = V[:,:Index] # subset of Unitary matrix
else: # improper rate choice may return Index=0
print('Invalid rate choice.\nPlease adjust the rate.')
print('Rate distribute follows:')
print([sum(U[:i])/sum(U) for i in range(1, len(U)+1)])
sys.exit(0)
# data transformation
T1 = np.dot(Mat, v)
# print the transformed data
print('We choose %d main factors.'%Index)
print('After PCA transformation, data becomes:\n',T1) # PCA by original algorithm using SVD
print('\nMethod 2: PCA by original algorithm using SVD:')
# u: Unitary matrix, eigenvectors in columns
# d: list of the singular values, sorted in descending order
u,d,v = np.linalg.svd(cov_Mat)
Index = index_lst(d, rate=0.95) # choose how many main factors
T2 = np.dot(Mat, u[:,:Index]) # transformed data
print('We choose %d main factors.'%Index)
print('After PCA transformation, data becomes:\n',T2) # PCA by Scikit-learn
pca = PCA(n_components=2) # n_components can be integer or float in (0,1)
pca.fit(mat) # fit the model
print('\nMethod 3: PCA by Scikit-learn:')
print('After PCA transformation, data becomes:')
print(pca.fit_transform(mat)) # transformed data main()
运行以上代码,输出结果为:
这说明用以上三种方法来实现PCA都是可行的。这样我们就能理解PCA的具体实现过程啦~~有兴趣的读者可以用其它语言实现一下哈~~
参考文献:
- PCA 维基百科: https://en.wikipedia.org/wiki/Principal_component_analysis.
- 讲解详细又全面的PCA教程: A tutorial on Principal Components Analysis, Lindsay I Smith.
- 博客:矩阵的奇异值分解(SVD)(理论):http://www.cnblogs.com/jclian91/p/8022426.html.
- 博客:主成分分析PCA: https://www.cnblogs.com/zhangchaoyang/articles/2222048.html.
- Scikit-learn的PCA介绍:http://scikit-learn.org/stable/modules/generated/sklearn.decomposition.PCA.html.
三种方法实现PCA算法(Python)的更多相关文章
- Python使用三种方法实现PCA算法[转]
主成分分析(PCA) vs 多元判别式分析(MDA) PCA和MDA都是线性变换的方法,二者关系密切.在PCA中,我们寻找数据集中最大化方差的成分,在MDA中,我们对类间最大散布的方向更感兴趣. 一句 ...
- python字符串连接的三种方法及其效率、适用场景详解
python字符串连接的方法,一般有以下三种:方法1:直接通过加号(+)操作符连接website=& 39;python& 39;+& 39;tab& 39;+& ...
- python每次处理一个字符的三种方法
python每次处理一个字符的三种方法 a_string = "abccdea" print 'the first' for c in a_string: print ord(c) ...
- python更新数据库脚本三种方法
最近项目的两次版本迭代中,根据业务需求的变化,需要对数据库进行更新,两次分别使用了不同的方式进行更新. 第一种:使用python的MySQLdb模块利用原生的sql语句进行更新 import MySQ ...
- python下载文件的三种方法
Python开发中时长遇到要下载文件的情况,最常用的方法就是通过Http利用urllib或者urllib2模块. 当然你也可以利用ftplib从ftp站点下载文件.此外Python还提供了另外一种方法 ...
- 服务器文档下载zip格式 SQL Server SQL分页查询 C#过滤html标签 EF 延时加载与死锁 在JS方法中返回多个值的三种方法(转载) IEnumerable,ICollection,IList接口问题 不吹不擂,你想要的Python面试都在这里了【315+道题】 基于mvc三层架构和ajax技术实现最简单的文件上传 事件管理
服务器文档下载zip格式 刚好这次项目中遇到了这个东西,就来弄一下,挺简单的,但是前台调用的时候弄错了,浪费了大半天的时间,本人也是菜鸟一枚.开始吧.(MVC的) @using Rattan.Co ...
- python网络编程调用recv函数完整接收数据的三种方法
最近在使用python进行网络编程开发一个通用的tcpclient测试小工具.在使用socket进行网络编程中,如何判定对端发送一条报文是否接收完成,是进行socket网络开发必须要考虑的一个问题.这 ...
- python 多线程编程之threading模块(Thread类)创建线程的三种方法
摘录 python核心编程 上节介绍的thread模块,是不支持守护线程的.当主线程退出的时候,所有的子线程都将终止,不管他们是否仍在工作. 本节开始,我们开始介绍python的另外多线程模块thre ...
- python—字符串拼接三种方法
python—字符串拼接三种方法 1.使用加号(+)号进行拼接 字符串拼接直接进行相加就可以,比较容易理解,但是一定要记得,变量直接相加,不是变量就要用引号引起来,不然会出错,另外数字是要转换为字 ...
随机推荐
- swift之函数式编程(五)
文章内容来源于<Functional Programing in Swift>,详情请看原著 The Value of Immutability swift 对于控制值改变有一些机制.在这 ...
- Bluetooth A2DP --Audio payload type
数据结构: 字段解释: payload type: 0x60(96), dynamic type type 定义: https://www.iana.org/assignments/rtp-param ...
- [板子]Floyd&Dijkstra
谨以此笔记记录jjw高三党四个月学习NOI的历程..如转载请标记出处 Floyd算法: 默认是业界最短路最简单的写法,并且只有五行.时间复杂度为O(N3),空间复杂度为O(N2). ;k<=n; ...
- hdu 3001 Travelling(状态压缩 三进制)
Travelling Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- shell编程下 特殊变量、test / [ ]判断、循环、脚本排错
第1章 shell中的特殊变量 1.1 $# $# 表示参数的个数 1.1.1 [示例]脚本内容 [root@znix ~]# cat /server/scripts/show2.sh #!/bin/ ...
- linq 在查询表达式中处理 null 值
此示例显示如何在源集合中处理可能的 null 值. IEnumerable<T> 等对象集合可包含值为 null 的元素. 如果源集合为 null 或包含值为 null 的元素,并且查询不 ...
- shell命令输入输出重定向
Linux命令的执行过程 首先是输入:stdin输入可以从键盘,也可以从文件得到 命令执行完成:把成功结果输出到屏幕,stout默认是屏幕 命令执行有错误:把错误也输出到屏幕上面,stderr默认也是 ...
- Python爬虫入门:Urllib库的基本使用
1.分分钟扒一个网页下来 怎样扒网页呢?其实就是根据URL来获取它的网页信息,虽然我们在浏览器中看到的是一幅幅优美的画面,但是其实是由浏览器解释才呈现出来的,实质它 是一段HTML代码,加 JS.CS ...
- 代码重构:用工厂+策略模式优化冗余的if else代码块
最近在工作中优化了一段冗余的if else代码块,感觉对设计模式的理解和运用很有帮助,所以分享出来.鉴于原代码会涉及到公司的隐私,因此就不贴出来了.下面以更加通俗易懂的案例来解析. 假如写一个针对员工 ...
- 15.javaweb XML详解教程
一.XML语言简介 1, 作用:用于描述和保存现实中具有某种关系的数据,还可以作为软件配置文件,和描述程序模块之间的关系 2, 语法: 首先 先看一个XML文件的组成部分 关于文档声明 Versi ...