ホーム
採用情報
テックレポート - TechReport
テックレポート詳細
テックレポート - TechReport
wavelet行列で高速な「もしかして友だち?」検索
執筆者
- 執筆者:
- 井上ゆり
- 所属部署:
- アドテク本部 アドテクスタジオ
- 業務経歴:
- Sierでのソフトウェア開発・大手メディアでのサービス運用を経て2012年サイバーエージェント入社。
アメーバ事業本部コミュニティサービスの開発責任者を経て、現在はアドテクスタジオで広告配信技術に注力。
好きな分野はグラフ探索とチューリングマシン。
概要
ソーシャルサービスでは、ユーザ間のつながりやユーザ同士の類似性がとても重要です。
つながりの近いユーザや自分と似ているユーザを「もしかして友だち?」とサジェストすることでユーザ間のつながりを伸展させることができます。
そこで、ユーザの「つながり」具合が似ているユーザを「友だちかもしれないユーザ」としてサジェストを行うことを考えました。
しかし「つながり」のデータというのはユーザ数のベキ乗であるため、容量が大きくなりやすい性質があります。
即ち、「つながり」類似度の算出には時間がかかる、ということです。
この「つながり」類似度算出を高速に行うため、ウェーブレット行列をインデックスとして使ったシステムを提案致します。
補足
本レポートで使用するプログラムコードはすべてscalaで記述しました。
requirement >= scala2.10
目次
1. ウェーブレット行列とは
ウェーブレット行列は計算量が定数時間のrank, selectなどをサポートする簡潔データ構造です。
「ウェーブレット行列とは」を説明することはこのレポートの趣旨ではないので、詳細は下記のスライドをご参照ください。
2. システム概要
本レポートで提案するシステムは、
- ユーザ間のリレーションデータからwavelet行列インデックスを作成
- wavelet行列インデックスから類似度検索
を主軸とします。
2-1. システム概要図
下記に検索システムの概要図を掲載します。
-
リレーションデータストア:ノード間のリレーション(フォロー/フォロワーなど)を保持しているデータストアです。
- これらのデータはRDBに保持されていることもあればKVSに保持されていることもあるでしょう。APIから取得するケースも考えられます。
- wavelet行列データストア:wavelet行列を格納するためのデータストアです。
2-2. データモデル
下記にリレーションデータのデータモデル例とwavelet行列のデータモデルを表示します。
リレーションデータモデルは一例です。上記と同じ形である必要はありません。
2-3. JSON例
上記のwavelet行列データモデルをJSON形式であらわした例を記します。
{"wavelet" : [ |
{"node_attributes" : { |
{"index_attributes" : { |
3. インデクシング
先に記述したとおり、ウェーブレット行列を検索に用いるためにはウェーブレット行列のインデックスを作成する必要があります。
3-1. ウェーブレット行列インデックスの作成
ユーザをノード、つながりをリレーションとしたグラフからウェーブレット行列を作成します。
3-1-1. インデックス作成フロー
1. エッジの終点ノードをすべてbit表現に変換します。
2. 1で作成した全ノードの最上位ビットを1つの配列に格納し、ウェーブレット行列の行0とします。
上図の赤枠で囲まれたビット配列をウェーブレット行列の行0に格納します。
{"wavelet" : [The Wavelet Matrix|http://www.dcc.uchile.cl/~gnavarr/ps/spire12.4.pdf] |
3. 最上位ビットが0だったノードの次ビットを順番に別の配列に格納します。(順番は保持したまま)
上図の下表の赤枠で囲まれたビット配列をウェーブレット行列の行1に先頭から格納します。
4. つづけて最上位ビットが1だったノードの次ビットを3の配列に追加します。(順番は保持したまま)
上図の下表の赤枠で囲まれたビット配列をウェーブレット行列の行1の末尾に追加します。
5. これを終わりまで繰り返します。
要は基数ソートです。
6. 最後に、それぞれのビットレベルのゼロの個数を保持しておきます。
これでウェーブレット行列インデックスの完成です。
3-2. ウェーブレット行列インデックスのデータ容量
ウェーブレット行列インデックスが必要とするデータ容量は下記の通りであることがわかっています。
n log σ
n: リレーション数
σ: ビット長
ビット長が十分に大きければ(≒即ちノード数が多いということ)、リレーション数と同程度になります。
3-3. ウェーブレット行列インデックス作成の実装例
package ly.inoueyu.wavelet |
4. 検索基本操作のオーダー
4-1. 出現数を返すrank
出現数が多い終端ノード≒人気のあるノードということになります。
通常の場合、データサイズが大きくなるとサイズに比例した時間がかかりますが、ウェーブレット行列を使うと、
rankn = Rl[[i/l]]+Rs[[i/l]]+popcount(u/[i/u], i mod u)
として計算することができ
Rl, Rs, popcountはnの準線形であることから、計算量は
O( n )
となります。
4-1-1. rankの実装例
package ly.inoueyu.wavelet |
4-2. 最初に出現するものを返すselect
rankを反対にたどるとselectが実現できます。
よってselectの計算量も
O( n ) -> O( 1 )
となります。
4-3. 共通して出現するものと頻度を返すintersect
あるユーザと別のユーザの共通リレーションがわかれば、どれだけつながり具合が似ているか算出することができます。
intersectの計算時間は、rankによる範囲の切り取り操作と二分木の枝刈り操作のため
- K:ノードの最大ビット長
- N:リレーション数
としたとき、
intersectn = O( K log N )
として計算できます。
いずれも極めて高速です。
5. まとめ
ソーシャルグラフの重要性がこんなに提起されているのに、そのグラフデータ及び探索に関するデファクト・スタンダードが出ていないという現実があります。
それは、ソーシャルグラフの起源自体が比較的新しいこともありますが、データサイズが膨らみやすいことやRDBとの親和性観点から採用が難しいという側面があることが考えられます。
本レポートで提出した類似度検索システムはまだまだ途上ですが、
-
ウェーブレット行列のインデックスサイズが比較的コンパクトであること
n log σ - インデックス構造が簡潔なため格納場所を選ばないこと
- なんといっても高速な検索操作
-
辞書さえ作ってしまえば各操作の実装はかんたん
からユーザ類似度に基づく高速サジェストに効果を出せるのではないかと思います。
このレポートでは述べていないのですが、下記の論文で示されているように、ウェーブレット行列でグラフの類似度検索の拡張まで行えば、よりバリエーションにとんだサジェストを行うこともできます。
Weisfeiler-Lehman graph kernels
6. 謝辞 ~ごめんなさい<(_ _)>
本レポートの最大の欠陥は、「高速」を唱っていながら実証結果を提示していないことです。
残念ながら、時間的な都合で十分大量なデータを用いての実証サンプルを得ることができませんでした。
理論的な計算量を提示したのみにとどめています。
また、掲載したプログラムコードにおいては、再帰処理を多用しているため、
スタック・オーバーフローの危険性が潜在しています。
これらのプログラム改善及び時間の計測は本レポートと関係なく進める所存です。
7. 参考文献
- 高速文字列解析の世界 -データ圧縮・全文検索・テキストマイニング 岡野原 大輔
- ウェーブレット木によるバイナリコードの高速検索 田部井 靖生 津田 宏治 IBISML2011-15
- ウェーブレット木の世界 http://www.slideshare.net/pfi/ss-15916040?ref=http://research.preferred.jp/2013/01/wavelettree_world/
- The Wavelet Matrix Francisco Claude1 and Gonzalo Navarro2;http://www.dcc.uchile.cl/~gnavarro/ps/spire12.4.pdf
- Weisfeiler-Lehman graph kernels http://www.mpi-inf.mpg.de/~mehlhorn/ftp/genWLpaper.pdf
- SDM2011でwavelet木を用いた大規模グラフデータベースの高速類似度検索手法について発表しましたhttp://d.hatena.ne.jp/tb_yasu/20110509/1304934628
- 中学生にもわかるウェーブレット行列 http://d.hatena.ne.jp/takeda25/20130303/1362301095