文档章节

主成分分析(PCA) Java

Harry_sir
 Harry_sir
发布于 2017/08/28 16:25
字数 1160
阅读 52
收藏 0
点赞 0
评论 0

导入jar包:Jama-1.0.2.jar

//========计算类===========

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;

import Jama.Matrix;

/*
 * 算法步骤:
 * 1)将原始数据按列组成n行m列矩阵X
 * 2)特征中心化。即每一维的数据都减去该维的均值,使每一维的均值都为0
 * 3)求出协方差矩阵
 * 4)求出协方差矩阵的特征值及对应的特征向量
 * 5)将特征向量按对应的特征值大小从上往下按行排列成矩阵,取前k行组成矩阵p
 * 6)Y=PX 即为降维到k维后的数据
 */
public class PCA {

    private static final double threshold = 0.95;// 特征值阈值

    /**
     * 
     * 使每个样本的均值为0
     * 
     * @param primary
     *            原始二维数组矩阵
     * @return averageArray 中心化后的矩阵
     */
    public double[][] changeAverageToZero(double[][] primary) {
        int n = primary.length;
        int m = primary[0].length;
        double[] sum = new double[m];
        double[] average = new double[m];
        double[][] averageArray = new double[n][m];
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                sum[i] += primary[j][i];
            }
            average[i] = sum[i] / n;
        }
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                averageArray[j][i] = primary[j][i] - average[i];
            }
        }
        return averageArray;
    }

    /**
     * 
     * 计算协方差矩阵
     * 
     * @param matrix
     *            中心化后的矩阵
     * @return result 协方差矩阵
     */
    public double[][] getVarianceMatrix(double[][] matrix) {
        int n = matrix.length;// 行数
        int m = matrix[0].length;// 列数
        double[][] result = new double[m][m];// 协方差矩阵
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < m; j++) {
                double temp = 0;
                for (int k = 0; k < n; k++) {
                    temp += matrix[k][i] * matrix[k][j];
                }
                result[i][j] = temp / (n - 1);
            }
        }
        return result;
    }

    /**
     * 求特征值矩阵
     * 
     * @param matrix
     *            协方差矩阵
     * @return result 向量的特征值二维数组矩阵
     */
    public double[][] getEigenvalueMatrix(double[][] matrix) {
        Matrix A = new Matrix(matrix);
        // 由特征值组成的对角矩阵,eig()获取特征值
        A.eig().getD().print(10, 6);
        double[][] result = A.eig().getD().getArray();
        return result;
    }

    /**
     * 标准化矩阵(特征向量矩阵)
     * 
     * @param matrix
     *            特征值矩阵
     * @return result 标准化后的二维数组矩阵
     */
    public double[][] getEigenVectorMatrix(double[][] matrix) {
        Matrix A = new Matrix(matrix);
        A.eig().getV().print(6, 2);
        double[][] result = A.eig().getV().getArray();
        return result;
    }

    /**
     * 寻找主成分
     * 
     * @param prinmaryArray
     *            原始二维数组数组
     * @param eigenvalue
     *            特征值二维数组
     * @param eigenVectors
     *            特征向量二维数组
     * @return principalMatrix 主成分矩阵
     */
    public Matrix getPrincipalComponent(double[][] primaryArray,
            double[][] eigenvalue, double[][] eigenVectors) {
        Matrix A = new Matrix(eigenVectors);// 定义一个特征向量矩阵
        double[][] tEigenVectors = A.transpose().getArray();// 特征向量转置
        Map<Integer, double[]> principalMap = new HashMap<Integer, double[]>();// key=主成分特征值,value=该特征值对应的特征向量
        TreeMap<Double, double[]> eigenMap = new TreeMap<Double, double[]>(
                Collections.reverseOrder());// key=特征值,value=对应的特征向量;初始化为翻转排序,使map按key值降序排列
        double total = 0;// 存储特征值总和
        int index = 0, n = eigenvalue.length;
        double[] eigenvalueArray = new double[n];// 把特征值矩阵对角线上的元素放到数组eigenvalueArray里
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                if (i == j)
                    eigenvalueArray[index] = eigenvalue[i][j];
            }
            index++;
        }

        for (int i = 0; i < tEigenVectors.length; i++) {
            double[] value = new double[tEigenVectors[0].length];
            value = tEigenVectors[i];
            eigenMap.put(eigenvalueArray[i], value);
        }

        // 求特征总和
        for (int i = 0; i < n; i++) {
            total += eigenvalueArray[i];
        }
        // 选出前几个主成分
        double temp = 0;
        int principalComponentNum = 0;// 主成分数
        List<Double> plist = new ArrayList<Double>();// 主成分特征值
        for (double key : eigenMap.keySet()) {
            if (temp / total <= threshold) {
                temp += key;
                plist.add(key);
                principalComponentNum++;
            }
        }
        System.out.println("\n" + "当前阈值: " + threshold);
        System.out.println("取得的主成分数: " + principalComponentNum + "\n");

        // 往主成分map里输入数据
        for (int i = 0; i < plist.size(); i++) {
            if (eigenMap.containsKey(plist.get(i))) {
                principalMap.put(i, eigenMap.get(plist.get(i)));
            }
        }

        // 把map里的值存到二维数组里
        double[][] principalArray = new double[principalMap.size()][];
        Iterator<Entry<Integer, double[]>> it = principalMap.entrySet()
                .iterator();
        for (int i = 0; it.hasNext(); i++) {
            principalArray[i] = it.next().getValue();
        }

        Matrix principalMatrix = new Matrix(principalArray);

        return principalMatrix;
    }

    /**
     * 矩阵相乘
     * 
     * @param primary
     *            原始二维数组
     * 
     * @param matrix
     *            主成分矩阵
     * 
     * @return result 结果矩阵
     */
    public Matrix getResult(double[][] primary, Matrix matrix) {
        Matrix primaryMatrix = new Matrix(primary);
        Matrix result = primaryMatrix.times(matrix.transpose());
        return result;
    }
}
 

