主成份分析(PCA)详解

主成分分析法(Principal Component Analysis)大多在数据维度比较高的时候,用来减少数据维度,因而加快模型训练速度。另外也有些用途,比如图片压缩(主要是用SVD,也可以用PCA来做)、因子分析等。具体怎么用,看个人需求如何,这篇文章主要解释一下PCA的原理。当然应用起来也非常简单,现在常用的语言,Python、R、matlab都有直接求解PCA或者SVD的包了。

这篇文章主要想讲讲PCA的思想,当然有很多看官并不在乎这个算法的思想是什么,而仅仅急切地想要实现它,在文章最后,我们给出了R语言的实现方法,想看实现方法的可以直接跳到文章最后。 
下面我们看看PCA具体做了些什么。

我们有一组数据X,维度是m x n,表示有 n个样本,每个样本有m个特征,即: 

X=x1,1x2,1xm,1x1,2x2,2xm,2x1,nx2,nxm,n

现在我们想知道这个数据具体包含了哪些信息,这里可能需要引入一个大家都很熟悉的概念,方差。让我们先看其中某一维的数据,例如: x1=[x1,1,x1,2,,x1,n] 。如果说 x1 其中每一项都相等,也就是每一项都等于一个常数,那么我们认为 x1 并没有包含什么信息,因为它 就是一个已知的常数。所以,我们想要某一维的数据越多样性越好,这样它可以包含更多的信息,我们可以据此做出更多的推断。笼统来说,我们可以用方差来表示数据的多样性。

PCA对数据的分布其实是有一个假设的,即每一个维度上的数据都服从Gaussian分布。假设x1平均值是x1¯¯¯¯、方差是σ21,令x1=[x1,1x1¯¯¯σ1,,x1,nx1¯¯¯σ1],这样x1就服从均值为0,方差为1的高斯分布。后面我们默认X的每一个维度都服从均值为0,方差为1 的高斯分布,即每一个维度上的数据方差都为1。这样处理过后,似乎每一个维度上的数据都包含等量的信息。

然而真实情况好像并不是这样,我们会发现有些特征能给我们带来更大的帮助,往往某一个或者两个特征能对模型产生重要的影响,而继续增加更多特征,也只会使模型在小幅度内提升。这说明有些特征能够给我们带来更多的信息,这是怎么回事呢?下面,我们来看另一个定义,协方差。

协方差是来反映数据间的相关性。有两组数据,他们的关系如下图: 
 
如果如图(a),则说明两组数据相关性低(或者说low redundancy);如果如图(c),则说明两组数据的相关性高,也就是high redundancy,因为我们基本上可以认为r2=kr1,也就是r2其实是多余的。

x1=[x1,1,x1,2,,x1,n]x2=[x2,1,x2,2,,x2,n]是服从均值为0,方差为1 的高斯分布的两组数据。我们知道方差的定义:

σ21=1n1i=1n(x1,ix1¯¯¯¯)2,σ22=1n1i=1n(x2,ix2¯¯¯¯)2

我们现在定义数据 x1 x2 的协方差: 
σ21,2=1n1i=1n(x1,ix1¯¯¯¯)(x2,ix2¯¯¯¯)

协方差有两个性质: 1)当且仅当 x1 x2 完全不相关时, σ21,2=0 ;2)如果 x1=x2 ,那么 σ21,2=σ21 。 
现在,让我们看一个矩阵 XXT ,实际上它是一个表示各维度之间方差的对称方阵, σ21,2=σ22,1 ,也可以叫做协方差矩阵。 X 的维度是 m×n XT 的维度是 n×m ,那么 XXT 的维度则是 m×m ,即: 
XXT=σ21,1σ22,1σ2m,1σ21,2σ22,2σ2m,2σ21,nσ22,nσ2m,n

假设我们有一个矩阵 3×4 的矩阵 A : 
A=0.3600.600.210.2100.200.720.860.800.140.290.000.65

我们可以得到矩阵 AAT : 
AAT=1.000.950.230.951.000.0940.230.0941.00

可以看到 AAT 是一个对称的矩阵,且每一个维度与自己的方差为1,而与其它维度的协方差则各不相同。也就是说每一个维度不仅表达了自身,这个维度所带有的信息,还表达了与其它维度的部分信息。这也就能解释,虽然每个维度的方差都为1,但是它们所包含的真实信息量是不同的。 
然而,假如我们得到一个 AAT 的矩阵: 
AAT=0.590000.290000.12

也就是说,各个维度是完全独立的,维度与维度之间的相关性为0。这样每个维度就只包含了自己的信息,我们现在就可以说第一个维度包含了矩阵 A  59%(0.59/(0.59 + 0.29 + 0.12))的信息,第二个维度包含了29%的信息,第三个维度包含了12%的信息。

