机器学习算法PCA降维之c++实现(不调用外源库)

 目前玩机器学习的小伙伴,上来就是使用现有的sklearn机器学习包,写两行代码,调调参数就能跑起来,看似方便,实则有时不利于个人能力发展,要知道现在公司需要的算法工程师,不仅仅只是会调参(这种工作,入门几个月的人就可以干了),而是要深入底层,能优化代码,能自己搭。

本文章适合以下几类人:

1)初学者,了解机器学习的实现过程

2)想提升自己的代码能力

第一步:原理

什么是PCA?

PCA(Principal Component Analysis)是一种常用的数据降维算法,其主要思想是将高维数据映射到低维空间中,同时尽可能地保留原始数据的信息。PCA算法的具体实现步骤如下:

1. 对原始数据进行中心化处理,即将每个特征的均值都减去该特征的平均值,使得数据的均值为0。

2. 计算协方差矩阵,即将中心化后的数据进行矩阵乘法,得到一个n×n的协方差矩阵C。

3. 对协方差矩阵进行特征值分解,得到特征值和特征向量。

4. 将特征值按照从大到小的顺序排序,选择前k个特征值对应的特征向量作为新的基向量。

5. 将原始数据投影到新的基向量上,得到降维后的数据。

PCA算法的优点是可以减少数据的冗余信息,提高计算效率和降低存储空间。但是也存在一些缺点,例如对于非线性数据降维效果不佳等。

PCA的推导,百度一下很多,这里就做一下搬运工了,可参考:【机器学习】降维——PCA(非常详细) - 知乎

第二步:代码实现

#include <iostream>
#include <stdlib.h>
#include "matrix.h"
#include <map>

using namespace std;

/**
* @brief 求实对称矩阵的特征值及特征向量的雅克比法
* 利用雅格比(Jacobi)方法求实对称矩阵的全部特征值及特征向量
* @param pMatrix                长度为n*n的数组,存放实对称矩阵
* @param nDim                   矩阵的阶数
* @param pdblVects              长度为n*n的数组,返回特征向量(按列存储)
* @param dbEps                  精度要求
* @param nJt                    整型变量,控制最大迭代次数
* @param pdbEigenValues         特征值数组
* @return
*/
bool JacbiCor(double * pMatrix,int nDim, double *pdblVects, double *pdbEigenValues, double dbEps,int nJt)
{

}
//mean 均值 pdblVects特征向量 pdbEigenValues特征值 k为取前k个
void pca(Matrix mean,Matrix pdblVects, int k, vector<double>&meanVal)
{
    if (k > mean.row || k < 0)
    {
        cout<<"error"<<endl;
        exit(0);;
    }
    Matrix pcaVects;
    pcaVects.initMatrix(&pcaVects,mean.row,k);
    for (int i = 0; i < k; i++)
    {
         pcaVects = pcaVects.getOneRow(pdblVects,i);
    }
    pcaVects.print(pcaVects);

    Matrix lowData;
    //cout<<endl;
    lowData.initMatrix(&lowData,mean.col,pcaVects.row);
    //mean.print(mean);
    //cout<<endl;
    //转换成低维数据
    lowData.multsmatrix(&lowData,mean,pcaVects);
    lowData.print(lowData);
    //需要转换到相同的坐标里面
    Matrix reconMat;
    reconMat.initMatrix(&reconMat, mean.col,mean.row);
    Matrix pcaVectsT;
    pcaVectsT.initMatrix(&pcaVectsT,k,mean.row);
    pcaVectsT.transposematrix(pcaVects,&pcaVectsT);//转置
    reconMat.multsmatrix(&reconMat,lowData,pcaVectsT);
    //cout<<endl;
    //reconMat.print(reconMat);
    //加上平均值
    for (int i = 0; i < reconMat.col; i++)
    {
        for (int j = 0; j < reconMat.row; j++)
        {
            reconMat.mat[i][j] += meanVal[j];
        }
    }
    //cout<<endl;
    reconMat.print(reconMat);
}

