Zipf分布に従う乱数の生成方法

877 views

Published on

Japanese version only

0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
877
On SlideShare
0
From Embeds
0
Number of Embeds
6
Actions
Shares
0
Downloads
4
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

Zipf分布に従う乱数の生成方法

  1. 1. Zipf 分布に従う乱数の生成方法 まるやま 2013/04/18 1 / 10
  2. 2. Zipf 分布に従う乱数を発生させたい そういう時もあるでしょ(あるんです) Zipf 分布とは → ja.wikipedia 一番簡単な Zipf 分布を考える 1/k f (k; N) = ∑N i=1 1/i 2 / 10
  3. 3. 調和級数の部分和 Zipf 分布の分母は、調和級数の部分和(要するに、調和数) 調和級数とは → ja.wikipedia だから、対数とオイラーの定数で近似できる オイラーの定数とは → ja.wikipedia ∑N 1 i=1 i ≒ log(N) + γ オイラーの定数:γ = 0.5772156649 · · · Partial Sums of Harmonic Series (Harmonic Number) and its approximate value 10 9.5 9 8.5 8 7.5 グラフでは見分けがつか 7 6.5 Harmonic Number 6 ない程、近い 5.5 Harmonic Number 5 approximate value 4.5 4 3.5 3 2.5 2 1.5 1 0.5 0 1000 2000 3000 4000 5000 6000 7000 8000 9000 10000 x-th partial sum 3 / 10
  4. 4. Zipf 分布の式を簡単に Zipf 分布の式が結構簡単になる 1 f (k; N) = k(log(N)+γ) グラフを描くのも楽チン Zipf Distribution (N=10000) Zipf Distribution (N=10000, Enlargement) 1 0.4 0.9 0.35 0.8 0.3 0.7 0.25 0.6 PDF and CDF PDF and CDF PDF PDF 0.5 0.2 CDF CDF 0.4 0.15 0.3 0.1 0.2 0.05 0.1 0 0 0 1000 2000 3000 4000 5000 6000 7000 8000 9000 10000 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 k k 4 / 10
  5. 5. 一様乱数から Zipf 乱数へ 確率分布な乱数を作る時は、累積分布関数(CDF)を使う 前のスライドに載せていた確率密度関数(PDF)ではなくて ジップ分布の累積密度関数だって、実は簡単 log(k)+γ F (k; N) = log(N)+γ 何も言わずに前のスライドにはグラフを載せていたけど 累積密度関数の逆関数で、確率分布な乱数を作れる G (x; N) = exp((log(N) + γ)x − γ) 5 / 10
  6. 6. Lua で作ってみる zipfr.lua euGm = 0.5772156649 max = 1000 count = 1000000 harm = math.log(max)+euGm math.randomseed(os.time()) hist = {} for i = 1, max, 1 do hist[i] = 0 end for i = 1, count, 1 do x = math.ceil(math.exp((math.random()*harm)-euGm)) hist[x] = hist[x]+1 end for i = 1, max, 1 do print(i, hist[i]/count, 1/i/harm) end 6 / 10
  7. 7. 作ってみたら… Zipf Distribution (N=1000) 0.15 0.14 0.13 0.12 0.11 0.1 0.09 probability 0.08 count 0.07 logical 0.06 0.05 0.04 0.03 0.02 0.01 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 k あれ?なんか違う? 7 / 10
  8. 8. 定義域と値域 一様乱数の入力 x = [0, 1) に対して、 出力 y = G (x; N) は y = [0, N) であって欲しい しかし、G (0; N) = e −γ 、G (1; N) = N だから1番目の値が小さかった! 値域の始まりを合わせるため、 G (x; N) = exp((log(N) + γ)x − γ) − e −γ とする すると今度は値域の終わりが G (1; N) = N − e −γ とズレる さらに値域の終わりを合わせるため、 G (x; N) = exp((log(N + e −γ ) + γ)x − γ) − e −γ とする これで G (0; N) = 0、G (1; N) = N になった! 8 / 10
  9. 9. Lua で再実装 zipfrand.lua euGm = 0.5772156649 max = 1000 count = 1000000 base = math.exp(-euGm) harm = math.log(max)+euGm cond = math.log(max+base)+euGm math.randomseed(os.time()) hist = {} for i = 1, max, 1 do hist[i] = 0 end for i = 1, count, 1 do x = math.ceil(math.exp((math.random()*cond)-euGm)-base) if (x == 0) then x = 1 end hist[x] = hist[x]+1 end for i = 1, max, 1 do print(i, hist[i]/count, 1/i/harm) end 9 / 10
  10. 10. 結果… Zipf Distribution (N=1000) 0.15 0.14 0.13 0.12 0.11 0.1 0.09 probability 0.08 count 0.07 logical 0.06 0.05 0.04 0.03 0.02 0.01 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 k できた! ! 10 / 10

×