//==================MainClass========================

import Jama.Matrix;

public class PCAMain {
    public static void main(String[] args) {
        PCA pca = new PCA();
        double[][] primaryArray = { { 100, 2, 3, 4, 1, 2, 32, 2 }, { 1, 2, 31, 52, 1, 2, 32, 2 },
                { 1, 2, 32, 2, 1, 2, 31, 52 }, { 1, 2, 32, 2, 1, 2, 30, 52 } };
        System.out.println("--------------------------------------------");
        System.out.println("原始数据: ");
        System.out.println(primaryArray.length + "行," + primaryArray[0].length + "列");
        for (int i = 0; i < primaryArray.length; i++) {
            for (int j = 0; j < primaryArray[0].length; j++) {
                System.out.print(+primaryArray[i][j] + " \t");
            }
            System.out.println();
        }

        // 均值中心化后的矩阵
        double[][] averageArray = pca.changeAverageToZero(primaryArray);
        System.out.println("--------------------------------------------");
        System.out.println("均值0化后的数据: ");
        System.out.println(averageArray.length + "行," + averageArray[0].length + "列");
        for (int i = 0; i < averageArray.length; i++) {
            for (int j = 0; j < averageArray[0].length; j++) {
                System.out.print((float) averageArray[i][j] + " \t");
            }
            System.out.println();
        }
        // 协方差矩阵
        double[][] varMatrix = pca.getVarianceMatrix(averageArray);
        System.out.println("---------------------------------------------");
        System.out.println("协方差矩阵: ");
        for (int i = 0; i < varMatrix.length; i++) {
            for (int j = 0; j < varMatrix[0].length; j++) {
                System.out.print((float) varMatrix[i][j] + "\t");
            }
            System.out.println();
        }
        // 特征值矩阵
        System.out.println("--------------------------------------------");
        System.out.println("特征值矩阵: ");
        double[][] eigenvalueMatrix = pca.getEigenvalueMatrix(varMatrix);

        // 特征向量矩阵
        System.out.println("--------------------------------------------");
        System.out.println("特征向量矩阵: ");
        double[][] eigenVectorMatrix = pca.getEigenVectorMatrix(varMatrix);

        // 主成分矩阵
        System.out.println("--------------------------------------------");
        Matrix principalMatrix = pca.getPrincipalComponent(primaryArray, eigenvalueMatrix, eigenVectorMatrix);
        System.out.println("主成分矩阵: ");
        principalMatrix.print(6, 2);

        // 降维后的矩阵
        System.out.println("--------------------------------------------");
        System.out.println("降维后的矩阵: ");
        Matrix resultMatrix = pca.getResult(primaryArray, principalMatrix);
        resultMatrix.print(10, 2);

    }
}
 

 

