SlideShare a Scribd company logo
2013/1/9 統数研チャンネル	

                       _	

                _	


                 _	
         _	



 ウェーブレット⽊木の世界
            岡野原  ⼤大輔

     株式会社Preferred  Infrastructure  
          hillbig@preferred.jp
⾼高速⽂文字列列解析の世界                   宣伝
  データ圧縮・全⽂文検索索・テキストマイニング

l  岩波書店
    l  「確率率率と情報の科学」シリーズ

    l  5巻発⾏行行済, 全18巻

    l  2012/12/27 発⾏行行

l  著者:岡野原⼤大輔
l  編者:⽢甘利利俊⼀一、⿇麻⽣生英樹、伊庭幸⼈人


l    新しい⽂文字列列解析の技術を初めて解説
      l  Burrows Wheeler変換

      l  簡潔データ構造

      l    ウェーブレット⽊木(今回紹介)


                          2
アジェンダ

l    現在の⼤大規模データ解析
l    ウェーブレット⽊木の作り⽅方
l    ウェーブレット⽊木を使った解析
l    ウェーブレット⽊木の最前線
l    まとめ                            _	

                              _	


                               _	
         _	




                        3
練習問題             v[0] v[1] v[2] v[3] v[3] v[4] …
                 17     19   80   66   10   6   …



1秒毎にセンサの温度度が整数値で得られ、
時刻と温度度を記録します。計測開始から10年年
(3億秒)が経ち、様々な統計データを求めたい
とします


l  問題1:最⼤大値、最⼩小値、中央値、最頻値を求めなさい
l  問題2:77度度であった時刻を全て求めなさい
l  問題3:過去7777777番⽬目に温度度が低かった時と
        その発⽣生時刻を求めなさい


簡単ですね
                  4
より強⼒力力なクエリ                                記法:a[s,  e]  =  a[s…e]
                                            a[s,  e)  =  a[s,  e-‐‑‒1]
  範囲指定、リッチな指定
正整数列列v[0, n)が与えられたする。
この時、v[s, e)の範囲内で次のクエリを⼤大量量に処理理したい




最⼤大値、最⼩小値、 値がm以上M未 値がwであった 頻度度が⼤大きい順
中央値、最頻値 満であった回数 中でk番⽬目の位置 にk個、値と頻度度




v[0] v[1] …. v[s] v[s+1] ..         ….v[e-1] …              v[n-1]




                              5
先程の問題は
どのくらいで求められると思いますか?
l  全て定数時間で求まる
     l  データ数によらず1回のクエリあたり数マイクロ秒で求まる

l  数億〜~数⼗十億といった⾮非常に⼤大規模なデータを処理理できる
     l  値域が0<=x<264の時、4GBのメモリがあれば5億点が処理理可能

     l  先程の温度度の例例の場合、16年年分が処理理できる

l  全ての統計値を同じデータ構造を利利⽤用して求めることができる
     l  各処理理毎に特別なデータ構造を利利⽤用しなくてよい

     l  しかも元のデータ⾃自⾝身も復復元できる

l  ⾼高速に構築でき(秒間100MB弱)、データ追記も可能


      ⇒  そう、ウェーブレット⽊木ならね

                      6
現在の⼤大規模データ解析
           の背景




7
記憶階層間のギャップは⼤大きい                 https://gist.github.com/2841832
                                http://lwn.net/Articles/252125/	

操作                  ナノ秒(10-9)                  サイズ(⽬目安)
1演算(CPU 2GHz)       0.5 〜~ 10                  数⼗十 words
L1キャッシュ参照           0.5                        32KB
L2キャッシュ参照           7.0                        256KB
主記憶参照               100                        1GB 〜~ 128GB
主記憶から連続した1MBをRead   250000
HDDのシーク             10000000(=10ms)            100GB〜~10TB
HDDから連続した1MBをRead   20000000(=20ms)


記憶階層間の速度度差は10〜~100倍
上位の記憶階層で処理理することが全体の⾼高速化につながる

SSDなどは主記憶とHDDの間に⼊入ってくる

                      8
並列列化で全てが解ける訳ではない

l    ⼤大規模データに対しては分散並列列処理理は必須
       l  ⾼高スループットの読み込み、書き込み、

       l  各処理理に依存関係がない⾃自明な並列列性を持つ場合



l  しかし、計算量量がデータサイズに対して線形よりも⼤大きかったら
    並列列化は殆ど意味がない
    l  例例えば計算量量がO(n3)の場合、例例え理理想的な並列列化効率率率にでも

        10000台並べても1台の時の10倍⼤大きい問題しか扱えない
l  アルゴリズムの選択で計算量量が数⼗十/百倍違うことはザラにある


l    ちゃんとしたアルゴリズム、データ構造、分析⼿手法を使おう


                         9
⼤大規模データを扱う⼼心構え

l    良良いデータ構造(データモデル)+ 良良いアルゴリズム
       l  省省スペース:より上位の記憶階層に載るように, せめて線形

       l  ⾼高速:データサイズnに依存しない、定数、せめて線形

       l  この選択で百倍から1万倍の差がでてきてもおかしくない



l    それから分散並列列化
      l  ⾼高可⽤用性やスケーラビリティが必須なら最初から検討

      l  分散並列列化のオーバーヘッドは⼤大きい、1台で解けるなら1台で



l    ウェーブレット⽊木は良良いデータ構造、良良いアルゴリズムです
      l    無理理と思われた多くの⼤大規模データを扱う問題が効率率率的に解ける


                           10
ウェーブレット⽊木


                 _	

          _	


           _	
         _	


11
ウェーブレット⽊木

l  整数列列(=⽂文字列列)に対するデータ構造
    l  ⼆二次元グリット、グラフ、フィンガープリントへも適⽤用可能

l  ウェーブレット⽊木の登場は⾮非常に地味    [Grossi, SODA 03]
    l  論論⽂文中の1段落落で簡単に紹介されただけで、当時は注⽬目されず

    l  数年年経ち、驚くほど多くの処理理できることがわかってきた

l  名はウェーブレットだが、ウェーブレット変換とは直接関係無い
    l  整数列列を⼤大きい値の集合、⼩小さい値の集合に再帰的にフィルタリ

        ングしていく考え⽅方は離離散ウェーブレット変換の分解に似ている




                              L	
                 H	


                      LL	
                       12	
         LH	
   HL	
         HH
ウェーブレット⽊木で何ができるのか

l    系列列データの解析
       l  これから紹介

l    全⽂文検索索(FM-index)
       l  現在最速, Burrows Wheeler変換と組み合わせる

