AB实验平台:为什么AB实验平台必不可少?
1.概述
1.1 為什么AB實驗平臺必不可少?
1.1.1 依據(jù)統(tǒng)計數(shù)據(jù)做決策
當(dāng)面對眾多選擇時,我們應(yīng)該怎么選才能最大化我們的收益(或者說最小化我們的開銷)呢?舉例來說,怎么選擇最優(yōu)的上班的路線才能使途中花費的時間最少?在這個例子中,我們的收益可能是依據(jù)于上班時間,但同樣可以是燃料成本或交通時間。
1.1.2 什么問題用于A/B測試?
任何問題,只要它的每個選項能夠被多次進行測試,并且每個選項在被測試時都能返回固定的結(jié)果,那么它就能使用A/B測試技術(shù)來進行優(yōu)化。
1.1.3 大廠產(chǎn)品
市面上可參考的平臺:
1.2 平臺架構(gòu)
1.2.1 架構(gòu)設(shè)計圖
@TODO
1.2.2 使用接口定義
請求數(shù)據(jù)
-- 按單一AB實驗訪問 {"page": 1,"uid": "111122233" }-- 按一系列AB實驗訪問 {"biz": "test","uid": "111122233" }返回數(shù)據(jù)
{"code": 0,"expid": [1, 2, 6],"params": {"add_recall": "deepfm","use_rank": "dnn"} }1.3 AB平臺的3大特性
AB平臺要發(fā)揮數(shù)據(jù)驅(qū)動的作用,要做到三大特性:并行性、先驗性、科學(xué)性。
1.3.1 并行性:實驗正交進行
基準(zhǔn)點
-
正交性:各層之間互相不影響
-
均勻性:實驗組和對照組的流量是對等的
-
充足性:每個分支實驗的流量是足夠的
-
日均人數(shù)少于1000的實驗結(jié)果波動將會非常大
-
日均人數(shù)大于2W的實驗結(jié)果更具參考性
-
最終目標(biāo)
-
快速構(gòu)建實驗
-
隨時上下線實驗
-
同時支持多組實驗
實現(xiàn)原理
**前提:在流量無窮的情況,每個層A組和B組的流量是均勻的
重點關(guān)注
-
實驗流量分配
-
排除實驗自身干擾
1.3.2 先驗性:驗證決策過程而非決策本身
A/B測試是當(dāng)面對一個改進目標(biāo)有兩種甚至多種不同的方案的時候,為了避免盲目決策帶來的不確定性好隨機性,將各種不同的實驗同時放到線上讓實際目標(biāo)群體選擇,然后利用實際數(shù)據(jù)分析的結(jié)果來輔助進行決策的一種方式和手段。
所以A/B的常見的應(yīng)用場景應(yīng)該滿足一下4個條件:
-
優(yōu)化場景
- A/B測試并不能給出解決方案,而只是輔助我們對若干候選方案進行選擇。
-
量化指標(biāo)
- 要運用A/B測試來改進系統(tǒng),另外一個重要的因素就是要改進的目標(biāo)需要有一個或多個可量化的明確指標(biāo),并且這個指標(biāo)會直接或間接收到該方案的影響
-
用戶穩(wěn)定
- 由于A/B測試將不同的設(shè)計或者策略呈現(xiàn)給一些隨機的用戶群體,之后統(tǒng)計各用戶群體的群體指標(biāo),因此用戶群體的選擇和劃分也是A/B測試是否成功的重要因素。
-
長期反饋
- 在設(shè)計和實現(xiàn)A/B測出實驗的時候,要盡量控制除實驗之外的影響因素保持固定
建議流程
-
步驟一:提出目標(biāo)
-
步驟二:建立假設(shè)
-
步驟三:設(shè)計方案
-
步驟四:執(zhí)行實驗
-
步驟五:分析數(shù)據(jù)
-
步驟六:發(fā)布版本
案例講解
搜索是發(fā)現(xiàn)好物的開始,是電商平臺主要的流量入口,可以說三分天下有其一
案例背景
-
搜索使用日均人次:3045w+(曝光)
-
搜索推薦詞的日均CTR:0.38%
怎樣提高搜索推薦詞的CTR,節(jié)省用戶時間?
步驟一:提出目標(biāo)
提升CTR:節(jié)省更多用戶更多時間,提升平臺體驗
步驟二:建立假設(shè)
CTR的原因(假設(shè))
-
前端體驗不佳
-
對搜索詞進行標(biāo)簽分類
-
通過色彩突出搜索詞
-
搜索詞添加熱度提示
-
-
后端推薦策略不佳
-
發(fā)掘用戶偏好
-
匹配用戶歷史搜索
-
協(xié)同過濾算法
-
步驟三:設(shè)計方案
-
A001:推薦詞添加類別標(biāo)簽,如書籍/店鋪/話題
-
A002:推薦詞依據(jù)排列的位置,字體顏色漸變
-
A003:推薦詞前三添加熱度指數(shù),體現(xiàn)詞熱度
步驟四:執(zhí)行實驗
-
抽樣人群:20000人,權(quán)衡實驗效果和成本
-
均勻分配:A001、A002、A003 三組均勻流量保證人群特征相似
-
上線環(huán)境:同時上線
-
監(jiān)控數(shù)據(jù):一致的統(tǒng)計方式,評估標(biāo)準(zhǔn)
步驟五:分析數(shù)據(jù)
-
數(shù)據(jù)短期看比較,長期看趨勢,要經(jīng)過一段的檢驗
-
總體的提升置信度提示等等
步驟六:發(fā)布版本
基于5的數(shù)據(jù)分析,選擇A001是毫無爭議的
1.3.3 科學(xué)性:經(jīng)典的統(tǒng)計學(xué)理論
決策相關(guān)的統(tǒng)計學(xué)參考,詳見2.2節(jié)。
2 原理
2.1 樣本分流
谷歌分層實驗框架論文

