大数据JAVA实现 基于皮尔逊相关系数的相似度

皮尔逊相关系数理解有两个角度  
1. 按照高中数学水平来理解, 它很简单, 可以看做将两组数据首先做Z分数处理之后, 然后两组数据的乘积和除以样本数Z分数一般代表正态分布中, 数据偏离中心点的距离.等于变量减掉平均数再除以标准差.(就是高考的标准分类似的处理)标准差则等于变量减掉平均数的平方和,再除以样本数,最后再开方. 
所以, 根据这个最朴素的理解,我们可以将公式依次精简为: 

公式

2.按照大学的线性数学水平来理解, 它比较复杂一点,可以看做是两组数据的向量夹角的余弦.

皮尔逊相关的约束条件 
1. 两个变量间有线性关系 
2. 变量是连续变量 
3. 变量均符合正态分布,且二元分布也符合正态分布 
4. 两变量独立


皮尔逊相关系数的值域等级

0.8-1.0 极强相关 
0.6-0.8 强相关 
0.4-0.6 中等程度相关 
0.2-0.4 弱相关 
0.0-0.2 极弱相关或无相关

以上内容看起来太过晦涩,不如看个手算的示例让人更容易懂 
使用维基中的例子

例如,假设五个国家的国民生产总值分别是1、2、3、5、8(单位10亿美元),又假设这五个国家的贫困比例分别是11%、12%、13%、15%、18%。

那么需要被计算的两个数据样本分别是

x->(1,2,3,5,8) 
y->(0.11,0.12,0.13,0.15,0.18)

接下来计算两个数据样本的平均值

x的平均值为3.8 
y的平均值为0.138

接下来计算皮尔逊系数的分子

用大白话来写就是: 
(1-3.8)*(0.11-0.138)=0.0784 
(2-3.8)*(0.12-0.138)=0.0324 
(3-3.8)*(0.13-0.138)=0.0064 
(5-3.8)*(0.15-0.138)=0.0144 
(8-3.8)*(0.18-0.138)=0.1764 
0.0784+0.0324+0.0064+0.0144+0.1764=0.308

同理分号下面的分别是 
sum((x-mean(x))^2)=30.8 sum((y-mean(y))^2)= 0.00308

sum((x-mean(x))^2)=30.8 
(1-3.8)^2=7.84 #平方 
(2-3.8)^2=3.24 #平方 
(3-3.8)^2=0.64 #平方 
(5-3.8)^2=1.44 #平方 
(8-3.8)^2=17.64 #平方 
7.84+3.24+0.64+1.44+17.64=30.8

同理,求得:

sum((y-mean(y))^2)= 0.00308

然后再开平方根,分别是:

30.8^0.5=5.549775 0.00308^0.5=0.05549775

用分子除以分母,就计算出最终结果:

0.308/(5.549775*0.05549775)=1


最后附上Java代码

DataNode

package org.data.entity;

import java.util.Arrays;

public class DataNode {
    double[] datas;

    public double[] getDatas() {
        return datas;
    }

    public void setDatas(double[] datas) {
        this.datas = datas;
    }

    @Override
    public String toString() {
        return "DataNode [datas=" + Arrays.toString(datas) + "]";
    }

    public DataNode() {

    }
    public DataNode(double[] datas) {
        super();
        this.datas = datas;
    }
}

PearsonCorrelationScore

package org.data.util;

import org.data.entity.DataNode;

/**
 * 计算两个样本数据之间的皮尔逊系数
 * @author Joe
 *
 */
public class PearsonCorrelationScore {
    private double[] xData;
    private double[] yData;
    private double xMeans;
    private double yMeans;
    /**
     * 求解皮尔逊的分子
     */
    private double numerator;
    /**
     * 求解皮尔逊系数的分母
     */
    private double denominator;
    /**
     * 计算最后的皮尔逊系数
     */
    private double pearsonCorrelationScore;

    public PearsonCorrelationScore(DataNode x, DataNode y) {
        //先获取DataNode的数据
        this.xData = x.getDatas();
        this.yData = y.getDatas();
        //拿到两个数据的平均值
        this.xMeans = this.getMeans(xData);
        this.yMeans = this.getMeans(yData);
        //计算皮尔逊系数的分子
 this.numerator = this.generateNumerator();
        //计算皮尔逊系数的分母
        this.denominator = this.generateDenomiator();
        //计算皮尔逊系数
        this.pearsonCorrelationScore = this.numerator / this.denominator;
    }

    /**
     * 生成分子
     * @return 分子
     */
    private double generateNumerator() {
        double sum = 0.0;
        for (int i = 0; i < xData.length; i++) {
            sum += (xData[i] - xMeans) * (yData[i] - yMeans);
        }
        return sum;
    }
    /**
     * 生成分母
     * @return 分母
     */
    private double generateDenomiator() {
        double xSum = 0.0;
        for (int i = 0; i < xData.length; i++) {
            xSum += (xData[i] - xMeans) * (xData[i] - xMeans);
        }

        double ySum = 0.0;
        for (int i = 0; i < yData.length; i++) {
            ySum += (yData[i] - yMeans) * (yData[i] - yMeans);
  }

        return Math.sqrt(xSum) * Math.sqrt(ySum);
    }

    /**
     * 根据给定的数据集进行平均值计算
     * @param datas 数据集
     * @return 给定数据集的平均值
     */
    private double getMeans(double[] datas) {
        double sum = 0.0;
        for (int i = 0; i < datas.length; i++) {
            sum += datas[i];
        }
        return sum / datas.length;
    }

    public double getPearsonCorrelationScore() {
        return this.pearsonCorrelationScore;
    }
}

最后代码测试

package org.data.client;

import org.data.entity.DataNode;
import org.data.util.PearsonCorrelationScore;

public class PearsonTest {
    public static void main(String[] args) {
        DataNode x = new DataNode(new double[] {1, 2, 3, 5, 8});
        DataNode y = new DataNode(new double[] {0.11, 0.12, 0.13, 0.15, 0.18});
        PearsonCorrelationScore score = new PearsonCorrelationScore(x, y);
        System.out.println(score.getPearsonCorrelationScore());
    }
}

转载地址


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值