l    ⼆二次元データの解析
l    グラフデータの解析
l    フィンガープリントの⾼高速処理理
       l  画像、グラフ(化合物)など様々な種類のデータから特徴抽出

           しフィンガープリントを作り、類似データを⾼高速検索索




                       13
実際に作ってみよう

次の整数列列を考えてみる
値の範囲は  [0…7]


  0721436725047263




               14
実際に作ってみよう

順序を保ったまま、値が[0…3]の場合左の⼦子、[4…7]の場合、右の
⼦子に振り分ける


  0721436725047263




                  15
実際に作ってみよう

順序を保ったまま、値が[0…3]の場合左の⼦子、[4…7]の場合、右の
⼦子に振り分ける


  0721436725047263
                         [0…3]の要素を振り分ける

 02132023




                  16
実際に作ってみよう

順序を保ったまま、値が[0…3]の場合左の⼦子、[4…7]の場合、右の
⼦子に振り分ける


  0721436725047263
                         [4…7]の要素を振り分ける

 02132023 74675476




                  17
実際に作ってみよう

再帰的に左側の⼦子について、[0…1]の値を左側の⼦子、[2…3]を右側
の⼦子に振り分ける


  0721436725047263
                         次に左側の⼦子を同様に
                         もっと細かく振り分ける
 02132023 74675476




                  18
実際に作ってみよう

再帰的に左側の⼦子について、[0, 1]の値を左側の⼦子、[2, 3]を右側の
⼦子に振り分ける


  0721436725047263

 02132023 74675476

 010


                    19
実際に作ってみよう

再帰的に左側の⼦子について、[0, 1]の値を左側の⼦子、[2, 3]を右側の
⼦子に振り分ける


  0721436725047263

 02132023 74675476

 010 23223


                    20
実際に作ってみよう

同様に右側の⼦子も[4…5]の値を左側の⼦子、[6…7]を右側の⼦子に振り
分ける


  0721436725047263

 02132023 74675476

 010 23223 454 76776


                   21
実際に作ってみよう

同じ値だけからなるまで振り分け続ける。最後は同じ値だけからなる



  0721436725047263

 02132023 74675476

 010 23223 454 76776

00 1            22
実際に作ってみよう

全て振り分けが終わる。完全⼆二分⽊木 + 各節点に整数列列が付随



  0721436725047263

 02132023 74675476

 010 23223 454 76776

00 1 222 33 44 5 66 777
                  23
実際に作ってみよう

各値がどちらの⼦子にいったかを記録するために
左の⼦子の場合0, 右の⼦子の場合1を記録する


  0721436725047263        このbitは実は
  0100101101011010        各値の最上位bitと同じ


 02132023 74675476

 010 23223 454 76776

00 1 222 33 44 5 66 777
                  24
実際に作ってみよう

各値がどちらにいったかを記録するために
左の⼦子の場合0, 右の⼦子の場合1を記録する


  0100101101011010

 02132023 74675476        各値の⼆二番⽬目のbitと同じ
 01011011 10110011

 010 23223 454 76776

00 1 222 33 44 5 66 777
                  25
ウェーブレット⽊木

完全⼆二分⽊木であり、各節点にビット列列が付随する
葉葉は各値に対応し、内部節点は⼦子孫の葉葉の範囲に対応する


  0100101101011010               [0, 7]に対応

                                 [4, 7]に対応
    01011011 10110011

                                 [6, 7]に対応
 010 01001 010 10110
                                 [4, 5]に対応

0    1   2   3   4   5   6   7
ウェーブレット⽊木の特徴

l  整数列列の⻑⾧長さがn, 値域が[0, s)とする
l  特徴1:⽊木の⾼高さは  log2 s
l  特徴2:サイズはn log2 s bitであり元の整数列列のサイズと同じ
    l  ウェーブレット⽊木はビットを並び替えていると考えられる

l  特徴3:構築はO(n log2 s)時間、2 n log2 s ビットで可能
    l  先程の通り⽂文字を振り分け、各節点のビットを順に決定すれば良良い




             L	
                 H	
                                              木の高さは log2 s	
      LL	
         LH	
   HL	
         HH	
                                               27
ウェーブレット⽊木に慣れる練習


練習1:整数列列の最初の値は何か?


  0100101101011010   最初の値は0なので左の子に存在	



    01011011         最初の値は0なので左の子に存在	



 010                 最初の値は0なので左の子に存在	

                     0	
0
ウェーブレット⽊木に慣れる練習


練習2:9番⽬目の値は何かを求める

                     9番目の値は1
  0100101101011010   1の中では5番目
                     
                     5番目の値は0
          10110011   0の中では2番目
                     
                     2番目の値は1
          010        1の中では1番目
                     
                     値は5
                5
完備辞書




30
完備辞書 (FID: Fully Indexable Dictionary)

l    ウェーブレット⽊木のビット列列上で⾃自由⾃自在に動きまわりたい


l    ビット列列 B[0…n)に対し次の操作を備えたを完備辞書(FID)と呼ぶ
      l  rankb(B, pos) : B[0…pos)中のbの出現回数を返す

      l  selectb(B, ind) : (ind+1)番⽬目のbの出現位置を返す



                                      rank1(6) = 2
i 0123456789                     B[0, 6)中に1は2回出現
B 0100101101
                                     select0(4) = 8
                                 (4+1)番⽬目の0は8で出現

                          31
完備辞書の簡単な事実(スキップ)

l  RankとSelectは逆関数みたい  
     l  rankb(selectb(ind)) = ind

     l  selectb(rankb(pos)) <= pos

l  rank1(pos) + rank0(pos) = pos
l  pos = select1(ind) の時、rank1(pos) = ind-1, rank1(pos+1) = ind


l    完備辞書の多くの簡潔データ構造の基本として使われる
      l  集合の表現

      l  ⾮非負整数列列の表現



l    ウェーブレット⽊木でも節点中の位置を調べる際に使う
      l  先程の”9番⽬目の値は1の中では5番⽬目」はrank1(B,  9)  =  5

                               32
完備辞書:密な場合

l    n + o(n) bitを⽤用いて, rank, selectをO(1)時間で実現できる
       l  現実的には1.3n bitで、rankをO(1)時間、

           selectをO(log log n)時間で実現


l    典型的な作り⽅方
      l  ビット列列を適当な⼤大きさのブロックに分割し、

          各ブロックの先頭のrankを記録
      l  rankを求める時は、ブロックの先頭のrankを表引きで求め

          残りをpopcount関数(次項)で求める


l    疎な場合、ばらつきがある場合は⾼高速⽂文字列列本を参照してください


                             33
