Python使用三种方法实现PCA算法


Posted in Python onDecember 12, 2017

主成分分析,即Principal Component Analysis(PCA),是多元统计中的重要内容,也广泛应用于机器学习和其它领域。它的主要作用是对高维数据进行降维。PCA把原先的n个特征用数目更少的k个特征取代,新特征是旧特征的线性组合,这些线性组合最大化样本方差,尽量使新的k个特征互不相关。关于PCA的更多介绍,请参考:https://en.wikipedia.org/wiki/Principal_component_analysis.

主成分分析(PCA) vs 多元判别式分析(MDA)

PCA和MDA都是线性变换的方法,二者关系密切。在PCA中,我们寻找数据集中最大化方差的成分,在MDA中,我们对类间最大散布的方向更感兴趣。

一句话,通过PCA,我们将整个数据集(不带类别标签)映射到一个子空间中,在MDA中,我们致力于找到一个能够最好区分各类的最佳子集。粗略来讲,PCA是通过寻找方差最大的轴(在一类中,因为PCA把整个数据集当做一类),在MDA中,我们还需要最大化类间散布。

在通常的模式识别问题中,MDA往往在PCA后面。

PCA的主要算法如下:

  1. 组织数据形式,以便于模型使用;
  2. 计算样本每个特征的平均值;
  3. 每个样本数据减去该特征的平均值(归一化处理);
  4. 求协方差矩阵;
  5. 找到协方差矩阵的特征值和特征向量;
  6. 对特征值和特征向量重新排列(特征值从大到小排列);
  7. 对特征值求取累计贡献率;
  8. 对累计贡献率按照某个特定比例,选取特征向量集的字迹合;
  9. 对原始数据(第三步后)。

其中协方差矩阵的分解可以通过按对称矩阵的特征向量来,也可以通过分解矩阵的SVD来实现,而在Scikit-learn中,也是采用SVD来实现PCA算法的。

本文将用三种方法来实现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()

运行以上代码,输出结果为:

Python使用三种方法实现PCA算法

这说明用以上三种方法来实现PCA都是可行的。这样我们就能理解PCA的具体实现过程啦~~有兴趣的读者可以用其它语言实现一下哈

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python图像处理之镜像实现方法
May 30 Python
wxPython中listbox用法实例详解
Jun 01 Python
Python实现删除当前目录下除当前脚本以外的文件和文件夹实例
Jul 27 Python
Python设置默认编码为utf8的方法
Jul 01 Python
Python实现爬取百度贴吧帖子所有楼层图片的爬虫示例
Apr 26 Python
Python3使用Matplotlib 绘制精美的数学函数图形
Apr 11 Python
python自动化测试之如何解析excel文件
Jun 27 Python
python mqtt 客户端的实现代码实例
Sep 25 Python
使用python快速在局域网内搭建http传输文件服务的方法
Nov 14 Python
Python包资源下载路径报404解决方案
Nov 05 Python
Python3.8.2安装包及安装教程图文详解(附安装包)
Nov 28 Python
Python使用pyecharts控件绘制图表
Jun 05 Python
Java分治归并排序算法实例详解
Dec 12 #Python
Python数据结构与算法之二叉树结构定义与遍历方法详解
Dec 12 #Python
Python数据结构与算法之图的基本实现及迭代器实例详解
Dec 12 #Python
Python数据结构与算法之图的最短路径(Dijkstra算法)完整实例
Dec 12 #Python
你真的了解Python的random模块吗?
Dec 12 #Python
Python判断两个对象相等的原理
Dec 12 #Python
浅谈Django REST Framework限速
Dec 12 #Python
You might like
PHP脚本的10个技巧(7)
2006/10/09 PHP
libmysql.dll与php.ini是否真的要拷贝到c:\windows目录下呢
2010/03/15 PHP
php中关于长度计算容易混淆的问题分析
2016/05/27 PHP
PHP延迟静态绑定的深入讲解
2018/04/02 PHP
PHP底层运行机制与工作原理详解
2020/07/31 PHP
JavaScript 小型打飞机游戏实现原理说明
2010/10/28 Javascript
JS简单的轮播的图片滚动实例
2013/06/17 Javascript
js中的getAttribute方法使用示例
2014/08/01 Javascript
JS交换变量的方法
2015/01/21 Javascript
详解JavaScript中this关键字的用法
2016/05/26 Javascript
JS for循环中i++ 和 ++i的区别介绍
2016/07/20 Javascript
JQuery遍历元素的后代和同胞实现方法
2016/09/18 Javascript
jQuery利用sort对DOM元素进行排序操作
2016/11/07 Javascript
Node.js中如何合并两个复杂对象详解
2016/12/31 Javascript
Vue2.x中的父组件传递数据至子组件的方法
2017/05/01 Javascript
js实现简单数字变动效果
2017/11/06 Javascript
关于react中组件通信的几种方式详解
2017/12/10 Javascript
VeeValidate在vue项目里表单校验应用案例
2018/05/09 Javascript
Makefile/cmake/node-gyp中区分判断不同平台的方法
2018/12/18 Javascript
JS实现数组深拷贝的方法分析
2019/03/06 Javascript
javascript面向对象创建对象的方式小结
2019/07/29 Javascript
vue+eslint+vscode配置教程
2019/08/09 Javascript
VUE 直接通过JS 修改html对象的值导致没有更新到数据中解决方法分析
2019/12/02 Javascript
对vuex中store和$store的区别说明
2020/07/24 Javascript
JavaScript读取本地文件常用方法流程解析
2020/10/12 Javascript
[49:17]DOTA2-DPC中国联赛 正赛 Phoenix vs Dynasty BO3 第三场 1月26日
2021/03/11 DOTA
django 发送手机验证码的示例代码
2018/04/25 Python
Python K最近邻从原理到实现的方法
2019/08/15 Python
使用python去除图片白色像素的实例
2019/12/12 Python
英国领先的汽车轮胎和快速健康中心:Kwik Fit
2017/10/29 全球购物
AJAX检测用户名是否存在的方法
2021/03/24 Javascript
活动总结新闻稿
2014/08/30 职场文书
党员批评与自我批评思想汇报
2014/10/08 职场文书
安全隐患整改报告
2014/11/06 职场文书
小班上学期幼儿评语
2014/12/30 职场文书
mysql 获取相邻数据项
2022/05/11 MySQL