最典型的因果图_因果关系分析图制作
1 dowhy介紹
github地址:microsoft/dowhy
 dowhy 文檔:DoWhy | An end-to-end library for causal inference
1.1 dowhy的分析流程
參考材料:
 因果推斷框架 DoWhy 入門
如果有的東西是不可以驗證的呢?比如我們的人生,如果當初的你去了不同的城市學校公司,那人生肯定不同了,然而有什么時光倒流的模型嗎?
DoWhy使用貝葉斯網絡模型框架,用戶可以在其中指定他們對數據生成過程的了解以及不了解的信息。為了進行estimation,作者提供了基于potential-outcomes框架的方法,例如匹配,分層和工具變量。
DoWhy 的整個因果推斷過程可以劃分為四大步驟:
步驟一:「因果圖建?!梗╩odel):
利用假設(先驗知識)對因果推斷問題建模,構建基礎的因果圖,你可以只提供部分圖,來表示某些變量的先驗知識(即指定其類型),DoWhy 支持自動將剩余的變量視為潛在的混雜因子。
步驟二:「因果圖表達式再識別」(identify):
 在假設(模型)下識別因果效應的表達式(因果估計量),準則:
- 「后門準則」(Back-door criterion)
- 「前門準則」(Front-door criterion)
- 「工具變量」(Instrumental Variables)
- 「中介-直接或間接結果識別」(Mediation-Direct and indirect effect identification)
步驟三:「因果效應估計」(estimate):
 使用統計方法對表達式進行估計,識別之后的估計
- 「基于估計干預分配的方法」
- 基于傾向的分層(Propensity-based Stratification)
- 傾向得分匹配(Propensity Score Matching)
- 逆向傾向加權(Inverse Propensity Weighting)
 
- 「基于估計結果模型的方法」
- 線性回歸(Linear Regression)
- 廣義線性模型(Generalized Linear Models)
 
- 「基于工具變量等式的方法」
- 二元工具/Wald 估計器(Binary Instrument/Wald Estimator)
- 兩階段最小二乘法(Two-stage least squares)
- 非連續回歸(Regression discontinuity)
 
- 「基于前門準則和一般中介的方法」
- 兩層線性回歸(Two-stage linear regression)
 
此外,DoWhy 還支持調用外部的估計方法,例如 EconML 與 CausalML。
步驟四:「反駁」(refute)
 使用各種魯棒性檢查來驗證估計的正確性
- 「添加隨機混雜因子」:添加一個隨機變量作為混雜因子后估計因果效應是否會改變(期望結果:不會)
- 「安慰劑干預」:將真實干預變量替換為獨立隨機變量后因果效應是否會改變(期望結果:因果效應歸零)
- 「虛擬結果」:將真實結果變量替換為獨立隨機變量后因果效應是否會改變(期望結果:因果效應歸零)
- 「模擬結果」:將數據集替換為基于接近給定數據集數據生成過程的方式模擬生成的數據集后因果效應是否會改變(期望結果:與數據生成過程的效應參數相匹配)
- 「添加未觀測混雜因子」:添加一個額外的與干預和結果相關的混雜因子后因果效應的敏感性(期望結果:不過度敏感)
- 「數據子集驗證」:將給定數據集替換為一個隨機子集后因果效應是否會改變(期望結果:不會)
- 「自助驗證」:將給定數據集替換為同一數據集的自助樣本后因果效應是否會改變(期望結果:不會)
2 案例
參考材料:
 因果推斷框架 DoWhy 入門
2.1 數據獲取與整理
下面將通過一個基于真實世界數據的案例對 DoWhy 的工作流程進行進一步說明。在本例中,我們的研究問題是估計當消費者在預定酒店時,為其分配一間與之前預定過的房間不同的房間對消費者取消當前預定的影響。分析此類問題的金標準是「隨機對照試驗」(Randomized Controlled Trials),即每位消費者被隨機分配到兩類干預中的一類:為其分配與之前預定過的房間相同或不同的房間。
 is_cancelled是Y;
 干預,treatment/V 是換一個房間;
 其他都是混淆變量W