直接可运行

© 著作权归作者所有

共有 人打赏支持
Harry_sir
粉丝 14
博文 80
码字总数 48004
作品 0
朝阳
其他
论文[基于WiFi信号的人体行为感知技术研究综述]阅读-知识补充

非视距 非视距最直接的解释是,通信的两点视线受阻,彼此看不到对方,菲涅尔区大于50%的范围被阻挡 。 在有障碍物的情况下,无线信号只能通过反射,散射和衍射方式到达接收端,我们称之为非视...

散人lins ⋅ 04/13 ⋅ 0

openJdk和sun jdk的区别

使用过LINUX的人都应该知道,在大多数LINUX发行版本里,内置或者通过软件源安装JDK的话,都是安装的OpenJDK, 那么到底什么是OpenJDK,它与SUN JDK有什么关系和区别呢? 历史上的原因是,Ope...

jason_kiss ⋅ 06/18 ⋅ 0

ThreadLocal源码分析

阅读原文请访问我的博客 BrightLoong's Blog 一. 简介 提醒篇幅较大需耐心。 简介来自ThreadLocal类注释 ThreadLocal类提供了线程局部 (thread-local) 变量。这些变量与普通变量不同,每个线...

BrightLoong ⋅ 05/28 ⋅ 0

升级到JDK9的一个BUG,你了解吗

概述 前几天在一个群里看到一个朋友发了一个demo,说是JDK的bug,昨天在JVM的一个群里又有朋友发了,觉得挺有意思,分享给大家,希望大家升级JDK的版本的时候注意下是否存在这样的代码,如果...

你假笨 ⋅ 06/06 ⋅ 0

sharding-jdbc源码分析—准备工作

原文作者:阿飞Javaer 原文链接:https://www.jianshu.com/p/7831817c1da8 接下来对sharding-jdbc源码的分析基于tag为源码,根据sharding-jdbc Features深入学习sharding-jdbc的几个主要特性...

飞哥-Javaer ⋅ 05/03 ⋅ 0

两道面试题,带你解析Java类加载机制

文章首发于【博客园-陈树义】,点击跳转到原文《两道面试题,带你解析Java类加载机制》 在许多Java面试中,我们经常会看到关于Java类加载机制的考察,例如下面这道题: 请写出最后的输出字符...

陈树义 ⋅ 06/12 ⋅ 0

两道面试题带你解析 Java 类加载机制

在许多Java面试中,我们经常会看到关于Java类加载机制的考察,例如下面这道题: class Grandpa{ } class Father extends Grandpa{ }class Son extends Father{ }public class Initialization...

⋅ 06/13 ⋅ 0

JavaWeb07-HTML篇笔记(二)

1.1 案例一:使用JDBC完成CRUD的操作:1.1.1 需求: 对分类管理使用JDBC进行CRUD的操作. 1.1.2 分析:1.1.2.1 技术分析: 【JDBC的概述】 Ø JDBC:Java DataBase Connectivity Java数据库的连...

