C/C++实现PCA降维以及故障监测

C/C++实现PCA降维以及故障监测@TOC欢迎使用Markdown编辑器你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章,了解一下Markdown的基本语法知识。新的改变我们对Markdown编辑器进行了一些功能拓展与语法支持,除了标准的Markdown编辑器功能,我们增加了如下几点新功能,帮助你用它写博客:全新的界面设计 ,将会带来全新的写作体验;在创作中心设置你喜爱的代码高亮样式,Markdown 将代码
摘要由CSDN通过智能技术生成

之前使用Matlab进行过关于PCA的研究,应用于故障诊断与监测中,为了方便以后与其他平台进行耦合,采用C/C++语言实现,参考了很多人编写的C/C++代码,也走过一些弯路,针对相关学习在此记录下来,有需要的朋友可以参考。

一些降维算法

Principal Component Analysis (PCA)
Linear Discriminant Analysis(LDA)
Locally linear embedding(LLE)
Laplacian Eigenmaps
PCA:PCA算法是一种线性投影技术,利用降维后使数据的方差最大原则保留尽可能多的信息;
KPCA:PCA仅考虑了数据的二阶统计信息,而没有利用高阶统计信息,忽略了数据的非线性相关性,而KPCA,通过非线性变换将数据映射到了高维,在高维空间中进行特征提取,获得了更好的特征提取性能;
PPCA:PCA没有将数据的概率分布考虑,PPCA对PCA做了概率上的解释,延伸了PCA算法。
总之:PPCA和KPCA都是针对PCA算法的缺陷,做出了不同方向上的改进。
数据降维参考

PCA

PCA(principal components analysis)即主成分分析技术,又称主分量分析。主成分分析也称主分量分析,旨在利用降维的思想,把多指标转化为少数几个综合指标。
在统计学中,主成分分析PCA是一种简化数据集的技术。它是一个线性变换。这个变换把数据变换到一个新的坐标系统中,使得任何数据投影的第一大方差在第一个坐标(称为第一主成分)上,第二大方差在第二个坐标(第二主成分)上,依次类推。主成分分析经常用于减少数据集的维数,同时保持数据集的对方差贡献最大的特征。这是通过保留低阶主成分,忽略高阶主成分做到的。这样低阶成分往往能够保留住数据的最重要方面。但是,这也不是一定的,要视具体应用而定。
PCA是模式识别中常见的特征降维的算法,其大体步骤可以分为以下几个部分:
(1)原始特征矩阵归一化处理
(2)求取归一化处理后特征矩阵的协方差矩阵
(3)计算协方差矩阵的特征值及其对应的特征向量
(4)按照特征值从大到小排列特征向量
(5)从大到小,挑选出前K个特征值对应的特征向量组成降维后的特征向量,即为所求。

工具

Boost库
Boost是为C++语言标准库提供扩展的一些C++程序库的总称。Boost库是一个可移植、提供源代码的C++库,作为标准库的后备,是C++标准化进程的开发引擎之一,是为C++语言标准库提供扩展的一些C++程序库的总称。
Boost库由C++标准委员会库工作组成员发起,其中有些内容有望成为下一代C++标准库内容。在C++社区中影响甚大,是不折不扣的“准”标准库。

Eigen库
Eigen是一个高层次的C ++库,有效支持线性代数,矩阵和矢量运算,数值分析及其相关的算法。Eigen是一个开源库,是一个基于C++模板的线性代数库.提供有关矩阵的的线性代数运算,解方程等功能。官方的文档在此,以SLAM十四讲代码阅读,快速入门。
Eigen库说明

VS2013
Visual Studio是目前最流行的Windows平台应用程序的集成开发环境。Microsoft Visual Studio(简称VS)是美国微软公司的开发工具包系列产品。VS是一个基本完整的开发工具集,它包括了整个软件生命周期中所需要的大部分工具,如UML工具、代码管控工具、集成开发环境(IDE)等等。
需要在项目属性中进行Boost和Eigen库的配置,可以参考下列文档。
Boost库配置
Eigen库配置

部分代码

由于涉及故障监测中的内容,需要计算两个统计量T^2和Q, 其中涉及F分布和正态分布的计算内容,在此不过多介绍。
统计量T^2:设X~Np(μ,∑),S~Wp(n,∑),且X与S相互独立,n≥p,则称统计量T2=nX’S-1X的分布为非中心Hotelling T2分布,记为T2~T2(p,n,μ)。当μ=0时,称T2服从(中心)Hotelling T2分布,记为T2(p,n),由于这一统计量的分布首先由Harold Hotelling提出来的,故称Hotelling T2分布

#include"pca.h"  
#include< iostream> 
#include< fstream> 
#include<Eigen/Dense>
#include<Eigen/Eigenvalues>
using namespace Eigen;
using namespace std;
//***********************************************************
#include<stdlib.h>
#include<stdio.h>
#include<math.h>
double FDist(double F, double m, double n);
double betainv(double p, double a, double b);
double betainc(double x, double a, double b);
double beta(double z, double w);
double gamma(double xx);
double beta_cf(double a, double b, double x);
//***************************************************************
#include <boost\math\distributions\normal.hpp>
#include <iostream>
#include <random>
#include <math.h>
//**********************************************************
double FDist(double F, double m, double n)
{
   
	double xx, p;

	if (m <= 0 || n <= 0) p = -1;
	else if (F>0)
	{
   
		xx = F / (F + n / m);
		p = betainc(xx, m / 2, n / 2);
	}
	return(1 - p);
}

double betainv(double p, double a, double b)
{
   

	int count_max_limit = 100;
	int count_max = 0;
	double x, xnew, y, h, pbeta, logkerna, logkernb;
	double crit = 1.818989403545857e-012; 
	//	float crit=6.4155306e-006;          

	if (p == 0) x = 0;
	if (p == 1) x = 1;

	x = a / (a + b);
	if (x<crit) x = crit;
	if (x>1 - crit) x = 1 - crit;
	h = 1;

	while ((h>(crit*fabs(x))) && (h>crit) && (count_max<count_max_limit))
	{
   
		count_max = count_max + 1;

		if (x>1) p = 1;
		pbeta = betainc(x, a, b);
		if (pbeta>1) pbeta = 1;

		logkerna = (a - 1)*log(x);
		if ((a == 1) && (x == 0)) logkerna = 0;
		logkernb = (b - 1)*log(1 - x);
		if ((b == 1) && (x == 1)) logkernb = 0;
		y = exp(logkerna + logkernb - log(beta(a, b)));

		h = (pbeta - p) / y;
		xnew = x - h;

		if (xnew <= 0) xnew = x / 10;
		if (xnew >= 1) xnew = 1 - (1 - x) / 10;

		x = xnew;
	}
	return x;
}

F分布参考
F分布C/C++代码
F分布是两个服从卡方分布的独立随机变量各除以其自由度后的比值的抽样分布,是一种非对称分布,且位置不可互换。F分布有着广泛的应用,如在方差分析、回归方程的显著性检验中都有着重要的地位。
正态分布使用Boost库即可,网络上也可以找到参考,不做介绍。

部分pca.h头文件

typedef struct sourcedata   
{
   
	int m;
	int n;
	double **data;
}SourceData;
class PCA
{
   
public:
	PCA(int m, int n);   
	SourceData getdata(const  char *file); 
	
  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
PCA(Principal Component Analysis)是一种常用的维算法,它通过线性变换将高维数据映射到低维空间中,且尽可能多地保留原始数据的信息。PCA的核心思想是将原始数据投影到新的坐标系上,新坐标系的选择是使得投影后数据方差最大的方向,也就是数据的主成分方向。以下是PCA维的步骤: 1. 数据预处理:对数据进行标准化处理,使得每个特征的均值为0,方差为1。 2. 计算协方差矩阵:协方差矩阵反映了特征之间的相关性,计算公式为:$\Sigma=\frac{1}{n-1}(X-\bar{X})^{T}(X-\bar{X})$,其中 $X$ 为 $n$ 行 $m$ 列的数据矩阵,$\bar{X}$ 为 $m$ 维向量,表示每一列的均值。 3. 计算特征值和特征向量:对协方差矩阵进行特征值分解,得到特征值和特征向量。 4. 选取主成分:将特征值按照从大到小的顺序排列,选择前 $k$ 个特征值对应的特征向量,组成新的 $k$ 维特征空间。 5. 投影到新的特征空间:将原始数据投影到新的 $k$ 维特征空间中,得到维后的数据。 下面是Python实现PCA维的代码: ```python import numpy as np class PCA: def __init__(self, n_components): self.n_components = n_components def fit_transform(self, X): # 数据预处理 X_std = (X - np.mean(X, axis=0)) / np.std(X, axis=0) # 计算协方差矩阵 cov_mat = np.cov(X_std.T) # 计算特征值和特征向量 eigenvals, eigenvecs = np.linalg.eig(cov_mat) # 选取前n个特征向量 idx = eigenvals.argsort()[::-1] eigenvecs = eigenvecs[:, idx][:, :self.n_components] # 投影到新的特征空间 X_new = np.dot(X_std, eigenvecs) return X_new ``` 使用示例: ```python import numpy as np from sklearn.datasets import load_iris # 加载数据 iris = load_iris() X = iris.data # PCApca = PCA(n_components=2) X_new = pca.fit_transform(X) # 可视化 import matplotlib.pyplot as plt plt.scatter(X_new[:,0], X_new[:,1], c=iris.target) plt.show() ``` 这里使用了鸢尾花数据集进行演示,将原始数据从4维到了2维,并将结果可视化出来。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值