參考:
從假設檢驗到AB實驗——面試前你要準備什么?
一文入門A/B測試(含流程、原理及示例)
A/B testing(一):隨機分配(Random Assignment)里的Why and How
AB測試的簡介
我們都或多或少聽說過A/B測試,即便沒有聽過其實也被動的參與過——作為受試者。AB實驗是數據分析、產品運營、算法開發在工作中都時常接觸到的工作。在網站和APP的設計、產品的運營中,經常會面臨多個設計/運營方案的選擇。小到按鈕的位置、文案的內容、主題的顏色,再到注冊表單的設計、不同的運營方案,都有不同的選擇。A/B test可以幫助我們做出選擇,消除客戶體驗(UX)設計中不同意見的爭執。按鈕顏色、廣告算法、標簽排序,這些互聯網產品里常見的功能與展示都是在一次次AB實驗中得到優化。
所謂A/B test,其實類似于初中生物說的對照試驗。對用戶分組,每個組使用一個方案(方案應遵從單變量前提),在相同的時間維度上去觀察用戶的反應(體現在業務數據和用戶體驗數據上)。需要注意的是各個用戶群組的組成成分應當盡量相似,譬如新老用戶很有可能表現出較大的偏好差異。最后根據假設檢驗的結果,判斷哪些版本較之原版有統計意義上的差異,并根據效應量選出其中表現最好的版本。
一個完整的AB測試流程
- 分析現狀,建立假設:分析業務,確定最高優先級的改進點,作出假設,提出優化建議。
- 設定指標:設置主要指標來衡量版本的優劣;設置輔助指標來評估其他影響。
- 設計與開發:設計優化版本的原型并完成開發。
- 確定測試時長:確定測試進行的時長。
- 確定分流方案:確定每個測試版本的分流比例及其他分流細節。
- 采集并分析數據:收集實驗數據,進行有效性和效果判斷。
- 給出結論:①確定發布新版本;②調整分流比例繼續測試;③優化迭代方案重新開發,回到步驟1。
注意點
測試時長 : 測試時長不宜過短,否則參與實驗的幾乎都是該產品的高級用戶(短時間新用戶流入較少)。
分流(抽樣):應該保持同時性、同質性、唯一性、均勻性。
同時性:分流應該是同時的,測試的進行也應該是同時的。
同質性:也可以說是相似性,是要求分出的用戶群,在各維度的特征都相似??梢曰谟脩舻脑O備特征(例如手機機型、操作系統版本號、手機語言等)和用戶的其他標簽(例如性別、年齡、新老用戶、會員等級等)進行分群,每一個A/B測試試驗都可以選定特定的用戶群進行試驗。 控制變量
思考:如何判斷是不是真的同質? 可以采用AAB測試。抽出兩份流量進行A版本的測試,進行AA測試,并分別與B版本進行AB測試。通過考察A1和A2組是否存在顯著性差異,就可以確定試驗的分流是否同質了。唯一性: 即要求用戶不被重復計入測試。
-
均勻性: 要求各組流量是均勻的。希望把每一個用戶隨機分配到試驗組(treatment group)和控制組(control group),但為什么我們要做隨機分配(why we need to do random assignment),和應該怎么做隨機分配(how to do random assignment)可以參考:隨機分配里的Why and How。(統計學原理上,我沒有找到均勻性這一要求的依據,其實雙樣本的假設檢驗并不要求兩個樣本的數量相等或相近。當然從直觀上是可以理解,希望分出的用戶組越相近越好,包括人數的相近。)
- 1 現在有一個user,他有一個user_id
- 2 每run一個實驗,我們都有一個特定的salt,把這個user_id和這個salt拼接起來成一個長字符串;
- 3 把2中得到的長字符串扔進一個哈希函數(可以是MD5或者SHA1),這里用MD5,然后生成一條哈希數據(Hashed data);
- 4 取3中得到的哈希數據的頭六位字符,轉換成一個十六進制整數;
- 5 拿4中得到的整數去除以最大的六位十六進制數字(0xffffff),注意用浮點數相除,會得到一個介于0和1之間的浮點數。
- 6 根據第5步得到的浮點數是否大于預設閾值,決定這個用戶的分組。舉個例子,如果我們想得到50-50的平均分配,那么我們會預先設定一個閾值0.5,如果第5步得到的是0.4,那么這個用戶被分到控制組,因為它小于0.5,如果第5步得到的是0.6,這個用戶被分配到試驗組。
理由:
- 我之前做隨機的時候都是取隨機數和閾值進行比較,超過閾值一組,低于閾值的是另一組。 但是如果發生了錯誤,對用戶精準定位就會比較麻煩(隨機數是隨機的,需要靠隨機數種子控制,而且每次試驗取不同的隨機數種子)。這種方法是可以對每次試驗的用戶的分組進行實現的(每個用戶的id是確定的,每個試驗的salt也是確定的),不僅方便精確定位用戶,而且實驗出問題了也方便debugging。
- 一個實驗對應一個salt,每個實驗不一樣,這樣保證不同實驗有完全不一樣的隨機分配。因為一家公司一天可能做很多實驗,如果一個用戶老是被分到試驗組,他用戶體驗會比較差
- 最后得到的隨機分配結果還是比較'Random'的,雖然本質上都是假Random。
A/B測試只能有兩個版本么?
A/B test不是只能A方案和B方案,實際上一個測試可以包含A/B/C/D/E/……多個版本,但是要保證單變量,比如按鈕的顏色赤/橙/黃/綠/青/藍/紫,那么這七個方案是可以做A/B測試的;但如果某方案在旁邊新增了另一個按鈕,即便實驗結果產生了顯著差異,我們也無法判斷這種差異的成因究竟是誰。
同一段時間內可以做不同的A/B測試么?
比如一個test抽取總體20%的流量做按鈕顏色的實驗,另一個test也抽取總體20%的流量做布局樣式的實驗。是否可行?
我認為是可行的。但要求多個方案并行測試,同層互斥。如果從總體里,先后兩次隨機抽取20%流量,則很有可能會有重疊的用戶,既無法滿足控制單變量,又影響了用戶的使用體驗。
- 同層指的是在同一流量層中創建實驗,在此層中創建的實驗共享此層中的100%流量。
- 互斥指的是在此層中,一個設備有且只能分配到此層多個實驗中的某一個實驗。
假設檢驗的示例
數據:對web新舊頁面的A/B測試結果,來自Udacity的示例案例
- 用戶id
- 時間戳
- 分組(實驗組還是對照組)
- 展示頁面的新舊版本(新版本還是舊版本)
- 該用戶是否發生了轉化(0-未轉化、1-轉化)
ab測試目的:判斷新舊兩版頁面在用戶的轉化情況上是否有顯著區別
數據清洗
- 查看總的數據行數 和 (去重后)的獨立用戶進行比較
- 發現上述不一致(出現了重復統計的用戶)
- 利用duplicated考察重復數據
- 分組group和展示頁面的新舊版本landing_page應當是匹配的(treatment-new_page、control-old_page),但是發現存在不匹配的情況。 去掉不匹配的記錄。
- 去掉不匹配的記錄之后利用drop_duplicates去掉重復值(發現此時只有一條重復值)。
6.檢查缺失值,若存在缺失值可以進行直接刪除、填充等處理。 - 比較收到新頁面的用戶占比和老頁面的用戶占比。
假設檢驗
1.給出零假設和備擇假設:
記舊頁面的轉化率為,新頁面的轉化率為
我們的目標是為了說明, 因此作出如下假設:
即
即
這個業務可以抽象為:X是否被轉化,也就是兩點分布
。對于n個個體則為二項分布
。
因此有:
和
由于滿足兩點分布
有以上的鋪墊下面求
此刻和
都是未知的,所以要通過樣本成數進行估計,即設
,其中
因此:-
確定檢驗類型和檢驗統計量
獨立雙樣本。樣本大小n>30,總體的均值和標準差未知,用Z檢驗。檢驗統計量為:
為轉化率的聯合估計,
,其中
。
給定顯著性水平
方法一、直接根據公式計算檢驗統計量Z
舊版總受試用戶數: 145274 舊版轉化用戶數: 17489 舊版轉化率: 0.1204
新版總受試用戶數: 145310 新版轉化用戶數: 17872 新版轉化率: 0.1230
轉化率的聯合估計: 0.12169
檢驗統計量z: -2.1484
, 拒絕域為
。
z=-2.15落入拒絕域。在顯著性水平時,拒絕零假設。
假設檢驗并不能真正的衡量差異的大小,它只能判斷差異是否比隨機造成的更大。cohen-s-d,因此,我們在報告假設檢驗結果的同時,給出效應的大小。對比平均值時,衡量效應大小的常見標準之一是Cohen's d,中文一般譯作科恩d值:
這里的標準差,由于是雙獨立樣本的,需要用合并標準差(pooled standard deviations)代替。也就是以合并標準差為單位,計算兩個樣本平均值之間相差多少。雙獨立樣本的并合標準差可以如下計算:
Cohen's d的值約為-0.00797,絕對值很小。兩者雖有顯著性水平5%時統計意義上的顯著差異,但差異的效應量很小??梢院唵蔚乩斫鉃?strong>顯著有差異,但差異的大小不顯著。
利用python進行計算:
statsmodels.stats.proportion.proportions_ztest
第一個參數為兩個概率的分子
第二個參數為兩個概率的分母
第三個參數alternative[‘two-sided’, ‘smaller’, ‘larger’]分別代表[雙側,左尾,右尾]
import statsmodels.stats.proportion as sp
# alternative='smaller'代表左尾
z_score, p_value = sp.proportions_ztest([convert_old, convert_new], [n_old, n_new], alternative='smaller')
可以同時得到檢驗統計量和P值,得到的z值和前面計算的完全相同,落在拒絕域,故拒絕零假設。同時我們也得到了p值,用p值判斷與用檢驗統計量z判斷是等效的,這里p值約等于0.016, ,同樣也拒絕零假設。
在python中一般的z檢驗是這樣做的statsmodels.stats.weightstats.ztest
直接輸入兩組的具體數值即可,同樣有alternative參數控制檢驗方向。
蒙特卡洛模擬
蒙特卡羅法其實就是計算機模擬多次抽樣,不過感覺好強啊,結果直觀又容易理解,能夠很好的幫助初學者理解分布、p值、顯著性、分位數等概念。
在零假設成立的前提下( 即
),
為臨界情況(零假設中最接近備擇假設的情況)。如果連臨界的情況都可以拒絕,那么剩下的部分更可以拒絕(
)。
可以利用樣本數據求得整體的總轉化率,下面考察臨界情況,以
為新舊版共同的轉化率,即取
,分別進行n_old次和n_new次二項分布的抽樣。
重復抽樣多次,每次抽樣之后,都可以得到:舊版本與新版本之間的轉化率差值。而此數據的轉化率差值為:-0.0026。
可以觀測模擬得到轉化率差值的分布(由于概率相等,應該接近于正態分布)和此數據的轉化率差值的位置關系。
在diffs列表的數值中,有多大比例小于ab_data.csv中觀察到的轉化率差值?此次模擬的結果為0.0155,每次模擬的結果都不太相同,但都在p值(0.016)上下浮動,且隨著樣本量的增大,更加接近p值。
上圖的含義是,在時進行的10000次隨機模擬得到的差值中,只有1.55%比數據集中的差值更極端,說明我們這個數據集在
的前提下是小概率事件。如果
則得到的差值的分布仍然近似于正態分布但是其均值會右移,此時數據中的差值會更加極端。因此,此數據的結果是零假設中的極端情況,零假設很有可能是不成立的。
若diffs的分布就是標準正態(這里只是近似),則豎線左側的面積占比其實就是p值(左側or右側or雙側要根據備擇假設給定的方向
p值到底要多小才算真的小?
這需要我們自己給定一個標準,這個標準其實就是,是犯第一類錯誤的上界,常見的取值有0.1、0.05、0.01。
所謂第一類錯誤,即拒真錯誤,也就是零假設為真,我們卻拒絕了。在這個例子里就是——新舊版轉化率明明相等,只不過我們很非酋,得到的樣本正好比較極端,以至于我們錯誤地認為新舊版轉化率不等。所以要取定一個時,認為原假設在該顯著性水平下被拒絕。(如果我們取的是0.01而不是0.05,則這個例子里就拒絕不了零假設了。)
并不是越小越好,這與第二類錯誤的概率有關,
越小,則
就越大,而第二類錯誤的概率也需要控制在一定的范圍,因此不能一味地取極小的
。