本文转载了一篇关于方差增量算法的文章,代码实现转换成 java。
原文地址如下:https://www.cnblogs.com/yoyaprogrammer/p/delta_variance.html,感谢作者的分享。
原文中关于公式推导写的很清晰了,这里只把原文中的代码实现转换成 java 代码。
1.entity 数组沉淀因子类,其中封装了数组增量方法,
public class Measures {
private Integer n;//数组元素个数
private Double sum;//数组中各元素之和
private Double variance;//数组方差
private Double avg;//数组的平均值
//有参构造器
public Measures(Integer n, Double sum, Double variance) {
this.n = n;
this.sum = sum;
this.variance = variance;
this.avg =sum/n;
}
//数组增量方法
public Measures appendDelta(Measures delta){
Integer newN = this.n + delta.getN();//数组长度之和
Double newSum = this.sum + delta.getSum();//数组元素总和
Double newAvg = newSum / newN;
Double variance = (this.partial(newAvg,this.avg,this.variance,this.n) + this.partial(newAvg,delta.getAvg(),delta.getVariance(),delta.getN()))/newN;//方差增量算法公式
return new Measures(newN,newSum,variance);
}
// 封装表达式 n*(variance + (newAvg - avg)*(newAvg - avg))
public Double partial(Double newAvg ,Double avg ,Double variance,Integer n){
Double deltaAvg =newAvg - avg;
return n * ( variance + deltaAvg * deltaAvg );
}
}
2.测试类
public class JavaTest {
public static void main(String[] args) {
Double[] d1 = {1.0,2.0};
Double[] d2 = {3.0,4.0};
//第一种:合并数组计算方差,不按增量算法
Double[] d3 = hebing(d1,d2);
Measures m1 = createMs(d3);
System.out.println("传统计算结果:"+m1.getVariance());
//第二种:方差增量算法
Measures m2 = createMs(d1);
Measures m3 = createMs(d2);
Measures m4 = m2.appendDelta(m3);
System.out.println("增量算法结果:"+m4.getVariance());
}
/**
* 单个数组方差的计算
* @return
*/
public static Measures createMs(Double[] values){
Measures ms = null;
if (values != null && values.length > 0){
Integer n = values.length;
//求和
Double sum =0.00;
//avg
Double avg = 0.00;
//方差计算
Double variance = 0.00;
Double sumSq = 0.00;
for (int i = 0;i<values.length;i++){
sum +=values[i];
}
avg = sum/n;
for (int i = 0;i<values.length;i++){
sumSq += Math.pow((values[i] - avg),2);
}
variance = sumSq / n;
ms = new Measures(n,sum,variance);
}else{
ms = new Measures(0,0.00,0.00);
}
return ms;
}
public static Double[] hebing(Double[] d1,Double[] d2){
if(d1 == null){
d1 = new Double[0];
}
if(d2 == null){
d2 = new Double[0];
}
Double[] d3 = new Double[d1.length+d2.length];
for (int i =0;i <d1.length; i++){
d3[i] = d1[i];
}
for(int i =0;i <d2.length; i++){
d3[i+d1.length] = d2[i];
}
return d3;
}
}
3.测试结果:
传统计算结果:1.25
增量算法结果:1.25