这是不是给了你一个启发,要是我能有一个数据(矩阵),它的每一个维度都是完全独立的,那么我计算出每个维度的方差,取方差最大的几个,这样我就可以用很少的几个维度,包含整个数据大部分的信息。比如上面那个例子,我用前面两个维度,就可以包含所有数据88%的信息。

这就是PCA的基本思想。然而现实中,并不是遇到的每个数据集合,它各个维度之间的方差均为0。实际上,基本上不可能存在这样的数据集合。我们收集到的数据之间或多或少都会存在关联。例如我们要预测一个人是否会发生购买行为,我们会看他浏览了了多少商品,收藏了多少商品,然而浏览与收藏之间肯定是有联系的。那么如何实现PCA呢。

矩阵当中有一个非常著名的理论,一个n×n的对称矩阵A可以表示为:A=VDVT。其中,V是一个正交矩阵,D是一个对角矩阵,除了对角线上的值可能不为0以外,其它的值均为0。

根据上面理论,对于任意一个m×n的矩阵AAAT是一个m×m的对称矩阵,因而AAT可以表示为:AAT=VDVT,即VTA(VTA)T=D。也就是对于任意一个m×n的矩阵A,我们可以找到一个m×m的矩阵V,使得矩阵VTA的方差矩阵VTA(VTA)T,只有对角线上的值不为0,即矩阵各个维度之间相互独立。 

D=σ1000σ2000¨

以上,PCA的思想就介绍完了。但是 VTA 具体是做了什么事情呢?它对矩阵 A 又有什么影响?让我们来看一下 V 是一个什么样子的矩阵。

根据这个定理AAT=VDVT,实际上V是矩阵A中所有的特征向量构成的一个矩阵,不过这里我们并不考虑V是如何求来的,如何求得,不过是线性代数里面的一些知识。这里我们关心的是,V是一个m×m的矩阵,所以VTA是一个m×n的矩阵。如果我们在的VTA左边乘上(VT)1,矩阵又会变回A,也就是(VT)1VTA=A。所以,实际上用V的转置乘上A,只是对A做了一些行列上的变换,并没有减少任何信息,如果我们想要,我们还可以把A变回来。这样,我们完全可以由变换后的矩阵VTA,来表示原来的数据A,且不会有任何信息损失。而且,转换后的矩阵有一个非常好的性质,就是各个维度之间相互独立,所以我们可以得到它的方差矩阵VTA(VTA)T=D,是一个只有对角线上元素不为0的对角矩阵。

这样,我们就可以知道每一个维度分别包含了多少信息。假如数据的维度m,是一个非常大的值,例如10,0000,如果我们发现仅仅使用前10个维度,就能包含95%以上的信息,那么我们将很高兴用这10个维度,而舍弃掉剩下的其它维度,这相当于将数据压缩了10000倍,而并没有损失多少信息。当然这只是我们的臆想,实际情况不一定有这么好。

R实现:

#从R内置数据集iris中取前10行
> A <- as.matrix(iris[1:10,-5])
> ASepal.Length Sepal.Width Petal.Length Petal.Width
1           5.1         3.5          1.4         0.2
2           4.9         3.0          1.4         0.2
3           4.7         3.2          1.3         0.2
4           4.6         3.1          1.5         0.2
5           5.0         3.6          1.4         0.2
6           5.4         3.9          1.7         0.4
7           4.6         3.4          1.4         0.3
8           5.0         3.4          1.5         0.2
9           4.4         2.9          1.4         0.2
10          4.9         3.1          1.5         0.1#可以看到A是一个10x4的矩阵,下面我们对A进行标准化
> A <- scale(A)
> ASepal.Length Sepal.Width Petal.Length Petal.Width
1     0.8237318   0.6186158     -0.46291  -0.2535463
2     0.1372886  -1.0093205     -0.46291  -0.2535463
3    -0.5491545  -0.3581460     -1.38873  -0.2535463
4    -0.8923761  -0.6837333      0.46291  -0.2535463
5     0.4805102   0.9442031     -0.46291  -0.2535463
6     1.8533965   1.9209649      2.31455   2.2819165
7    -0.8923761   0.2930285     -0.46291   1.0141851
8     0.4805102   0.2930285      0.46291  -0.2535463
9    -1.5788192  -1.3349078     -0.46291  -0.2535463
10    0.1372886  -0.6837333      0.46291  -1.5212777#未对其进行转化前A的协方差矩阵如下,对角线上的值均为1,而协方差各异,
#因而不好估量每个维度所包含的信息
> var(A)Sepal.Length Sepal.Width Petal.Length Petal.Width
Sepal.Length    1.0000000   0.7872066    0.6002160   0.3770977
Sepal.Width     0.7872066   1.0000000    0.5191385   0.6787563
Petal.Length    0.6002160   0.5191385    1.0000000   0.5216405
Petal.Width     0.3770977   0.6787563    0.5216405   1.0000000#利用内置svd函数队矩阵t(A)进行分解,t(A)即A的转置,转置后变成4x10的矩阵,
#与文中一致。其中,得到的矩阵s$u即为文中的矩阵V 
> s <- svd(t(A))
> s$u[,1]        [,2]        [,3]       [,4]
[1,] -0.5088012  0.60992283 -0.19490104 -0.5754381
[2,] -0.5486817  0.02313419 -0.49127967  0.6760603
[3,] -0.4747485  0.08790411  0.84594304  0.2264225
[4,] -0.4633397 -0.78723048 -0.07098059 -0.4006822#利用t(V)%*%t(A)原矩阵进行转换,再看一下转换后矩阵的协方差矩阵,这里保留两位小数
> AA <- t(s$u) %*% t(A)
> round(var(t(AA)), 2)[,1] [,2] [,3] [,4]
[1,] 2.75 0.00 0.00  0.0
[2,] 0.00 0.63 0.00  0.0
[3,] 0.00 0.00 0.52  0.0
[4,] 0.00 0.00 0.00  0.1#可以看到,转换后矩阵各维度之间相互独立,并且可以知道每个矩阵包含了多少信息。
#假如我们取前三个纬度,则可以包含97.5%的信息,(2.75+0.63+0.53)/( 2.75+0.63+0.53+0.1)=0.975。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60

