• 聊聊基于Alink库的主成分分析(PCA)


    概述

    主成分分析(Principal Component Analysis,PCA)是一种常用的数据降维和特征提取技术,用于将高维数据转换为低维的特征空间。其目标是通过线性变换将原始特征转化为一组新的互相无关的变量,这些新变量称为主成分,它们按照方差递减的顺序排列,以保留尽可能多的原始数据信息。
    主成分分析的基本思想可以总结如下:

    1. 寻找新的特征空间:PCA通过线性变换,寻找一组新的特征空间,使得新的特征具有以下性质:
      • 主成分具有最大的方差,尽可能保留原始数据的信息。
      • 不同主成分之间彼此无关,即它们是正交的(互相垂直)。
    2. 降低数据维度:保留方差较大的主成分,舍弃方差较小的主成分,从而实现数据降维。

    主成分分析的步骤如下:

    • 中心化数据:将原始数据进行中心化,使得数据的均值为零。
    • 计算协方差矩阵:计算特征之间的协方差矩阵,描述了特征之间的线性关系。
    • 计算特征值和特征向量:对协方差矩阵进行特征值分解,得到特征值和对应的特征向量。
    • 选择主成分:按照特征值的大小选择保留的主成分数量,通常选择方差较大的前几个主成分。
    • 得到新的特征空间:将原始特征投影到选定的主成分上,得到新的特征空间。

    主成分分析的应用包括降维、去除数据噪声、数据可视化、特征选择等。通过保留最重要的特征,可以在减少数据维度的同时保持对数据的关键信息进行捕获。
    在实际使用中,有时会将各个变量进行标准化,此时的协方差矩阵就相当于原始数据的相关系数矩阵。所以Alink的主成分分析组件提供了两种计算选择,参数CalculationType可以设置为相关系数矩阵(CORR)或者协方差矩阵(COV),默认为相关系数矩阵,即对标准化后的数据计算其主成分。

    Alink库中的实现与应用

    示例

    以美国50个州的7种犯罪率为例,做主成分分析。这7种犯罪分别是:"murder", "rape", "robbery", "assault", "burglary", "larceny", "auto"。从这7个变量出发来评价各州的治安和犯罪情况是很难的,而使用主成分分析可以把这些变量概括为2-3个综合变量(即主成分),便于更简便的分析这些数据。

    /**
     * 主成分分析
     * 1.基于默认的计算方式(CORR),计算主成分
     * 2.设置K为4,将原先的7个维度降低到4个维度
     * 3.输出向量列,使用VectorToColumnsBatchOp组组件将向量列转为4个数据列,名称分别为"prin1, prin2, prin3, prin4"
     * */
    static void c_1() throws Exception {
    
        MemSourceBatchOp source = new MemSourceBatchOp(CRIME_ROWS_DATA, CRIME_COL_NAMES);
    
        source.lazyPrint(10, "Origin data");
    
        BatchOperator  pca_result = new PCA()
            .setK(4)
            .setSelectedCols("murder", "rape", "robbery", "assault", "burglary", "larceny", "auto")
            .setPredictionCol(VECTOR_COL_NAME)
            .enableLazyPrintModelInfo()
            .fit(source)
            .transform(source)
            .link(
                new VectorToColumnsBatchOp()
                    .setVectorCol(VECTOR_COL_NAME)
                    .setSchemaStr("prin1 double, prin2 double, prin3 double, prin4 double")
                    .setReservedCols("state")
            )
            .lazyPrint(10, "state with principle components");
    
        pca_result
            .select("state, prin1")
            .orderBy("prin1", 100, false)
            .lazyPrint(-1, "Order by prin1");
    
        pca_result
            .select("state, prin2")
            .orderBy("prin2", 100, false)
            .lazyPrint(-1, "Order by prin2");
    
        BatchOperator.execute();
    
    }
    

    当然还可以先将数据标准化后再做主成分分析。如下

    /**
     * 主成分分析
     * 1. 先将数据标准化
     * 2. 设置计算方式为协方差计算,设置K为4,将原先的7个维度降低到4个维度
     * 3.输出向量列,使用VectorToColumnsBatchOp组组件将向量列转为4个数据列,名称分别为"prin1, prin2, prin3, prin4"
     * */
    static void c_2() throws Exception {
    
        MemSourceBatchOp source = new MemSourceBatchOp(CRIME_ROWS_DATA, CRIME_COL_NAMES);
    
        Pipeline std_pca = new Pipeline()
            .add(
                new StandardScaler()
                    .setSelectedCols("murder", "rape", "robbery", "assault", "burglary", "larceny", "auto")
            )
            .add(
                new PCA()
                    .setCalculationType(CalculationType.COV)
                    .setK(4)
                    .setSelectedCols("murder", "rape", "robbery", "assault", "burglary", "larceny", "auto")
                    .setPredictionCol(VECTOR_COL_NAME)
                    .enableLazyPrintModelInfo()
            );
    
        std_pca
            .fit(source)
            .transform(source)
            .link(
                new VectorToColumnsBatchOp()
                    .setVectorCol(VECTOR_COL_NAME)
                    .setSchemaStr("prin1 double, prin2 double, prin3 double, prin4 double")
                    .setReservedCols("state")
            )
            .lazyPrint(10, "state with principle components");
        BatchOperator.execute();
    
    }
    

    应用

    在聚类方面的应用

    主要通过降维来减少特征的维度,从而在聚类过程中降低数据的复杂度和计算成本,同时提高聚类的效果。主要实现过程如下:

    1. 使用 PCA 对数据进行降维,得到新的特征空间。设置降维后的维度,通常选择较小的维度以减少特征数。
    2. 在降维后的特征空间上应用聚类算法,比如 K-means、DBSCAN 等。
    3. 使用适当的聚类评估指标,如轮廓系数等,来评估聚类的效果。

    示例代码如下:

    /**
     * 聚类+主成分分析
     * 1. 将数据降维,只使用5%的维度数据
     * 2. K-Means聚类:分别将原始数据与主成分分析后的数据做聚类操作
     * */
    static void c_3() throws Exception {
    
        AkSourceBatchOp source = new AkSourceBatchOp().setFilePath(DATA_DIR + SPARSE_TRAIN_FILE);
    
        source
            .link(
                new PcaTrainBatchOp()
                    .setK(39)
                    .setCalculationType(CalculationType.COV)
                    .setVectorCol(VECTOR_COL_NAME)
                    .lazyPrintModelInfo()
            )
            .link(
                new AkSinkBatchOp()
                    .setFilePath(DATA_DIR + PCA_MODEL_FILE)
                    .setOverwriteSink(true)
            );
        BatchOperator.execute();
    
        BatchOperator  pca_result = new PcaPredictBatchOp()
            .setVectorCol(VECTOR_COL_NAME)
            .setPredictionCol(VECTOR_COL_NAME)
            .linkFrom(
                new AkSourceBatchOp().setFilePath(DATA_DIR + PCA_MODEL_FILE),
                source
            );
    
        Stopwatch sw = new Stopwatch();
    
        KMeans kmeans = new KMeans()
            .setK(10)
            .setVectorCol(VECTOR_COL_NAME)
            .setPredictionCol(PREDICTION_COL_NAME);
    
        sw.reset();
        sw.start();
        kmeans
            .fit(source)
            .transform(source)
            .link(
                new EvalClusterBatchOp()
                    .setVectorCol(VECTOR_COL_NAME)
                    .setPredictionCol(PREDICTION_COL_NAME)
                    .setLabelCol(LABEL_COL_NAME)
                    .lazyPrintMetrics("KMeans")
            );
        BatchOperator.execute();
        sw.stop();
        System.out.println(sw.getElapsedTimeSpan());
    
        sw.reset();
        sw.start();
        kmeans
            .fit(pca_result)
            .transform(pca_result)
            .link(
                new EvalClusterBatchOp()
                    .setVectorCol(VECTOR_COL_NAME)
                    .setPredictionCol(PREDICTION_COL_NAME)
                    .setLabelCol(LABEL_COL_NAME)
                    .lazyPrintMetrics("KMeans + PCA")
            );
        BatchOperator.execute();
        sw.stop();
        System.out.println(sw.getElapsedTimeSpan());
    
    }
    
  • 相关阅读:
    DayDayUp:计算机技术与软件专业技术资格证书之《系统集成项目管理工程师》课程讲解之十大知识领域之4核心—项目范围管理
    java处理异常这一篇就够了
    react经验14:动态修改第三方组件的样式
    gRPC 四模式之 服务器端流RPC模式
    SpringMVC详解
    LVS+Keepalived群集实验
    注册【小程序】和注册页面
    SpringIoc容器之Aware
    博途1200PLC编码器速度信号采集和滤波处理
    VisionPro学习笔记(3)——BeadInspectTool
  • 原文地址:https://www.cnblogs.com/zhiyong-ITNote/p/17740962.html