【Python/因果探索】LiNGAMでIrisの因果構造を解明:DoWhyの因果推論と結果を比較する
はじめに
相関関係と因果関係は異なります。データ分析において、変数間の関係性の「向き」と「構造」を明らかにすることは、非常に重要です。この記事では、Pythonのlingamパッケージを使い、因果探索(Causal Discovery) の手法であるLiNGAM(Linear Non-Gaussian Acyclic Model) を実践します。
以前の記事Pythonの因果推論ライブラリ「DoWhy」でIrisデータセットを分析するでは、「AがBに影響を与える」という仮説のもとで因果効果を推定する因果推論を行いました。
それに対し、LiNGAMを用いる因果探索は、特定の仮説を必要とせず、データそのものから 変数間の因果関係の構造(どの変数が原因で、どの変数が結果か) を推定します。
この記事を読めば、以下のことができるようになります。
- LiNGAMの基本的な考え方と使い方を理解する。
- Pythonで
lingamを使い、データから因果グラフを推定する。 - 因果探索と因果推論のアプローチの違いを理解し、結果を比較検討する。
LiNGAMとは?
LiNGAMは、以下の2つの重要な仮定に基づき、データから因果構造(DAG: 有向非巡回グラフ)を推定する手法です。
- 線形性 (Linearity): 変数間の関係が線形である。
- 非ガウス性 (Non-Gaussianity): 誤差変数が正規分布に従わない。
特に「非ガウス性」の仮定が強力で、これによりLiNGAMは単なる相関ではなく、変数間の因果の「向き」を特定することができます。
分析コード
それでは、実際にIrisデータセットを使って因果探索を行ってみましょう。
このコードは、データの準備、DirectLiNGAMモデルの学習、そして結果(因果順序と隣接行列)の出力を一気に行います。
import sklearn
import pandas as pd
import lingam
import graphviz
from lingam.utils import make_dot
# 1. データの準備
iris = sklearn.datasets.load_iris()
df_features = pd.DataFrame(data=iris.data, columns=iris.feature_names)
feature_names = iris.feature_names
# 2. モデリングと学習
model = lingam.DirectLiNGAM()
model.fit(df_features)
# 3. 因果順序の表示
# どの変数が"根源"に近いかを示す
causal_order = model.causal_order_
print("Causal Order:", [feature_names[i] for i in causal_order])
# 4. 隣接行列の表示
# 変数間の直接的な因果効果の強さを示す
adjacency_matrix = model.adjacency_matrix_
print("Adjacency Matrix:\n", adjacency_matrix)
# 5. 可視化
# 推定された因果グラフを画像として保存
dot = make_dot(model.adjacency_matrix_, labels=feature_names)
dot.format = 'png'
dot.render('lingam_causal_graph')
dot
実行結果
上記のコードを実行すると、以下の結果が得られます。
因果順序 (Causal Order)
LiNGAMは、最も他の変数に影響を与える(外生的な)変数を順に並べます。
Causal Order: ['petal length (cm)', 'petal width (cm)', 'sepal width (cm)', 'sepal length (cm)']
この結果は、「花弁の長さ」が因果の根源に最も近いことを示唆しています。
隣接行列 (Adjacency Matrix)
隣接行列は、変数間の直接的な因果効果の大きさを表す重み行列です。行が「原因」、列が「結果」に対応します。
結果の考察
得られた因果順序と隣接行列から、Irisデータセットの特徴量間の因果関係を読み解いていきましょう。
📊 変数とインデックスの対応
まず、行列のインデックスがどの特徴量に対応するかを確認します。
| インデックス | 特徴量 (Feature) |
|---|---|
| 0 |
petal length (cm) (花弁の長さ) |
| 1 |
petal width (cm) (花弁の幅) |
| 2 |
sepal width (cm) (萼片の幅) |
| 3 |
sepal length (cm) (萼片の長さ) |
🔍 隣接行列から因果パスを読み解く
隣接行列の非ゼロ要素は、直接的な因果関係(矢印)を示します。
-
petal length( ) の影響 (因果の根源)X_0 - →
petal width( ): +0.65 (強い正の相関)X_1 - →
sepal width( ): +0.71 (最も強い正の相関)X_2 - →
sepal length( ): -0.56 (強い負の相関)X_3 - 花弁の長さは他のすべての特徴に直接影響を与えています。特に、花弁が長くなると萼片の長さが短くなるという負の相関は興味深い点です。これは成長リソースのトレードオフを示唆しているかもしれません。
- →
-
petal width( ) の影響X_1 - →
sepal width( ): -0.26 (弱い負の相関)X_2 - →
sepal length( ): +0.36 (中程度の正の相関)X_3
- →
-
sepal length( ) の影響X_3 - →
sepal width( ): +0.42 (中程度の正の相関)X_2 - 因果順序では後の方にある萼片の長さが、萼片の幅に影響を与えています。グラフ全体が非巡回的(ループしない)構造であれば、このようなパスも許容されます。
- →
-
sepal width( ) の影響X_2 - このモデルでは、萼片の幅は他のどの変数にも直接的な影響を与えない終端の変数として推定されました。
グラフによる可視化
これらの因果関係を可視化したものが、以下の有向非巡回グラフ(DAG)です。矢印が因果の向きを、線の太さが因果効果の強さを表しています。