这里我们使用R中内置的函数SVD,来实现PCA的算法。实际情况中,我们常常可以看到SVD和批PCA在一起被提到,它们之间又有什么关系。感兴趣的话,可以看看我的下一篇blog:SVD与PCA详解。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/387831.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何安装pylab:python如何导入matplotlib模块

pylab是python下挺不错的一个画图模块&#xff0c;使用也非常简单&#xff0c;记得Mit的计算机科学及编程导论有节课也是用到了这个工具&#xff0c;但这个工具安装不象用起来那么方便&#xff0c;小编就图文全程直播下吧 工具/原料 python2.7.10win10 32位方法/步骤 1缺省状态…

BP神经网络python简单实现

BP神经网络的原理在网上有很详细的说明&#xff0c;这里就不打算细说&#xff0c;这篇文章主要简单的方式设计及实现BP神经网络&#xff0c;并简单测试下在恒等计算&#xff08;编码&#xff09;作测试。 BP神经网络模型图如下 BP神经网络基本思想 BP神经网络学习过程由信息的…

golang的reflection(转)(一)

2019独角兽企业重金招聘Python工程师标准>>> 反射reflection 可以大大提高程序的灵活性&#xff0c;使得interface{}有更大的发挥余地反射可以使用TypeOf和ValueOf函数从接口中获取目标对象信息反射会将匿名字段作为独立字段&#xff08;匿名字段的本质&#xff09;…

datatables.js 简单使用--多选框和服务器端分页

说明&#xff1a;datatables是一款jQuery表格插件。感觉EasyUI的datagrid更易用 内容&#xff1a;多选框和服务器端分页 缘由&#xff1a;写这篇博客的原因是datatables的文档写的不怎么样&#xff0c;找东西很麻烦 环境&#xff1a;asp.net mvc , vs2015sqlserver2012 显示效…

python异常(高级) Exception

异常(高级) Exception 异常回顾:     try-except 语句 捕获(接收)异常通知,把异常流程变为正常流程     try-finally 语句 执行必须要执行的语句.     raise 语句 发送异常通知,同时进入异常流程     assert 语句 发送AssertionError异常     with 语句 wi…

从BMW Vision iNEXT 看宝马如何进军自动驾驶

安全很重要&#xff0c;空间也要很大&#xff0c;砍掉大量物理按键&#xff0c;内饰材料要环保&#xff0c;还要提供自动和主动两套驾驶方案。这些描述仅是BMW Vision iNEXT&#xff08;下称Vision iNEXT&#xff09;概念车的设计之冰山一角。 一款概念车当然无法完全代表未来…

CSS浮动(二)---Float

重新认识float 2.1. 误解和“误用” 既然提到“误用”&#xff0c;各位看官就此想想&#xff0c;自己平日是怎么使用float的&#xff1f;另外&#xff0c;既然“误用”加了引号&#xff0c;就说明这样的使用并不是真正的误用&#xff0c;而是误打误撞使用之后&#xff0c;带…

云原生生态周报 Vol. 2

