技术背景

PCA主成分分析在数据处理和降维中经常被使用到,是一个非常经典的降维算法,本文提供一个PCA降维的流程分解,和对应的Python代码实现。

二维数据生成

如果没有自己的测试数据,我们可以生成一些特殊的随机数据点。例如我们使用Numpy的均匀随机数生成一系列二维的数据点\(\mathbf{r}=\left(x,y\right)\),其中数据点分布在一个椭圆内:

\[x^2+4y^2\leq 1
\]

生成数据点的Python代码如下所示:

import numpy as np

def plot_points(data):
import matplotlib.pyplot as plt
plt.figure()
plt.xlim(-1, 1)
plt.ylim(-1, 1)
plt.plot(data[:, 0], data[:, 1], '.', color='blue')
plt.savefig("PCA.png") def data_generator(nodes, seed=0):
np.random.seed(seed)
data = 2 * np.random.random((nodes, 2)) - 1
mask_index = np.where(data[:,0]**2+4*data[:,1]**2<=1)[0]
masked_data = data[mask_index]
return masked_data if __name__ == "__main__":
masked_data = data_generator(1000)
plot_points(masked_data)

运行上述代码会在当前路径下生成一个PCA.png的图片,结果如下所示:

数据标准化

因为不同类型的数据有不同的范围和特征,可以做一个标准化方便后续处理,但标准化之后的数据,记得降维之后要进行还原:

\[\mathbf{x}'=\frac{x-\bar{x}}{\sqrt{\frac{\sum_i(x-\bar{x})^2}{n-1}}}
\]

这是\(x\)方向的标准化,\(y\)方向的标准化同理,最终可以得到\(\mathbf{Z}=\left(\mathbf{x}',\mathbf{y}'\right)\)。对应的Python函数实现为:

def normalization(data):
data_avg = np.average(data, axis=0)
data_shift = data - data_avg
output = np.zeros_like(data)
for i in range(data.shape[-1]):
output[:, i] = data_shift[:, i] / np.sqrt(np.sum(data_shift[:, i] ** 2)/(data.shape[0]-1))
return output

协方差矩阵

正常我们写样本协方差矩阵的形式是这样的:

\[C_{jk}=\frac{\sum_{i=1}^n(x_{ij}-\bar{x})(y_{ik}-\bar{y})}{n-1}
\]

但是因为前面已经分别得到了两个方向的标准化数据,所以我们直接用下面这个公式计算就可以了:

\[C=\frac{Z^TZ}{n-1}
\]

对应的Python实现为:

def cov_matrix(Z):
return (Z.T @ Z) / (Z.shape[0] - 1)

如果对标准化之后的数据计算一个协方差矩阵可以得到:

[[1.         0.04955086]
[0.04955086 1. ]]

特征值分解

关于特征值分解的内容,可以参考上一篇文章中的介绍。总体来说就是把一个矩阵分解为如下形式:

\[C=U\Sigma U^{-1}
\]

其中\(\Sigma\)是由本征值组成的对角矩阵,\(U\)是由本征列向量组成的本征矩阵。对应的Python代码实现为:

def eig_decomp(C):
vals, vecs = np.linalg.eig(C)
sort_idx = np.argsort(vals)
return np.diag(vals), vecs, sort_idx

如果对上面的协方差矩阵做一个特征值分解,可以得到输出的特征值为:

[[1.04955086 0.        ]
[0. 0.95044914]]

输出的特征列向量组成的矩阵\(U\)为:

[[ 0.70710678 -0.70710678]
[ 0.70710678 0.70710678]]

可以把这两个列向量画到数据点中:

PCA降维

根据上面生成的对角化矩阵,我们已经可以从中筛选一些比较大的值和对应的本征向量,作为数据点的“主要成分”。一般是在本征值之间的值差异较大的时候可以更好的降维,这里生成的数据其实两个本征值没有很好的降维效果,但是我们依然可以执行降维的操作。例如我们选取第一个本征向量\(\mathbf{v}\)作为投影空间,把所有的数据点都投影到这个向量上:

\[\mathbf{r}'=\bar{\mathbf{r}}+\frac{(\mathbf{r}-\bar{\mathbf{r}})\cdot\mathbf{v}}{|\mathbf{v}|^2}\mathbf{v}
\]

就可以完成对数据点的降维,效果如下所示:

所用到的完整Python代码示例如下:

PCA Python完整代码
import numpy as np

