Reservoir sampling
件のデータから 件をランダムサンプリングする場合のアルゴリズムで、
が未知数であっても、 を求める必要がなく、
1passでランダムサンプリングができる。
今まで を求めるためにかかっていた時間を家事や育児にあてることができる。
概要
件のデータを とする。
このアルゴリズムでは、Reservoir(貯水池)を として、
そこに 件のデータを随時貯めておく。
Reservoirは処理の過程でどんどん更新されていき、
最終的にはこれがサンプリング結果となる。
アルゴリズム
アルゴリズムは基本的に2つのステップから構成される。
ステップ①
最初の 件をとりあえずReservoirにぶっこんでおく。
にデータ を代入。
ステップ②
データ については の確率でReservoirの保持内容を更新する。
の整数値をとる一様乱数 を生成し、 の場合、 に を代入。
解釈
本当にランダムサンプリングされているのか気になるところ。
2つの場合に分けてデータ が選ばれる確率を考えてみる。
データ がReservoirに残る確率
が更新されない確率
データ がReservoirに残る確率
に が代入される確率 が更新されない確率
実装例
行数が未知のテキストファイルから 行をReservoir samplingにて取り出す例。
サンプリング結果はテキストファイルとして出力。
import random def random_sampling(inputFile, k=10000, header=True): R = [] columns = '' with open(inputFile) as fin: if header: columns = fin.next() for i in range(k): R.append(fin.next()) i = k for line in fin: j = random.randint(0,i) if j<k: R[j] = line i += 1 outputFile = inputFile.split('.')[0] + '_random' + str(k) + '.' \ + inputFile.split('.')[1] with open(outputFile,"w") as fout: if header: fout.write(columns) for line in R: fout.write(line)