本投稿は、以下の本の実装例を学習用に写経したものになります。詳細について気になりましたら、本を読んでみてください。
Bitly
実装例は筆者らのgithubに公開されています。
GitHub - YutaroOgawa/causal_book: 書籍「作りながら学ぶ! PyTorchによる因果推論・因果探索」の実装コードのリポジトリです
書籍「作りながら学ぶ! PyTorchによる因果推論・因果探索」の実装コードのリポジトリです. Contribute to YutaroOgawa/causal_book development by creating an account on GitHub.
ライブラリインポート
# 乱数のシードを設定
import random
import numpy as np
np.random.seed(1234)
random.seed(1234)
# 使用するパッケージ(ライブラリと関数)を定義
# 標準正規分布の生成用
from numpy.random import *
# グラフの描画用
import matplotlib.pyplot as plt
# SciPy 平均0、分散1に正規化(標準化)関数
import scipy.stats
# シグモイド関数をimport
from scipy.special import expit
# その他
import pandas as pd
データ作成
# データ数
num_data = 200
# 年齢
x_1 = randint(15, 76, num_data) # 15から75歳の一様乱数
# 性別(0を女性、1を男性とします)
x_2 = randint(0, 2, num_data) # 0か1の乱数
# x_1, x_2に依存する変数Zを作成する
# ノイズの生成
e_z = randn(num_data)
# シグモイド関数に入れる部分
z_base = x_1 + (1-x_2)*15 - 40 + 5*e_z
# シグモイド関数を計算
z_prob = expit(0.1*z_base)
# テレビCMを見たかどうかの変数(0は見ていない、1は見た)
Z = np.array([])
for i in range(num_data):
Z_i = np.random.choice(2, size=1, p=[1-z_prob[i], z_prob[i]])[0]
Z = np.append(Z, Z_i)
# 購入量Yを作成
# ノイズの生成
e_y = randn(num_data)
Y = -x_1 + 20*x_2 + 15*Z + 80 + 10*e_y
# データフレームにまとめる
df = pd.DataFrame({'年齢': x_1,
'性別': x_2,
'CMを見た': Z,
'購入量': Y,
})
# 平均値を確認
print('CMを見たデータ')
print(df[df["CMを見た"] == 1.0].mean())
print("--------")
print('CMを見てないデータ')
print(df[df["CMを見た"] == 0.0].mean())
CMを見たデータ
年齢 54.968750
性別 0.460938
CMを見た 1.000000
購入量 50.485554
dtype: float64
--------
CMを見てないデータ
年齢 31.708333
性別 0.750000
CMを見た 0.000000
購入量 63.071757
dtype: float64
傾向スコアの推定
# scikit-learnからロジスティク回帰をimport
from sklearn.linear_model import LogisticRegression
# 説明変数
X = df[["年齢", "性別"]]
# 被説明変数(目的変数)
Z = df["CMを見た"]
# 回帰の実施
reg = LogisticRegression().fit(X,Z)
# 回帰した結果の係数を出力
print("係数beta:", reg.coef_)
print("係数alpha:", reg.intercept_)
係数beta: [[ 0.10797803 -1.90183645]]
係数alpha: [-2.92565399]
各人の傾向スコアを求める
Z_pre = reg.predict_proba(X)
print('傾向スコア')
print(Z_pre[0:5]) # 5人ほどの結果を見てみる
print("----")
print('CMを見たかの正解')
print(Z[0:5]) # 5人ほどの正解
傾向スコア
[[0.02255503 0.97744497]
[0.32178103 0.67821897]
[0.29000804 0.70999196]
[0.07481223 0.92518777]
[0.87125306 0.12874694]]
----
CMを見たかの正解
0 1.0
1 1.0
2 1.0
3 1.0
4 0.0
Name: CMを見た, dtype: float64
平均処置効果ATEを求める
ATE_i = Y/Z_pre[:, 1]*Z - Y/Z_pre[:, 0]*(1-Z)
ATE = 1/len(Y)*ATE_i.sum()
print("推定したATE", ATE)
推定したATE: 16.378782114604427
コメント