はじめに
因果の方向までデータから推測できる方法としてLiNGAMが注目されています。
本記事ではLiNGAMが推論した因果グラフの結果がどれだけ信頼できるのか確かめる方法について調べた結果とライブラリによる計算方法を記載しています。
LiNGAMとは
因果探索手法の1つ。データからサクッと因果の方向を含めて因果グラフをアウトプットできる。DAGを使った因果推論では予め人が因果グラフを設定する必要があるが、因果探索手法では因果グラフそのものも推測します。
手法のロジックなどは開発者の清水先生が書かれた以下の本で分かりやすく説明されています。
統計的因果探索 (機械学習プロフェッショナルシリーズ)
PythonライブラリによるLiNGAM[基本編]
pythonのライブラリも提供されており、ライブラリとデータ読み込みを除けは以下のようにたったの3行で簡単に実行できます。
公式ドキュメント:https://lingam.readthedocs.io/en/latest/index.html
(以下のコードは公式ドキュメントから抜粋)
import numpy as np
import pandas as pd
import graphviz
import lingam
from lingam.utils import make_dot
###
#データ読み込み
###
X = hogehoge #numpyで分析したいデータを2次元配列で格納する
###
#LiNGAMによる推測と結果アウトプット箇所
###
model = lingam.DirectLiNGAM()#DirectLiNGAMを手法として指定(回帰ベースの方法、他にも独立主成分分析ベースがある)
model.fit(X)#推測
make_dot(model.adjacency_matrix_)#因果グラフとして結果アウトプット
どうして信頼性を調べようとしたのか
機械学習の予測モデルの確からしさは精度という指標で確かめることができ、モデルを安心して利用できるが。LiNGAMの推論した結果にもビジネスで使う場合にある程度、精度に近い指標があればと思い調べた次第(そも正解の因果グラフがないので精度というものは測れない)
調べたところ以下の清水先生のスライドにブートストラップ法を用いた方法があるとのこと。
また以下の論文にて活用が記載されています。
https://dspace.jaist.ac.jp/dspace/bitstream/10119/17798/1/kouen36_162.pdf
ブートストラップ法による因果グラフの信頼性評価
ブートストラップ法とは
ブートストラップ法とは計算機のパワーを利用して「データからランダムにサンプリング」と「サンプリングしたデータによる推定」を繰り返すことで推定値をたくさん計算。計算した推定値データから推定値のばらつきなどの統計量を計算しようというもの。
LiNGAMの場合
シンプルにイメージだけ記載すると、推定値を「因果グラフ」と置き換えて考えればよく、サンプリングと因果グラフの推測を繰り返し、ある因果グラフ(もしくは因果パス)が全サンプリング回数中に何回、結果として推測されたか割合を調べる。多くの回数推測されている因果グラフ(もしくは因果パス)であればデータによる揺らぎがあってもロバストな推測結果として信頼できる。
※シンプルすぎるかも、興味のある人は以下の論文を参照してください。
Assessing Statistical Reliability of LiNGAM via Multiscale Bootstrap
ライブラリによる計算方法と結果
公式ドキュメントでは以下を参照。ドキュメントを見ればわかるがコードと結果を記載。
https://lingam.readthedocs.io/en/latest/tutorial/bootstrap.html#bootstrap
「因果パス毎に出現割合を計算する機能」と「因果グラフ毎に計算する機能」の2種類があります。
(以下のコードは公式ドキュメントから抜粋)
import numpy as np
import pandas as pd
import graphviz
import lingam
from lingam.utils import print_causal_directions, print_dagc, make_dot
#データ読み込み
X = hogehoge #numpyで分析したいデータを2次元配列で格納する
#ブートストラップ法実行
model = lingam.DirectLiNGAM()
result = model.bootstrap(X, n_sampling=100)#fitをbootstrapにするだけ!n_samplingでサンプリング回数を指定
#因果パス(A->Bなど)毎の出現割合を計算
cdc = result.get_causal_direction_counts(n_directions=8, min_causal_effect=0.01, split_by_causal_effect_sign=True)
print_causal_directions(cdc, 100)
#因果グラフ毎の出現割合を計算
dagc = result.get_directed_acyclic_graph_counts(n_dags=3, min_causal_effect=0.01, split_by_causal_effect_sign=True)
print_dagc(dagc, 100)
各引数については以下の通り
引数 | 内容 |
---|---|
n_samplin | ブートストラップでのサンプリング回数 |
n_directions | 上位の出力因果パス数 |
n_dags | 上位の出力因果グラフ数 |
min_causal_effect | 考慮するパス係数の最小値 |
split_by_causal_effect_sign | Trueなら符号を結果に表示 |
結果は以下のようにアウトプットされます。
%でサンプリング回数中の出現割合を、(b>0) or (b<0)で係数の符号をアウトプットしています。
#----------------------------------
#因果パス版
#-----------------------------------
x1 <--- x0 (b>0) (100.0%)
x1 <--- x2 (b>0) (100.0%)
x5 <--- x0 (b>0) (100.0%)
x0 <--- x3 (b>0) (99.0%)
x4 <--- x0 (b>0) (98.0%)
x2 <--- x3 (b>0) (96.0%)
x4 <--- x2 (b<0) (94.0%)
x4 <--- x5 (b>0) (20.0%)
#----------------------------------
#因果グラフ版
#-----------------------------------
DAG[0]: 54.0%
x0 <--- x3 (b>0)
x1 <--- x0 (b>0)
x1 <--- x2 (b>0)
x2 <--- x3 (b>0)
x4 <--- x0 (b>0)
x4 <--- x2 (b<0)
x5 <--- x0 (b>0)
DAG[1]: 16.0%
x0 <--- x3 (b>0)
x1 <--- x0 (b>0)
x1 <--- x2 (b>0)
x2 <--- x3 (b>0)
x4 <--- x0 (b>0)
x4 <--- x2 (b<0)
x4 <--- x5 (b>0)
x5 <--- x0 (b>0)
DAG[2]: 7.0%
x0 <--- x3 (b>0)
x1 <--- x0 (b>0)
x1 <--- x2 (b>0)
x1 <--- x3 (b>0)
x2 <--- x3 (b>0)
x4 <--- x0 (b>0)
x4 <--- x2 (b<0)
x5 <--- x0 (b>0)
最後に
LiNGAMはライブラリが充実していて短時間で試すことができます!
因果グラフや因果パスの信頼性評価も簡単にできます。
因果パスについては多くのパスが推測された場合に足切りにも利用できそうです。
ただ、割合が100%だとしても100%正しい因果を推測できているわけではないので注意。