2011年2月28日月曜日

Incremental PageRank , スケールの話

(20110301 Tue. 追記)
ページランクを正しく求める方法では、反復計算の初期値によらずただ一つのページランク(固有ベクトル)に収束するのだから、「頂点の削除」を扱わないのならば、
・元々あった頂点 ⇒ 値を変更しない
・新たに追加された頂点 ⇒ 初期値0 (id=0の頂点のみ初期値1)
で計算すれば、べき乗法で、ページランクの総和が1になるやり方でも、正しくページランクが求まるはず。

ただし、総和が1になるやり方では、ランダムジャンプの遷移によるページランクの値が
(1-c)/n となり、このnの値が変わるので、計算が収束した頂点も結局計算しなおす必要が生じるかもしれない。

そもそも、どこにもリンクしていないページの存在を正しく扱うと、そのページからは必ずランダムジャンプを行うように扱う必要が生じるため、
そのような頂点が発生すると、計算が収束した頂点のページランクにも影響が生じるので結局計算しなおす必要があるのかも?
(どこにもリンクしていない頂点が少ない(and,or)ページランクが小さい場合であれば、それによるページランクへの影響は多くの場合スレッショルド未満かもしれないが)

収束判定 (総和が1の場合) : abs(PR_new-PR_old)/PR_old < threashold (where threashold = 0.001)
Adaptive PageRankでのやり方

(20110228 Mon.)

Incremental PageRankについて、前回の全体ミーティングで、前のスライドのスケールのやり方では各ページのページランクの総和を取っても 1 にならない、と雁瀬君から指摘を受けましたが、その後、雁瀬君との議論により、総和が 1 になるようなスケールの仕方(というか、直接的にはスケールしなくて良い方法)を見つけました。

まず、本来のページランクでは総和が 1 になるようになっていますが、ここでは総和が n (頂点数) となるように全体を拡大します。
 ΣVi = n
また、グラフの構造の変化として、辺の追加と削除、頂点の追加のみを扱い、「頂点の削除」は扱わないものとします。

Incremental PageRankの計算で扱う頂点は以下の三種類に分けられます。
(計算時の分け方 Vul, Vb, Vur, Vcr とは異なる)
(1) 元からあった頂点で、スケールのみでよい (Vul, Vb)
(2) 元からあった頂点で、再計算が必要
(3) 追加された頂点で、再計算が必要

このうち、(1)と(2)はすでにページランクが割り当てられていて、その総和は(1)と(2)の頂点数と一致します。

頂点が追加されたので、その数だけ全体のページランクの総和も増える必要があります。そこで、(3)の頂点の初期ページランクとして1 を設定します。

ここで、(1)(2)(3)に対してページランク計算を実行すれば、その総和は『どこにもリンクしていない頂点は存在しない』という仮定の下であれば、頂点数と一致します。

このうち、(1)の部分はページランク計算の際に値が変わらない(はずな)ので、ページランク計算の際には(2)(3)にページランク遷移を送るだけでよい(Vb)ので、処理を簡略化できます。

本来必要だったスケール処理部分は、PageRankの値を常に「頂点数」倍にした値で計算することによって省略されます。

なお、このページランクの計算方法では、全体が強連結であるとは限らないという仮定の下で計算しているので、計算の初期値によって収束する値が異なる可能性があります。

2011年2月8日火曜日

Incremental GIM-V 必要メモリ概算

頂点id の型を Long (int64_t) とする。
頂点id を0以上の整数として扱うならば、扱うことのできる頂点数の上限は
2^64 ≒ 9.22 エクサ個となる。
SPADEの整数型に Unsigned なものってないんですかね。

===

SPADEのリファレンスをよく見てみると、"each list is limited to 2^32 - 1 entries"
とある。RWRとHADIでは頂点の値の型およびcombine2の値の型にリストを使うので、
頂点数の上限は 2^32 - 1 ≒ 4.29 ギガ個となる。

===

各アルゴリズムで必要とするメモリの大きさを概算してみる。
頂点数を N 辺数を E と置く。

PageRankの場合、

辺の値の型は Double (8 Bytes)、これに始点id (Long ;8 Bytes) 終点id (Long)
を足すので一辺あたり 24 Bytes。辺全体で 24*E Bytes。
頂点の値の型は Double。頂点全体で 8*N Bytes。
combine2の最終値を保存しておく必要がある。
combine2の値の型は Double、これに辺の終点id(Long)を足して、辺全体で 16*E Bytes。
各頂点のグラフ分割(Byte)も保存する。頂点全体で N Bytes。
あとは頂点数や辺数に依存しないデータのみなので省略。

合計すると 32*E + 9*N Bytes

頂点数が 1Mi 辺数が 100Mi とすると全体で 3209 MiB。

===

RWRの場合、

辺の値の型 : Double
辺全体 : 24*E Bytes
頂点の値の型 : DoubleList (要素数N)
頂点全体 : 24*N*N Bytes
combine2の値の型 : DoubleList (要素数N)
combine2最終値全体 : (8*N + 8)*E Bytes
グラフ分割情報全体 : N Bytes

合計 : 8*N*E + 24*N*N + 32*E + N Bytes

頂点数が 1Mi 辺数が 100Mi とすると全体で 824 TiB (+ 3201 MiB)。大きすぎ。

===

TODO:HADI, HCCについて書く。
HADIはByteListの履歴が必要となる。非常に大きくなると思う。

2011年2月7日月曜日

StreamGraph テクニカルチャレンジ(およびスライド修正点)

■ テクニカルチャレンジ
>GPU

>頂点配置の最適化
ハッシュ ⇒ マイグレーション 頂点の配置についてどこが管理するか
非対称構成などで特定のノードが遅くなる場合などにも配置最適化は有効

>フォールトトレラント
現状、GAが1つでも落ちると処理が次のステップに移れなくなりシステムが止まってしまう

>解析開始の最適タイミング
どのくらい構造変化が生じたら解析を始めるべきか

■スライド修正点
>システム全体が頂点数を知らないといけない
PageRank → スケールに必要
RWR, HADI → 頂点値とcombine2の次元数の決定に必要
解析開始トリガを通じて、グラフの総頂点数をシステムに通知する、など

>HADIについて、履歴がまだ残っている(収束していない)場合に解析が終わってしまう可能性がある
履歴が収束するまではGIM-V反復計算を行うようにする

>名称変更 : add_or_remove ⇒ update_or_remove
値もString("add", "remove")からint(1,0)などに変更

>状態遷移図で「前処理」と「GIM-V計算」の部分の色を分けてわかりやすくする

>表記変更 : 「計算内容」 ⇒ 「グラフ分割」
Q : 構造変化 | b : 変化なし、ボーダー | u : 変化なし

■とりあえず
>プロトタイプ実装しよう