Tho*_*orf 8 javascript random algorithm split data-science
给定“分割比例”,我试图将数据集随机分为两组。问题是,我事先不知道数据集包含多少个项目。我的库从输入流中一个接一个地接收数据,并且期望将数据返回到两个输出流。理想情况下,应将所得的两个数据集精确地拆分为给定的拆分比率。
插图:
??? stream A
input stream ??? LIBRARY ???
??? stream B
Run Code Online (Sandbox Code Playgroud)
例如,给定分流比30/70,流A有望从输入流中接收30%的元素,而流B剩余的70%。订单必须保留。
理念1:为每个元素“掷骰子”
一个明显的方法是:对于每个元素,算法都会随机决定该元素应该进入流A还是流B。问题是,结果数据集可能与预期的分割率相去甚远。给定的拆分率50/50,所得数据拆分可能会相去甚远(甚至可能100/0是非常小的数据集)。目的是使所得的分光比尽可能接近所需的分光比。
想法2:使用缓存并随机化缓存的数据
另一个想法是在传递元素之前先缓存固定数量的元素。这将导致缓存1000个元素并改组数据(或其对应的索引以保持顺序稳定),将它们拆分并传递结果数据集。这应该工作得很好,但是我不确定对于大型数据集,随机化是否真的是随机的(我想看分布时会出现模式)。
两种算法都不是最优的,所以希望您能对我有所帮助。
背景
这是关于基于层的数据科学工具的,其中每个层都通过流从上一层接收数据。在传递数据之前,希望该层将数据(向量)拆分为训练和测试集。输入数据的范围可以从几个元素到一个永无止境的数据流(因此,这些流)。该代码是用JavaScript开发的,但是这个问题更多的是关于算法而不是实际的实现。
您可以在概率偏离所需速率时对其进行调整。
这是一个示例以及对各种调整概率级别的测试。随着我们增加调整,我们看到分流器与理想比率的偏差较小,但这也意味着它的随机性较小(知道之前的值,您可以预测下一个值)。
// rateStrictness = 0 will lead to "rolling the dice" for each invocations
// higher values of rateStrictness will lead to strong "correcting" forces
function* splitter(desiredARate, rateStrictness = .5) {
let aCount = 0, bCount = 0;
while (true) {
let actualARate = aCount / (aCount + bCount);
let aRate = desiredARate + (desiredARate - actualARate) * rateStrictness;
if (Math.random() < aRate) {
aCount++;
yield 'a';
} else {
bCount++;
yield 'b';
}
}
}
let test = (desiredARate, rateStrictness) => {
let s = splitter(desiredARate, rateStrictness);
let values = [...Array(1000)].map(() => s.next().value);
let aCount = values.map((_, i) => values.reduce((count, v, j) => count + (v === 'a' && j <= i), 0));
let aRate = aCount.map((c, i) => c / (i + 1));
let deviation = aRate.map(a => a - desiredARate);
let avgDeviation = deviation.reduce((sum, dev) => sum + dev, 0) / deviation.length;
console.log(`inputs: desiredARate = ${desiredARate}; rateStrictness = ${rateStrictness}; average deviation = ${avgDeviation}`);
};
test(.5, 0);
test(.5, .25);
test(.5, .5);
test(.5, .75);
test(.5, 1);
test(.5, 10);
test(.5, 100);Run Code Online (Sandbox Code Playgroud)
掷骰子两次怎么样:首先决定是否应该随机选择流,或者是否应该考虑比率。然后对于第一种情况,掷骰子,对于第二种情况,取比率。一些伪代码:
const toA =
Math.random() > 0.5 // 1 -> totally random, 0 -> totally equally distributed
? Math.random() > 0.7
: (numberA / (numberA + numberB) > 0.7);
Run Code Online (Sandbox Code Playgroud)
这只是我的一个想法,我还没有尝试过......