Weighted Reservoir Sampling を実装する必要があります。このブログで言及されている論文を参照しました。実装を単体テストするためのテストケースを書きたいのですが、貯水池にあるさまざまな要素の期待確率を計算する方法について混乱しています。
に比例するはずだと思っていましたが、ここで(weight_of_element/weight_of_all_elements)
言及されているテストケースでは計算が異なります。どうすればいいですか?
テストケースを書くために、要素が選択される確率を実際に見積もることができます。次のような重みを割り当てたとします:
weights = [1, 5, 8, 2, 5]
ここで、 1 つの要素を描画するために加重リザーバー サンプリングを実行しています。結果に要素が現れる確率は? それらは正確に(weight_of_element/weight_of_all_elements)
:
prob = [0.048, 0.238, 0.381, 0.095, 0.238]
つまり、1 つの要素を 10 6回繰り返し描画すると、3 番目の要素のインスタンスは 0.381 * 10 6 回、最初の要素のインスタンスは0.048 * 10 6回、というようになります。もちろん、およそ。
したがって、10 6回の試行のうち最初の要素が出現した回数の割合を見ることができます。これはおよそ でなければなりません(weight_of_first_element/weight_of_all_elements)
。これらの値を比較して、互いに近いかどうかを確認します。
したがって、テストケースは次のようになります (疑似コード):
numTrials = 1000000
histogram = map<int, int>
for i = 1..numTrials:
element = WeightedReservoir.sample(weights, 1) # draw one element
histogram[element]++
for i = 1..len(weights):
real_probability = weights[i] / sum(weights)
observed_probability = histogram[elements[i]] / numTrials
assert(abs(real_probability - observed_probability) <= epsilon) # measuring absolute difference, but you can switch to relative difference
Java での特定の実装については、このスレッドを 参照してください。
あなたが指摘したClouderaテストに関しては、それは異なるロジックに従います(これは、numpy.random.choiceの Pythonパッケージnumpyテストでも見ました):
シード値を制御できない場合、この方法は適していません。