PythonでGraphvizを使ってマルコフチェーンを描画する

概要

マルコフチェーン(markov chain)を、PythonのPydotplus(又はPydot)からGraphvizを使って簡単に作るモジュール(markovViz)を作成しました。以下イメージです。

環境構築

以下の記事と同じなので省略します。

PythonでGraphvizを使ってニューラルネットワークを描画する


入力条件

pandasのデータフレームのindexを遷移元、columnを遷移先とし、値として遷移確率を設けたデータフレームを入力とします。
以下がイメージです。

表の値の説明(抜粋)

  • 状態aからbに遷移する確率:20%
  • 状態aからdに遷移する確率: 0%
  • 状態bからaに遷移する確率:70%
  • 状態bから遷移しない確率:30%

プログラム

以下がソースコードです。適当に張り付けて使ってください。

#必要なモジュールのインポート
import pandas as pd
import numpy as np
import pydotplus
 
def markovViz(markovdf, fileName='default.png'):
    
    #オブジェクトを定義
    graph = pydotplus.Dot(graph_type='digraph')
    
    #ノードを追加
    for c in df.columns:
        node = pydotplus.Node(c)
        graph.add_node(node)
    
    #エッジを追加    
    for i in df.index:
        for c in df.columns:
            if df.ix[i, c] > 0:
                edge = pydotplus.Edge(graph.get_node(i)[0], graph.get_node(c)[0])
                edge.set_label('{:.1f}'.format(df.ix[i, c]))
                graph.add_edge(edge)

    #グラフ描画                
    graph.write_png(fileName, prog='dot')

いろいろ試してみる

せっかく作ったのでいろいろ試してみました。
まずは例題の結果。

if __name__ == "__main__":    
    df = pd.DataFrame(index=['a', 'b', 'c', 'd'],
                      columns=['a', 'b', 'c', 'd'], 
                      data=[[0.6, 0.2, 0.2, 0.0],
                            [0.7, 0.3, 0.0, 0.0],
                            [0.0, 0.4, 0.5, 0.1],
                            [0.1, 0.3, 0.3, 0.3]])
    
    markovViz(df)


ラベルと線の間の余白や線の曲がりがちょっと気になりますが、まずは使えるレベルと言えそうですね。

10の状態を設けた場合の結果。

if __name__ == "__main__":
    
    #ランダムなデータを作成
    np.random.seed(0)
    data = np.random.rand(10, 10)
    
    #行方向の合計が1になるように正規化
    data = (data / data.sum(axis=0)).T
           
    #DataFrame作成
    df = pd.DataFrame(data, index=np.arange(10).astype('str'), columns=np.arange(10).astype('str'))
    
    #グラフ作成
    markovViz(df)


うまくかけていますね。こういうのを見ると、Graphvizやるなぁ、という気がします。

20の状態を設けた場合の結果。

ここまでくると何が何だかわかりませんが、参考ということで。


コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA