本文書では, Jubatus のノードがクラッシュしたり追加されたりしたときに, 各アルゴリズムが ANALYZE および UPDATE の処理を続けられるかどうかについて述べる.
挙動について簡単に表にまとめた. 詳細については次節以降で述べる. ノード削除 (crash) については CHT の冗長度も重要となってくるが, ここではある row に対応するノードがすべてクラッシュした場合について述べる.
アルゴリズム | ノード削除 (crash) | ノード追加 (join) |
---|---|---|
classifier, regression | ANALYZE, UPDATE とも続行可能 | 続行可能 |
recommender | ANALYZE 続行可能,UPDATE は一部不可能 | CHT 再構成の問題 |
anomaly (lof) | recommender に準ずるが,スコアは不正確になる | CHT 再構成の問題 |
stat | ANALYZE, UPDATE とも一部不可能に | CHT 再構成の問題 |
graph | 正しい MIX ができなくなり,壊れる | CHT 再構成の問題 |
ANALYZE, UPDATE ともに続行可能である. クラッシュしたノードの, 前回の MIX からの更新差分は失われる.
ノードを追加するだけ. join による精度低下を防ぎたい場合,save
と load
を使って他のサーバーからモデルをパクると良い.
recommender では CHT で元データが分配されるため, ノードがクラッシュしたとき, 冗長度が足りないと元データが失われる. 失われた row に対しては UPDATE できない. 他の row に対する UPDATE や, すべての row に対する ANALYZE は引き続き可能である.
ノードを join させる場合, CHT における row の振り分け方が変わる. すなわち各ノードが担当する row の集合が変わる. これに追従するためにはノード間で row の元データを交換する必要がある. 現在の recommender::recommender_base
は元データを直接取り出したりセットしたりする操作に対応していないため, join に対応するためにはインターフェイスの変更が必要である.
元データについては, 内部で使用している recommender の挙動に準ずる.
失われた row のパラメーター (lrd, kdist
) が更新されなくなる. その結果, 場合のよってはほぼすべてのクエリーに対する LOF 値が不正確になる可能性がある.
本来ならば, ある row の近傍にデータ点が追加されたとき, その row 自身に対する UPDATE がなくても, この row のパラメーターが更新されなくてはならない.
失われた row のパラメーターが更新されなくなることにより, その逆近傍にある row の lrd
値が不正確になる. その結果, 失われた row およびその逆近傍に属するデータ点を近傍に含むクエリーに対する LOF 値が不正確になる.
クラッシュしたノードが CHT で担当する row がランダムに分布しているとすれば, ノード数や近傍サイズにもよるが, それらの逆近傍の逆近傍でデータの大部分をカバーする可能性が高い (つまり, どのクエリーに対しても, その近傍の近傍がすべて失われずに残っている可能性は低い). つまりほぼすべてのクエリーに対する LOF 値が不正確になる.
ただし, 不正確になった LOF 値のうちどれくらいが異常検知の観点から問題になるかは, パッとはわからない. もしかしたらほんの少し狂うだけで問題ないのかもしれない.
lof 固有のパラメーターについては join の影響は受けない. 内部で使用する recommender については上記の通り問題がある.
stat では UPDATE も ANALYZE も CHT を用いているため, 一部の row に対して CHT で対応するノードがすべてクラッシュした場合, その row に対する UPDATE, ANALYZE ともにできなくなる. 他のノードの row に対する操作は引き続き行える. また, row によらないパラメーター(現在は entropy のみ)は引き続き UPDATE, ANALYZE できるが, クラッシュ後の MIX 以降では残された row のみを用いて計算した値となる.
CHT を用いて各 row に対する直近のデータ列を保存している. そのため join によって CHT を作りなおす場合, recommender の場合と同様にノード間で row を交換する必要がある.
graph には eigenvector(いわゆる PageRank の実装)と shortest path という二つのアルゴリズムがある. 実装上はこれらは単一のクラス graph_wo_index
で実装されている. グラフでは, 各頂点は CHT で分配され, 各エッジは両端の頂点を担当するノードすべてに分配されることに注意する.
CHT なので, 一部の頂点とエッジが失われる.
eigenvector では CHT で分配された頂点に関するスコア伝搬を MIX 時に行うが, クラッシュしたノードが担当する頂点に関してスコア伝搬が行われなくなるため, 以降グラフ全体において正しいスコアを計算できなくなる.
shortest path についてもモデルが壊れる. shortest path はいくつかの頂点をルートとした最短路木を構築し, これらをもとのグラフの近似だと思って最短路を近似的に求めるが, クラッシュ時には失われたエッジをルートへのパスに含むような頂点についてただしく最短路木を更新できなくなるため, 以降の UPDATE のあとでは最短路を正しく近似できなくなる.
recommender などと同様に, CHT で分配される頂点とエッジをノード間で交換する必要がある.
Keeperに頼らないJubatusプロセス側でのCHT再構成は遅かれ早かれ必要ですね。
が必要なのはclassify・regression以外では共通そうに見えます。
共通なので、recommender::recommender_baseなどにそれぞれ個別実装するよりは、
共有アルゴリズムそのものを複数のアルゴリズムから共有させたいところです。
そのshared-nothingなストレージ対する要求仕様が上の3つの他にどんなのがあるかな、というのを洗い出す事が最初の一歩になると考えます。