然而,實際上對于酒店來說其不可能進行這樣的試驗,只能使用歷史數據(觀察性數據)來進行評估。我們首先導入相關包與數據集:
數據集處理:
import dowhy
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import logging
logging.getLogger("dowhy").setLevel(logging.INFO)
dataset = pd.read_csv('https://raw.githubusercontent.com/Sid-darthvader/DoWhy-The-Causal-Story-Behind-Hotel-Booking-Cancellations/master/hotel_bookings.csv')
dataset.columns
# Total stay in nights
dataset['total_stay'] = dataset['stays_in_week_nights']+dataset['stays_in_weekend_nights']
# Total number of guests
dataset['guests'] = dataset['adults']+dataset['children'] +dataset['babies']
# Creating the different_room_assigned feature
dataset['different_room_assigned']=0
slice_indices =dataset['reserved_room_type']!=dataset['assigned_room_type']
dataset.loc[slice_indices,'different_room_assigned']=1
# Deleting older features
dataset = dataset.drop(['stays_in_week_nights','stays_in_weekend_nights','adults','children','babies'
                        ,'reserved_room_type','assigned_room_type'],axis=1)
dataset.isnull().sum() # Country,Agent,Company contain 488,16340,112593 missing entries
dataset = dataset.drop(['agent','company'],axis=1)
# Replacing missing countries with most freqently occuring countries
dataset['country']= dataset['country'].fillna(dataset['country'].mode()[0])
dataset = dataset.drop(['reservation_status','reservation_status_date','arrival_date_day_of_month'],axis=1)
dataset = dataset.drop(['arrival_date_year'],axis=1)
# Replacing 1 by True and 0 by False for the experiment and outcome variables
dataset['different_room_assigned']= dataset['different_room_assigned'].replace(1,True)
dataset['different_room_assigned']= dataset['different_room_assigned'].replace(0,False)
dataset['is_canceled']= dataset['is_canceled'].replace(1,True)
dataset['is_canceled']= dataset['is_canceled'].replace(0,False)
dataset.dropna(inplace=True) # 新增對NA值的處理
dataset.columns
2.2 如何簡單證明變量之間的因果關系
非常簡單的看Y ~ X隨機抽取中,多少會是相等的,如果100%相等,大概率X-> Y;
如果50%那就不確定有無因果關系
針對目標變量 is_cancelled 與 different_room_assigned ,我們隨機選取 1000 次觀測查看有多少次上述兩個變量的值相同(即可能存在因果關系)
 檢查的方法:
# different_room_assigned  - 518 不確定因果關系
counts_sum=0
for i in range(1,10000):
        counts_i = 0
        rdf = dataset.sample(1000)
        counts_i = rdf[rdf["is_canceled"]== rdf["different_room_assigned"]].shape[0]
        counts_sum+= counts_i
counts_sum/10000
# 預約變化 booking_changes - 492,不確定
counts_sum=0
for i in range(1,10000):
        counts_i = 0
        rdf = dataset[dataset["booking_changes"]==0].sample(1000)
        counts_i = rdf[rdf["is_canceled"]== rdf["different_room_assigned"]].shape[0]
        counts_sum+= counts_i
counts_sum/10000
2.3 步驟一:因果圖建模
import pygraphviz
model= dowhy.CausalModel(
        data = dataset,
        graph=causal_graph.replace("\n", " "),
        treatment='different_room_assigned',
        outcome='is_canceled')
model.view_model()
from IPython.display import Image, display
display(Image(filename="causal_model.png"))
2.4 步驟二:識別
我們稱「干預」(Treatment)導致了「結果」(Outcome)當且僅當在其他所有狀況不變的情況下,干預的改變引起了結果的改變。因果效應即干預發生一個單位的改變時,結果變化的程度。下面我們將使用因果圖的屬性來識別因果效應的估計量。
#Identify the causal effect
identified_estimand = model.identify_effect()
print(identified_estimand)
輸出結果:
### Estimand : 1
Estimand name: backdoor
Estimand expression:
            d                                                                 
──────────────────────────(Expectation(is_canceled|days_in_waiting_list,bookin
d[different_room_assigned]                                                    
g_changes,total_stay,is_repeated_guest,previous_bookings_not_canceled,meal,lea
d_time,market_segment,guests,country))
                                      