我是小谷粒 ⋅ 05/16 ⋅ 0

Oracle Java Mission Control 帮助

缩写 含义 JDK Java 开发工具包 JDP Java Discovery Protocol JFR Java 飞行记录器 JMC Java Mission Control JMX Java Management Extensions JVM Java 虚拟机 MBean 托管 Bean (Java) RCP ......

光斑 ⋅ 04/27 ⋅ 0

sharding-jdbc源码解析全集

sharding-jdbc源码解析之词法解析 sharding源码解析之api分析 sharding-jdbc源码解析之spring集成 sharding-jdbc源码解析之spring集成分片构造实现 sharding-jdbc源码解析之jdbc规范重写 sh...

天河2018 ⋅ 05/03 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

火狐浏览器各版本下载及插件httprequest

各版本下载地址:http://ftp.mozilla.org/pub/mozilla.org//firefox/releases/ httprequest插件截至57版本可用

xiaoge2016 ⋅ 14分钟前 ⋅ 0

Java学习路径及练手项目合集

Java学习路径及练手项目合集

颖伙虫 ⋅ 30分钟前 ⋅ 0

Docker系列教程28-实战:使用Docker Compose运行ELK

原文:http://www.itmuch.com/docker/28-docker-compose-in-action-elk/,转载请说明出处。 ElasticSearch【存储】 Logtash【日志聚合器】 Kibana【界面】 答案: version: '2'services: ...

周立_ITMuch ⋅ 56分钟前 ⋅ 0

使用快嘉sdkg极速搭建接口模拟系统

在具体项目研发过程中,一旦前后端双方约定好接口,前端和app同事就会希望后台同事可以尽快提供可供对接的接口方便调试,而对后台同事来说定好接口还仅是个开始、设计流程,实现业务逻辑,编...

fastjrun ⋅ 今天 ⋅ 0

PXE/KickStart 无人值守安装

导言 作为中小公司的运维,经常会遇到一些机械式的重复工作,例如:有时公司同时上线几十甚至上百台服务器,而且需要我们在短时间内完成系统安装。 常规的办法有什么? 光盘安装系统 ===> 一...

kangvcar ⋅ 昨天 ⋅ 0

使用Puppeteer撸一个爬虫

Puppeteer是什么 puppeteer是谷歌chrome团队官方开发的一个无界面(Headless)chrome工具。Chrome Headless将成为web应用自动化测试的行业标杆。所以我们很有必要来了解一下它。所谓的无头浏...

小草先森 ⋅ 昨天 ⋅ 0

Java Done Right

* 表示难度较大或理论性较强。 ** 表示难度更大或理论性更强。 【Java语言本身】 基础语法,面向对象,顺序编程,并发编程,网络编程,泛型,注解,lambda(Java8),module(Java9),var(...

风华神使 ⋅ 昨天 ⋅ 0

Linux系统日志

linux 系统日志 /var/log/messages /etc/logrotate.conf 日志切割配置文件 https://my.oschina.net/u/2000675/blog/908189 logrotate 使用详解 dmesg 命令 /var/log/dmesg 日志 last命令,调......

Linux学习笔记 ⋅ 昨天 ⋅ 0

MVC——统一报文格式的异常处理响应

在我们写controller层的时候,常常会有这样的困惑,如果需要返回一个数据是,可能为了统一回去构造一个类似下列的数据格式: { status:true, msg:"保存成功!", data:[]} 而且在写...

alexzhu592 ⋅ 昨天 ⋅ 0

android -------- 打开本地浏览器或指定浏览器加载,打电话,打开第三方app

开发中常常有打开本地浏览器加载url或者指定浏览器加载, 还有打开第三方app, 如 打开高德地图 百度地图等 在Android程序中我们可以通过发送隐式Intent来启动系统默认的浏览器。 如果手机本身...

切切歆语 ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部