int main()
{
    dataToMatrix dtm;
    char file[30]="G:/data/pca.txt";
    dtm.loadData(&dtm,file);
    Matrix x;
    x.loadMatrix(&x,dtm);

    Matrix result;
    vector<double>meanVal;//存放均值,在降维数据之后,映射到原坐标有用到
    result = result.covMatrix(x,meanVal);
//    cout<<endl;
//    result.print(result);
//    cout<<endl;
    double *pMatrix = new double[result.row * result.row];
    for (int i = 0; i < result.row; i++)
    {
        for (int j = 0; j < result.row; j++)
        {
            pMatrix[i * result.row + j] = result.mat[i][j];
        }
    }
    double *pdblVects = new double[result.row * result.row];
    double *pdbEigenValues = new double[result.row];
    bool a = JacbiCor(pMatrix,2, pdblVects, pdbEigenValues, 0.0001,10000);

    //将数组转换到矩阵里面
    Matrix vectsMatrix;
    vectsMatrix.initMatrix(&vectsMatrix,result.row,result.row);
    for (int i = 0; i < result.row; i++)
    {
        for (int j = 0; j < result.row; j++)
        {
            vectsMatrix.mat[i][j] = pdblVects[i * result.row + j];
        }
    }
    vectsMatrix.print(vectsMatrix);
    pca(x,vectsMatrix, 1, meanVal);
    return 0;
}

第三步:运行过程

运行结果

​用到的软件是vs2010以上的版本都可以,不用额外配置什么,没调包,会用这个软件进行c++开发,就会使用这个软件

此程序由于不调用任何外源库,所以读者可以看清楚每一个算法的原理,要想学好机器学习算法,必须打好基础,不要好高骛远,另外,程序都是有备注,应该很好理解的,实在不懂,可以来问店主

代码的下载路径(新窗口打开链接)机器学习算法PCA降维之c++实现(不调用外源库)

有问题可以私信或者留言,有问必答

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
PCA (Principal Component Analysis) 和 SVD (Singular Value Decomposition) 都是用于数据降维的重要数学工具,在机器学习和数据分析中广泛应用。它们都可以帮助我们在高维空间中找到关键特征,减少数据的复杂性和计算成本。 **PCA(主成分分析)**: 1. **基本原理**:PCA通过线性变换将原始数据投影到一组新的坐标轴上,新轴的方向对应数据方差最大的方向。通过保留主要的特征方向(即主成分),我们可以丢弃那些对数据解释度不大的维度。 2. **SVD的应用**:实际上,PCA可以通过SVD来实现,因为数据矩阵(中心化后)的SVD分解会产生正交的左奇异向量作为新坐标轴,而这些向量对应的奇异值代表了信息的重要性。 3. **降维步骤**:计算数据的协方差矩阵,然后做SVD分解得到UΣVT。前k个主成分对应矩阵U的前k列,降维后的数据就是这k列对应的原始数据乘积。 **SVD(奇异值分解)**: 1. **直接应用**:SVD本身就是将一个矩阵分解为三个部分:UΣV^T,其中U和V是对称正交矩阵,Σ是对角矩阵,包含的是数据的奇异值。奇异值反映了数据的“能量”或“影响力”。 2. **降维与重构**:SVD可用于降维,选择前k个最大的奇异值和对应的左/右奇异向量,仅使用这部分信息就可以重建近似的原始数据,从而达到降维效果。 3. **SVD与PCA的关系**:当处理标准化的数据时,SVD与PCA的结果相同。SVD提供了一种更通用的框架,但PCA在解释性上有优势,因为它构造的新坐标是根据数据的方差。 **相关问题--:** 1. PCA如何选择保留多少维度? 2. SVD降维在实际应用中的优势是什么? 3. 如何利用SVD进行数据的压缩存储?

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值