您的位置:首页 > 其它

分布式水库抽样算法实现以及原理

2017-10-13 15:32 369 查看
分布式书库抽样算法实现以及原理:

package com.bonree.project.browser.utils;

import java.util.ArrayList;

import java.util.List;

import java.util.Random;

/[b]*********************************************************************[/b]

* 版权信息:博睿宏远科技发展有限公司

* @author xuchang@bonree.com

* Copyright: Copyright (c) 2007博睿宏远科技发展有限公司,Inc.All Rights Reserved.

* Description: Browser计算模块,算术工具类

[b]********************************************************************[/b]/

public class MathUtils {

/**
* 单机水库抽样算法
* 如果样本数量小数抽样样本数量,则值向水库样本中添加样本数据,而不需要进行样本抽样算法了
*
* @param samples 样本库
* @param sample  当前样本
* @param num     样本可长度
*/
public static void reservoirSampling(List<Double> samples, Double sample, int num) {
if (samples.size() < num) {
//如果集合数量小于样本数量
samples.add(sample);
} else {
Random random = new Random();
int i = random.nextInt(num);
if (i < num) {
//直接用当前样本替换掉之前样本库中的索引为i的样本
samples.set(i, sample);
}
}
}

/**
* (1)两个完成抽样后端库抽样合并的方法
* 对于两个样本库进行抽样合并成一个样本库的分布式抽样算法实现
* 对于两个样本库,需要抽样和并处一个长度为num的样本库的方法,是给两个样本库分别设置权重,
* 比如说,样本库为1 抽取的样本数为n 那么样本抽的概率为1/n 样本库2,所有样本数为m ,那么样本可以抽取的概率为,1/m
* 现在需要从连个不同概率的样本可以种抽取合并成以个书库样本,那么可以给样本库一每一个数据设置权重为n/m+n
* 给样本库2中的数据被抽取的概率设置权重为m/m+n
* 那么得出结论,样本库1中样本抽取的的概率为(1/n)*(n/m+n)=1/m+n
* 以上逻辑正对于最后抽样的的书库均抽满样本
* (2)两个均为抽样的的集合,分布式抽样方法,是分别遍历每个集合,完成抽样
* (3)两个集合至多只有一个集合抽样的情况。如果有抽样的集合,那么就
* 在这个情况下又有多个小情况:
* (i)如果有一个样本库发生抽样,那么以这个集合作为样本库
* 将未抽样的数据继续遍历抽样到样本库中
* (ii)如果没有样本库发生抽样
* 分别遍历两个集合,进行水库抽样
* (4)两个集合不够抽样,直接填入到抽样样本库中
*
* @param samples1 样本库一
* @param samples2 样本库二
* @param num      样本库长度
* @return
*/
public static List<Double> distributeReservoirSampling(List<Double> samples1, long m, List<Double> samples2, long n, int num) {
List<Double> samples = new ArrayList<>(num);
double d;
double weight = (double) m / (m + n);
if (samples1.size() > num && samples2.size() > num) {
//两个集合均没有抽样
for (Double sample : samples1) {
reservoirSampling(samples, sample, num);
}
for (Double sample : samples2) {
reservoirSampling(samples, sample, num);
}
} else if (samples1.size() == num && samples2.size() == num) {
//两个集合均抽样
for (int i = 0; i &l
4000
t; num; i++) {
d = Math.random();
if (d < weight) {
//如果权重落在m/(m+n)内,那么就可以从samples1中取值
samples.add(samples1.get(i));
} else {
//否则,就从samples2中取值
samples.add(samples2.get(i));
}
}
} else if (samples1.size() + samples2.size() > num && samples1.size() + samples2.size() < 2 * num) {
//两个集合至多只有一个抽样,以数据较大的库为样本库,遍历较小的样本库,抽样至样本库中
if (samples1.size() > samples2.size()) {
//samples1完成抽样
for (Double sample : samples1) {
reservoirSampling(samples1, sample, num);
}
samples.addAll(samples2);
} else if (samples2.size() == num) {
for (Double sample : samples2) {
reservoirSampling(samples1, sample, num);
}
samples.addAll(samples1);
}
} else {
//不够填满抽样样本
samples.addAll(samples1);
samples.addAll(samples2);
}
return samples;
}


}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: