干擾AB測試
A/B測試是大多數(shù)公司用來測試其產(chǎn)品特性的在線實(shí)驗(yàn)的黃金標(biāo)準(zhǔn)。雖然A/B測試試驗(yàn)在大多數(shù)情況下效果良好,但特別容易受到干擾,特別是在在線市場或社交網(wǎng)絡(luò)中。在本文中,我們旨在研究帶有干擾偏差的情況,以及一些減輕其對(duì)評(píng)價(jià)影響的潛在方法。
A/B測試的基本假設(shè)及其違反情況
A/B測試的基本假設(shè)之一是Sutva--穩(wěn)定的單位處理值假設(shè)。隨機(jī)化單元治療的潛在結(jié)果只取決于他們所接受的治療,而不是分配給其他受試者的治療。
在市場和社會(huì)網(wǎng)絡(luò)上的實(shí)驗(yàn)中,這種情況經(jīng)常遭到侵犯。可能的侵權(quán)行為包括:
· a/b在社交網(wǎng)絡(luò)上測試實(shí)驗(yàn)。比如說,我們想了解在"信碼"上添加"故事"功能的效果。一個(gè)增加治療部門人員參與度的功能會(huì)影響到與他們有聯(lián)系的控制部門人員??刂撇块T的人回應(yīng)他們的故事,這可以增加他們的參與。這是一個(gè)實(shí)際治療效果比我們?cè)趯?shí)驗(yàn)中看到的要小的例子。
· A/B在里茲野兔市場的測試實(shí)驗(yàn):假設(shè)一個(gè)里茲野兔市場引入了對(duì)騎馬者的折扣,并希望在無折扣控制下對(duì)其進(jìn)行測試。另外,利息的度量是乘坐的次數(shù)。然而,如果治療者開始要求更多的乘坐,那么控制者可以使用的駕駛就會(huì)減少。這種情況下的治療效果被夸大了。
· 一個(gè)類似的例子是一個(gè)廣告市場,在這個(gè)市場中,多個(gè)活動(dòng)都在競爭一個(gè)廣告。然而,假設(shè)有固定的廣告商預(yù)算。該預(yù)算由治療和控制部門分?jǐn)?。想象一?我們提出的功能增加了點(diǎn)擊率。在治療中,如果預(yù)算開始花費(fèi)更多,控制組的可用預(yù)算就會(huì)減少。在這種情況下,治療效果再次膨脹。
減緩干擾效應(yīng)
通過修改實(shí)驗(yàn)設(shè)置和因果推理技術(shù),我們可以減輕A/B測試中干擾的影響。我探究了技術(shù)背后的直覺,而不是技術(shù)細(xì)節(jié)。我將分享推薦信,這樣你也可以稍后再做。
預(yù)算分割測試
這通常是在處理和控制之間共享廣告商預(yù)算等公共資源時(shí)使用的。在這方面,預(yù)算是按實(shí)驗(yàn)流量的比例來分配的,這樣處理和控制就有了自己的預(yù)算,并且沒有拆食。這種方法費(fèi)用高昂,因?yàn)榭赡軐?dǎo)致預(yù)算利用不足。有關(guān)這方面的更多細(xì)節(jié),可在民劉等人的論文中找到。,2021年。我給出了一個(gè)基本代碼來創(chuàng)建一個(gè)預(yù)算劃分實(shí)驗(yàn)系統(tǒng)。
import random
class BudgetSplitTest:
def __init__(self, total_budget, control_traffic_ratio):
self.total_budget = total_budget
self.control_traffic_ratio = control_traffic_ratio
self.treatment_traffic_ratio = 1 - control_traffic_ratio
# Split budget based on traffic ratio
self.control_budget = total_budget * control_traffic_ratio
self.treatment_budget = total_budget * self.treatment_traffic_ratio
# Track spent budget and conversions
self.control_spent = 0
self.treatment_spent = 0
self.control_conversions = 0
self.treatment_conversions = 0
def run_experiment(self, total_impressions):
for _ in range(total_impressions):
if random.random() < self.control_traffic_ratio:
self._serve_control_ad()
else:
self._serve_treatment_ad()
def _serve_control_ad(self):
if self.control_spent < self.control_budget:
spend = min(random.uniform(0.1, 1.0), self.control_budget - self.control_spent)
self.control_spent += spend
if random.random() < 0.1: # 10% conversion rate for control
self.control_conversions += 1
def _serve_treatment_ad(self):
if self.treatment_spent < self.treatment_budget:
spend = min(random.uniform(0.1, 1.0), self.treatment_budget - self.treatment_spent)
self.treatment_spent += spend
if random.random() < 0.15: # 15% conversion rate for treatment
self.treatment_conversions += 1
def get_results(self):
return {
"Control": {
"Budget": round(self.control_budget, 2),
"Spent": round(self.control_spent, 2),
"Conversions": self.control_conversions,
"CPA": round(self.control_spent / self.control_conversions, 2) if self.control_conversions else 0
},
"Treatment": {
"Budget": round(self.treatment_budget, 2),
"Spent": round(self.treatment_spent, 2),
"Conversions": self.treatment_conversions,
"CPA": round(self.treatment_spent / self.treatment_conversions, 2) if self.treatment_conversions else 0
}
}
# Run the experiment
total_budget = 10000
control_traffic_ratio = 0.5 # 50% traffic to control, 50% to treatment
total_impressions = 100000
experiment = BudgetSplitTest(total_budget, control_traffic_ratio)
experiment.run_experiment(total_impressions)
results = experiment.get_results()
轉(zhuǎn)換實(shí)驗(yàn)
開關(guān)回用在兩面市場更常見,比如來夫特,Uber,多達(dá)什,所有的用戶都在處理和控制之間切換。這里的隨機(jī)化單元不是用戶而是時(shí)間單位。如果時(shí)間間隔短,這種方法可以從處理到控制產(chǎn)生溢出效應(yīng),否則會(huì)導(dǎo)致實(shí)驗(yàn)?zāi)芰Σ蛔恪N覀兛梢允褂没貧w分析等方法來增加功率。
import random
from datetime import datetime, timedelta
class SwitchbackExperiment:
def __init__(self, experiment_name, start_time, end_time, interval_hours=1):
self.name = experiment_name
self.start_time = start_time
self.end_time = end_time
self.interval_hours = interval_hours
self.schedule = self._create_schedule()
self.data = []
def _create_schedule(self):
schedule = []
current_time = self.start_time
while current_time < self.end_time:
schedule.append({
'start': current_time,
'end': current_time + timedelta(hours=self.interval_hours),
'variant': random.choice(['control', 'treatment'])
})
current_time += timedelta(hours=self.interval_hours)
return schedule
def get_active_variant(self, timestamp):
for interval in self.schedule:
if interval['start'] <= timestamp < interval['end']:
return interval['variant']
return None # Outside experiment time range
def record_event(self, timestamp, metric_value):
variant = self.get_active_variant(timestamp)
if variant:
self.data.append({
'timestamp': timestamp,
'variant': variant,
'metric_value': metric_value
})
def get_results(self):
control_data = [event['metric_value'] for event in self.data if event['variant'] == 'control']
treatment_data = [event['metric_value'] for event in self.data if event['variant'] == 'treatment']
return {
'control': {
'count': len(control_data),
'total': sum(control_data),
'average': sum(control_data) / len(control_data) if control_data else 0
},
'treatment': {
'count': len(treatment_data),
'total': sum(treatment_data),
'average': sum(treatment_data) / len(treatment_data) if treatment_data else 0
}
}
# Example usage
if __name__ == "__main__":
# Set up the experiment
start = datetime(2023, 5, 1, 0, 0)
end = datetime(2023, 5, 8, 0, 0) # One week experiment
exp = SwitchbackExperiment("New Pricing Algorithm", start, end, interval_hours=4)
# Simulate events (e.g., rides in a rideshare app)
current_time = start
while current_time < end:
# Simulate more rides during peak hours
num_rides = random.randint(5, 20)
if 7 <= current_time.hour <= 9 or 16 <= current_time.hour <= 18:
num_rides *= 2
for _ in range(num_rides):
# Simulate a ride
ride_time = current_time + timedelta(minutes=random.randint(0, 59))
ride_value = random.uniform(10, 50) # Ride value between $10 and $50
exp.record_event(ride_time, ride_value)
current_time += timedelta(hours=1)
# Analyze results
results = exp.get_results()
圖組隨機(jī)化(GCR)
在社會(huì)網(wǎng)絡(luò)實(shí)驗(yàn)中,圖形集群隨機(jī)化是一種進(jìn)一步減少干擾偏差的技術(shù)。 . 該方法在形成集群時(shí)考慮到網(wǎng)絡(luò)結(jié)構(gòu),有助于在網(wǎng)絡(luò)社區(qū)中隔離處理效果。然后將集群隨機(jī)分配給處理和控制。由于集群的孤立,干擾會(huì)自動(dòng)減小.
資源調(diào)整指標(biāo)
我們可以使用解釋資源分配的衡量標(biāo)準(zhǔn),而不僅僅側(cè)重于絕對(duì)結(jié)果。例如,在廣告活動(dòng)中,我們可能不僅僅是衡量點(diǎn)擊率,而是跟蹤每次點(diǎn)擊的成本或廣告支出的返回,這使不同預(yù)算水平的結(jié)果正?;?。
合成控制
在出現(xiàn)干擾的情況下,可以構(gòu)建綜合控制組,根據(jù)其他單位的指標(biāo)來模擬處理對(duì)某一單位的指標(biāo)的影響。例如,假設(shè)我們把這個(gè)國家作為一個(gè)整體,在一個(gè)預(yù)先測試的時(shí)期,一個(gè)國家的度量標(biāo)準(zhǔn)是根據(jù)其他國家的度量標(biāo)準(zhǔn)建模的。當(dāng)我們?cè)谝粋€(gè)國家推廣這一特征后,我們可以通過比較這一模型所預(yù)測的指標(biāo)來模擬推廣干預(yù)的效果。結(jié)果的差異可能很大,足以衡量小影響。
信息技術(shù)服務(wù)
中斷時(shí)間序列模型。定義干預(yù)點(diǎn),如特征推廣,然后使用干預(yù)前時(shí)間序列預(yù)測觀測結(jié)果。將其與實(shí)際觀察結(jié)果進(jìn)行比較,以確定干預(yù)是否對(duì)時(shí)間序列產(chǎn)生影響。
亂滾
逐步引入對(duì)一小部分用戶的更改,并在擴(kuò)展展開之前監(jiān)控結(jié)果。這使您能夠及早發(fā)現(xiàn)潛在的問題并減輕干擾的影響。
實(shí)際上,所有這些方法都應(yīng)該與AB測試方法結(jié)合使用。例如,可以定義一些指標(biāo),以查看是否檢測到廣告市場的干擾。如果沒有問題,AB測試結(jié)果是可以信任的,否則,我們可以進(jìn)行預(yù)算分割測試。