グラフィカルモデルを綺麗に書く(未完成)

あらまし

「グラフィカルモデルを綺麗に描きたい」
という欲求は誰にでも存在する [要出展]

毎度のごとく、ペイントソフトやパワーポイントを使ってグラフィカルモデルを描くのはなんとももどかしい。

そんな悩みを吐露したら、綺麗に書けるライブラリを教えていただいた。

それがdaftと呼ばれるpythonで使えるライブラリで、日本語ではこちらで紹介されている。

nzw0301.github.io

各関数の定義などはこちらのブログの方が詳しいので割愛させていただく。

やったこと(やりたいこと)

以下を用意した時に自動的にグラフィカルモデルを描いて欲しいと思ったので、 それが行えるようなクラスを作った。

(自分的には以下の要素が最低限構築に必要な要素かな?と思っている。)

  • ノードに付するラベル(αとかwとか)
  • ノードの位置関係
  • 各エッジの始点ノード、終点ノードの関係
  • 各プレートで囲むノードの集合  

現状出来ていないのはプレートを囲むノードの集合からうまく落とし込むところ、 というのも単純なモデルならなんとかなるが、複雑な図を描こうとするとちょっと面倒臭くなる。

プレートは大きく分けて二つに分けられて、

  • 他のプレートと独立しているもの(LDAの場合、Kに相当)
  • 他のプレートと関係があるもの(LDAの場合、DやNに相当)

となるので今回は明示的にこれを定義してしまっている。  

コードはこれ

コードの説明

LDAを例にとって軽く説明を付します。

上記の定義をどうしたか

  • ノードに付するラベル(αとかwとか)

辞書で定義、tex記法(と呼んでいいのかしら?)で文字は書けるので、各種文字や下付き上付きなどが表現できる。良い。

node_list = {"alpha":r"$\alpha$",
             "theta": r"$\theta$",
             "z":r"$z$",
             "w":r"$w_i$",
             "phi": r"$\phi$",
             "beta": r"$\beta$"}
  • ノードの位置関係

二次元arrayで定義した、上で定義した辞書のkeyを位置と対応させて配置する。 この表現でいいのかは疑問だけど、とりあえずこれで。

node_pos = np.array([["alpha","" ],
                     ["theta",""],
                     ["z",    ""],
                     ["w",    ""],
                     ["phi"   ,""],
                     ["",     "beta"]])
  • 各エッジの始点ノード、終点ノードの関係

(始点,終点)といった形で表現されたエッジをリストで保持

edge_list = [("alpha", "theta"),
            ("theta", "z"),
            ("z", "w"),
            ("beta", "phi"),
            ("phi", "w")]
  • 各プレートで囲む変数の集合

これまたこの表現でいいのかわからない。。。 上で述べたようにプレートは大きく二つに大分されるので、 それぞれを"人手"で判断して定義する(ここをどうにかしたい)

plate_list = {"depend":[[r"$D$",["theta","z","w"]],[r"$N$",["z","w"]]],
              "independ":[[r"$K$",["phi"]]]}

To Do

  • プレートの包含関係とかを(半)自動的に識別する。
  • プレートの配置を""いい感じ""にする。(どうするのか?)

まとめ

気が向いたら、改良しようかなと思ってるけど、図の描画は一回限りのことが多かったりもするので、 そこまで使用頻度は結局のところ高くないのかもしれない。。。

こんなことはもう◯◯で既に出来る!みたいなご指摘があったら是非教えていただきたいです。

余談

  • コードを見てもらうとお分かりかもしれないが、Plateの位置調節の値は経験的に決めているのでdependの方のplate数が増えるとうまく行かないです
  • 先輩や同輩には、keynoteinkscapeの方が綺麗と言われたorz...。
  • グラフの描画としてigraph(http://igraph.org/python/)に触れた時は力学モデル?を用いてノードを配置する(レイアウトって呼ばれてた)。 みたいなのがあったけどグラフィカルモデルの場合は出来なさそうだなぁと思ったりなどした。