例例:PopCount (x)
64bit code中の1の数を数える
uint64_t EnumCoder::PopCount(uint64_t code){
  uint64_t r = code;
  r = (r & 0x5555555555555555ULL) +
    ((r >> 1) & 0x5555555555555555ULL);
  r = (r & 0x3333333333333333ULL) +
    ((r >> 2) & 0x3333333333333333ULL);
  r = (r + (r >> 4)) & 0x0f0f0f0f0f0f0f0fULL;
  r = r + (r >> 8);
  r = r + (r >> 16);
  r = r + (r >> 32);
    return (uint64_t)(r & 0x7f);
}

                            34
各データに対する処理理




35
系列列データ(=⽂文字列列データ)

l    系列列データ    T[0, n), 0<=T[i]<s
      l  s :値域(アルファベットサイズ)

             l    DNA : 4 (ATCG), 英⽂文:100, ⽇日本語:数万,
                   ログデータ : 数百万(URL毎に違う値)
l    ウェーブレット⽊木は多くの操作を効率率率的に備える
      l  殆どの操作をデータサイズに依存しない時間でサポート

      l  例例えば  T[123456789, 987654321]の777777777番⽬目に⼤大きい

          値を探すことが数μ秒で実現可能


l    この他多くの操作を実現可能(次項)
      l    最後にkが付くものはO(k log s)時間(⼀一つずつ logs時間)
      l    残り  rangelist, intersect以外はO(log s)時間

                                       36
操作名                        説明
access(T, i)               T[i]を返す
rankc(T, i)                T[0, i) 中のcの出現数を返す
selectc(T, i)              (i+1)番⽬目のcの出現位置を返す
quantile(T, s, e, r)       T[s, e)中の(r+1)番⽬目に⼤大きい値を返す
topk(T, s, e, k)           T[s, e)中の出現数が多い値をk個返す
rangefreq(T, s, e, x, y)   T[s, e)中の  x<=c<yを満たすcの出現数を返
                           す
rangelist(T, s, e, x, y)   rangefreqで出現した値と頻度度を返す
rangemaxk(T, s, e, k)      T[s, e)中で値が⼤大きい順にk個返す
rangemink(T, s, e, k)      T[s, e)中に値が⼩小さい順にk個返す
prevvalue(T, s, e, x, y)   T[s, e)中でx<=c<yを満たす最⼤大のcを返す
nextvalue(T, s, e, x, y)   T[s, e)中でx<=c<yを満たす最⼩小のcを返す
intersect(T, s, e, u, v)   T[s, e)とT[u, v)で共通して出現する値を返す
                                   37
rank2(T, 12)
                           0123456789012345
                       T = 0721436725047263
T[0, 12) 中の2の出現数を返す	

                                   (1)  2は左側の⼦子(=0)
    0100101101011010               Rank0(B,  12)  =  6

                                   (2)  2は右側の⼦子(=1)
    01011011 10110011              Rank1(B,  6)  =  3

                                   (3)  2は左側の⼦子(=0)
 010 01001 010 10110               Rank0(B,  3)  =  2

                                       
0    1   2     3   4   5   6   7   =  2回
select2(T, 1)
                            0123456789012345
                        T = 0721436725047263
Tの(1+1)番目の2の出現位置を返す	

                                    (3)  2は左側の⼦子(=0)
    0100101101011010                select0(B,  4)  =  8

                                    (2)  2は右側の⼦子(=1)
    01011011 10110011               select1(B,  2)  =  4

                                    (1)  2は左側の⼦子(=0)
 010 01001 010 10110                select0(B,  1)  =  2
                                    
                                        
0    1   2      3   4   5   6   7
rangemaxk(T, 8, 12, 1)
                         0123456789012345
                     T = 0721436725047263
T[8, 12) の大きい順に1個返す(=最大値)	

                                 範囲内に1があるなら
  0100101101011010               右の⼦子に進む。
                                 全て0なら左の⼦子に進む

    01011011 10110011            最終的に辿りついた値が
                                 最⼤大値

                                 k個順に列列挙する場合は
 010 01001 010 10110             残りの有効な節点で同様に
                                 可能な限り右の⼦子に進めば
                                 よい
0    1   2   3   4   5   6   7
quantile(T, 4, 12, 3)
                            0123456789012345
                        T = 0721436725047263
T[4, 12)中の3番目に大きい値を返す	

                               (1) 範囲内の1の数は5個で
  0100101101011010             あり、3番⽬目に⼤大きい値は
                               1側に存在。1側に進む


                 10110011      (2) 範囲内の1の数は2個で
                               あり、3番⽬目に⼤大きい値は
                               0側に存在。1側で2個ある
                010            ので、0側の3-2=1番⽬目を
                               探す
                               (3) 範囲内の1の数は1個で
                        5      あり、1番⽬目に⼤大きい値は
                               1側に存在
rangefreq (T, st, en, min, max)


T[st,  en)中のmin以上max未満の値の出現数を報告
根からmin,  maxの葉葉までの内側の節点のヒット数を報告

                                   内側の節点数の個数は
                                   高々 2log2 s
                                   
                                   範囲、ヒット件数によらず
                                   O(log s)時間	




     min                     max
topk(T, s, e, k)

T[s,  e)中の出現数が多い値をk個返す
範囲が⼤大きい節点を優先して展開していけば良良い

                    100        queue  qs  //  優先度度が⼆二項⽬目
                               qs.push(root,  e  –  s)
          67              33   while  (true){
                                     q  =  qs.pop()
                                     if  (qが葉葉){
     17        50                            report  q;  
                                             break  if  k個⽬目
                                     }
          40        10
                                    qs.push(qの左の⼦子,  0の幅)
                                 qs.push(qの左の⼦子,  1の幅)
                               }
ウェーブレット⽊木
⼆二次元データへの利利⽤用
l    ⼆二次元中の点集合  (x1, y1), (x2, y2) … (xn, yn), xi,yi∈R
       l  xの値は全て異異なると仮定
l    矩形内[xs, xe] x [ys, ye]の点を全て報告する
           xs	
        xe	
                                       R⽊木  ?  KD⽊木  ?  
  ys	
                                   -‐‑‒>  最悪計算量量が保証されない

                                       ウェーブレット⽊木を使うと
  ye	
                                 常に圧倒的に⾼高速かつ⼤大規模
                                       データを扱える(数⼗十億点)


                                44
⼆二次元データ

l    順位空間への変換
      l  座標を、順位へ変換する(=⾃自分より⼩小さい点数)


      0	
 1	
 2	
 3	
 4	
