今回は「因果探索手法LiNGAMを試してみた」の後編です。
前編の最後でも言いましたが、LiNGAMを実データに適用してみます。
「前編まだ見てないよ」という方は以下のページからご覧ください。
「そもそも因果探索って何よ」という方は、以下の記事で少し説明しておりますので参照いただければと思います。
必要な準備
一応おさらいしておきます。
LiNGAMはPythonにライブラリが存在しますので、そちらを用います。
pip install lingam
で利用可能になります。環境構築後に実行しておいてください。
環境は、WindowsのローカルでAnacondaを用いて構築しました。
バージョンは以下の通り。
- python:3.11.5
- numpy:1.26.3
- pandas:2.1.4
- graphviz:0.20.1
実データ投げてみた
早速、やっていきましょう。
オープンデータである「National Health and Nutrition Health Survey 2013-2014 (NHANES) Age Prediction Subset」に適用してみて、確かめてみます。
データは以下からとってきてます。
まずはimport。
import pandas as pd
import numpy as np
import lingam
データセットをロードして、中身を確認します。
df = pd.read_csv('dataset/NHANES_age_prediction.csv')
データ数は2278。前回の疑似データが3000だったので、少し足りないかもしれないですね。
データのカラムは、①Index、②年齢層、③年齢、④性別、⑤運動の有無、⑥BMI、⑦血糖値、⑧糖尿病の分類、⑨被験者の口頭の血糖値、⑩血中インスリン濃度で構成されています。(⑨のデータの意味は推測です、すいません)
②以外は数値データで入っていたので、①②以外を対象に因果探索やっていきます。(④、⑤、⑧のような離散値もありますが、今回はお試しで含めておきます。)
以前と同様にLiNGAMを適用します。
labels = ["③", "④", "⑤", "⑥", "⑦", "⑧", "⑨", "⑩"]
model = lingam.DirectLiNGAM()
model.fit(df[df.columns[2:]])
#出力用
# dot = lingam.utils.make_dot(model.adjacency_matrix_, labels = labels)
# dot
出力結果がこちら。
少しわかりづらいと思うので、もう少し簡潔にします。
以下のコードのように「lower_limit」を設定することで、表示する影響の下限値を設定することができます。
dot = lingam.utils.make_dot(model.adjacency_matrix_,
lower_limit=1,
labels = labels)
その結果が以下の図です。
結果を見てみて
気になる要素がいくつかあります。
⑧→③・⑩のように関係はありそうだけど、因果逆じゃないかという出力もありますね。
年齢やインスリン濃度が高いから、糖尿病の重症度合いが決まりそうなイメージです。
一方で、④→⑦は実際の関係を表している印象です。性別(1:男性、2:女性)の値が増えることで、血糖値が減少することは因果の探索がうまく行えている点と言えるのではないでしょうか。
ただ、全体を通していい因果関係が取れているとは言えませんね。インスリン濃度、血糖値、糖尿病の重症度とかはもっと関係が見られると思っていました。
LiNGAMの前提条件を網羅できている保証がないことやデータ数が少なめだったことも一因と考えられます。
最後に
ここまで、因果探索手法LiNGAMを使ってきました。
制約はあるものの、因果が見えることでより具体的な関係性の把握につながる可能性があると思います。また、万能ではないものの、1つの示唆を与えるという意味では有用だと考えます。
LiNGAMには制約を変えた別バージョンもたくさんあるので、機会があればそこにも触れてみたいと思っています。