重疊實驗框架.pdf
2.2 提升的衡量
(p-value , 置信區(qū)間 ,power的具體含義和計算方法)
2.2.1 基礎(chǔ)概念
互逆假設(shè)
統(tǒng)計學(xué)上有2個互逆的假設(shè):
- 原假設(shè):我們希望通過試驗結(jié)果推翻的假設(shè)
- 備擇假設(shè):我們希望通過試驗結(jié)果驗證的假設(shè)
在A/B測試過程中,我們試驗的目的是通過反證法證明測試版本和對照版本有明顯的不同(提升),因此在這個場景中,原假設(shè)就是原始版本和試驗版本無差異,而備擇假設(shè)就是這兩個版本存在差異,因此,A/B試驗的目的,做A/B試驗的目的就是推翻2個版本無差異的原假設(shè),驗證他們有差異的備擇假設(shè)。
**
在統(tǒng)計學(xué)上,存在兩大錯誤,一是棄真錯誤,二是納偽錯誤。
第一類錯誤(棄真錯誤):原假設(shè)為真時拒絕了原假設(shè)
首先我們?nèi)菀追傅木褪堑谝活愬e誤,就是原假設(shè)為真時拒絕了原假設(shè),說白了就是過來就是2個版本無差異時候,我們錯誤 的認為他們有差異(從統(tǒng)計學(xué)角度講也叫棄真錯誤)這個錯誤的后果非常嚴重,所以我們把這它的標(biāo)準(zhǔn)設(shè)一個值0.05, 它其實就是一個概率, 這個概率就是我們?nèi)菰S自己出錯的概率。
這個5%就是在統(tǒng)計學(xué)里的 α , 它代表著我們這個試驗結(jié)果的置信水平。與這個置信水平相對應(yīng)的就是置信區(qū)間的置信度,由 1- α 得出,所以你在這里看到如果 α 是0.05,那置信度就是0.95,也就是說,如果我們?nèi)菰S自己出錯的幾率是5%,那我們將得到一個有 95% 的可能性包含真實的總體均值區(qū)間范圍,如果你把這個 α 調(diào)整成0.07,那你的置信區(qū)間的置信度將變成93%。
由于 α 是我們自己設(shè)置的,那么當(dāng)然需要通過數(shù)據(jù)去驗證一下,這個通過計算出來的值就是p-value , p 的定義就是,如果兩個版本無差異的前提下,得到當(dāng)前試驗數(shù)據(jù)的概率。
**
第二類錯誤(納偽錯誤):原假設(shè)為假時接受了原假設(shè)
第二類錯誤是指原假設(shè)為假時接受了原假設(shè),即當(dāng)2個版本有差異時候,我們錯誤的認為他們沒有差異 ,這個錯誤的概率在統(tǒng)計學(xué)角度也稱為取偽錯誤,記為 β ,這個概率可以相對大一些,業(yè)界大約定俗成的一個標(biāo)準(zhǔn)就是10%和20%的概率。
和顯著性水平一樣,為了避免我們犯第二類錯誤,我們需要通核算 β 從而計算出另一個參數(shù)來給我們參考,就是統(tǒng)計功效,和核算置信區(qū)間的置信度類似,它是的思路是 1-β 來得出 (統(tǒng)計功效 power = 1 – β )
** 統(tǒng)計功效是指版本差異(效果)為某個指定值時,通過顯著性檢驗?zāi)苷_地把差異檢驗出來的概率。說白了就是,假設(shè)兩個版本的確存在差異,我們能夠正確拒絕原假設(shè),獲得統(tǒng)計顯著性結(jié)果(95%置信區(qū)間中數(shù)據(jù))的概率。
** 統(tǒng)計功效的核算涉及樣本數(shù)量,方差, α 、以及最小變化度或者置信區(qū)間下限。
由此可見,只有我們把第一類錯誤控制在5%以內(nèi),第二類錯誤控制在10%-20%左右,我們才可以說得出具有參考價值的出的試驗數(shù)據(jù)。換句話說,我們在做A/B測試時,試驗結(jié)果達到95%的置信度,以及80%-90%的統(tǒng)計功效時,它對我們來說才是有意義、可以作為決策參考的。
**
各值推理及計算
因為AB的統(tǒng)計符合二項分布,接下來的公式用二項分布做推導(dǎo)
p-value
p-value的定義是,如果兩個版本無差異的前提下,得到當(dāng)前試驗數(shù)據(jù)的概率,其計算公式如下圖所示,在A/B實驗中,采用右側(cè)檢驗的方式

中心極限定理說明,在適當(dāng)?shù)臈l件下,大量相互獨立隨機變量的均值經(jīng)適當(dāng)標(biāo)準(zhǔn)化后依分布收斂于正態(tài)分布(具體推導(dǎo)參考大數(shù)定理、中心極限定理),在樣本數(shù)量比較大情況下,可以采用z檢驗。
ABtest需要采用雙樣本對照的z檢驗公式。
**
z=pexp?pctrlSEexp2+SEctrl2z = \frac{p_{exp} - p_{ctrl}}{\sqrt{SE_{exp}^2 + SE_{ctrl}^2}}z=SEexp2?+SEctrl2??pexp??pctrl??
**
其中p代表轉(zhuǎn)化率,KaTeX parse error: Expected group after '^' at position 3: SE^?代表標(biāo)準(zhǔn)誤差,由于轉(zhuǎn)化過程是符合二項分布的,因此用戶行為可以看作單次伯努利試驗(single Bernoulli trial),而積極結(jié)果(完成轉(zhuǎn)化)的可能性是未知的。假設(shè)樣本數(shù)量足夠大,我們可以使用廣泛采用的Wald方法,將該分布近似為正態(tài)分布。因此有
SE2=SEexp2+SEctrl2SE^2 = SE_{exp}^2 + SE_{ctrl}^2SE2=SEexp2?+SEctrl2?
SEexp2=pexp(1?pexp)nexpSE_{exp}^2 = \frac{p_{exp}(1 - p_{exp})}{n_{exp}}SEexp2?=nexp?pexp?(1?pexp?)?
SEctrl2=pctrl(1?pctrl)nctrlSE_{ctrl}^2 = \frac{p_{ctrl}(1 - p_{ctrl})}{n_{ctrl}}SEctrl2?=nctrl?pctrl?(1?pctrl?)?
** 根據(jù)計算出的z值,即可根據(jù)概率累積函數(shù)(CDF)計算出p-value**
** p-value = 1 - **Φ(z)
置信區(qū)間
根據(jù)統(tǒng)計學(xué)的中心極限定理,樣本均值的抽樣分布呈正態(tài)分布。由之前計算得出Z值,再根據(jù)兩個總體的均值、標(biāo)準(zhǔn)差和樣本大小,利用以下公式即可求出兩個總體均值差的置信度為α置信區(qū)間。
(ρ1?ρ2)±zα2?σ12n1+σ22n2(\rho_1 - \rho_2) ± z_{\frac{\alpha}{2}}\cdot \sqrt{\frac{\sigma_1^2}{n_1} + \frac{\sigma_2^2}{n_2}}(ρ1??ρ2?)±z2α???n1?σ12??+n2?σ22???
ρ1,ρ2是雙樣本的觀察均值\rho_1,\rho_2是雙樣本的觀察均值ρ1?,ρ2?是雙樣本的觀察均值
統(tǒng)計功效
**統(tǒng)計功效是指版本差異(效果)為某個指定值時,通過顯著性檢驗?zāi)苷_地把差異檢驗出來的概率。**說白了就是,假設(shè)兩個版本的確存在差異,我們能夠正確拒絕原假設(shè),獲得統(tǒng)計顯著性結(jié)果(95%置信區(qū)間中數(shù)據(jù))的概率。其計算公式如下圖所示

2.2.2 代碼實現(xiàn)
Java版本
import org.apache.commons.math3.distribution.NormalDistribution;import java.math.BigDecimal; import java.math.MathContext; import java.math.RoundingMode; import java.util.ArrayList; import java.util.List;/*** 描述:** @author zhourao* @create 2020-04-26 2:40 下午*/ public class AlalysisUtils {private static NormalDistribution nd = new NormalDistribution();private final static int SCALE = 16;//采用雙邊檢測private static final double FIRST_TYPE_ERROR_CHANCE = 0.05;// 統(tǒng)計功效計算public static double GetStatisticalPower(BigDecimal expCt, BigDecimal controlCt, BigDecimal expCnt, BigDecimal controlCnt) {if (BigDecimal.ZERO.equals(expCt) && BigDecimal.ZERO.equals(controlCt)) {return 0;}BigDecimal zScore = GetZScore(expCt, controlCt, expCnt, controlCnt);BigDecimal staticZScore = BigDecimal.ZERO.subtract(new BigDecimal(nd.inverseCumulativeProbability(1 - FIRST_TYPE_ERROR_CHANCE / 2)));return 2 - nd.cumulativeProbability(staticZScore.add(zScore).doubleValue()) - nd.cumulativeProbability(staticZScore.subtract(zScore).doubleValue());}// 置信區(qū)間計算public static List<BigDecimal> GetConfidenceInterval(BigDecimal expCt, BigDecimal controlCt, BigDecimal expCnt, BigDecimal controlCnt) {List<BigDecimal> result = new ArrayList<>();if (BigDecimal.ZERO.equals(expCt) && BigDecimal.ZERO.equals(controlCt)) {result.add(BigDecimal.ZERO);result.add(BigDecimal.ZERO);return result;}BigDecimal expRatio = expCt.divide(expCnt, SCALE, BigDecimal.ROUND_HALF_UP);BigDecimal controlRatio = controlCt.divide(controlCnt, SCALE, BigDecimal.ROUND_HALF_UP);BigDecimal variance = getVariance(expRatio, controlRatio, expCnt, controlCnt);double v = nd.inverseCumulativeProbability(FIRST_TYPE_ERROR_CHANCE / 2);BigDecimal wave = variance.multiply(new BigDecimal(v)).abs();result.add(expRatio.subtract(controlRatio).subtract(wave));result.add(expRatio.subtract(controlRatio).add(wave));return result;}// p值計算public static double GetPValue(BigDecimal expCt, BigDecimal controlCt, BigDecimal expCnt, BigDecimal controlCnt) {if (BigDecimal.ZERO.equals(expCt) && BigDecimal.ZERO.equals(controlCt)) {return 1;}BigDecimal zScore = GetZScore(expCt, controlCt, expCnt, controlCnt);return 1 - nd.cumulativeProbability(zScore.doubleValue());}// z分數(shù)計算public static BigDecimal GetZScore(BigDecimal expCt, BigDecimal controlCt, BigDecimal expCnt, BigDecimal controlCnt) {BigDecimal expRatio = expCt.divide(expCnt, SCALE, BigDecimal.ROUND_HALF_UP);BigDecimal controlRatio = controlCt.divide(controlCnt, SCALE, BigDecimal.ROUND_HALF_UP);BigDecimal variance = getVariance(expRatio, controlRatio, expCnt, controlCnt);return (expRatio.subtract(controlRatio)).divide(variance, SCALE, BigDecimal.ROUND_HALF_UP).abs();}private static BigDecimal getVariance(BigDecimal expRatio, BigDecimal controlRatio, BigDecimal expCnt, BigDecimal controlCnt) {BigDecimal se_experiment = expRatio.multiply(BigDecimal.ONE.subtract(expRatio)).divide(expCnt, SCALE, BigDecimal.ROUND_HALF_UP);BigDecimal se_control = controlRatio.multiply(BigDecimal.ONE.subtract(controlRatio)).divide(controlCnt, SCALE, BigDecimal.ROUND_HALF_UP);return sqrt(se_experiment.add(se_control));}public static BigDecimal sqrt(BigDecimal value) {BigDecimal num2 = BigDecimal.valueOf(2);int precision = 100;MathContext mc = new MathContext(precision, RoundingMode.HALF_UP);BigDecimal deviation = value;int cnt = 0;while (cnt < precision) {deviation = (deviation.add(value.divide(deviation, mc))).divide(num2, mc);cnt++;}deviation = deviation.setScale(SCALE, BigDecimal.ROUND_HALF_UP);return deviation;} }2.2.3 使用流量建議
在做AB測試的時候,我們希望能測試兩組間的轉(zhuǎn)化率在統(tǒng)計上是否存在明顯差異。由于樣本量大,我們可以采用雙樣本單尾z-檢驗(two-sample, one-tailed z-test)。另外,對于較小的樣本集合,我們可以依賴于t-檢驗。
- 轉(zhuǎn)化率的數(shù)據(jù)分布按二項分布計算
大流量-z檢驗
大流量及推薦用戶量
確定相較原來有轉(zhuǎn)化率的增長,置信度95%(p-value<0.05)
| 1 | 5% | 1032974 | 259459 |
| 2 | 10% | 489160 | 122829 |
| 3 | 20% | 217253 | 54514 |
| 4 | 30% | 126617 | 31743 |
| 5 | 40% | 81299 | 20357 |
| 6 | 50% | 54109 | 13526 |
過程推理
按二項分布,推導(dǎo)的z值求解公式如下:
z=pexp?pctrlSEexp2+SEctrl2z = \frac{p_{exp} - p_{ctrl}}{\sqrt{SE_{exp}^2 + SE_{ctrl}^2}}z=SEexp2?+SEctrl2??pexp??pctrl??
置信區(qū)間95%對應(yīng)的z值為1.65,按相對原來增長1%計算
結(jié)果圖

小流量-t檢驗
- 小用戶流量推薦:單邊檢測,統(tǒng)計功效大于80%,

import math from scipy.stats import normdef get_cnt(old_cvr, ratio):p_experiment = old_cvr + old_cvr * ratiop_control = old_cvrreturn math.ceil((norm.ppf(0.95) + norm.ppf(0.8)) ** 2 * (p_experiment * (1 - p_experiment) + p_control * (1 - p_control)) / (old_cvr * ratio ** 2))print(get_cnt(0.05, 0.01)) print(get_cnt(0.10, 0.01)) print(get_cnt(0.20, 0.01)) print(get_cnt(0.30, 0.01)) print(get_cnt(0.40, 0.01)) print(get_cnt(0.50, 0.01))print(get_cnt(0.05, 0.02)) print(get_cnt(0.10, 0.02)) print(get_cnt(0.20, 0.02)) print(get_cnt(0.30, 0.02)) print(get_cnt(0.40, 0.02)) print(get_cnt(0.50, 0.02))| 1 | 5% | 118025 | 29646 |
| 2 | 10% | 111781 | 28069 |
| 3 | 20% | 99291 | 24915 |
| 4 | 30% | 86802 | 21761 |
| 5 | 40% | 74312 | 18608 |
| 6 | 50% | 61823 | 15454 |
3 實戰(zhàn)經(jīng)驗
3.1 指標(biāo)體系的設(shè)立
3.3.1 常用指標(biāo)類別
- 人次
- 頻次
- 人均
- 普通人均=頻次/人次
- 同一個人重復(fù)點擊去除的人均,A點擊了B 2次、C 1次,按上述人均是3,按此人均是2
- 頻次轉(zhuǎn)化率
- 人次轉(zhuǎn)化率
- 總和(如成交金額)
3.2 結(jié)合數(shù)據(jù)分析
3.2.1 AAARR漏斗模型
3.2.2 渠道分析統(tǒng)計
3.3 報表統(tǒng)計分層
4 常見問題
4.1 辛普森悖論
當(dāng)人們嘗試探究兩種變量(比如新生錄取率與性別)是否具有相關(guān)性的時候,會分別對之進行分組研究。然而,在分組比較中都占優(yōu)勢的一方,在總評中有時反而是失勢的一方。該現(xiàn)象于20世紀初就有人討論,但一直到1951年,E.H.辛普森在他發(fā)表的論文中闡述此一現(xiàn)象后,該現(xiàn)象才算正式被描述解釋。后來就以他的名字命名此悖論,即辛普森悖論。
4.2 A/B測試方法的副作用和處理辦法
對于非常小的效果變化,往往都需要創(chuàng)建相當(dāng)大的對照組和測試組來實現(xiàn)AB測試,這個的代價往往是很大的。設(shè)想下在零售商場中,每天觀察到的用戶數(shù)量,往往需要很久的時間才能得出明顯的結(jié)論。在實際業(yè)務(wù)應(yīng)用中,會遇到的問題是:當(dāng)你運行測試時整體運行的效果是受到很大影響的,因為必須有一半的用戶處于效果不佳的實驗組,或者有一半的用戶處于效果不佳的對照組,而且你必須等待測試完成才能停止這種局面。
這是被稱為**探索利用難題(explore-exploit conundrum)**的一個經(jīng)典問題。我們需要運行次優(yōu)方法,以探索空間,并找到效果更好的解決方案,而一旦找到了更好的解決方案,我們還需要盡快利用它們來實現(xiàn)效果提升。能否可以更快地利用新的解決方案,而不必等待測試完全完成呢?答案是肯定的。下面簡單介紹下多臂賭博機(multi-armed bandit,MAB)的概念。
多臂賭博機的定義
多臂賭博機(multi-armed bandit,MAB)的名字來源于著名的賭博游戲角子賭博機(one-armed bandit)。對那些從沒去過賭場的人,我們來做下解釋:角子機(又稱老虎機)是一個需要你拉杠桿(或搖臂)的賭博機器,根據(jù)機器展示的數(shù)值,你可能會得到一筆獎勵,也可能(更大幾率)得不到任何東西。和你想的一樣,這些機器的設(shè)置都對莊家有利,所以能獲的獎勵的幾率是非常非常小的。
多臂賭博機(理論上的)擴展了這種形式,想象你面對的是一堆角子賭博機,每個賭博機都被分配按照一個獨立的概率進行獎勵。作為一個玩家,你不知道在這些機器后的獲獎概率,你唯一可以找到獲獎概率的方法是進行游戲。你的任務(wù)是通過玩這些機器,最大限度地提高所獲的獎勵。那么你應(yīng)該使用什么策略呢?
附錄
附錄A 流程
附錄B 問題排查
總結(jié)
以上是生活随笔為你收集整理的AB实验平台:为什么AB实验平台必不可少?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用 Mailgun 配置 Ghost
- 下一篇: 图解GHOST使用教程