5	
6	
 8	
                             7	
                                                 0 1 2 3 4 5 6 7
                                      0	
                                             0                         *
                                      1	
                                             1     *           *
                                      2	
                                      3	
    2             *
                                      4	
    3 *
                                      5	
    4                     *
                                      6	
    5                             *
                                      7	
    6         *
                                      45
⼆二次元データ
整数列列への変換
l    各yの値を順に並べて整数列列を作り、ウェーブレット⽊木を作る



      0 1 2 3 4 5 6 7
 0                         *
 1     *           *
 2             *                   T  =  31621405
 3 *
 4                     *
 5                             *
 6         *
⼆二次元データ
整数列列への変換
l    各yの値を順に並べて整数列列を作り、ウェーブレット⽊木を作る
l    [xs, xe] x [ys, ye] 中の点を求める
       l  クエリを順位空間  [ps, pe] x [qs, qe] に変換
       l  T[ps, pe] 中のqs以上qe未満の値を列列挙=> rangefreq/list


      0 1 2 3 4 5 6 7
 0                          *
 1      *           *                   31621405	
 2              *
 3 *                                点数によらずO(log  n)時間
 4                      *           1点あたりO(log  n)時間で報告可能
 5                              *
 6          *
ウェーブレット⽊木
グラフへの利利⽤用
l    有向グラフを考える(無向でも良良い)
      l  ループや多重辺を許す


                  各辺毎のその頂点の終点

          0       頂点          到達先の頂点
                  0           155
      1       5
                  1           24
                  2
      2       4   3           24
          3       4           1
                  5           2
                       48
グラフ

頂点   到達先の頂点        頂点リストを全てつなげて⽂文字列列作る
0    155           T = 155242412
1    24
                   各頂点リストがどこから始まっているかを
2                  完備辞書で格納
3    24            B = 100010011001010
4    1             i番⽬目の頂点番号の範囲は
5    2             B上のselect操作で定数時間でも⽌止まる


(1)   i番⽬目の頂点から向かう頂点を列列挙する  T上の連続範囲
(2)   i番⽬目の頂点へ向かう頂点を列列挙する  selecti(T,  p)

この他頂点、枝に情報を付随して様々な操作が実現可能
               49
ウェーブレット⽊木の最前線




50
ウェーブレット⾏行行列列

l    ウェーブレット⽊木の問題点:値の範囲が⼤大きい時にサイズが⼤大きい
      l  節点数 = 値の範囲-1

      l  値の範囲が[0…264-1]の場合、節点数は264-1で⾮非現実的



l    ウェーブレット⽊木とは異異なる形でのフィルタリングが可能
      l  節点を明⽰示的に管理理する必要がない

      l  表現⽅方法としてはこちらの⽅方が⾃自然で常にこちらを利利⽤用すべき?



l    最初からウェーブレット⾏行行列列を説明しておけば?
      l  ⼀一応順番に説明に




                        51
ウェーブレット⾏行行列列


 0721436725047263




               52
ウェーブレット⾏行行列列


 0721436725047263
                      1bit目が0のものを左
 0213202374675476     1であるものを右に
                      [0…3]が左、[4…7]が右	




               53
ウェーブレット⾏行行列列


 0721436725047263
 0213202374675476     2bit目が0であるのを左に
                      そうでないものを右に
 0104542322376776     
                      0, 1, 4, 5が左
                      2, 3, 6, 7が右	




               54
ウェーブレット⾏行行列列


 0721436725047263
 0213202374675476
 0104542322376776     3bit⽬目が0であるのを左に
                      そうでないものを右に
 0044222661533777
                      0,  2,  4,  6が左、
                      1,  3,  5,  7が右



               55
ウェーブレット⾏行行列列


 0721436725047263
 0213202374675476
 0104542322376776
 0044222661533777




               56
ウェーブレット⾏行行列列


0721436725047263      ウェーブレット⽊木と同じ節点が
                      存在する。
                      しかし、必ずしも⼦子が
0213202374675476      ⾃自分の直下には存在しない。

0104542322376776
0044222661533777




               57
ウェーブレット⾏行行列列


0100101101011010
                                    左と右に⾏行行った情報を元に
0101101110110011                    0と1を記録。
                                    それぞれに完備辞書を構築
                                    
0100100100110110

 0   4   2   6   1   5   3   7
                             58
ウェーブレット⾏行行列列


0100101101011010
0101101110110011
0100100100110110

 節点情報は必要ない(移動時は節点の境⽬目の位置も更更新する)
                  59	

 値の範囲が[0…s-‐‑‒1]の時、log2s  個のビット列列と、
 1の開始位置(nzd=⼀一つ上のビット列列の0の合計数)があれば良良い

 例例えば値の範囲が[0…264-‐‑‒1]の時でも、64個のビット列列と
 1の開始位置を保持するだけで良良い
rank2(T, 12)
                        0123456789012345
                    T = 0721436725047263
s    (節点の開始位置)   e    (節点の開始位置)
                               Bd : d番⽬目のbit列列
0100101101011010               nzd : Bd-1の0の数
                               s = 0, e = pos
0101101110110011               for d = 0 to log2s
                                 b = cのd番⽬目の上位bit
                                 s = rankb(Bd, s)
0100100100110110                 e = rankb(Bd, e)
                                 if (b == 1)
0044222661533777                   s += nzd, e += nzd
                                 end if
                               end for
最後の数は説明のために⽤用意          60	
   return e - s
ウェーブレット⽊木の圧縮

l    ウェーブレット⽊木のサイズは元のデータと同じ
      l  通常、こうしたデータ構造は元のデータ + 補助データ構造で

          あり、補助データ構造が元のデータの数倍になる場合も多い
      l  ウェーブレット⽊木は常にデータサイズが安定して同じサイズ



l    さらにデータに次のような規則性がある場合圧縮することが可能
      l  同じ値が連続して出現しやすい

      l  数値的に似た値が連続して出現しやすい

      l  値の出現数に⼤大きな偏りがある



l    さらに規則性が必要な場合はBurrows Wheeler変換を利利⽤用
      l  ⾼高速⽂文字列列本を参照してください


                         61
圧縮1:ハフマン⽊木を利利⽤用する

l  各値の頻度度に⼤大きな偏りがある場合に有効
l  各値の頻度度に基づいたハフマン⽊木を作り、それを利利⽤用して各値
    をフィルタリングする
    l  値の⼤大⼩小関係が失われてしまうので、access, rank, select, topk,

        などしか使わない場合は可能
            l    値の⼤大⼩小関係を保ったまま、全体符号⻑⾧長を最⼩小化するような⽅方法
                  も存在する
      l    ハフマン符号で符号化した時とサイズが同じになる
            l    0次経験エントロピー(本書参照)
            l    計算量量も0次経験エントロピーに
      l    ⼀一般的な英⽂文であれば2/3〜~1/2程度度


                                62
圧縮2:各ビット列列を圧縮格納する

l    値に規則性があれば、ビット列列は0や1が連続して出現しやすい
      l  各ビット列列を圧縮することで、全体の圧縮を達成可能(本書参考)



l    完備辞書の圧縮バージョンは既に無圧縮と同じ程度度の速さ
      l  RRRで圧縮してもrank/selectは秒間100万クエリ程度度は可能

      l  “rsdic” でググる



l    冗⻑⾧長性が⾼高い場合、数分の1から数⼗十分の1にできる




                          63
まとめ




64
実際につかってみる

l    ⾼高速⽂文字列列解析のサポートページにいくつか実装例例があります
       l  “⾼高速⽂文字列列解析  サポートページ”でググる

       l  完備辞書

              l    sdarray
              l    rsdic
       l    ウェーブレット⽊木
              l    wat_̲array


l    その他の利利⽤用例例(どちらも⽥田部井さん)
      l  全⽂文検索索 fmindex++ http://code.google.com/p/fmindex-plus-plus/

       l    グラフの類似検索索 gwt http://code.google.com/p/gwt/


                                      65
まとめ

l  ウェーブレット⽊木は万能のデータ構造
    l  様々な解析を⾼高速かつ省省スペースで実現

    l  系列列マイニング、全⽂文検索索、グラフ、⼆二次元情報など広い問題で

        これまでのstate-of-the-artをやぶる
    l  「それは⾮非現実的だから」といってた多くの壁がなくなる

l  まだまだ発展途上
    l  基礎:

            l    ウェーブレット⾏行行列列がでてくるように基本的な伸びしろはまだ多い
      l    応⽤用:
            l    フィンガープリントや転置ファイル、グラフ解析などでの利利⽤用
l    まだ⼀一部にしか知られていない(=チャンス!)


                               66
参考⽂文献

l  “⾼高速⽂文字列列解析の世界”, 岡野原  ⼤大輔, 岩波書店
l  “Wavele Trees for All”, G. Navarro, CPM2012
l  “The Wavelet Matrix”, F Claude, G. Navarro, SPIRE 2012
                            .




                                67

More Related Content

