Skip to content

Instantly share code, notes, and snippets.

@kumagi
Last active December 31, 2015 14:29
Show Gist options
  • Save kumagi/8000306 to your computer and use it in GitHub Desktop.
Save kumagi/8000306 to your computer and use it in GitHub Desktop.
JubatusのMixアルゴリズム改善について

解決したい問題

  • put_diffを取り漏らした時などに学習モデルがズレる
  • 新規マシンを追加する機能がない

解決方針

  • モデルにバージョン番号を埋め込む事で一番多くmixを受け取ったモデルを識別可能にする
  • get_diff時にバージョン番号を埋め込む事でそのdiffをmixに利用するかを判断する
  • put_diff時にバージョン番号を埋め込む事で受け取った側が今持っているモデルが最新かどうかを判断する
  • 今持っているモデルが最新でないと判断したら他のプロセスからモデルを受け取る

変更に伴う外部/内部IFの非互換な変更

  • /jubatus/actors/classifier/[NAME]/activeを追加
    • これはnodesと異なり「ProxyがRPCを投げても良いプロセス」を意味するEphemeralノード
    • これに伴いnodesは「ZKから生きていると認識されているプロセスとなるよう意味を変更
  • save/load時のデータ非互換
    • バージョン番号のメンバを加えた分、save/load時に型が合わない
      • masterとして公開する際にコンバータを用意するなどで対処予定(別のパッチ)
  • put_diffの戻り値をvoidからboolへ変更
    • これまでput_diffは成功シナリオのみしか想定していなかったが、バージョン番号埋め込みと共に失敗するパターンを考慮する必要がある
    • フレームワークとしてのJubatusは個々のアルゴリズム内部に踏み込まない為、アルゴリズム側から「put_diffに失敗した」と教えてもらう必要がある
    • classifier以外のすべてのアルゴリズムは暫定的にput_diffはすべてtrueを返す。これはこれまでの挙動を全く変更しない。
      • それらのアルゴリズムでモデルの最新バージョン獲得機能を使いたい場合にはput_diffにfalseを返せば良い(regressionもできるがやるとしたら別のパッチ)

linear_mix.cpp

外観

  • 他のプロセスにモデル全部を要求するget_modelの送信側と受信側を実装
  • mixer_loopは、「mix」のみの無限ループだったがこの処理を「mix」及び「必要なら他のプロセスからモデルを全部もらってくる」の2つの処理を行うループへと変更。それに伴って名前をstabilizer_loopに変更
  • put_diff適用時にfalseが帰ってきたら、自身のモデルが世代遅れになっていることを意味するので、is_obsolete_フラグを立て、activeとして保存したZKのエントリを消去
  • stabilizer_loop内で、is_obsolete_フラグが立っている事を検知したら他のプロセスからモデルを獲得しにいく
    • モデル獲得時(get_model)は自分以外のプロセスからランダムに一つ選んでget_model RPCを投げる。獲得したら即Mixして最新であるか試す。
  • 晴れてモデルが最新になっていればis_obsolete_フラグを折り、put_diffの成功時にactiveとしてZooKeeperに保存。
    • これによりproxy経由でリクエストが来るようになる。

議論

  • 1プロセスのみしか居ない場合、get_modelは諦めて即座にactiveとして昇格する。
  • どこかのタイミングで最新のモデルを持つプロセスがすべて死んだ場合、古いモデル同士のmix時に採用するバージョン番号は必ずその古いモデルに合成可能なものとなるため、いずれ何らかの形で可能な限り最新なモデルが共有されるはず − get_modelをリクエストする先をランダムで決定しているが、性能的にはランダムではなくバージョン確認RPCを別で用意するなどの最適化が考えられるが、その場合いくつか問題がある
    • RPCコマンドが更に増えてしまう
    • フレームワークがバージョン番号というアルゴリズム固有のデータに踏み込んだ情報を管理する必要がある
  • なぜモデル側に番号を持たせるのか。フレームワーク側ではダメなのか
    • linear_mixerの用例によっては古いものをput_diffしても問題なく動いて欲しいタイプの物もあると想定し、フレームワーク側ですべてを吸収するのは避けた。将来的にはフレームワーク側で吸収するモードのlinear_mixerを作り分けても良いかもしれない
@unnonouno
Copy link

はい、あとは清書すればOKだとおもいます

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment