首頁>技術>

譯者:朱先忠

引言

在許多情況下,我們不僅對估計因果效應感興趣,而且對不同用戶的這種效應是否不同也感興趣。我們可能有興趣瞭解一種藥物是否對不同年齡的人有不同的副作用。或者,我們可能有興趣瞭解廣告活動是否在某些地理區域特別有效。

這一知識至關重要,因為它使我們能夠實施針對性治療。如果一種藥物對兒童有嚴重的副作用,我們可能希望限制其使用人群僅向成年人銷售。或者,如果一個廣告活動只在英語國家有效,那麼它就不值得在其他地方展示。

在本文中,我們將探計利用機器學習算法揭示治療效果異質性的一些方法。

案例分析

假設我們是一家公司,有興趣瞭解新的保險功能能夠在多大程度上增加用戶收入。特別是,我們知道不同年齡段的用戶有不同的消費態度,我們懷疑保險功能的影響也可能因用戶年齡而異。

這些信息可能非常重要,例如對於像廣告定位或折扣設計這樣的應用尤其如此。如果我們發現保險功能增加了特定用戶群的收入,我們可能希望針對該用戶群的廣告或為他們提供個性化折扣。

我們選擇使用src.dgp庫提供的數據生成過程dgp_premium()函數來生成試驗中所需要的模擬數據。此外,我們還要從src.utils庫導入一些必要的繪圖函數和庫。

複製
from src.utils import *from src.dgp import dgp_premiumdgp = dgp_premium()df = dgp.generate_data(seed=5)df.head()1.2.3.4.

數據快照

實驗中,我們採集了300名用戶的數據,我們觀察他們產生的收入,以及他們是否獲得了醫療保險功能。此外,我們還記錄了這些用戶的年齡。

為了瞭解隨機化是否有效,我們使用美國Uber公司的causalml軟件包中的create_table_one函數生成了一個協變量平衡表,其中包含實驗組和對照組的可觀察特徵的平均值。顧名思義,這應該始終是您在因果推理分析中呈現的第一個表。

複製
from causalml.match import create_table_onecreate_table_one(df, "premium", ["age", "revenue"])1.2.

平衡表

由上表可見,大多數用戶都出現在對照組中,只有31個用戶位於實驗組中。不同組的平均年齡具有可比性(標準化平均差,SMD<0.1),而且看起來保險功能平均為每個用戶增加了2.59美元的收入。

那麼,保險功能的效果是否因用戶年齡而異?

一種簡單的方法是,在保險功能和年齡的充分交互作用下對收入進行迴歸分析。

複製
linear_model = smf.ols("revenue ~ premium * age", data=df).fit()linear_model.summary().tables[1]1.2.

線性迴歸結果

從上述分析結果看出,交互作用係數接近零且不顯著。似乎保險費方面不存在年齡差異效應。但事實上,這是真的嗎?因為交互作用係數僅捕捉線性關係。如果這種關係是非線性的呢?

我們可以通過直接繪製原始數據進行檢查。我們按年齡劃分收入,將數據分為保險用戶和非保險用戶。

複製
sns.scatterplot(data=df, x="age", y="revenue", hue="premium", s=40);1.

原始圖像

從原始數據來看,30歲至50歲的人的收入通常較高,而保險費對35歲至45歲的人的影響尤為顯著。

我們可以按年齡將估計的收入值加以可視化,其中包括治療和不治療兩種類型。

複製
def plot_TE(df, true_te=False):    sns.scatterplot(data=df, x="age", y="revenue", hue="premium", s=40, legend=True)    sns.lineplot(df["age"], df["mu0_hat"], label="$\mu_0$")    sns.lineplot(df["age"], df["mu1_hat"], label="$\mu_1$")    if true_te:        plt.fill_between(df["age"], df["y0"], df["y0"] + df["y1"], color="grey", alpha=0.2, label="True TE")    plt.title("Distribution of revenue by age and premium status")    plt.legend(title="Treated")1.2.3.4.5.6.7.8.

我們首先用(μ)計算預測收入;注意,我們並沒有使用保險特徵(μ)。然後,將它們與原始數據一起繪製出來。

複製
df["mu0_hat"] = linear_model.predict(df.assign(premium=0))df["mu1_hat"] = linear_model.predict(df.assign(premium=1))plot_TE(df)1.2.3.

顯示有原始數據的線性估計結果

正如我們從上圖中觀察到的,橙色線高於藍色線,這表明保費對收入有積極影響。然而,這兩條線基本上是平行的,表明實驗效果沒有異質性。

我們能否更精確一點?有沒有一種方法可以在沒有假設使用功能形式的情況下,以靈活的方式估計這種治療異質性?

答案是肯定的!我們可以使用機器學習方法靈活地估計異質治療效果。具體地說,我們將從現在開始細緻分析Künzel、Sekhon、Bickel和Yu介紹的下面三種流行方法:

n S-learner

n T-learner

n X-learner

初始設置

我們假設有這樣一組接受試驗者i=1,…,n,我們要觀察一個元組(X, D, Y)。其中:

實驗任務D∈{0,1} (保費)

響應 Y∈ (收入)

特徵向量 X∈ (年齡)

我們對估計平均實驗效果感興趣。

平均實驗效果

其中,Y表明個體i在實驗狀態d下的潛在結果。我們還做出以下假設:

假設1:無根據性(或可忽略性,或對可觀察項的選擇)

無根據假設

也就是,以可觀察特徵X為條件,實驗任務D與隨機分配一樣好。我們實際上假設的是,不存在我們觀察不到的情形——此情形下可能影響用戶是否獲得保險特徵和收入特徵。這是一個強有力的假設,我們觀察到的個性化特徵越多,就越有可能得到滿足。

假設2:穩定的單位治療費用(SUTVA)

SUTVA假設

也就是,潛在結果不取決於實驗狀態。在我們的案例中,我們排除了另一個用戶獲得保險功能可能會影響我的保險對收入的影響這一事實。違反上述SUTVA假設的一種最常見情形是存在網絡影響:例如,我的一個朋友通過社交網絡增加了我的就醫費用。

S-Learner方案

最簡單的元算法是單學習器(single learner)或S學習器(S-learner)。為了構建S-learner估計量,我們為所有觀察值擬合一個模型μ。

S-learner響應函數

估計量由經過和未經處理的預測值之間的差值得出,分別為d=1和d=0。

S-learner估計量

複製
def S_learner(dgp, model, y, D, X):    temp = dgp.generate_data(true_te=True).sort_values(X)    mu = model.fit(temp[X + [D]], temp[y])    temp["mu0_hat"] = mu.predict(temp[X + [D]].assign(premium=0))    temp["mu1_hat"] = mu.predict(temp[X + [D]].assign(premium=1))    plot_TE(temp, true_te=True)1.2.3.4.5.6.

讓我們使用sklearn包中的DecisionTreeRegressor函數,並使用決策樹迴歸模型來構建s-learner。篇幅所限,我不會在這裡詳細介紹決策樹信息;僅說明下決策樹是一種非參數估計量,它使用訓練數據將狀態空間(在我們的例子中是保費和年齡)分割成塊,並預測結果(在我們的例子中是收入)作為其在每個塊中的平均值。

複製
from sklearn.tree import DecisionTreeRegressormodel = DecisionTreeRegressor(min_impurity_decrease=0.001)S_learner(dgp, model, y="revenue", D="premium", X=["age"])1.2.3.

估計效果與真實實驗效果比較

上圖給出了此部分代碼的結果數據以及響應函數μ(x,1)和μ(x,0)圖示。另外,我還使用灰色繪製了真實響應函數之間的區域:真實實驗效果。

正如我們從圖中看到的,S-learner足夠靈活,能夠理解實驗組和對照組之間的水平差異(我們有兩條獨立的線)。此外,它還能夠很好地捕捉到對照組的響應函數μ(x,1),但沒有很好地捕捉到實驗組的控制函數μ(x,1)。

S-learner的問題是,它學習的是單個模型,因此我們必須希望該模型能夠揭示實驗D中的異質性,但情況可能並非如此。此外,如果由於X的高維數,模型被嚴重正則化,則可能無法恢復任何實驗效果。例如,對於決策樹,我們可能不會在實驗變量D上進行拆分。

T-learner方案

為了構建雙學習器(two-learner)或T-learner的估計量,我們擬合了兩個不同的模型,一個用於實驗單元,另一個用於對照單元。

T-learner響應函數

其中,估計量由兩個模型的預測值之差得出。

T-learner估計量

複製
def T_learner(df, model, y, D, X):    temp = dgp.generate_data(true_te=True).sort_values(X)    mu0 = model.fit(temp.loc[temp[D]==0, X], temp.loc[temp[D]==0, y])    temp["mu0_hat"] = mu0.predict(temp[X])    mu1 = model.fit(temp.loc[temp[D]==1, X], temp.loc[temp[D]==1, y])    temp["mu1_hat"] = mu1.predict(temp[X])    plot_TE(temp, true_te=True)1.2.3.4.5.6.7.

我們像以前一樣使用決策樹迴歸模型。但是這次,我們為實驗組和對照組擬合了兩個獨立的決策樹。

複製
T_learner(dgp, model, y="revenue", D="premium", X=["age"])1.

真實與估計的實驗效果對比示意圖

