在數(shù)據(jù)科學(xué)和機器學(xué)習(xí)領(lǐng)域,許多模型都假設(shè)數(shù)據(jù)呈現(xiàn)正態(tài)分布,或者假設(shè)數(shù)據(jù)在正態(tài)分布下表現(xiàn)更好。例如,線性回歸假設(shè)殘差呈正態(tài)分布,線性判別分析(LDA)基于正態(tài)分布等假設(shè)進行推導(dǎo)。
因此,了解如何測試數(shù)據(jù)正態(tài)性的方法對于數(shù)據(jù)科學(xué)家和機器學(xué)習(xí)從業(yè)者至關(guān)重要。
本文將介紹「測試數(shù)據(jù)正態(tài)性的11種基本方法」,幫助讀者更好地理解數(shù)據(jù)分布的特征和如何應(yīng)用合適的方法進行分析,以便在機器學(xué)習(xí)和數(shù)據(jù)建模過程中更好地處理數(shù)據(jù)分布對模型性能的影響。
繪圖法Plotting Methods
QQ Plot
QQ圖(Quantile-Quantile Plot)是一種用于檢驗數(shù)據(jù)分布是否符合正態(tài)分布的常用方法。在QQ圖中,將數(shù)據(jù)的分位數(shù)與標準正態(tài)分布的分位數(shù)進行比較,如果數(shù)據(jù)分布接近正態(tài)分布,QQ圖上的點將大致落在一條直線上。
如下示例代碼生成了一組服從正態(tài)分布的隨機數(shù)據(jù)來演示QQ Plot,運行代碼后,既可看到QQ Plot以及與之對應(yīng)的正態(tài)分布曲線,通過觀察圖上的點的分布情況來初步判斷數(shù)據(jù)是否接近正態(tài)分布。
import numpy as np
import scipy.stats as stats
import matplotlib.pyplot as plt
# 生成一組隨機數(shù)據(jù),假設(shè)它們服從正態(tài)分布
data = np.random.normal(0, 1, 1000)
# 繪制QQ圖
stats.probplot(data, dist='norm', plot=plt)
plt.title('Q-Q Plot')
plt.show()
KDE Plot
KDE(Kernel Density Estimation)Plot是一種用于可視化數(shù)據(jù)分布的方法,它可以幫助我們檢測數(shù)據(jù)的正態(tài)性。在KDE Plot中,數(shù)據(jù)的密度被估計并繪制成一條平滑的曲線,這有助于我們觀察數(shù)據(jù)的分布形狀。
如下示例代碼生成了一組服從正態(tài)分布的隨機數(shù)據(jù)來演示KDE Plot,運行代碼后,既可看到KDE Plot以及與之對應(yīng)的正態(tài)分布曲線,從而通過可視化來檢測數(shù)據(jù)分布的正態(tài)性。
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
# 生成隨機數(shù)據(jù)
np.random.seed(0)
data = np.random.normal(loc=0, scale=1, size=1000)
# 創(chuàng)建KDE Plot
sns.kdeplot(data, shade=True, label='KDE Plot')
# 添加正態(tài)分布曲線
mu, sigma = np.mean(data), np.std(data)
x = np.linspace(min(data), max(data), 100)
y = (1/(sigma * np.sqrt(2 * np.pi))) * np.exp(-0.5 * ((x - mu) / sigma) ** 2)
plt.plot(x, y, 'r--', label='Normal Distribution')
# 顯示圖表
plt.legend()
plt.show()
Violin Plot
通過觀察Violin Plot可以發(fā)現(xiàn)數(shù)據(jù)的分布形狀,從而初步判斷數(shù)據(jù)是否接近正態(tài)分布。如果 Violin Plot 呈現(xiàn)出類似鐘形曲線的形狀,那么數(shù)據(jù)可能是近似正態(tài)分布的。如果 Violin Plot 偏斜嚴重或者有多個峰值,那么數(shù)據(jù)可能不是正態(tài)分布的。
如下示例代碼生成了一組服從正態(tài)分布的隨機數(shù)據(jù)來演示Violin Plot,運行代碼后,既可看到Violin Plot以及與之對應(yīng)的正態(tài)分布曲線,通過可視化來檢測數(shù)據(jù)分布的形狀,從而初步判斷數(shù)據(jù)是否接近正態(tài)分布。
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
# 生成隨機數(shù)據(jù)
np.random.seed(0)
data = np.random.normal(loc=0, scale=1, size=100)
# 創(chuàng)建 Violin Plot
sns.violinplot(data, inner='points')
# 添加正態(tài)分布曲線
mu, sigma = np.mean(data), np.std(data)
x = np.linspace(min(data), max(data), 100)
y = (1/(sigma * np.sqrt(2 * np.pi))) * np.exp(-0.5 * ((x - mu) / sigma) ** 2)
plt.plot(x, y, 'r--', label='Normal Distribution')
# 顯示圖表
plt.legend()
plt.show()
Histogram
使用直方圖(Histogram)來檢測數(shù)據(jù)分布的正態(tài)性也是一種常用的方法。直方圖可以幫助你直觀地了解數(shù)據(jù)的分布情況,并且可以初步判斷數(shù)據(jù)是否接近正態(tài)分布。
import numpy as np
import matplotlib.pyplot as plt
import scipy.stats as stats
# 生成一組隨機數(shù)據(jù),假設(shè)它們服從正態(tài)分布
data = np.random.normal(0, 1, 1000)
# 繪制直方圖
plt.hist(data, bins=30, density=True, alpha=0.6, color='g')
plt.title('Histogram of Data')
plt.xlabel('Value')
plt.ylabel('Frequency')
# 繪制正態(tài)分布的概率密度函數(shù)
xmin, xmax = plt.xlim()
x = np.linspace(xmin, xmax, 100)
p = stats.norm.pdf(x, np.mean(data), np.std(data))
plt.plot(x, p, 'k', linewidth=2)
plt.show()
如上圖所示,如果直方圖近似呈現(xiàn)鐘形曲線,并且與對應(yīng)的正態(tài)分布曲線形狀相似,那么數(shù)據(jù)可能符合正態(tài)分布。當然,可視化只是一種初步的判斷,如果需要更精確的檢測,可以結(jié)合使用正態(tài)性檢驗等統(tǒng)計方法進行分析。
統(tǒng)計方法Statistical Methods
夏皮羅一威爾克(Shapiro-Wilk)檢驗
是一種用于檢驗數(shù)據(jù)是否滿足正態(tài)分布的統(tǒng)計方法,又稱之為W檢驗。在進行Shapiro-Wilk檢驗時,我們通常會關(guān)注兩個主要指標:
- 統(tǒng)計量W:基于觀測數(shù)據(jù)與在正態(tài)分布下的期望值之間的相關(guān)性來計算統(tǒng)計量W,W的取值范圍在0和1之間,當W接近1時,表示觀測數(shù)據(jù)與正態(tài)分布的擬合程度較好。
- P值:P值表示觀測到這種相關(guān)性的可能性,如果P值大于顯著水平(通常為0.05),則表明觀測數(shù)據(jù)很可能來自正態(tài)分布。
因此,當統(tǒng)計量W接近1且P值大于0.05時,我們可以得出結(jié)論:觀測數(shù)據(jù)滿足正態(tài)分布。
如下代碼中,首先生成一組服從正態(tài)分布的隨機數(shù)據(jù),然后進行Shapiro-Wilk檢驗,得到檢驗統(tǒng)計量和P值。根據(jù)P值與顯著性水平的比較,即可判斷樣本數(shù)據(jù)是否來自正態(tài)分布。
from scipy import stats
import numpy as np
# 生成一組服從正態(tài)分布的隨機數(shù)據(jù)
data = np.random.normal(0, 1, 100)
# 執(zhí)行Shapiro-Wilk檢驗
stat, p = stats.shapiro(data)
print('Shapiro-Wilk Statistic:', stat)
print('P-value:', p)
# 根據(jù)P值判斷正態(tài)性
alpha = 0.05
if p > alpha:
print('樣本數(shù)據(jù)可能來自正態(tài)分布')
else:
print('樣本數(shù)據(jù)不符合正態(tài)分布')
KS檢驗
KS檢驗(Kolmogorov-Smirnov test)是一種用于檢驗數(shù)據(jù)是否符合特定分布(比如正態(tài)分布)的統(tǒng)計方法。它通過測量觀測數(shù)據(jù)與特定理論分布的累積分布函數(shù)(CDF)之間的最大差異來評估二者是否來自同一分布?;静襟E如下:
- 計算兩個樣本的經(jīng)驗累積分布函數(shù)(ECDF),即計算每個值在樣本中的累積百分比。
- 計算兩個累積分布函數(shù)之間的差異,通常使用KS統(tǒng)計量衡量。
- 根據(jù)樣本的大小和顯著性水平,使用參考表活計算p值判斷兩個樣本是否來自同一分布。
Python中使用KS檢驗來檢驗數(shù)據(jù)是否符合正態(tài)分布時,可以使用Scipy庫中的kstest函數(shù)。下面是一個簡單的示例,演示了如何使用Python進行KS檢驗來檢驗數(shù)據(jù)是否符合正態(tài)分布。
from scipy import stats
import numpy as np
# 生成一組服從正態(tài)分布的隨機數(shù)據(jù)
data = np.random.normal(0, 1, 100)
# 執(zhí)行KS檢驗
statistic, p_value = stats.kstest(data, 'norm')
print('KS Statistic:', statistic)
print('P-value:', p_value)
# 根據(jù)P值判斷正態(tài)性
alpha = 0.05
if p_value > alpha:
print('樣本數(shù)據(jù)可能來自正態(tài)分布')
else:
print('樣本數(shù)據(jù)不符合正態(tài)分布')
Anderson-Darling檢驗
Anderson-Darling檢驗是一種用于檢驗數(shù)據(jù)是否來自特定分布(例如正態(tài)分布)的統(tǒng)計方法。它特別強調(diào)觀察值在分布尾部的差異,因此在檢測極端值的偏差方面非常有效。
如下代碼使用stats.anderson函數(shù)執(zhí)行Anderson-Darling檢驗,并獲得檢驗統(tǒng)計量、臨界值以及顯著性水平。然后根據(jù)統(tǒng)計量與臨界值的比較,即可判斷樣本數(shù)據(jù)是否來自正態(tài)分布。
from scipy import stats
import numpy as np
# 生成一組服從正態(tài)分布的隨機數(shù)據(jù)
data = np.random.normal(0, 1, 100)
# 執(zhí)行Anderson-Darling檢驗
result = stats.anderson(data, dist='norm')
print('Anderson-Darling Statistic:', result.statistic)
print('Critical Values:', result.critical_values)
print('Significance Level:', result.significance_level)
# 判斷正態(tài)性
if result.statistic < result.critical_values[2]:
print('樣本數(shù)據(jù)可能來自正態(tài)分布')
else:
print('樣本數(shù)據(jù)不符合正態(tài)分布')
Lilliefors檢驗
Lilliefors檢驗(也稱為Kolmogorov-Smirnov-Lilliefors檢驗)是一種用于檢驗數(shù)據(jù)是否符合正態(tài)分布的統(tǒng)計檢驗方法,它是Kolmogorov-Smirnov檢驗的一種變體,專門用于小樣本情況。與K-S檢驗不同,Lilliefors檢驗不需要假定數(shù)據(jù)的分布類型,它基于觀測數(shù)據(jù)來評估是否來自正態(tài)分布。
如下示例中,使用lilliefors函數(shù)執(zhí)行Lilliefors檢驗,并獲得檢驗統(tǒng)計量和P值。根據(jù)P值與顯著性水平的比較,即可以判斷樣本數(shù)據(jù)是否來自正態(tài)分布。
import numpy as np
from statsmodels.stats.diagnostic import lilliefors
# 生成一組服從正態(tài)分布的隨機數(shù)據(jù)
data = np.random.normal(0, 1, 100)
# 執(zhí)行Lilliefors檢驗
statistic, p_value = lilliefors(data)
print('Lilliefors Statistic:', statistic)
print('P-value:', p_value)
# 根據(jù)P值判斷正態(tài)性
alpha = 0.05
if p_value > alpha:
print('樣本數(shù)據(jù)可能來自正態(tài)分布')
else:
print('樣本數(shù)據(jù)不符合正態(tài)分布')
距離測量Distance Measures
距離測量(Distance measures)是一種有效的測試數(shù)據(jù)正態(tài)性的方法,它提供了更直觀的方式來比較觀察數(shù)據(jù)分布與參考分布之間的差異。
下面是一些常見的距離測量方法及其在測試正態(tài)性時的應(yīng)用:
「巴氏距離(Bhattacharyya distance)」:
- 測量兩個分布之間的重疊,通常被解釋為兩個分布之間的接近程度。
- 選擇與觀察到的分布具有最小Bhattacharyya距離的參考分布,作為最接近的分布。
「海林格距離(Hellinger distance)」:
- 用于衡量兩個分布之間的相似度,類似于Bhattacharyya距離。
- 與Bhattacharyya距離不同的是,Hellinger距離滿足三角不等式,這使得它在一些情況下更為實用。
- 它本身并不是嚴格意義上的“距離度量”,但在測試正態(tài)性時可以用作衡量信息丟失的指標。
- 選擇與觀察到的分布具有最小KL散度的參考分布,作為最接近的分布。
這些距離測量方法可以幫助我們比較觀察到的分布與多個參考分布之間的差異,從而更好地評估數(shù)據(jù)的正態(tài)性。通過選擇與觀察到的分布距離最小的參考分布,我們可以更準確地判斷數(shù)據(jù)是否來自正態(tài)分布。