业界要闻 Kubernetes External Secrets 近日&#xff0c;世界上最大的域名托管公司 Godaddy公司&#xff0c;正式宣布并详细解读了其开源的K8s外部 Secrets 管理项目&#xff1a; Kubernetes External Secrets&#xff0c;简称KES。这个项目定义了ExternalSecrets API&#xff…

centos 7新机使用前操作

关闭防火墙 systemctl stop firewalld&#xff08;停服务&#xff09; systemctl status firewalld&#xff08;看状态&#xff09; systemctl disable firewalld.service &#xff08;永久关闭&#xff09; selinux getenforce&#xff08;查状态&#xff09; vi /etc/selinux…

软件架构演进

传统架构到分布式架构详解 软件架构演进软件架构的发展经历了从单体架构、垂直架构、SOA架构到微服务架构的过程&#xff0c;博客里写到了这四种架构的特点以及优缺点分析&#xff0c;个人学习之用&#xff0c;仅供参考&#xff01; 1.1.1 单体架构 特点&#xff1a;1、所有的…

hadoop0.20.0第一个例子

这是Hadoop学习全程记录第2篇&#xff0c;在这篇里我将介绍一下如何在Eclipse下写第一个MapReduce程序。 新说明一下我的开发环境&#xff1a; 操作系统&#xff1a;在windows下使用wubi安装了ubuntu 10.10 hadoop版本&#xff1a;hadoop-0.20.2.tar.gz Eclipse版本&…

IDEA 修改JavaWeb的访问路径

问题描述 对于我这个刚刚使用IDEA不久的新手来说&#xff0c;能够正常运行就不错了,不过到了后面&#xff0c;可能会觉得IDEA给你分配的默认访问路径很不顺手&#xff0c;比如访问的时候需要通过: http://localhost:8080/web_war_exploded/ 来访问&#xff0c;对于web_w…

做一个vue的todolist列表

<template><div id"app"><input type"text" v-model"todo" ref"ip"/><button click"add()">新增</button><br/><br/><hr/><ul><li v-for"(item,key) in li…

一种解决 MacBook 里的 App Store 无法登录的问题

刚刚买回来的 2018 款带有 touchbar 的 MacBook Pro 15 inc 在用 App Store 安装 app 时一直无法登录成功&#xff08;网络链接都是好的&#xff09;&#xff0c;导致软件都无法更新&#xff0c;折腾了挺一会的。 后来发现是要退出设置里的 iCloud 登录&#xff0c;然后重新登录…

第二次冲刺

1、今日各个成员的问题 组员问题张晋誌对mui的API看得不是很懂&#xff0c;无法顺利的使用袁庆杰基础不牢,编写困难周建峰eclipse没法创建web项目&#xff0c;按照网上的方法&#xff0c;check for updates 和 install new software 之后也没用许家烨给单一功能知道如何实现但项…

单纯形法

单纯形法 如果目标函数中所有系数都非正&#xff0c;那么显然这些变量直接取0是最优的&#xff0c;所以此时答案为即为常数项。 我们要做的就是通过转化把目标函数的系数全部搞成非负。 思路就是用非基变量替换基变量。 先找到一个目标函数中系数为正的变量&#xff0c;在所有限…

分布式数据库数据一致性的原理、与技术实现方案

http://youzhixueyuan.com/the-principle-and-technology-realization-of-distributed-data-consistency.html 背景 可用性&#xff08;Availability&#xff09;和一致性&#xff08;Consistency&#xff09;是分布式系统的基本问题&#xff0c;先有著名的CAP理论定义过分布式…

模块之re模块 —— 正则

#‘match’只匹配从左向右第一个值是否在中括号的范围内&#xff0c;如果没有就返回None 如果有就直接打印一个对象&#xff0c;加上.group()就可以返回你要找的区间里面的值&#xff0c;如果没有找到对应的值&#xff0c;加上‘.group()’会报错 #‘search’ 默认是从整个st…

centos7 docker

Docker 是一个开源工具&#xff0c;它可以让创建和管理 Linux 容器变得简单。容器就像是轻量级的虚拟机&#xff0c;并且可以以毫秒级的速度来启动或停止。Docker 帮助系统管理员和程序员在容器中开发应用程序&#xff0c;并且可以扩展到成千上万的节点。 容器和 VM&#xff08…

Intellij Idea 2017创建web项目及tomcat部署实战

相关软件&#xff1a;Intellij Idea2017、jdk16、tomcat7 Intellij Idea直接安装&#xff08;可根据需要选择自己设置的安装目录&#xff09;&#xff0c;jdk使用1.6/1.7/1.8都可以&#xff0c;主要是配置好系统环境变量&#xff0c;tomcat7上tomcat的官网下载压缩包解压即可。…