ウェーブレット木の世界

  • 1. 2013/1/9 統数研チャンネル _ _ _ _ ウェーブレット⽊木の世界 岡野原  ⼤大輔 株式会社Preferred  Infrastructure   [email protected]
  • 2. ⾼高速⽂文字列列解析の世界 宣伝   データ圧縮・全⽂文検索索・テキストマイニング l  岩波書店 l  「確率率率と情報の科学」シリーズ l  5巻発⾏行行済, 全18巻 l  2012/12/27 発⾏行行 l  著者:岡野原⼤大輔 l  編者:⽢甘利利俊⼀一、⿇麻⽣生英樹、伊庭幸⼈人 l  新しい⽂文字列列解析の技術を初めて解説 l  Burrows Wheeler変換 l  簡潔データ構造 l  ウェーブレット⽊木(今回紹介) 2
  • 3. アジェンダ l  現在の⼤大規模データ解析 l  ウェーブレット⽊木の作り⽅方 l  ウェーブレット⽊木を使った解析 l  ウェーブレット⽊木の最前線 l  まとめ _ _ _ _ 3
  • 4. 練習問題 v[0] v[1] v[2] v[3] v[3] v[4] … 17 19 80 66 10 6 … 1秒毎にセンサの温度度が整数値で得られ、 時刻と温度度を記録します。計測開始から10年年 (3億秒)が経ち、様々な統計データを求めたい とします l  問題1:最⼤大値、最⼩小値、中央値、最頻値を求めなさい l  問題2:77度度であった時刻を全て求めなさい l  問題3:過去7777777番⽬目に温度度が低かった時と その発⽣生時刻を求めなさい 簡単ですね 4
  • 5. より強⼒力力なクエリ 記法:a[s,  e]  =  a[s…e] a[s,  e)  =  a[s,  e-‐‑‒1]   範囲指定、リッチな指定 正整数列列v[0, n)が与えられたする。 この時、v[s, e)の範囲内で次のクエリを⼤大量量に処理理したい 最⼤大値、最⼩小値、 値がm以上M未 値がwであった 頻度度が⼤大きい順 中央値、最頻値 満であった回数 中でk番⽬目の位置 にk個、値と頻度度 v[0] v[1] …. v[s] v[s+1] .. ….v[e-1] … v[n-1] 5
  • 6. 先程の問題は どのくらいで求められると思いますか? l  全て定数時間で求まる l  データ数によらず1回のクエリあたり数マイクロ秒で求まる l  数億〜~数⼗十億といった⾮非常に⼤大規模なデータを処理理できる l  値域が0<=x<264の時、4GBのメモリがあれば5億点が処理理可能 l  先程の温度度の例例の場合、16年年分が処理理できる l  全ての統計値を同じデータ構造を利利⽤用して求めることができる l  各処理理毎に特別なデータ構造を利利⽤用しなくてよい l  しかも元のデータ⾃自⾝身も復復元できる l  ⾼高速に構築でき(秒間100MB弱)、データ追記も可能 ⇒  そう、ウェーブレット⽊木ならね 6
  • 8. 記憶階層間のギャップは⼤大きい https://gist.github.com/2841832 http://lwn.net/Articles/252125/ 操作 ナノ秒(10-9) サイズ(⽬目安) 1演算(CPU 2GHz) 0.5 〜~ 10 数⼗十 words L1キャッシュ参照 0.5 32KB L2キャッシュ参照 7.0 256KB 主記憶参照 100 1GB 〜~ 128GB 主記憶から連続した1MBをRead 250000 HDDのシーク 10000000(=10ms) 100GB〜~10TB HDDから連続した1MBをRead 20000000(=20ms) 記憶階層間の速度度差は10〜~100倍 上位の記憶階層で処理理することが全体の⾼高速化につながる SSDなどは主記憶とHDDの間に⼊入ってくる 8
  • 9. 並列列化で全てが解ける訳ではない l  ⼤大規模データに対しては分散並列列処理理は必須 l  ⾼高スループットの読み込み、書き込み、 l  各処理理に依存関係がない⾃自明な並列列性を持つ場合 l  しかし、計算量量がデータサイズに対して線形よりも⼤大きかったら 並列列化は殆ど意味がない l  例例えば計算量量がO(n3)の場合、例例え理理想的な並列列化効率率率にでも 10000台並べても1台の時の10倍⼤大きい問題しか扱えない l  アルゴリズムの選択で計算量量が数⼗十/百倍違うことはザラにある l  ちゃんとしたアルゴリズム、データ構造、分析⼿手法を使おう 9
  • 10. ⼤大規模データを扱う⼼心構え l  良良いデータ構造(データモデル)+ 良良いアルゴリズム l  省省スペース:より上位の記憶階層に載るように, せめて線形 l  ⾼高速:データサイズnに依存しない、定数、せめて線形 l  この選択で百倍から1万倍の差がでてきてもおかしくない l  それから分散並列列化 l  ⾼高可⽤用性やスケーラビリティが必須なら最初から検討 l  分散並列列化のオーバーヘッドは⼤大きい、1台で解けるなら1台で l  ウェーブレット⽊木は良良いデータ構造、良良いアルゴリズムです l  無理理と思われた多くの⼤大規模データを扱う問題が効率率率的に解ける 10
  • 12. ウェーブレット⽊木 l  整数列列(=⽂文字列列)に対するデータ構造 l  ⼆二次元グリット、グラフ、フィンガープリントへも適⽤用可能 l  ウェーブレット⽊木の登場は⾮非常に地味    [Grossi, SODA 03] l  論論⽂文中の1段落落で簡単に紹介されただけで、当時は注⽬目されず l  数年年経ち、驚くほど多くの処理理できることがわかってきた l  名はウェーブレットだが、ウェーブレット変換とは直接関係無い l  整数列列を⼤大きい値の集合、⼩小さい値の集合に再帰的にフィルタリ ングしていく考え⽅方は離離散ウェーブレット変換の分解に似ている L H LL 12 LH HL HH
  • 13. ウェーブレット⽊木で何ができるのか l  系列列データの解析 l  これから紹介 l  全⽂文検索索(FM-index) l  現在最速, Burrows Wheeler変換と組み合わせる l  ⼆二次元データの解析 l  グラフデータの解析 l  フィンガープリントの⾼高速処理理 l  画像、グラフ(化合物)など様々な種類のデータから特徴抽出 しフィンガープリントを作り、類似データを⾼高速検索索 13
  • 23. 実際に作ってみよう 全て振り分けが終わる。完全⼆二分⽊木 + 各節点に整数列列が付随 0721436725047263 02132023 74675476 010 23223 454 76776 00 1 222 33 44 5 66 777 23
  • 24. 実際に作ってみよう 各値がどちらの⼦子にいったかを記録するために 左の⼦子の場合0, 右の⼦子の場合1を記録する 0721436725047263 このbitは実は 0100101101011010 各値の最上位bitと同じ 02132023 74675476 010 23223 454 76776 00 1 222 33 44 5 66 777 24
  • 27. ウェーブレット⽊木の特徴 l  整数列列の⻑⾧長さがn, 値域が[0, s)とする l  特徴1:⽊木の⾼高さは  log2 s l  特徴2:サイズはn log2 s bitであり元の整数列列のサイズと同じ l  ウェーブレット⽊木はビットを並び替えていると考えられる l  特徴3:構築はO(n log2 s)時間、2 n log2 s ビットで可能 l  先程の通り⽂文字を振り分け、各節点のビットを順に決定すれば良良い L H 木の高さは log2 s LL LH HL HH 27
  • 28. ウェーブレット⽊木に慣れる練習 練習1:整数列列の最初の値は何か?   0100101101011010 最初の値は0なので左の子に存在 01011011 最初の値は0なので左の子に存在 010 最初の値は0なので左の子に存在 0 0
  • 29. ウェーブレット⽊木に慣れる練習 練習2:9番⽬目の値は何かを求める 9番目の値は1   0100101101011010 1の中では5番目 5番目の値は0 10110011 0の中では2番目 2番目の値は1 010 1の中では1番目 値は5 5
  • 31. 完備辞書 (FID: Fully Indexable Dictionary) l  ウェーブレット⽊木のビット列列上で⾃自由⾃自在に動きまわりたい l  ビット列列 B[0…n)に対し次の操作を備えたを完備辞書(FID)と呼ぶ l  rankb(B, pos) : B[0…pos)中のbの出現回数を返す l  selectb(B, ind) : (ind+1)番⽬目のbの出現位置を返す rank1(6) = 2 i 0123456789 B[0, 6)中に1は2回出現 B 0100101101 select0(4) = 8 (4+1)番⽬目の0は8で出現 31
  • 32. 完備辞書の簡単な事実(スキップ) l  RankとSelectは逆関数みたい   l  rankb(selectb(ind)) = ind l  selectb(rankb(pos)) <= pos l  rank1(pos) + rank0(pos) = pos l  pos = select1(ind) の時、rank1(pos) = ind-1, rank1(pos+1) = ind l  完備辞書の多くの簡潔データ構造の基本として使われる l  集合の表現 l  ⾮非負整数列列の表現 l  ウェーブレット⽊木でも節点中の位置を調べる際に使う l  先程の”9番⽬目の値は1の中では5番⽬目」はrank1(B,  9)  =  5 32
  • 33. 完備辞書:密な場合 l  n + o(n) bitを⽤用いて, rank, selectをO(1)時間で実現できる l  現実的には1.3n bitで、rankをO(1)時間、 selectをO(log log n)時間で実現 l  典型的な作り⽅方 l  ビット列列を適当な⼤大きさのブロックに分割し、 各ブロックの先頭のrankを記録 l  rankを求める時は、ブロックの先頭のrankを表引きで求め 残りをpopcount関数(次項)で求める l  疎な場合、ばらつきがある場合は⾼高速⽂文字列列本を参照してください 33
  • 34. 例例:PopCount (x) 64bit code中の1の数を数える uint64_t EnumCoder::PopCount(uint64_t code){ uint64_t r = code; r = (r & 0x5555555555555555ULL) + ((r >> 1) & 0x5555555555555555ULL); r = (r & 0x3333333333333333ULL) + ((r >> 2) & 0x3333333333333333ULL); r = (r + (r >> 4)) & 0x0f0f0f0f0f0f0f0fULL; r = r + (r >> 8); r = r + (r >> 16); r = r + (r >> 32); return (uint64_t)(r & 0x7f); } 34
  • 36. 系列列データ(=⽂文字列列データ) l  系列列データ    T[0, n), 0<=T[i]<s l  s :値域(アルファベットサイズ) l  DNA : 4 (ATCG), 英⽂文:100, ⽇日本語:数万, ログデータ : 数百万(URL毎に違う値) l  ウェーブレット⽊木は多くの操作を効率率率的に備える l  殆どの操作をデータサイズに依存しない時間でサポート l  例例えば  T[123456789, 987654321]の777777777番⽬目に⼤大きい 値を探すことが数μ秒で実現可能 l  この他多くの操作を実現可能(次項) l  最後にkが付くものはO(k log s)時間(⼀一つずつ logs時間) l  残り  rangelist, intersect以外はO(log s)時間 36
  • 37. 操作名 説明 access(T, i) T[i]を返す rankc(T, i) T[0, i) 中のcの出現数を返す selectc(T, i) (i+1)番⽬目のcの出現位置を返す quantile(T, s, e, r) T[s, e)中の(r+1)番⽬目に⼤大きい値を返す topk(T, s, e, k) T[s, e)中の出現数が多い値をk個返す rangefreq(T, s, e, x, y) T[s, e)中の  x<=c<yを満たすcの出現数を返 す rangelist(T, s, e, x, y) rangefreqで出現した値と頻度度を返す rangemaxk(T, s, e, k) T[s, e)中で値が⼤大きい順にk個返す rangemink(T, s, e, k) T[s, e)中に値が⼩小さい順にk個返す prevvalue(T, s, e, x, y) T[s, e)中でx<=c<yを満たす最⼤大のcを返す nextvalue(T, s, e, x, y) T[s, e)中でx<=c<yを満たす最⼩小のcを返す intersect(T, s, e, u, v) T[s, e)とT[u, v)で共通して出現する値を返す 37
  • 38. rank2(T, 12) 0123456789012345 T = 0721436725047263 T[0, 12) 中の2の出現数を返す (1)  2は左側の⼦子(=0) 0100101101011010 Rank0(B,  12)  =  6 (2)  2は右側の⼦子(=1) 01011011 10110011 Rank1(B,  6)  =  3 (3)  2は左側の⼦子(=0) 010 01001 010 10110 Rank0(B,  3)  =  2     0 1 2 3 4 5 6 7 =  2回
  • 39. select2(T, 1) 0123456789012345 T = 0721436725047263 Tの(1+1)番目の2の出現位置を返す (3)  2は左側の⼦子(=0) 0100101101011010 select0(B,  4)  =  8 (2)  2は右側の⼦子(=1) 01011011 10110011 select1(B,  2)  =  4 (1)  2は左側の⼦子(=0) 010 01001 010 10110 select0(B,  1)  =  2 0 1 2 3 4 5 6 7
  • 40. rangemaxk(T, 8, 12, 1) 0123456789012345 T = 0721436725047263 T[8, 12) の大きい順に1個返す(=最大値) 範囲内に1があるなら   0100101101011010 右の⼦子に進む。 全て0なら左の⼦子に進む 01011011 10110011 最終的に辿りついた値が 最⼤大値 k個順に列列挙する場合は 010 01001 010 10110 残りの有効な節点で同様に 可能な限り右の⼦子に進めば よい 0 1 2 3 4 5 6 7
  • 41. quantile(T, 4, 12, 3) 0123456789012345 T = 0721436725047263 T[4, 12)中の3番目に大きい値を返す (1) 範囲内の1の数は5個で   0100101101011010 あり、3番⽬目に⼤大きい値は 1側に存在。1側に進む 10110011 (2) 範囲内の1の数は2個で あり、3番⽬目に⼤大きい値は 0側に存在。1側で2個ある 010 ので、0側の3-2=1番⽬目を 探す (3) 範囲内の1の数は1個で 5 あり、1番⽬目に⼤大きい値は 1側に存在
  • 42. rangefreq (T, st, en, min, max) T[st,  en)中のmin以上max未満の値の出現数を報告 根からmin,  maxの葉葉までの内側の節点のヒット数を報告    内側の節点数の個数は 高々 2log2 s 範囲、ヒット件数によらず O(log s)時間 min max
  • 43. topk(T, s, e, k) T[s,  e)中の出現数が多い値をk個返す 範囲が⼤大きい節点を優先して展開していけば良良い    100 queue  qs  //  優先度度が⼆二項⽬目 qs.push(root,  e  –  s) 67 33 while  (true){      q  =  qs.pop()      if  (qが葉葉){ 17 50              report  q;                break  if  k個⽬目      } 40 10    qs.push(qの左の⼦子,  0の幅)   qs.push(qの左の⼦子,  1の幅) }
  • 44. ウェーブレット⽊木 ⼆二次元データへの利利⽤用 l  ⼆二次元中の点集合  (x1, y1), (x2, y2) … (xn, yn), xi,yi∈R l  xの値は全て異異なると仮定 l  矩形内[xs, xe] x [ys, ye]の点を全て報告する xs xe R⽊木  ?  KD⽊木  ?   ys  -‐‑‒>  最悪計算量量が保証されない ウェーブレット⽊木を使うと ye 常に圧倒的に⾼高速かつ⼤大規模 データを扱える(数⼗十億点) 44
  • 45. ⼆二次元データ l  順位空間への変換 l  座標を、順位へ変換する(=⾃自分より⼩小さい点数) 0 1 2 3 4 5 6 8 7 0 1 2 3 4 5 6 7 0 0 * 1 1 * * 2 3 2 * 4 3 * 5 4 * 6 5 * 7 6 * 45
  • 46. ⼆二次元データ 整数列列への変換 l  各yの値を順に並べて整数列列を作り、ウェーブレット⽊木を作る 0 1 2 3 4 5 6 7 0 * 1 * * 2 * T  =  31621405 3 * 4 * 5 * 6 *
  • 47. ⼆二次元データ 整数列列への変換 l  各yの値を順に並べて整数列列を作り、ウェーブレット⽊木を作る l  [xs, xe] x [ys, ye] 中の点を求める l  クエリを順位空間  [ps, pe] x [qs, qe] に変換 l  T[ps, pe] 中のqs以上qe未満の値を列列挙=> rangefreq/list 0 1 2 3 4 5 6 7 0 * 1 * * 31621405 2 * 3 * 点数によらずO(log  n)時間 4 * 1点あたりO(log  n)時間で報告可能 5 * 6 *
  • 48. ウェーブレット⽊木 グラフへの利利⽤用 l  有向グラフを考える(無向でも良良い) l  ループや多重辺を許す 各辺毎のその頂点の終点 0 頂点 到達先の頂点 0 155 1 5 1 24 2 2 4 3 24 3 4 1 5 2 48
  • 49. グラフ 頂点 到達先の頂点 頂点リストを全てつなげて⽂文字列列作る 0 155 T = 155242412 1 24 各頂点リストがどこから始まっているかを 2 完備辞書で格納 3 24 B = 100010011001010 4 1 i番⽬目の頂点番号の範囲は 5 2 B上のselect操作で定数時間でも⽌止まる (1)   i番⽬目の頂点から向かう頂点を列列挙する  T上の連続範囲 (2)   i番⽬目の頂点へ向かう頂点を列列挙する  selecti(T,  p) この他頂点、枝に情報を付随して様々な操作が実現可能 49
  • 51. ウェーブレット⾏行行列列 l  ウェーブレット⽊木の問題点:値の範囲が⼤大きい時にサイズが⼤大きい l  節点数 = 値の範囲-1 l  値の範囲が[0…264-1]の場合、節点数は264-1で⾮非現実的 l  ウェーブレット⽊木とは異異なる形でのフィルタリングが可能 l  節点を明⽰示的に管理理する必要がない l  表現⽅方法としてはこちらの⽅方が⾃自然で常にこちらを利利⽤用すべき? l  最初からウェーブレット⾏行行列列を説明しておけば? l  ⼀一応順番に説明に 51
  • 53. ウェーブレット⾏行行列列 0721436725047263 1bit目が0のものを左 0213202374675476 1であるものを右に [0…3]が左、[4…7]が右 53
  • 54. ウェーブレット⾏行行列列 0721436725047263 0213202374675476 2bit目が0であるのを左に そうでないものを右に 0104542322376776 0, 1, 4, 5が左 2, 3, 6, 7が右 54
  • 55. ウェーブレット⾏行行列列 0721436725047263 0213202374675476 0104542322376776 3bit⽬目が0であるのを左に そうでないものを右に 0044222661533777 0,  2,  4,  6が左、 1,  3,  5,  7が右 55
  • 57. ウェーブレット⾏行行列列 0721436725047263 ウェーブレット⽊木と同じ節点が 存在する。 しかし、必ずしも⼦子が 0213202374675476 ⾃自分の直下には存在しない。 0104542322376776 0044222661533777 57
  • 58. ウェーブレット⾏行行列列 0100101101011010 左と右に⾏行行った情報を元に 0101101110110011 0と1を記録。 それぞれに完備辞書を構築 0100100100110110 0 4 2 6 1 5 3 7 58
  • 59. ウェーブレット⾏行行列列 0100101101011010 0101101110110011 0100100100110110 節点情報は必要ない(移動時は節点の境⽬目の位置も更更新する) 59 値の範囲が[0…s-‐‑‒1]の時、log2s  個のビット列列と、 1の開始位置(nzd=⼀一つ上のビット列列の0の合計数)があれば良良い 例例えば値の範囲が[0…264-‐‑‒1]の時でも、64個のビット列列と 1の開始位置を保持するだけで良良い
  • 60. rank2(T, 12) 0123456789012345 T = 0721436725047263 s    (節点の開始位置) e    (節点の開始位置) Bd : d番⽬目のbit列列 0100101101011010 nzd : Bd-1の0の数 s = 0, e = pos 0101101110110011 for d = 0 to log2s b = cのd番⽬目の上位bit s = rankb(Bd, s) 0100100100110110 e = rankb(Bd, e) if (b == 1) 0044222661533777 s += nzd, e += nzd end if end for 最後の数は説明のために⽤用意 60 return e - s
  • 61. ウェーブレット⽊木の圧縮 l  ウェーブレット⽊木のサイズは元のデータと同じ l  通常、こうしたデータ構造は元のデータ + 補助データ構造で あり、補助データ構造が元のデータの数倍になる場合も多い l  ウェーブレット⽊木は常にデータサイズが安定して同じサイズ l  さらにデータに次のような規則性がある場合圧縮することが可能 l  同じ値が連続して出現しやすい l  数値的に似た値が連続して出現しやすい l  値の出現数に⼤大きな偏りがある l  さらに規則性が必要な場合はBurrows Wheeler変換を利利⽤用 l  ⾼高速⽂文字列列本を参照してください 61
  • 62. 圧縮1:ハフマン⽊木を利利⽤用する l  各値の頻度度に⼤大きな偏りがある場合に有効 l  各値の頻度度に基づいたハフマン⽊木を作り、それを利利⽤用して各値 をフィルタリングする l  値の⼤大⼩小関係が失われてしまうので、access, rank, select, topk, などしか使わない場合は可能 l  値の⼤大⼩小関係を保ったまま、全体符号⻑⾧長を最⼩小化するような⽅方法 も存在する l  ハフマン符号で符号化した時とサイズが同じになる l  0次経験エントロピー(本書参照) l  計算量量も0次経験エントロピーに l  ⼀一般的な英⽂文であれば2/3〜~1/2程度度 62
  • 63. 圧縮2:各ビット列列を圧縮格納する l  値に規則性があれば、ビット列列は0や1が連続して出現しやすい l  各ビット列列を圧縮することで、全体の圧縮を達成可能(本書参考) l  完備辞書の圧縮バージョンは既に無圧縮と同じ程度度の速さ l  RRRで圧縮してもrank/selectは秒間100万クエリ程度度は可能 l  “rsdic” でググる l  冗⻑⾧長性が⾼高い場合、数分の1から数⼗十分の1にできる 63
  • 65. 実際につかってみる l  ⾼高速⽂文字列列解析のサポートページにいくつか実装例例があります l  “⾼高速⽂文字列列解析  サポートページ”でググる l  完備辞書 l  sdarray l  rsdic l  ウェーブレット⽊木 l  wat_̲array l  その他の利利⽤用例例(どちらも⽥田部井さん) l  全⽂文検索索 fmindex++ http://code.google.com/p/fmindex-plus-plus/ l  グラフの類似検索索 gwt http://code.google.com/p/gwt/ 65
  • 66. まとめ l  ウェーブレット⽊木は万能のデータ構造 l  様々な解析を⾼高速かつ省省スペースで実現 l  系列列マイニング、全⽂文検索索、グラフ、⼆二次元情報など広い問題で これまでのstate-of-the-artをやぶる l  「それは⾮非現実的だから」といってた多くの壁がなくなる l  まだまだ発展途上 l  基礎: l  ウェーブレット⾏行行列列がでてくるように基本的な伸びしろはまだ多い l  応⽤用: l  フィンガープリントや転置ファイル、グラフ解析などでの利利⽤用 l  まだ⼀一部にしか知られていない(=チャンス!) 66
  • 67. 参考⽂文献 l  “⾼高速⽂文字列列解析の世界”, 岡野原  ⼤大輔, 岩波書店 l  “Wavele Trees for All”, G. Navarro, CPM2012 l  “The Wavelet Matrix”, F Claude, G. Navarro, SPIRE 2012 . 67