Upgrade to Pro — share decks privately, control downloads, hide ads and more …

HyperLogLog

Avatar for xorphitus xorphitus
November 18, 2015

 HyperLogLog

HyperLogLog の解説を試みました。

Avatar for xorphitus

xorphitus

November 18, 2015
Tweet

More Decks by xorphitus

Other Decks in Programming

Transcript

  1. HyperLogLog とは • カーディナリティの推定値を求めるアルゴリズム ◦ MultiSet {1, 1, 2, 3,

    4, 4, 4} なら 4 • 巨大な入力に対して、少ないメモリ消費量で値を算出できる ◦ イメージとしては, n+1 番目の入力が来たときのカーディナリティを Cn+1 とすると ▪ Cn+1 = f(xn+1, Cn) みたいな ▪ x1,...,xn は捨てて C のその時の値だけ保持していればよい ◦ Web みたいにどんどん次の入力がくるパターンに向いている • 乱択的である ◦ 元の入力ハッシュを値をとり , その一部の bit 列を使って ▪ 複数ある入れ物に振り分けたり ▪ 推定値を算出したり ◦ でもって最後に統計的手法で最終的な値を算出する
  2. 基本的な考え方 1. 元の入力 (MultiSet) を Μ とする 2. Μ を

    m 個の部分集合 Μ1,...,Μm に分ける 3. Μ1,...,Μm についてカーディナリティの推定値を求める 4. Μ1,...,Μm の推定値の調和平均を取る • Μi のカーディナリティを求める時, 古い入力データは保持せず済むのでメモリが節 約できる • Μ の各要素がどの部分集合に振り分けられるかは乱択的である
  3. • m = 2^b with b∈Z>0 ◦ となる m と

    b を考える • m 個のレジスタ M[1]...M[m] を用意する • for v∈Μ do ◦ let x = hash(v) ◦ let j = 1 + (v の先頭 b bit) ◦ v をレジスタ M[j] の値の算出に用いる ▪ m と b の定義を考えると、j の値は 1,...,m の範囲であると分かりますね 部分集合への振り分けについて
  4. • m = 2^b with b∈Z>0 ◦ となる m と

    b を考える • m 個のレジスタ M[1]...M[m] を用意する • for v∈Μ do ◦ let x = hash(v) ◦ let j = 1 + (v の先頭 b bit) ◦ let w = v の先頭 b+1 bit 目以降 ◦ M[j] = Max(M[j], ρ(w)) ▪ where ρ(s), s∈任意のbit列, 先頭から数えて最初に 1 になった桁の数 • s = 000101110 ならば 4 ▪ つまり ρ(w) の最大値だけ覚えておいて他のデータは捨てる で、カーディナリティどうやって求めるの? 1
  5. • m = 2^b with b∈Z>0 ◦ となる m と

    b を考える • m 個のレジスタ M[1]...M[m] を用意する • for v∈Μ do ◦ let x = hash(v) ◦ let j = 1 + (v の先頭 b bit) ◦ let w = v の先頭 b+1 bit 目以降 ◦ M[j] = Max(M[j], ρ(w)) ▪ where ρ(s), s∈任意のbit列, 先頭から数えて最初に 1 になった桁の数 • カーディナリティ = α_m * m * (2^(-M[1])...2^(-M[m]))の調和平均 ◦ α_m は m に依存する値で, この掛け算で正規化をしている (面倒だから中身は割愛 ) で、カーディナリティどうやって求めるの? 2
  6. ?!

  7. • m = 2^b with b∈Z>0 ◦ となる m と

    b を考える • m 個のレジスタ M[1]...M[m] を用意する • for v∈Μ do ◦ let x = hash(v) ◦ let j = 1 + (v の先頭 b bit) ◦ let w = v の先頭 b+1 bit 目以降 ◦ M[j] = Max(M[j], ρ(w)) ▪ where ρ(s), s∈任意のbit列, 先頭から数えて最初に 1 になった桁の数 • カーディナリティ = α_m * m * (2^(-M[1])...2^(-M[m]))の調和平均 ◦ α_m は m に依存する値で, この掛け算で正規化をしている (面倒だから中身は割愛 ) ちょっと待て イミフ
  8. • for v∈Μ do ◦ let x = hash(v) ◦

    let j = 1 + (v の先頭 b bit) ◦ let w = v の先頭 b+1 bit 目以降 ◦ M[j] = Max(M[j], ρ(w)) ▪ where ρ(s), s∈任意のbit列, 先頭から数えて最初に 1 になった桁の数 • Μ の j 番目の部分集合の各要素について, b+1 桁目から 0 が連続しているのは 最大で何回か, に1を足した数が M[j] ◦ 0 の連続数…つまり「レア度」だ ◦ M[j] は部分集合 Μj の中で最もレア, つまり重複しにくいものを指している まず M[j] とは何なのか
  9. • Μ の j 番目の部分集合の各要素について, b+1 桁目から 0 が連続しているのは 最大で何回か,

    に1を足した数が M[j] ◦ 01 の列において 0 が k 回連続する確率は 2^(-k) なので ◦ M[j] が得られる確率は 2^(-M[j]+1) である ▪ つまり ▪ M[j] よりも 0 が連続する (すなわち重複しない ) 値が次にくる確率は • 2^(-M[j]) • ここで, 確率 p の事象 A が発生するまで試行を続けた場合の, A が発生するまで にかかる試行数の期待値が 1/p であることを考えると ◦ 平均して 1/(2^(-M[j])) すなわち 2^(M[j]) 個の入力があれば Μj のカーディナリティは増加する M[j] とはレア度?
  10. • 平均して 2^(M[j]) 個の入力があれば Μj のカーディナリティは増加する ◦ j は 1,...,m

    まであるので, これらの調和平均をとることでより偏りをなくす ◦ 2^(M[j])の調和平均 は mZ と置く (m 個の要素だと分子が m になるので) ▪ 割合の場合は算術平均だと変な値になるので • ここで部分集合 Μj について関数 Max を以下のように定義する ◦ Max(Μj) = max(ρ(x)), x∈Μj ◦ すると恐らく近似的に以下が成り立つ ◦ 2^(Max(Μj)) = mZ M[j] が何だか結局分からんけどまあいいか
  11. • (再掲) 部分集合Μj について関数 Max を以下のように定義する ◦ Max(Μj) = max(ρ(x)),

    x∈Μj ◦ このとき ρ が bit 列において 0 の連続数+1 であることを考えると ◦ nj を Μj のカーディナリティとして ◦ Max(Μj) = log2(nj) ▪ 最大 0 連続数と, カーディナリティの数値の bit 長 が一致する?? • ここで Μ のカーディナリティを n とするとレジスタ数 m に均一に分散するとしたら Μj のカーディナリティは n/m となるから ◦ Max(Μj) = log2(n/m) ◦ ここで前ページで導出した 2^(Max(Μj)) = mZ を用いると ◦ n = (m^2)Z 別の切り口から
  12. • だいぶ前のイミフだった式を再掲 ◦ カーディナリティ = α_m * m * (2^(-M[1])...2^(-M[m]))の調和平均

    • ここで上記の調和平均を mZ と置いているので ◦ カーディナリティ = α_m * (m^2) * Z ◦ あれ, 前のページで導出した結果に α_m の積が余分にくっついてんじゃん ! ▪ これはどうも正規化するのに必要なものらしい ▪ 具体的には やっと戻ってきた
  13. まとめ • HyperLogLog とは • m 個のレジスタを持つデータ構造であり • 長大な入力が来ても, そのカーディナリティの推定を上記

    m 個だけで実現する • ちなみに, ここへきて突然言及しますが ◦ 各レジスタはだいたい 5B あれば十分らしく ◦ 相対誤差は 1.04/√m であり, これがどんなもんかというと ▪ m = 1 だと真値の2倍くらいの誤った値が出る ▪ m = 100 だと, 真値±10% くらいの範囲の推定値に収まる