在模擬研究中,事件發生率的準確估計至關重要。卜瓦松和指數分佈適用於恆定發生率的場景,而威布林分佈則能更好地模擬故障率等隨時間變化的情況。理解這些分佈的特性以及引數估計方法,有助於更精確地模擬和預測事件發生。A/B 測試是一種常用的比較不同方案效果的方法,其核心在於隨機分組和嚴謹的實驗設計。透過統計假設檢定,例如排列測試,可以評估觀察到的差異是否具有統計顯著性,避免被隨機性誤導。選擇單尾或雙尾檢定取決於研究問題和假設。
事件發生率的估計
在卜瓦松分佈或指數分佈的模擬研究中,一個關鍵假設是事件發生率$\lambda$在所考慮的時間段內保持不變。這種假設很少在全域性意義上成立;例如,道路或資料網路上的流量會根據一天中的時間和一週中的哪一天而變化。然而,時間段或空間區域通常可以劃分為足夠均勻的部分,以便在這些部分內進行分析和模擬是有效的。
估計故障率
在許多應用中,事件發生率$\lambda$是已知的,或者可以根據先前的資料估計。然而,對於罕見事件,這並不一定成立。例如,飛機引擎故障足夠罕見(幸運的是),對於某種引擎型別,可能幾乎沒有資料可用於估計故障之間的時間。如果完全沒有資料,就很難估計事件發生率。然而,透過模擬或直接電腦率,可以評估不同的假設事件發生率,並估計出不太可能低於的閾值。如果有一些資料但不足以提供精確可靠的估計,可以對各種發生率應用適合度測試(參見第124頁的「卡方測試」),以確定它們與觀察到的資料的擬合程度。
威布林分佈
在許多情況下,事件發生率不會隨時間保持不變。如果事件發生率變化的時間段遠遠長於事件之間的典型間隔,那麼就沒有問題;只需將分析細分為事件發生率相對穩定的部分,如前所述。但是,如果事件發生率在間隔內變化,卜瓦松分佈或指數分佈就不再適用。這種情況很可能出現在機械故障中——隨著時間的推移,故障的風險會增加。威布林分佈是指數分佈的擴充套件,其中允許事件發生率根據形狀引數$\beta$變化。如果$\beta > 1$,事件發生的機率隨時間增加;如果$\beta < 1$,機率會降低。由於威布林分佈用於失效時間分析而不是事件發生率,第二個引數用特徵壽命表示,而不是用每個間隔的事件發生率表示。使用的符號是$\eta$(eta),希臘字母。它也被稱為尺度引數。
使用威布林分佈時,估計任務現在包括估計兩個引數:$\beta$和$\eta$。軟體用於建模資料並得出最佳擬合威布林分佈的估計。
R語言中生成威布林分佈隨機數的程式碼需要三個引數:n(要生成的數字數量)、shape和scale。例如,以下程式碼將生成100個來自威布林分佈的隨機數(壽命),其形狀為1.5,特徵壽命為5,000:
rweibull(100, 1.5, 5000)
要在Python中實作相同的功能,請使用函式stats.weibull_min.rvs:
stats.weibull_min.rvs(1.5, scale=5000, size=100)
內容解密:
rweibull(100, 1.5, 5000)和stats.weibull_min.rvs(1.5, scale=5000, size=100)生成100個來自威布林分佈的隨機壽命,其中形狀引數為1.5,特徵壽命為5000。- 這兩個函式分別在R和Python中實作,用於模擬具有指定威布林分佈特性的壽命資料。
主要觀念
- 當事件以恆定速率發生時,每單位時間或空間內的事件數量可以用卜瓦松分佈來建模。
- 事件之間的時間或距離可以用指數分佈來建模。
- 事件發生率隨時間變化(例如,裝置故障機率增加)的情況,可以用威布林分佈來建模。
此圖示呈現了卜瓦松分佈、指數分佈和威布林分佈之間的關係:
@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle
title 事件發生率估計與威布林分佈應用
package "統計分析流程" {
package "資料收集" {
component [樣本資料] as sample
component [母體資料] as population
}
package "描述統計" {
component [平均數/中位數] as central
component [標準差/變異數] as dispersion
component [分佈形狀] as shape
}
package "推論統計" {
component [假設檢定] as hypothesis
component [信賴區間] as confidence
component [迴歸分析] as regression
}
}
sample --> central : 計算
sample --> dispersion : 計算
central --> hypothesis : 檢驗
dispersion --> confidence : 估計
hypothesis --> regression : 建模
note right of hypothesis
H0: 虛無假設
H1: 對立假設
α: 顯著水準
end note
@enduml此圖示說明:
卜瓦松分佈和指數分佈都根據恆定的事件發生率,而威布林分佈則允許事件發生率隨時間變化。它們分別適用於不同的場景,如排隊理論和失效時間分析。
統計實驗與顯著性檢驗
實驗設計的重要性
實驗設計是統計實踐的根本,幾乎在所有研究領域都有應用。其主要目標是設計一個實驗來確認或拒絕一個假設。資料科學家經常需要進行持續的實驗,特別是在使用者介面和產品行銷方面。本章回顧了傳統的實驗設計,並討論了資料科學中的一些常見挑戰。同時,也涵蓋了統計推斷中的一些常見概念,並解釋了它們的含義和與資料科學的相關性。
A/B 測試
A/B 測試是一種具有兩組的實驗,用於確定兩種處理、產品、程式等中哪一個更優越。通常,其中一種處理是標準的現有處理,或是沒有處理。如果使用標準(或沒有)處理,則稱為對照組。一個典型的假設是新的處理比對照組更好。
A/B 測試的關鍵術語
- 處理:某事物(藥物、價格、網頁標題)對其施加影響的主體。
- 處理組:接觸特定處理的主體群體。
- 對照組:未接觸(或接觸標準)處理的主體群體。
- 隨機化:將主體隨機分配到處理的過程。
- 主體:接觸處理的專案(網頁訪客、患者等)。
- 測試統計量:用於衡量處理效果的指標。
A/B 測試在網頁設計和行銷中很常見,因為結果很容易被衡量。一些 A/B 測試的例子包括:
- 測試兩種土壤處理以確定哪一種產生更好的種子發芽率
- 測試兩種療法以確定哪一種更有效地抑制癌症
- 測試兩種價格以確定哪一種產生更多的淨利
- 測試兩個網頁標題以確定哪一個產生更多的點選量
- 測試兩個網頁廣告以確定哪一個產生更多的轉換率
為什麼需要對照組?
為什麼不跳過對照組,只執行一個實驗,將感興趣的處理應用於一組,並將結果與之前的經驗進行比較?
沒有對照組,就無法確保“所有其他條件都相同”,並且任何差異確實是由於處理(或機會)造成的。當你有一個對照組時,它會受到與實驗組相同的條件(除了處理),這樣你就可以確定任何差異都是由於處理或隨機分配造成的。
統計顯著性與 p 值
在 A/B 測試中,通常會使用統計顯著性檢驗來確定結果是否具有統計顯著性。p 值是用於衡量觀察到的差異是否是由於機會造成的機率。
示例:價格測試結果
假設我們進行了一個價格測試,結果如下表所示:
| 結果 | 價格 A | 價格 B |
|---|---|---|
| 轉換 | 200 | 182 |
| 未轉換 | 23,539 | 22,406 |
或者,如果指標是連續變數(購買金額、利潤等)或計數(例如,住院天數、存取頁面數),結果可能會以不同的方式顯示。例如,如果我們感興趣的是每個頁面檢視的收入,而不是轉換率,價格測試的結果可能如下所示:
每個頁面檢視的收入(價格 A):平均值 = 3.87,標準差 = 51.10 每個頁面檢視的收入(價格 B):平均值 = 4.11,標準差 = 62.98
程式碼範例:A/B 測試分析
import numpy as np
from scipy import stats
# 模擬 A/B 測試資料
np.random.seed(0)
n_samples = 1000
conversion_rate_A = 0.08
conversion_rate_B = 0.09
data_A = np.random.binomial(n=1, p=conversion_rate_A, size=n_samples)
data_B = np.random.binomial(n=1, p=conversion_rate_B, size=n_samples)
# 計算轉換率
conversion_rate_A_sample = np.mean(data_A)
conversion_rate_B_sample = np.mean(data_B)
# 進行 t 檢驗
t_stat, p_value = stats.ttest_ind(data_A, data_B)
print(f"轉換率 A:{conversion_rate_A_sample:.4f}")
print(f"轉換率 B:{conversion_rate_B_sample:.4f}")
print(f"t 統計量:{t_stat:.4f}")
print(f"p 值:{p_value:.4f}")
#### 內容解密:
此程式碼範例模擬了一個 A/B 測試,比較了兩個不同的轉換率。我們使用 numpy 生成二項分佈的隨機資料,以模擬轉換率。然後,我們計算樣本轉換率,並使用 scipy.stats.ttest_ind 進行獨立樣本 t 檢驗,以比較兩個轉換率之間的差異。輸出的結果包括樣本轉換率、t 統計量和 p 值。
A/B 測試:隨機分組與盲測的重要性
在資料科學領域中,A/B 測試是一種常見的實驗設計方法,用於比較不同處理方法(如網頁設計、產品價格或標題用語)對使用者行為的影響。在進行 A/B 測試時,將受試者隨機分配到不同的組別中,除了研究的處理方法不同外,其他條件均保持一致。
為何需要隨機分組?
隨機分組是 A/B 測試中的關鍵要素,它可以確保不同組別之間的差異僅在於處理方法,而非其他因素。這樣可以避免其他變數對實驗結果的幹擾。例如,如果簡單地將新使用者分配到實驗組,將舊使用者分配到對照組,則實驗結果可能會受到使用者經驗的影響,而非處理方法的影響。
### 隨機分組範例
- 將網頁訪客隨機分配到 A 組(舊設計)或 B 組(新設計)
- 比較兩組訪客的點選率、購買率或其他行為指標
內容解密:
在上述範例中,我們透過隨機分組確保了兩組訪客的基本特徵相似,只有網頁設計不同。這樣可以確保實驗結果的差異是由於設計變更引起的。
盲測在研究中的重要性
盲測是指受試者不知道自己接受的是哪種處理方法。在醫學研究中,雙盲測試是指研究人員和參與者都不知道誰接受了哪種處理。這樣可以避免參與者的心理反應和研究人員的主觀偏差對實驗結果的影響。
A/B 測試在資料科學中的應用
在資料科學領域,A/B 測試常用於網頁最佳化、產品定價和廣告設計等領域。研究人員需要謹慎設計實驗,以確保隨機化和控制其他變數。此外,在實驗前需要確定評估指標,以避免研究人員偏差。
import random
def ab_test_assignment(visitors):
# 將訪客隨機分配到 A 組或 B 組
assignments = {}
for visitor in visitors:
assignments[visitor] = 'A' if random.random() < 0.5 else 'B'
return assignments
# 範例使用
visitors = ['user1', 'user2', 'user3']
assignments = ab_test_assignment(visitors)
print(assignments)
內容解密:
上述程式碼透過 random.random() 函式將訪客隨機分配到 A 組或 B 組。這確保了分組的隨機性,從而減少了其他變數對實驗結果的幹擾。
為何僅限於 A/B 測試?
雖然 A/B 測試很常見,但並非唯一的統計實驗設計。傳統的統計實驗設計關注於回答靜態問題,如特定處理方法的效果。然而,資料科學家更感興趣的是從多個可能的選項中找到最佳方案,例如從多個價格中找到最佳價格。這時,可以使用多臂老虎機演算法(Multi-Arm Bandit Algorithm)。
取得許可的重要性
在涉及人類受試者的科學和醫學研究中,通常需要獲得受試者的許可以及機構審查委員會的批准。然而,在商業營運中進行的實驗通常不需要這樣做。Facebook 在 2014 年進行的新聞推播情感分析實驗引發了爭議,因為該實驗未經使用者同意。
主要觀念
- 將受試者隨機分配到不同組別,除了研究的處理方法外,其他條件均保持一致。
- 理想情況下,受試者應被隨機分配到各組別。
假設檢定:避免隨機性誤導
假設檢定(Hypothesis Tests)是傳統統計分析中常見的方法,用於判斷觀察到的效果是否可能是由隨機性引起的。其目的是幫助研究人員避免被隨機性誤導。
假設檢定的關鍵術語
- 零假設(Null Hypothesis):假設觀察到的效果是由於隨機性。
- 替代假設(Alternative Hypothesis):與零假設相反的假設,即研究人員希望證明的假設。
- 單尾檢定(One-way Test):只考慮一個方向的隨機結果。
- 雙尾檢定(Two-way Test):考慮兩個方向的隨機結果。
人類傾向於低估隨機性
人類的大腦傾向於低估隨機性的範圍,並將隨機事件誤解為具有某種意義。統計假設檢定正是為了保護研究人員免受這種誤導而發明的。我們可以透過一個簡單的實驗來觀察這種現象:讓朋友們創造一系列 50 次拋硬幣的結果,並與實際拋硬幣的結果進行比較。真實的結果通常會有更長的連續正反面序列。
import random
def simulate_coin_flips(n):
# 模擬 n 次拋硬幣
return [random.choice(['H', 'T']) for _ in range(n)]
# 範例使用
flips = simulate_coin_flips(50)
print(''.join(flips))
內容解密:
上述程式碼模擬了 50 次拋硬幣,並輸出結果。這可以用來比較真實拋硬幣和人為創造的序列之間的差異。
統計實驗與顯著性測試中的假設檢定
在進行A/B測試或其他隨機實驗時,我們會收集治療組A和B的資料,以評估兩組之間的差異是否由於隨機機會或兩組之間的真實差異。統計假設檢定進一步分析這些實驗,以評估隨機機會是否是觀察到的組間差異的合理解釋。
虛無假設
假設檢定使用以下邏輯:「鑒於人類傾向於對不尋常但隨機的行為做出反應,並將其解釋為有意義和真實的,在我們的實驗中,我們將要求證明組間差異比機會所能合理產生的更極端。」這涉及到一個基線假設,即治療組是等效的,組間的任何差異都是由於機會。這一基線假設被稱為虛無假設。我們的希望是,事實上,我們可以證明虛無假設是錯誤的,並表明組A和B的結果比機會所能產生的更不同。
進行虛無假設檢定的一種方法是透過重抽樣排列程式,將組A和B的結果混合在一起,然後重複將資料分配到大小相似的組中,並觀察我們多久會得到與觀察到的差異一樣極端的差異。將組A和B的結果混合在一起,並從中重抽樣的過程,體現了組A和B是等效和可互換的虛無假設,被稱為虛無模型。
程式碼範例:重抽樣排列程式
import numpy as np
# 模擬組A和組B的資料
np.random.seed(0)
group_A = np.random.normal(loc=0, scale=1, size=100)
group_B = np.random.normal(loc=0.5, scale=1, size=100)
# 合併資料
combined_data = np.concatenate([group_A, group_B])
# 重抽樣排列程式
n_replications = 10000
n_A = len(group_A)
differences = np.zeros(n_replications)
for i in range(n_replications):
np.random.shuffle(combined_data)
group_A_resample = combined_data[:n_A]
group_B_resample = combined_data[n_A:]
differences[i] = np.mean(group_A_resample) - np.mean(group_B_resample)
# 計算p值
observed_difference = np.mean(group_A) - np.mean(group_B)
p_value = np.mean(np.abs(differences) >= np.abs(observed_difference))
print(f'p-value: {p_value}')
內容解密:
- 匯入必要的函式庫:使用
numpy進行數值運算。 - 模擬資料:分別為組A和組B生成正態分佈的隨機資料。
- 合併資料:將組A和組B的資料合併成一個陣列。
- 重抽樣排列:透過重複洗牌合併後的資料,並將其分成與原始組A和組B大小相同的兩組,來模擬虛無假設。
- 計算差異:計算每次重抽樣後兩組之間的平均值差異。
- 計算p值:比較觀察到的差異與重抽樣得到的差異分佈,計算p值。
對立假設
假設檢定本質上不僅涉及虛無假設,還涉及一個對立假設。對立假設與虛無假設一起,必須涵蓋所有可能性。虛無假設的性質決定了假設檢定的結構。
- 虛無假設 = 「組A和組B的平均值之間沒有差異」;對立假設 = 「A與B不同(可能更大或更小)」
- 虛無假設 = 「A ≤ B」;對立假設 = 「A > B」
- 虛無假設 = 「B不比A大X%」;對立假設 = 「B比A大X%」
單尾檢定與雙尾檢定
在A/B測試中,通常是在測試一個新的選項(例如B)與一個既定的預設選項(A)。除非新的選項被證明是絕對更好的,否則預設是堅持預設選項。在這種情況下,您需要一個假設檢定來保護您免受機會在有利於B的方向上愚弄您的影響。您不需要擔心在另一個方向上被機會愚弄,因為除非B被證明是絕對更好的,否則您將堅持A。因此,您需要一個方向性的對立假設(B優於A)。在這種情況下,您使用單尾(或單側)假設檢定。
如果您希望假設檢定能夠保護您免受機會在任何方向上愚弄您的影響,那麼對立假設是雙向的(A與B不同;可能更大或更小)。在這種情況下,您使用雙尾(或雙側)假設檢定。
重抽樣中的關鍵術語
排列測試(Permutation Test)
排列測試是一種統計方法,涉及將兩個或多個樣本合併,並隨機(或詳盡地)將觀察值重新分配到重抽樣的樣本中,以測試假設。
同義詞
- 隨機化測試(Randomization Test)
- 隨機排列測試(Random Permutation Test)
- 精確測試(Exact Test)
重抽樣(Resampling)
重抽樣是指從觀察到的資料集中抽取額外的樣本(稱為重抽樣樣本)。重抽樣可以是有放回或無放回的。
有無放回
在抽樣過程中,是否將專案傳回到樣本中,然後再進行下一次抽取。
排列測試步驟
- 將不同群組的結果合併成一個單一的資料集。
- 對合併的資料進行洗牌,然後隨機抽取(無放回)一個與群組A大小相同的重抽樣樣本。
- 從剩餘的資料中,隨機抽取(無放回)一個與群組B大小相同的重抽樣樣本。
- 對群組C、D等重複相同的過程。
- 對原始樣本計算的統計量或估計值,現在對重抽樣樣本進行計算,並記錄;這構成了一次排列迭代。
- 重複上述步驟R次,以產生測試統計量的排列分佈。
網頁黏著度示例
某公司銷售高價值服務,想要測試哪種網頁呈現方式更能促成銷售。由於銷售週期長,難以累積足夠的銷售資料,因此決定使用代理變數,如使用者在詳細介紹頁面的停留時間。合理的假設是,能夠讓使用者停留更長時間的網頁呈現方式更有可能促成銷售。
資料處理
- 總共有36個會話時間資料,分別來自兩個不同的網頁呈現方式(頁面A和頁面B)。
- 使用
ggplot或pandas繪製箱線圖比較兩個頁面的會話時間。
ggplot(session_times, aes(x=Page, y=Time)) +
geom_boxplot()
ax = session_times.boxplot(by='Page', column='Time')
ax.set_xlabel('')
ax.set_ylabel('Time (in seconds)')
plt.suptitle('')
結果比較
- 計算兩個群組的平均會話時間,並比較差異。
- 頁面B的平均會話時間比頁面A長35.67秒。
mean_a <- mean(session_times[session_times['Page'] == 'Page A', 'Time'])
mean_b <- mean(session_times[session_times['Page'] == 'Page B', 'Time'])
mean_b - mean_a
mean_a = session_times[session_times.Page == 'Page A'].Time.mean()
mean_b = session_times[session_times.Page == 'Page B'].Time.mean()
mean_b - mean_a
排列測試應用
為了判斷觀察到的差異是否在隨機機會所能產生的範圍內,需要進行排列測試。
perm_fun <- function(x, nA, nB)
{
n <- nA + nB
idx_b <- sample(1:n, nB)
idx_a <- setdiff(1:n, idx_b)
mean_diff <- mean(x[idx_b]) - mean(x[idx_a])
return(mean_diff)
}
def perm_fun(x, nA, nB):
n = nA + nB
idx_B = set(random.sample(range(n), nB))
idx_A = set(range(n)) - idx_B
return x.loc[idx_B].mean() - x.loc[idx_A].mean()
排列測試結果解釋
透過重複呼叫perm_fun函式R次,可以產生測試統計量的排列分佈。然後,將觀察到的差異與排列分佈進行比較。如果觀察到的差異位於排列分佈的大部分範圍之外,則認為該差異具有統計顯著性。