def plot_points(data):
import matplotlib.pyplot as plt
plt.figure()
plt.xlim(-1, 1)
plt.ylim(-1, 1)
plt.plot(data[:, 0], data[:, 1], '.', color='blue')
plt.savefig("PCA.png") def plot_vec(data, center, vecs):
import matplotlib.pyplot as plt
plt.figure()
plt.xlim(-1, 1)
plt.ylim(-1, 1)
plt.plot(data[:, 0], data[:, 1], '.', color='blue')
for i in range(vecs.shape[-1]):
plt.arrow(center[0], center[1], vecs[:,i][0], vecs[:,i][1], width=0.02, alpha=0.8)
plt.savefig("PCA.png") def plot_reduced(data, center, vec_proj, vecs):
import matplotlib.pyplot as plt
plt.figure(figsize=(5,5))
plt.xlim(-1, 1)
plt.ylim(-1, 1)
plt.plot(data[:, 0], data[:, 1], '.', color='blue')
vec_proj += center
plt.plot(vec_proj[:, 0], vec_proj[:, 1], '.', color='red')
for i in range(vecs.shape[-1]):
plt.arrow(center[0], center[1], vecs[:,i][0], vecs[:,i][1], width=0.02, alpha=0.8)
plt.savefig("PCA.png") def data_generator(nodes, seed=0):
np.random.seed(seed)
data = 2 * np.random.random((nodes, 2)) - 1
mask_index = np.where(data[:,0]**2+4*data[:,1]**2<=1)[0]
masked_data = data[mask_index]
return masked_data def normalization(data):
data_avg = np.average(data, axis=0)
data_shift = data - data_avg
output = np.zeros_like(data)
sigmai = np.zeros(data.shape[-1])
for i in range(data.shape[-1]):
sigmai[i] = np.sqrt(np.sum(data_shift[:, i] ** 2)/(data.shape[0]-1))
output[:, i] = data_shift[:, i] / sigmai[i]
return output, data_avg, sigmai def cov_matrix(Z):
return (Z.T @ Z) / (Z.shape[0] - 1) def eig_decomp(C):
vals, vecs = np.linalg.eig(C)
sort_idx = np.argsort(vals)
return np.diag(vals), vecs, sort_idx def dimension_reduction(data, center, v):
return np.einsum('ij,j->i', data-center, v/np.linalg.norm(v))[:,None] * v[None]/np.linalg.norm(v) if __name__ == "__main__":
masked_data = data_generator(1000)
normalized_data, center, sigmai = normalization(masked_data)
C = cov_matrix(normalized_data)
Sigma, U, idx = eig_decomp(C)
reduced_data = dimension_reduction(masked_data, center, (U*sigmai[:,None])[:, 0])
plot_reduced(masked_data, center, reduced_data, U*sigmai[:,None])

总结概要

接上一篇文章介绍的矩阵特征分解,本文介绍了矩阵特征分解在主成分分析(PCA)算法中的应用。对于PCA算法,最直观的理解就是,在高维数据中找到一个低维的空间,使得所有的数据点投影到该低维空间之后尽可能的分离。

版权声明

本文首发链接为:https://www.cnblogs.com/dechinphy/p/pca.html

作者ID:DechinPhy

更多原著文章:https://www.cnblogs.com/dechinphy/

请博主喝咖啡:https://www.cnblogs.com/dechinphy/gallery/image/379634.html

