確定數(shù)據(jù)分布正態(tài)性的11種基本方法
在數(shù)據(jù)科學(xué)和機(jī)器學(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è)進(jìn)行推導(dǎo)。 因此,了解如何測試數(shù)據(jù)正態(tài)性的方法對于數(shù)據(jù)科學(xué)家和機(jī)器學(xué)習(xí)從業(yè)者至關(guān)重要。
本文將介紹測試數(shù)據(jù)正態(tài)性的11種基本方法,幫助讀者更好地理解數(shù)據(jù)分布的特征和如何應(yīng)用合適的方法進(jìn)行分析,以便在機(jī)器學(xué)習(xí)和數(shù)據(jù)建模過程中更好地處理數(shù)據(jù)分布對模型性能的影響。
繪圖法Plotting Methods
1.QQ Plot
QQ圖(Quantile-Quantile Plot)是一種用于檢驗(yàn)數(shù)據(jù)分布是否符合正態(tài)分布的常用方法。在QQ圖中,將數(shù)據(jù)的分位數(shù)與標(biāo)準(zhǔn)正態(tài)分布的分位數(shù)進(jìn)行比較,如果數(shù)據(jù)分布接近正態(tài)分布,QQ圖上的點(diǎn)將大致落在一條直線上。
如下示例代碼生成了一組服從正態(tài)分布的隨機(jī)數(shù)據(jù)來演示QQ Plot,運(yùn)行代碼后,既可看到QQ Plot以及與之對應(yīng)的正態(tài)分布曲線,通過觀察圖上的點(diǎn)的分布情況來初步判斷數(shù)據(jù)是否接近正態(tài)分布。
import numpy as np
import scipy.stats as stats
import matplotlib.pyplot as plt
# 生成一組隨機(jī)數(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()
2.KDE Plot
KDE(Kernel Density Estimation)Plot是一種用于可視化數(shù)據(jù)分布的方法,它可以幫助我們檢測數(shù)據(jù)的正態(tài)性。在KDE Plot中,數(shù)據(jù)的密度被估計(jì)并繪制成一條平滑的曲線,這有助于我們觀察數(shù)據(jù)的分布形狀。
如下示例代碼生成了一組服從正態(tài)分布的隨機(jī)數(shù)據(jù)來演示KDE Plot,運(yùn)行代碼后,既可看到KDE Plot以及與之對應(yīng)的正態(tài)分布曲線,從而通過可視化來檢測數(shù)據(jù)分布的正態(tài)性。
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
# 生成隨機(jī)數(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()
3.Violin Plot
通過觀察Violin Plot可以發(fā)現(xiàn)數(shù)據(jù)的分布形狀,從而初步判斷數(shù)據(jù)是否接近正態(tài)分布。如果 Violin Plot 呈現(xiàn)出類似鐘形曲線的形狀,那么數(shù)據(jù)可能是近似正態(tài)分布的。如果 Violin Plot 偏斜嚴(yán)重或者有多個(gè)峰值,那么數(shù)據(jù)可能不是正態(tài)分布的。
如下示例代碼生成了一組服從正態(tài)分布的隨機(jī)數(shù)據(jù)來演示Violin Plot,運(yùn)行代碼后,既可看到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
# 生成隨機(jī)數(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()
4.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
# 生成一組隨機(jī)數(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)分布。當(dāng)然,可視化只是一種初步的判斷,如果需要更精確的檢測,可以結(jié)合使用正態(tài)性檢驗(yàn)等統(tǒng)計(jì)方法進(jìn)行分析。
統(tǒng)計(jì)方法Statistical Methods
5.夏皮羅一威爾克(Shapiro-Wilk)檢驗(yàn)
是一種用于檢驗(yàn)數(shù)據(jù)是否滿足正態(tài)分布的統(tǒng)計(jì)方法,又稱之為W檢驗(yàn)。在進(jìn)行Shapiro-Wilk檢驗(yàn)時(shí),我們通常會(huì)關(guān)注兩個(gè)主要指標(biāo):
- 統(tǒng)計(jì)量W:基于觀測數(shù)據(jù)與在正態(tài)分布下的期望值之間的相關(guān)性來計(jì)算統(tǒng)計(jì)量W,W的取值范圍在0和1之間,當(dāng)W接近1時(shí),表示觀測數(shù)據(jù)與正態(tài)分布的擬合程度較好。
- P值:P值表示觀測到這種相關(guān)性的可能性,如果P值大于顯著水平(通常為0.05),則表明觀測數(shù)據(jù)很可能來自正態(tài)分布。
因此,當(dāng)統(tǒng)計(jì)量W接近1且P值大于0.05時(shí),我們可以得出結(jié)論:觀測數(shù)據(jù)滿足正態(tài)分布。
如下代碼中,首先生成一組服從正態(tài)分布的隨機(jī)數(shù)據(jù),然后進(jìn)行Shapiro-Wilk檢驗(yàn),得到檢驗(yàn)統(tǒng)計(jì)量和P值。根據(jù)P值與顯著性水平的比較,即可判斷樣本數(shù)據(jù)是否來自正態(tài)分布。
from scipy import stats
import numpy as np
# 生成一組服從正態(tài)分布的隨機(jī)數(shù)據(jù)
data = np.random.normal(0, 1, 100)
# 執(zhí)行Shapiro-Wilk檢驗(yàn)
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)分布')
6.KS檢驗(yàn)
KS檢驗(yàn)(Kolmogorov-Smirnov test)是一種用于檢驗(yàn)數(shù)據(jù)是否符合特定分布(比如正態(tài)分布)的統(tǒng)計(jì)方法。它通過測量觀測數(shù)據(jù)與特定理論分布的累積分布函數(shù)(CDF)之間的最大差異來評估二者是否來自同一分布。基本步驟如下:
- 對兩個(gè)樣本數(shù)據(jù)進(jìn)行排序。
- 計(jì)算兩個(gè)樣本的經(jīng)驗(yàn)累積分布函數(shù)(ECDF),即計(jì)算每個(gè)值在樣本中的累積百分比。
- 計(jì)算兩個(gè)累積分布函數(shù)之間的差異,通常使用KS統(tǒng)計(jì)量衡量。
- 根據(jù)樣本的大小和顯著性水平,使用參考表活計(jì)算p值判斷兩個(gè)樣本是否來自同一分布。
Python中使用KS檢驗(yàn)來檢驗(yàn)數(shù)據(jù)是否符合正態(tài)分布時(shí),可以使用Scipy庫中的kstest函數(shù)。下面是一個(gè)簡單的示例,演示了如何使用Python進(jìn)行KS檢驗(yàn)來檢驗(yàn)數(shù)據(jù)是否符合正態(tài)分布。
from scipy import stats
import numpy as np
# 生成一組服從正態(tài)分布的隨機(jī)數(shù)據(jù)
data = np.random.normal(0, 1, 100)
# 執(zhí)行KS檢驗(yàn)
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)分布')
7.Anderson-Darling檢驗(yàn)
Anderson-Darling檢驗(yàn)是一種用于檢驗(yàn)數(shù)據(jù)是否來自特定分布(例如正態(tài)分布)的統(tǒng)計(jì)方法。它特別強(qiáng)調(diào)觀察值在分布尾部的差異,因此在檢測極端值的偏差方面非常有效。
如下代碼使用stats.anderson函數(shù)執(zhí)行Anderson-Darling檢驗(yàn),并獲得檢驗(yàn)統(tǒng)計(jì)量、臨界值以及顯著性水平。然后根據(jù)統(tǒng)計(jì)量與臨界值的比較,即可判斷樣本數(shù)據(jù)是否來自正態(tài)分布。
from scipy import stats
import numpy as np
# 生成一組服從正態(tài)分布的隨機(jī)數(shù)據(jù)
data = np.random.normal(0, 1, 100)
# 執(zhí)行Anderson-Darling檢驗(yàn)
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)分布')
8.Lilliefors檢驗(yàn)
Lilliefors檢驗(yàn)(也稱為Kolmogorov-Smirnov-Lilliefors檢驗(yàn))是一種用于檢驗(yàn)數(shù)據(jù)是否符合正態(tài)分布的統(tǒng)計(jì)檢驗(yàn)方法,它是Kolmogorov-Smirnov檢驗(yàn)的一種變體,專門用于小樣本情況。與K-S檢驗(yàn)不同,Lilliefors檢驗(yàn)不需要假定數(shù)據(jù)的分布類型,它基于觀測數(shù)據(jù)來評估是否來自正態(tài)分布。
如下示例中,使用lilliefors函數(shù)執(zhí)行Lilliefors檢驗(yàn),并獲得檢驗(yàn)統(tǒng)計(jì)量和P值。根據(jù)P值與顯著性水平的比較,即可以判斷樣本數(shù)據(jù)是否來自正態(tài)分布。
import numpy as np
from statsmodels.stats.diagnostic import lilliefors
# 生成一組服從正態(tài)分布的隨機(jī)數(shù)據(jù)
data = np.random.normal(0, 1, 100)
# 執(zhí)行Lilliefors檢驗(yàn)
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)分布')
9.距離測量Distance Measures
距離測量(Distance measures)是一種有效的測試數(shù)據(jù)正態(tài)性的方法,它提供了更直觀的方式來比較觀察數(shù)據(jù)分布與參考分布之間的差異。
下面是一些常見的距離測量方法及其在測試正態(tài)性時(shí)的應(yīng)用:
(1) 「巴氏距離(Bhattacharyya distance)」:
- 測量兩個(gè)分布之間的重疊,通常被解釋為兩個(gè)分布之間的接近程度。
- 選擇與觀察到的分布具有最小Bhattacharyya距離的參考分布,作為最接近的分布。
(2) 「海林格距離(Hellinger distance)」:
- 用于衡量兩個(gè)分布之間的相似度,類似于Bhattacharyya距離。
- 與Bhattacharyya距離不同的是,Hellinger距離滿足三角不等式,這使得它在一些情況下更為實(shí)用。
(3) 「KL 散度(KL Divergence)」:
- 它本身并不是嚴(yán)格意義上的“距離度量”,但在測試正態(tài)性時(shí)可以用作衡量信息丟失的指標(biāo)。
- 選擇與觀察到的分布具有最小KL散度的參考分布,作為最接近的分布。
這些距離測量方法可以幫助我們比較觀察到的分布與多個(gè)參考分布之間的差異,從而更好地評估數(shù)據(jù)的正態(tài)性。通過選擇與觀察到的分布距離最小的參考分布,我們可以更準(zhǔn)確地判斷數(shù)據(jù)是否來自正態(tài)分布。