Estimand assumption 1, Unconfoundedness: If U→{different_room_assigned} and U→is_canceled then P(is_canceled|different_room_assigned,days_in_waiting_list,booking_changes,total_stay,is_repeated_guest,previous_bookings_not_canceled,meal,lead_time,market_segment,guests,country,U) = P(is_canceled|different_room_assigned,days_in_waiting_list,booking_changes,total_stay,is_repeated_guest,previous_bookings_not_canceled,meal,lead_time,market_segment,guests,country)
### Estimand : 2
Estimand name: iv
No such variable found!
### Estimand : 3
Estimand name: frontdoor
No such variable found!
這里的輸出結果其實滿費解的,包含了后門準則檢驗、前門準則檢驗、IV工具變量檢驗三個;
 主要的目的是了解當下因果圖里面的變量之間的結構關系
- 如果存在后門準則的變量,就跟現在這樣,那么說明T-> Y之間有混淆變量是在兩者的后門路徑上,那么這些W變量都會直接影響T/Y;
- 前門準則,案例中沒有,如果有,則說明存在變量是,T -> Z -> Y,是在T-Y的前門路徑上,會起到“中介”的效果
2.5 步驟三:估計因果效應
因果效應即干預進行單位改變時結果的變化程度。DoWhy 支持采用各種各樣的方法計算因果效應估計量(回歸系數),并最終返回單個平均值。
 代碼如下所示:
estimate = model.estimate_effect(identified_estimand,
                                 method_name="backdoor.propensity_score_stratification",target_units="ate")
print(estimate)
來看看估計方法method_name有幾種類型:
 * Propensity Score Matching: "backdoor.propensity_score_matching"
 * Propensity Score Stratification: "backdoor.propensity_score_stratification"
 * Propensity Score-based Inverse Weighting: "backdoor.propensity_score_weighting"
 * Linear Regression: "backdoor.linear_regression"
 * Generalized Linear Models (e.g., logistic regression): "backdoor.generalized_linear_model"
 * Instrumental Variables: "iv.instrumental_variable"
 * Regression Discontinuity: "iv.regression_discontinuity"
傾向性評分法的幾種方法都有:PSM / PSS / PSW,
 額外的還有線性回歸 、 logistic回歸、工具變量法等。
 
 target_units因果效應的類型有ATE / ATT/ ATC :
# ATE = Average Treatment Effect
# ATT = Average Treatment Effect on Treated (i.e. those who were assigned a different room)
# ATC = Average Treatment Effect on Control (i.e. those who were not assigned a different room)
估計平均干預效應(ATE),也可以選擇估計干預組(ATT)或對照組(ATC)的因果效應
來看一下整體的輸出的結果為:
*** Causal Estimate ***
## Identified estimand
Estimand type: nonparametric-ate
### Estimand : 1
Estimand name: backdoor
Estimand expression:
            d                                                                 
──────────────────────────(Expectation(is_canceled|days_in_waiting_list,bookin
d[different_room_assigned]                                  
g_changes,total_stay,is_repeated_guest,previous_bookings_not_canceled,meal,lea
d_time,market_segment,guests,country))
Estimand assumption 1, Unconfoundedness: If U→{different_room_assigned} and U→is_canceled then P(is_canceled|different_room_assigned,days_in_waiting_list,booking_changes,total_stay,is_repeated_guest,previous_bookings_not_canceled,meal,lead_time,market_segment,guests,country,U) = P(is_canceled|different_room_assigned,days_in_waiting_list,booking_changes,total_stay,is_repeated_guest,previous_bookings_not_canceled,meal,lead_time,market_segment,guests,country)
## Realized estimand
b: is_canceled~different_room_assigned+days_in_waiting_list+booking_changes+total_stay+is_repeated_guest+previous_bookings_not_canceled+meal+lead_time+market_segment+guests+country
Target units: ate
## Estimate
Mean value: -0.3354060769218102
ate 平均估計效應,估計方法選擇的是「傾向得分匹配」,所以的含義是,different_room_assigned = 1 比 different_room_assigned = 0取消的概率,
 也就是說,換房間(different_room_assigned = 1 )比不換房間(different_room_assigned = 0 ),取消概率高33.5%