正如我們所見,T-learner比S-learner靈活得多,因為它適合兩種不同的模型。而且,對照組的響應函數μ(x)仍然非常準確;同時,實驗組的響應函數μ(x)也比以前更加靈活。

現在的問題是,對於每個預測問題,我們只使用了一小部分數據,而S-learner使用了所有數據。通過擬合兩個獨立的模型,我們正在丟失一些信息。此外,通過使用兩種不同的模型,我們可能會在沒有異質性的地方獲得異質性。例如,使用決策樹,即使數據生成過程相同,我們也可能使用不同的樣本獲得不同的分割。

X-learner方案

交叉學習器或X學習器(X-learner)估計量是T-learner估計量的擴展。其構建方式如下:

1. 對於T-learner,分別使用實驗單元與對照單元來單獨計算μ(x)和μ0)(x)的模型。

2. 計算增量δ函數,如下所示:

增量δ函數計算方法

3. 從X預測Δ,並通過實驗單元與對照單元計算τ(x)。

4. 估計傾向得分,即實驗概率

傾向得分

5. 計算實驗效果。

X-learner估計值

為了更好地理解X-learner是如何工作的,我們可以像以前一樣來直觀地繪製出響應函數。然而,該方法並不直接依賴於響應函數。那麼,我們還能恢復偽響應函數嗎?是可以的。

首先,我們可以將實驗效果改寫為:

X-learner估計分解展開式

因此,X-learner估計的偽響應函數就可以寫成如下形式:

X-learner偽響應函數

正如我們所見,X-learner結合了真實值Y和估計值μ(x),並按傾向分數e(x)加權(即估計的實驗概率)。

這是什麼意思呢?這意味著,如果對於某些觀察值,我們可以清楚地將實驗組和對照組分開,那麼對照響應函數μ將獲得大部分權重。相反,如果兩組無法區分,則實際結果Y將獲得大部分權重。

為了說明該方法,我將通過經最近觀測得到的近似Y並使用Kneighbors迴歸函數來構建偽響應函數。我將使用Logistic迴歸中的LogisticRegressionCV函數來估計傾向分數。

複製
from sklearn.neighbors import KNeighborsRegressorfrom sklearn.linear_model import LogisticRegressionCVdef X_learner(df, model, y, D, X):    temp = dgp.generate_data(true_te=True).sort_values(X)        # Mu    mu0 = model.fit(temp.loc[temp[D]==0, X], temp.loc[temp[D]==0, y])    temp["mu0_hat_"] = mu0.predict(temp[X])    mu1 = model.fit(temp.loc[temp[D]==1, X], temp.loc[temp[D]==1, y])    temp["mu1_hat_"] = mu1.predict(temp[X])        # Y    y0 = KNeighborsRegressor(n_neighbors=1).fit(temp.loc[temp[D]==0, X], temp.loc[temp[D]==0, y])    temp["y0_hat"] = y0.predict(temp[X])    y1 = KNeighborsRegressor(n_neighbors=1).fit(temp.loc[temp[D]==1, X], temp.loc[temp[D]==1, y])    temp["y1_hat"] = y1.predict(temp[X])        #計算權重    e = LogisticRegressionCV().fit(y=temp[D], X=temp[X]).predict_proba(temp[X])[:,1]    temp["mu0_hat"] = e * temp["y0_hat"] + (1-e) * temp["mu0_hat_"]    temp["mu1_hat"] = (1-e) * temp["y1_hat"] + e * temp["mu1_hat_"]        #繪圖    plot_TE(temp, true_te=True)X_learner(df, model, y="revenue", D="premium", X=["age"])1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.

真實和估計實驗結果示意圖

從這張圖中我們可以清楚地看到,X-learner的主要優勢在於它能夠根據上下文調整響應函數的靈活性。在狀態空間中有大量數據的區域(對照組),它主要使用估計的響應函數。另外,在狀態空間中還有一個顯示有少量數據的區域(實驗組),這是使用觀測值本身的結果。

總結

在本文中,我們學習了Künzel、Sekhon、Bickel、Yu在2019論文中引入的不同估計量,它們利用靈活的機器學習算法來估計異質實驗效果。這三個估計量的複雜程度不同。其中,S-learner適合單個估計量,包括作為協變量的實驗指標。T-learner適合實驗組和對照組的兩個獨立估計量。最後,X-learner是T-learner的擴展,根據實驗組和對照組的可用數據量,能夠實現不同程度的靈活性。

異質處理效果的估計對於治療靶向至關重要,這在企業應用中尤其關鍵。事實上,這篇文獻的引用量迅速增加,並受到廣泛關注。在眾多其他論文中,值得一提的是Nie和Wager(2021)的R-learner程序以及Athey和Wager(2018)的因果樹和森林。

10
最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • 如何使用ROS 2簡化機器人的硬件加速