PCA主成分分析的Python实现的更多相关文章

  1. PCA主成分分析Python实现

    作者:拾毅者 出处:http://blog.csdn.net/Dream_angel_Z/article/details/50760130 Github源代码:https://github.com/c ...

  2. 机器学习 - 算法 - PCA 主成分分析

    PCA 主成分分析 原理概述 用途 - 降维中最常用的手段 目标 - 提取最有价值的信息( 基于方差 ) 问题 - 降维后的数据的意义 ? 所需数学基础概念 向量的表示 基变换 协方差矩阵 协方差 优 ...

  3. 用PCA(主成分分析法)进行信号滤波

    用PCA(主成分分析法)进行信号滤波 此文章从我之前的C博客上导入,代码什么的可以参考matlab官方帮助文档 现在网上大多是通过PCA对数据进行降维,其实PCA还有一个用处就是可以进行信号滤波.网上 ...

  4. PCA历程详细python代码(原创)

    #PCA主成分分析,原文为文末的链接,代码为自己亲自手码 def cov_out1(dx,dy): #第一步:求解x,y各自的均值 mean_x=0 mean_y=0 for i in range(l ...

  5. 机器学习之PCA主成分分析

    前言            以下内容是个人学习之后的感悟,转载请注明出处~ 简介 在用统计分析方法研究多变量的课题时,变量个数太多就会增加课题的复杂性.人们自然希望变量个数较少而得到的 信息较多.在很 ...

  6. PCA(主成分分析)方法浅析

    PCA(主成分分析)方法浅析 降维.数据压缩 找到数据中最重要的方向:方差最大的方向,也就是样本间差距最显著的方向 在与第一个正交的超平面上找最合适的第二个方向 PCA算法流程 上图第一步描述不正确, ...

  7. PCA主成分分析(上)

    PCA主成分分析 PCA目的 最大可分性(最大投影方差) 投影 优化目标 关键点 推导 为什么要找最大特征值对应的特征向量呢? 之前看3DMM的论文的看到其用了PCA的方法,一开始以为自己对于PCA已 ...

  8. [机器学习] PCA主成分分析原理分析和Matlab实现方法

    转载于http://blog.csdn.net/guyuealian/article/details/68487833 网上关于PCA(主成分分析)原理和分析的博客很多,本博客并不打算长篇大论推论PC ...

  9. [机器学习笔记]主成分分析PCA简介及其python实现

    主成分分析(principal component analysis)是一种常见的数据降维方法,其目的是在“信息”损失较小的前提下,将高维的数据转换到低维,从而减小计算量. PCA的本质就是找一些投影 ...

  10. 【机器学习算法-python实现】PCA 主成分分析、降维

    1.背景         PCA(Principal Component Analysis),PAC的作用主要是减少数据集的维度,然后挑选出基本的特征.         PCA的主要思想是移动坐标轴, ...

随机推荐

  1. dfs与贪心算法——洛谷5194

    问题描述: 有n个砝码,将砝码从大到小排列,从第三个砝码开始,所有砝码均大于其前两个砝码之和,问怎样的砝码组合才可以组合出不大于c的最大重量,输出该重量 输入: 第一行输入两个个整数N,c,代表有N个 ...

  2. ant-design-vue 登录表单校验

    最近刚刚上手了 Vue3 的 antdv ui框架,来做个简单的登录校验练练手 安装 antdv 依赖 npm install ant-design-vue --save 在 main.ts/js 中 ...

  3. SaaS架构:开放平台架构设计

    大家好,我是汤师爷~ 今天聊聊开放平台架构设计. 为什么需要搭建开放平台 增强产品能力 开放平台能够让三方开发者和合作伙伴开发新的应用或服务,增加原有SaaS产品能力.这样就可以满足更多用户需求,从而 ...

  4. kubernetes的Deployment

    Deployment 在我们发布容器中的服务时,总共有一下几种方式: 将旧的pod停掉,创建新的pod并发布 创建新的pod,然后将旧的pod停掉 滚动式升级.创建一个新的pod,删除一个旧的pod, ...

  5. kubernetes日志回滚测试

    kubernetes日志回滚测试 操作节点 podName 查询日志的命令 得到结果 初始pod ms-zipkin-deployment-5949c78884-4x5h7 kubectl logs ...

  6. KubeSphere 后端源码深度解析

    这篇文章我们将学习在 vscode 上的 ssh remote 插件基础上,尝试 debug 和学习 KubeSphere 后端模块架构. 前提 安装好 vscode 以及 ssh remote co ...

  7. 什么是前后端分离应用(Full-stack Separation),想当然就会理解错

    前后端分离应用指的是将应用的前端部分(用户界面与交互逻辑)和后端部分(业务逻辑.数据处理.服务器响应)拆分成独立的模块,各自通过 API 进行通信.这种架构设计的目的是提高开发效率.增强可扩展性和灵活 ...

  8. 连接ORACLE数据库,是否必须要安装oracle客户端

    公司升级Oracle版本(12g~19C),服务器端是DBA团队升级.客户端的升级工作由各个团队自己负责完成.突然想为什么Oracle提供的JDBC Driver需要客户端的软件.没有Oracle客户 ...

  9. 如何优雅地将AI人工智能在线客服嵌入企业网站

    随着人工智能(AI)技术的飞速发展,越来越多的企业意识到,将AI客服嵌入企业网站是提升客户体验.提高工作效率的重要手段.相比于传统的人工客服,AI客服可以24/7全天候服务,不仅能有效处理大部分用户问 ...

  10. pandas的一些基本操作

    Pandas 是一个开源的数据分析和操作库,它是 Python 编程语言的一个扩展.Pandas 提供了快速.灵活和表达能力强的数据结构,旨在使数据清洗和分析工作变得更加简单易行. 1.为什么要学习p ...