🚀 銀行向け自動因果推論
このプロジェクトは、銀行業務における因果推論を自動化するパイプラインを提供します。ユーザーは treatment 変数と outcome 変数を指定するだけで、自動的に因果関係や因果変数を特定し、因果構造の検証を行います。
🚀 クイックスタート
このプロジェクトを使用するには、以下の手順に従ってください。
必要条件
- Python 3.10
- Claude Desktop (MCPを実行する場合)
依存関係のインストール
pip install requirements.txt
LangGraphの実行
cd agent
python app.py
LangGraph Studioでテストするには、以下のコマンドを実行します。
langgraph dev
UIのアドレスはこちらです: https://smith.langchain.com/studio/?baseUrl=http://127.0.0.1:2024
Claude DesktopでMCPを実行する
cd mcp_agent
python client.py
✨ 主な機能
- 自動因果構造の特定: LLMの強力な意味理解と推論能力を利用して、因果関係や因果変数を自動的に特定します。
- 多様なツールの統合: CausalNex、CausalTune、Refutation Testなどのツールを統合して、自動因果推論をより堅牢にします。
- 柔軟なアーキテクチャ: LangGraph AgentとMCP Agentの2つのアーキテクチャを提供し、ユーザーのニーズに合わせて選択できます。
📦 インストール
必要条件
- Python 3.10
- Claude Desktop (MCPを実行する場合)
依存関係のインストール
pip install requirements.txt
💻 使用例
基本的な使用法
User asks: "Does offering a promotion increase digital product activation ?"
age -> promotion_offer;
age -> activated_ib;
income -> promotion_offer;
income -> activated_ib;
education -> promotion_offer;
education -> activated_ib;
region_code -> promotion_offer;
promotion_offer -> branch_visits;
branch_visits -> activated_ib;
promotion_offer -> customer_engagement;
activated_ib -> customer_engagement;
channel_preference -> activated_ib;
promotion_offer -> activated_ib
{
"confounders": ["age", "income", "education"],
"mediators": ["branch_visits"],
"effect_modifiers": ["channel_preference"],
"colliders": ["customer_engagement"],
"instruments": ["region_code"],
"causal_graph": "...DOT format...",
"dowhy_code": "...Python code..."
}
import dowhy
from dowhy import CausalModel
model = CausalModel(
data=df,
treatment='promotion_offer',
outcome='activated_ib',
common_causes=['age', 'income', 'education'],
instruments=['region_code'],
mediators=['branch_visits']
)
identified_model = model.identify_effect()
estimate = model.estimate_effect(identified_model, method_name='backdoor.propensity_score_matching')
print(estimate)
estimators = ["S-learner", "T-learner", "X-learner"]
cd = CausalityDataset(data=df, treatment=state['treatment'], outcomes=[state["outcome"]],
common_causes=state['confounders'])
cd.preprocess_dataset()
estimators = ["SLearner", "TLearner"]
ct = CausalTune(
estimator_list=estimators,
metric="energy_distance",
verbose=1,
components_time_budget=10,
outcome_model="auto",
)
ct.fit(data=cd, outcome=cd.outcomes[0])
print(f"Best estimator: {ct.best_estimator}")
print(f"Best score: {ct.best_score}")
refute_results = []
refute_methods = [
"placebo_treatment_refuter",
"random_common_cause",
"data_subset_refuter"
]
for method in refute_methods:
refute = model.refute_estimate(identified_estimand, estimate, method_name=method)
refute_results.append({"method": method, "result": str(refute)})
pass_test = all("fail" not in r["result"].lower() for r in refute_results)
| Role | Variable | Why it's assigned this role |
| ------------------- | ---------------------------- | ---------------------------------------------------------------- |
| **Confounder** | `age`, `income`, `education` | Affect both the chance of receiving promotions and IB usage. |
| **Mediator** | `branch_visits` | A step in the causal path: promotion → visit → IB activation. |
| **Effect Modifier** | `channel_preference` | Alters the strength of the effect of promotion on IB activation. |
| **Collider** | `customer_engagement` | Affected by both promotion and IB usage; should not be adjusted. |
| **Instrument** | `region_code` | Randomized promotion assignment at the regional level. |
Best estimator: backdoor.econml.metalearners.TLearner, score: 483.1930697900207
Refutation passed: True.
[
{'method': 'placebo_treatment_refuter',
'result': 'Refute: Use a Placebo Treatment Estimated effect:0.23849549989874572
New effect:-0.0004960408910311281
p value:0.96'},
{'method': 'random_common_cause',
'result': 'Refute: Add a random common cause
Estimated effect:0.23849549989874572
New effect:0.23847067700750038
p value:0.98'},
{'method': 'data_subset_refuter',
'result': 'Refute: Use a subset of data
Estimated effect:0.23849549989874572
New effect:0.23749715031525756
p value:0.96'}
]
Result Summary:
1. There is a causal effect between offering promotions and activating internet banking services, with a 15% increase of activating internet banking if we open the promotion for everybody. This shows a strong positive impact of the promotion offer on activation.
2. Factors like age, income, education level could have influenced both the decision to offer promotions and the likelihood of activating internet banking services. These factors may have affected the outcome regardless of the promotion offer.
📚 ドキュメント
バージョン変更について
v1.1 (現在のバージョン): CausalNex、CausalTune、Refutation Test などを統合して、Auto-Causalをより堅牢にしました。
v1.0 (リンク): LLM の強力な意味理解と推論能力を利用して、因果構造(因果関係、因果変数など)を即座に特定します。
動機
因果推論 の最も難しい点の1つは、推定アルゴリズムを実行することではなく、システム内の変数の 因果的な役割 を 正しく特定すること です。例えば、交絡因子、媒介変数、コライダー、効果修飾因子、操作変数 などです。
このタスクは通常、ドメインの専門知識と経験が必要です。なぜなら、以下の理由があるからです。
- モデルに より多くの変数 を追加するだけでは、必ずしも より良い因果推定 が得られるわけではありません。実際、コライダーや媒介変数を誤って調整すると、結果が 偏る 可能性があります。
- 従来のアプローチでは、しばしば 手動によるDAG構築 と注意深い事前分析に依存しています。
✅ 自動因果推論 (Auto-Causal) は、この問題を解決するために LLM (大規模言語モデル) を使用して作成されました。ユーザーは 処置 と 結果 を指定するだけで、変数の役割と提案される因果グラフを自動的に推論できます。
これにより、以下のことが可能になります。
- 因果的な質問に対するより迅速な実験
- 分析に適した交絡変数の自動選択
- ドメイン固有の手動DAGへの依存度の低下
- 推論プロセスのより高い透明性と再現性
エージェントアーキテクチャ
このプロジェクトは、因果推論ワークフローを実行するための2つの異なるエージェントアーキテクチャを提供します。
- LangGraph Agent: 分析をタスク(ノード)のグラフとして実装し、同期的または非同期的に実行され、単一のプロセスで調整されます。
- MCP Agent: 各タスクを独立したMVPサーバーに分割し、Model-Context-Protocol (MCP) パターンに従ってHTTPを介して通信します。これにより、簡単なスケーリングとモジュール化されたサービスのデプロイが可能になります。
プロジェクト構造
auto_causal_inference/
├── agent/ # LangGraphエージェントのソースコード
│ ├── data/ # サンプルデータ (bank.db)
│ ├── app.py # LangGraph因果エージェントのメインエントリーポイント
│ ├── generate_data.py # 因果推論のためのデータ生成スクリプト
│ ├── requirements.txt # LangGraphエージェントの依存関係
│ └── ... # その他のヘルパーモジュールとノートブック
│
├── mcp_agent/ # MCPエージェントの実装
│ ├── data/ # サンプルデータ (bank.db)
│ ├── server.py # MCP因果推論サーバー
│ ├── client.py # MCPクライアントを呼び出すためのクライアント
│ ├── requirements.txt # MCPエージェントの依存関係
│ └── ... # 追加のファイル
│
└── README.md # このドキュメントファイル
入力例
User asks: "Does offering a promotion increase digital product activation ?"
出力例
因果関係
age -> promotion_offer;
age -> activated_ib;
income -> promotion_offer;
income -> activated_ib;
education -> promotion_offer;
education -> activated_ib;
region_code -> promotion_offer;
promotion_offer -> branch_visits;
branch_visits -> activated_ib;
promotion_offer -> customer_engagement;
activated_ib -> customer_engagement;
channel_preference -> activated_ib;
promotion_offer -> activated_ib
因果変数
{
"confounders": ["age", "income", "education"],
"mediators": ["branch_visits"],
"effect_modifiers": ["channel_preference"],
"colliders": ["customer_engagement"],
"instruments": ["region_code"],
"causal_graph": "...DOT format...",
"dowhy_code": "...Python code..."
}
平均処置効果 (ATE) の計算
import dowhy
from dowhy import CausalModel
model = CausalModel(
data=df,
treatment='promotion_offer',
outcome='activated_ib',
common_causes=['age', 'income', 'education'],
instruments=['region_code'],
mediators=['branch_visits']
)
identified_model = model.identify_effect()
estimate = model.estimate_effect(identified_model, method_name='backdoor.propensity_score_matching')
print(estimate)
モデルのチューニング
estimators = ["S-learner", "T-learner", "X-learner"]
cd = CausalityDataset(data=df, treatment=state['treatment'], outcomes=[state["outcome"]],
common_causes=state['confounders'])
cd.preprocess_dataset()
estimators = ["SLearner", "TLearner"]
ct = CausalTune(
estimator_list=estimators,
metric="energy_distance",
verbose=1,
components_time_budget=10,
outcome_model="auto",
)
ct.fit(data=cd, outcome=cd.outcomes[0])
print(f"Best estimator: {ct.best_estimator}")
print(f"Best score: {ct.best_score}")
反証テスト
refute_results = []
refute_methods = [
"placebo_treatment_refuter",
"random_common_cause",
"data_subset_refuter"
]
for method in refute_methods:
refute = model.refute_estimate(identified_estimand, estimate, method_name=method)
refute_results.append({"method": method, "result": str(refute)})
pass_test = all("fail" not in r["result"].lower() for r in refute_results)
結果の分析
| Role | Variable | Why it's assigned this role |
| ------------------- | ---------------------------- | ---------------------------------------------------------------- |
| **Confounder** | `age`, `income`, `education` | Affect both the chance of receiving promotions and IB usage. |
| **Mediator** | `branch_visits` | A step in the causal path: promotion → visit → IB activation. |
| **Effect Modifier** | `channel_preference` | Alters the strength of the effect of promotion on IB activation. |
| **Collider** | `customer_engagement` | Affected by both promotion and IB usage; should not be adjusted. |
| **Instrument** | `region_code` | Randomized promotion assignment at the regional level. |
Best estimator: backdoor.econml.metalearners.TLearner, score: 483.1930697900207
Refutation passed: True.
[
{'method': 'placebo_treatment_refuter',
'result': 'Refute: Use a Placebo Treatment Estimated effect:0.23849549989874572
New effect:-0.0004960408910311281
p value:0.96'},
{'method': 'random_common_cause',
'result': 'Refute: Add a random common cause
Estimated effect:0.23849549989874572
New effect:0.23847067700750038
p value:0.98'},
{'method': 'data_subset_refuter',
'result': 'Refute: Use a subset of data
Estimated effect:0.23849549989874572
New effect:0.23749715031525756
p value:0.96'}
]
Result Summary:
1. There is a causal effect between offering promotions and activating internet banking services, with a 15% increase of activating internet banking if we open the promotion for everybody. This shows a strong positive impact of the promotion offer on activation.
2. Factors like age, income, education level could have influenced both the decision to offer promotions and the likelihood of activating internet banking services. These factors may have affected the outcome regardless of the promotion offer.
他のツール/方法との比較
| 📝 基準 |
🔍 CausalNex |
⚖️ DoWhy |
🤖 CausalTune |
🚀 自動因果推論 |
| 🎯 主な目的 |
因果グラフの学習 |
完全な因果パイプライン |
自動推定器のチューニング |
自動因果的な質問と回答: 発見 → 推定 → チューニング |
| 🔎 発見 |
はい (NOTEARS, Hill Climb) |
はい (PC, NOTEARS, LiNGAM) |
いいえ |
はい (CausalNex + DoWhyの発見) |
| 🧩 交絡因子の特定 |
いいえ |
はい |
いいえ |
はい (LLMがグラフを分析して交絡因子を特定) |
| 📊 推定 |
限定的 (ベイジアンネットワーク) |
豊富な推定器 |
はい (多くの学習器) |
はい (DoWhyがATEを推定) |
| ⚙️ 自動推定器 |
いいえ |
いいえ |
はい |
はい (CausalTuneが最適な推定器を自動選択) |
| ✅ 反証 |
いいえ |
はい |
いいえ |
はい (DoWhyの反証テスト) |
| 👤 ユーザー入力が必要 |
手動によるグラフと方法 |
手動による推定器 |
推定器の選択 |
ただ処置 → 結果の質問をするだけ |
| 🤖 自動化レベル |
低から中 |
中 |
高 |
非常に高い |
| 📥 入力データ |
観測的な表形式 |
観測データ + グラフ |
観測データ + モデル |
観測データ + DBメタデータ |
| 🔄 柔軟性 |
高い構造学習 |
高い推論と反証 |
高いチューニング |
非常に高い、多くのツールとLLMを組み合わせ |
| 🎯 最適な用途 |
グラフを構築する研究者 |
パイプラインユーザー |
MLの本番環境でのチューニング |
迅速な因果的な回答を求めるビジネスユーザー |
| 💪 強み |
良好な因果グラフの学習 |
完全な因果ワークフロー |
自動推定器のチューニング |
エンドツーエンドの自動化 + LLMのサポート |
| ⚠️ 制限 |
組み込みの検証がない |
自動チューニングがない |
発見/反証がない |
データ品質に依存する、反証に失敗した場合は手動で確認が必要 |