本文是对PCA和SVD学习的整理笔记,为了避免很多重复内容的工作,我会在介绍概念的时候引用其他童鞋的工作和内容,具体来源我会标记在参考资料中。

一.PCA (Principle component analysis)

PCA(主成分分析)通过线性变换将原始数据变换为一组各维度线性无关的表示,可用于提取数据的主要特征分量,常用于高维数据的降维。

为什么需要降维?以下图为例,图c中的点x y 呈现明显线性相关,假如以数据其实以数据点分布的方向的直线上的投影(一维)已经能够很好的描述这组数据特点了 。明显的,将数据维度降低:1能够降低数据计算量  2压缩数据重构  3.部分情况下甚至能够改善数据特征。

  那么如何在降维时尽量保留源数据的特征,PCA就是一种。关于如何理解,PCA,通常可以用两种方式进行理解:一是让降维后的数据分布尽量分散能够保留信息(方差尽量大) 二是降维导致的信息损失尽量小。关于第一种理解方式,大家可以参考这里,细致而清晰。第二种方法通常需要简单的公式推导,利用拉格朗日乘子将带约束的优化转化为无约束优化后求导,有兴趣的童鞋可以参考这里.

上面两篇文章关于两个不同方向解释PCA,那么这里就直接写出PCA的降维方法,假设原数据为X:

    设有m条n个特征的数据。

    1)将原始数据按列组成n行m列矩阵X,即每一列代表一组数据

    2)将X的每一行(代表一个属性字段)进行零均值化,即减去这一行的均值

    3)求出协方差矩阵\[C=\frac{1}{m}XX^{T}\]

    4)求出协方差矩阵的特征值及对应的特征向量(对\[XX^{T}\]进行特征分解)

    5)将特征向量按对应特征值大小从上到下按行排列成矩阵,取前k行组成矩阵P

    6)Y=PX即为降维到k维后的数据

好了,PCA的流程中似乎和奇异值似乎没有什么关系。但是,首先\[XX^{T}\]计算过程中如果有较小的值很容易造成精度损失,其次特征分解只能处理方针,有没有更方便的方式获得降维矩阵P,这就要用到SVD了。

二 SVD(Singular value decomposition)

首先,关于特征分解和奇异值分解的物理意义理解,我推荐看这里

总结一下,特征值分解和奇异值分解都是给一个矩阵(线性变换)找一组特殊的基,特征值分解找到了特征向量这组基,在这组基下该线性变换只有缩放效果。而奇异值分解则是找到另一组基,这组基下线性变换的旋转、缩放、投影三种功能独立地展示出来了, 简而言之:

1.特征值分解其实是对旋转缩放两种效应的归并

2.奇异值分解其实是岁旋转缩放和投影效应的归并

 也就是说,奇异值分解可以说是包含了特征分解!来看Wikipedia的解释:

在矩阵M的奇异值分解中

  • V的列(columns)组成一套对正交"输入"或"分析"的基向量。这些向量是特征向量
  • U的列(columns)组成一套对正交"输出"的基向量。这些向量是特征向量
  • Σ对角线上的元素是奇异值,可视为是在输入与输出间进行的标量的"膨胀控制"。这些是特征值的非负平方根,并与UV的行向量相对应。

这里的*标识转置T。看到其中U就是MM*的特征向量了,那么也就是说利用奇异值分解也可以做PCA了,而且还不用求\[XX^{T}\]!

不仅如此,单独观看奇异值分解的式子,我们也可以利用主成分的思想,利用奇异值分解的公式对高维数据进行压缩,具体看下面的代码。

from PIL import Image
import numpy as np
import matplotlib.pyplot as plt def decide_k(s, ratio):
sum_tmp = 0
sum_s = np.sum(s)
k = 0
for i in s:
k += 1
sum_tmp += i
if (sum_tmp / sum_s) >= ratio:
print("reduce dims is:", k)
return k if k >= s.shape:
raise ValueError('input dim could not less than compress dims') def svd_refactor(x, ratio=0.90): # compress to a k dims data before = x.shape[0] * x.shape[1]
print("before compress:", before) # after svd, save cu cv and cs ,then we could use them to refactor picture
mean_ = np.mean(x, axis=1, keepdims=True)
x = x - mean_
u, s, v = np.linalg.svd(x)
k = decide_k(s, ratio)
c_u = u[:, :k]
c_v = v[:k, :]
c_s = s[0:k] after = c_u.shape[0] * c_u.shape[1] + c_v.shape[0] * c_v.shape[1] + c_s.shape[0]
print("after compress:", after)
print("ratio", after / before) # refactor
s_s = np.diag(c_s)
return np.dot(c_u, np.dot(s_s, c_v)) def pca_refactor(x, ratio=0.90): # compress to a k dims data before = x.shape[0] * x.shape[1]
print("before pca:", before) # after svd, save cu cv and cs ,then we could use them to refactor picture
mean_ = np.mean(x, axis=1, keepdims=True)
x = x - mean_
u, s, v = np.linalg.svd(x)
k = decide_k(s, ratio)
c_u = u[:, :k] eig_vec = c_u.transpose()
pca_result = np.dot(eig_vec, x) after = c_u.shape[0] * c_u.shape[1] + pca_result.shape[0] * pca_result.shape[1]
print("after pca:", after)
print("ratio", after / before) # since U*U=I
return np.dot(c_u, pca_result) if __name__ == '__main__':
img_file = Image.open('test.jpg').convert('L') # convert picture to gray
img_array = np.array(img_file)
print(img_array.shape) img_array = pca_refactor(img_array) plt.figure("beauty")
plt.imshow(img_array, cmap=plt.cm.gray)
plt.axis('off')
plt.show()

其中 关于如何选择降低维度到多少维的decide_k函数,采用了贡献率。就是指当剩余特征值和的比例小于一定百分比(0.05)的时候舍弃他们。

Reference:

李航《统计学习方法》

Relationship between SVD and PCA. How to use SVD to perform PCA?

PCA的数学原理

机器学习中的数学(5)-强大的矩阵奇异值分解(SVD)及其应用

机器学习中的SVD和PCA.知乎

奇异值的物理意义是什么?

矩阵的奇异值与特征值有什么相似之处与区别之处

从PCA和SVD的关系拾遗

PCA, SVD以及代码示例的更多相关文章

  1. 高级渲染技巧和代码示例 GPU Pro 7

    下载代码示例 移动设备正呈现着像素越来越高,屏幕尺寸越来越小的发展趋势. 由于像素着色的能耗非常大,因此 DPI 的增加以及移动设备固有的功耗受限环境为降低像素着色成本带来了巨大的压力. MSAA 有 ...

  2. Java8-Function使用及Groovy闭包的代码示例

    导航 定位 概述 代码示例 Java-Function Groovy闭包 定位 本文适用于想要了解Java8 Function接口编程及闭包表达式的筒鞋. 概述 在实际开发中,常常遇到使用模板模式的场 ...

  3. [IOS 开发] 懒加载 (延迟加载) 的基本方式,好处,代码示例

    懒加载的好处: 1> 不必将创建对象的代码全部写在viewDidLoad方法中,代码的可读性更强 2> 每个属性的getter方法中分别负责各自的实例化处理,代码彼此之间的独立性强,松耦合 ...

  4. SELECT控件操作的JS代码示例

    SELECT控件操作的JS代码示例 1 检测是否有选中 if(objSelect.selectedIndex > -1) { //说明选中 } else { //说明没有选中 } 2.动态创建s ...

  5. 转:HIBERNATE一些_方法_@注解_代码示例---写的非常好

    HIBERNATE一些_方法_@注解_代码示例操作数据库7步骤 : 1 创建一个SessionFactory对象 2 创建Session对象 3 开启事务Transaction : hibernate ...

  6. Python实现各种排序算法的代码示例总结

    Python实现各种排序算法的代码示例总结 作者:Donald Knuth 字体:[增加 减小] 类型:转载 时间:2015-12-11我要评论 这篇文章主要介绍了Python实现各种排序算法的代码示 ...

  7. C#与数据库访问技术总结(十五)之 DataAdapter对象代码示例

    DataAdapter对象代码示例 下面的代码将说明如何利用DataAdapter对象填充DataSet对象. private static string strConnect=" data ...

  8. C#与数据库访问技术总结(六)之Command对象创建SQl语句代码示例

    Command对象创建SQl语句代码示例 说明:前面介绍了 Command 对象的方法和一些属性,回顾一下 Command对象主要用来执行SQL语句.利用Command对象,可以查询数据和修改数据. ...

  9. 领域驱动开发推荐代码示例 — Microsoft NLayerApp

    简介: Microsoft NLayerApp是由微软西班牙团队出品的基于.NET 4.0的“面向领域N层分布式架构”代码示例,在codeplex上的地址是:http://microsoftnlaye ...

随机推荐

  1. JavaScript+HTML5 实现打地鼠小游戏

    一.游戏简介 打地鼠这个游戏相信大家都不陌生,也是童年时候一款经典的游戏.本次游戏的编写是以html文件形式完成的,并且使用HBulider软件进行编写,使用谷歌浏览器展示效果,游戏将会采用JavaS ...

  2. Leetcode题解(十五)

    42.Trapping Rain Water 题目 这道题目参考http://www.cnblogs.com/felixfang/p/3713197.html 观察下就可以发现被水填满后的形状是先升后 ...

  3. 2015ACM/ICPC亚洲区沈阳站 B-Bazinga

    Bazinga Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Sub ...

  4. SQL——按照季度,固定时间段,分组统计数据

    最近在工作中接到了一个需求,要求统计当月以10天为一个周期,每个周期的数据汇总信息.假设有一张表如下: 表table_test中 ID           AMOUNT         CREATE_ ...

  5. C++中模板template <typename T>

    最近在看C++的源码,遇到了不少问题,一点一点进行补充. 首先就是遇到template <typename Dtype>. 网上解释的非常多,觉得比较啰嗦,其实就是一个类型模板. 比如我们 ...

  6. Windows下caffe的配置和调用caffe库(一)

    一.Windows下caffe的配置: 1. 下载caffe官网提供的开发包,https://github.com/microsoft/caffe 2. 将caffe-master目录下的Window ...

  7. 蓝桥杯-算法训练--ALGO-8 操作格子

    问题描述 有n个格子,从左到右放成一排,编号为1-n. 共有m次操作,有3种操作类型: 1.修改一个格子的权值, 2.求连续一段格子权值和, 3.求连续一段格子的最大值. 对于每个2.3操作输出你所求 ...

  8. Flex布局语法

    flexbox 弹性盒布局和布局原理 新版的flexbox规范分两部分:一部分是container,一部分是 items. flexbox是一整套布局规范,包含了多个css属性,所以学习起来比`flo ...

  9. 实现一个websocket服务器-理论篇

    本文是Writing WebSocket servers的中文文档,翻译自MDNWriting WebSocket servers.篇幅略长,个人能力有限难免有所错误,抛砖引玉共同进步. websoc ...

  10. 在ASP.NET开发中一些单词的标准缩写

    有些词可能共用一些缩写.带星号的缩写或词来源于PeopleSoft标准. The following standard word abbreviations should be used in nam ...