DoWhyによる因果推論との比較
以前のDoWhyを用いた分析では、「sepal length(萼片の長さ)が petal length(花弁の長さ)に与える影響」を分析し、ATE(平均処置効果)が約 +0.87 であると推定しました。これは「萼片が1cm長くなると、花弁も約0.87cm長くなる」という直感に合う結果でした。
しかし、今回のLiNGAMによる因果探索の結果は、因果の向きが逆であることを示唆しています。
-
DoWhy (因果推論):
sepal length→petal lengthという 仮説 を検証 -
LiNGAM (因果探索):
petal length→sepal lengthという 構造 を発見
🚨 なぜ向きが異なるのか?
この違いは、因果分析における2つのアプローチの目的と限界を浮き彫りにします。
-
DoWhy (仮説検証型アプローチ)
-
前提: 分析者が「
sepal lengthが原因である」という因果グラフを仮定する。 -
結果の意味: その仮定のもとで、観測データに見られる相関(大きな花は全体的に各パーツも大きい)を定量化したものがATE
+0.87です。これは、共通の原因(例:個体の栄養状態)による見せかけの因果を含んでいる可能性があります。
-
前提: 分析者が「
-
LiNGAM (データ駆動型アプローチ)
- 前提: データが線形・非ガウス性の構造を持つと仮定する。
-
結果の意味: データから客観的に最も確からしい因果の向きを推定します。その結果、
petal lengthが根源であり、sepal lengthへは -0.56 の直接的な負の効果を持つと発見しました。これは、DoWhyが見つけた全体的な相関とは異なり、他の変数の影響を取り除いた上での純粋な直接効果と解釈できます。
この「直接的な負の効果」は、生物学的な「リソースのトレードオフ」のような、より深い洞察を示唆しているかもしれません。
結論:因果探索が拓く新たな視点
今回の分析から、因果探索(LiNGAM)が、従来の仮説ベースの因果推論(DoWhy)を補完し、新たな洞察をもたらす強力なツールであることがわかります。
- 因果の根源を発見: LiNGAMは、分析者の思い込みを排除し、データが語る因果の出発点を特定しました。
- 隠れた関係性の発見: 全体的な正の相関の裏に隠れていた、直接的な負の因果(トレードオフ)という、より深い構造的関係を明らかにしました。
- 仮説の健全性を問う: 因果推論を行う前に因果探索を行うことで、立てた仮説がデータと整合的であるかを確認し、より信頼性の高い分析につながります。
相関分析から一歩進んで、データに隠された因果構造を明らかにしたいとき、LiNGAMのような因果探索の手法は非常に価値のある選択肢となるでしょう。
Discussion