2021-12-2 更新:
這里概率高 33.5%感覺有歧義,在這篇文章因果推斷框架 DoWhy 入門中是33.5%,我回到最原始的原文:DoWhy-The Causal Story Behind Hotel Booking Cancellations,這里表示,換房間(different_room_assigned = 1)比不換房間(different_room_assigned = 0),取消概率低25%,換房間反而是好事兒? 作者就在猜,可能發生在check-in的時候,肯定要住,換了更好
2.6 反駁結果
反駁的過程就是檢驗最終結果的過程,就跟回歸系數還需要P檢驗一樣。
 我們需要驗證假設的正確性。DoWhy 支持通過各種各樣的魯棒性檢查方法來測試假設的正確性。下面進行其中幾項測試:
**「添加隨機混雜因子」。**如果假設正確,則添加隨機的混雜因子后,因果效應不會變化太多。
refute1_results=model.refute_estimate(identified_estimand, estimate,
        method_name="random_common_cause")
print(refute1_results)
Refute: Add a Random Common Cause
Estimated effect:-0.3359905635051836
New effect:-0.3365742386420179 # 基本保持穩定
結果解讀:
 修改之后的New effect估計量為-0.3365742386420179,與之前的model.estimate_effect估計的Estimated effect為-0.3354060769218102,差不多
**「安慰劑干預」。**將干預替換為隨機變量,如果假設正確,因果效應應該接近 0。
refute2_results=model.refute_estimate(identified_estimand, estimate,
        method_name="placebo_treatment_refuter")
print(refute2_results)
Refute: Use a Placebo Treatment
Estimated effect:-0.3359905635051836
New effect:-0.00028277666065981027 # 因果效應歸零
p value:0.43999999999999995
結果解讀:
 new effect 結果約等于0,屬于正常范圍;這種方法含義就是,隨便給你整點數,你要是跟這些數字都有關系,那你之前的因果關系就很有問題了。
「數據子集驗證」。在數據子集上估計因果效應,如果假設正確,因果效應應該變化不大。
refute3_results=model.refute_estimate(identified_estimand, estimate,
        method_name="data_subset_refuter")
print(refute3_results)
Refute: Use a subset of data
Estimated effect:-0.3359905635051836
New effect:-0.33647521997465524
p value:0.35
結果解讀:
 我們的因果模型基本可以通過上述幾個測試(即取得預期的結果)。因此,根據估計階段的結果,我們得出結論:當消費者在預定房間時,為其分配之前預定過的房間( different_room_assigned = 0 )所導致的平均預定取消概率( is_canceled )要比為其分配不同的房間( different_room_assigned = 1 )低 「33%」。
2.7 與普通ML分類模型比較特征重要性
# plot feature importance using built-in function
from xgboost import XGBClassifier
from xgboost import plot_importance
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, classification_report
from matplotlib import pyplot
# split data into X and y
X = dataset_copy # 這里使用的是copy,請自行復制(處理完后的數據)
y = dataset_copy['is_canceled']
X = X.drop(['is_canceled'],axis=1)
# One-Hot Encode the dataset
X = pd.get_dummies(X)
# split data into train and test sets
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=26)
# fit model no training data
model = XGBClassifier()
model.fit(X_train, y_train)
# make predictions for test data and evaluate
y_pred = model.predict(X_test)
predictions = [int(value) for value in y_pred] # 注意這里之前用的是round,會報錯
accuracy = accuracy_score(y_test, predictions)
print("Accuracy: %.2f%%" % (accuracy * 100.0))
print(classification_report(y_test, predictions))
給出特征重要性
# plot feature importance
plot_importance(model,max_num_features=20)
pyplot.show()
 可以看出,different_room_assigned 變量的特征權重并不是非常高,這與我們的因果推斷結果有一定的差異性,這也體現了因果推斷模型和傳統機器學習模型在原理上的差異性,我們需要根據實際的需要來選擇最合適的方法。
以上就是 DoWhy 入門的全部內容,總的來看, DoWhy 為因果推斷研究提供了一個非常方便的工具,研究人員需要做的就是先對數據進行分析并給出適當的假設(可以是多個),然后將數據輸入到 DoWhy 提供的框架中進行自動化估計(需要指定估計方法與估計目標),最后對估計的結果進行魯棒性測試以驗證假設的正確性,即可得出較為合理的因果關系推論。
總結
以上是生活随笔為你收集整理的最典型的因果图_因果关系分析图制作的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: CRM WebUI的错误消息是如何从后台
- 下一篇: SSTI 学习笔记
