天天看点

【特征工程】判断一组数据的分布形态

思考:输入到NN模型中的特征要做归一化处理,我看到airbnb对特征归一化的方式因特征而异,这点惊讶到我,我当前的工作中,对特征归一化处理方式是同一种。然而并不知道特征服从什么分布,或许选择了一个大家通用的归一化方法?这个不得而知。言归正传,airbnb根据不同特征做不一样的归一化,因为他们对数据进行了观察,发现了部分长尾数据,因此做了log的归一化处理[1],这点很惊喜。在我刚工作的时候,也有人问过我,一些特征的分布,当时基于人工统计做了一些表格直方图,能看出一个大概,但是真说不上来是什么分布,只是一个统计而已。

随后查阅了一些资料,主题是:如何确定一组数据的分布。

查阅到了一个博客[2],里面汇总了一些判断该分布为什么分布的方法及代码,这里我补充了一些原理及概念解释(因为我不太明白这些方法是什么,使用范围是什么)。首先我们先看下有哪些分布,然后再研究有哪些方法可以去确定一组数据符合什么分布。

(1) 离散分布:

 伯努利分布(零一分布,两点分布),二项分布,几何分布,泊松分布(Poisson分布)

(2) 连续分布:

 指数分布,正态分布(高斯分布),均匀分布

(3) 抽样分布:

 卡方分布(X2分布),F分布,T分布

(4) 其它分布:

 多项分布,Beta分布,Dirichlet分布

方法1:夏皮罗维尔克检验(Shapiro-Wilk test)

概念:是一种在频率上统计检验中检验正态性的方法。它在1965年由夏皮罗和威尔克发表。

适用范围:检验小样本数据是否服从正态分布,数据量大于5000时不适用。

代码:这里需要生成一组正态分布的数据,待验证的数据跟它进行对比。

##生成40个服从N(2,1)的随机数
import numpy as np
np.random.seed(0)
mu = 2 ; sigma = 1; sampleNo = 40;
testData = np.random.normal(mu, sigma, sampleNo)
 
##利用Shapiro-Wilk test检验其是否服从正态分布
import scipy.stats as stats
print(stats.shapiro(testData))
##输出(统计量W的值,P值)=(0.9782678484916687, 0.6254357695579529)
##W的值越接近1就越表明数据和正态分布拟合得越好,P值>指定水平,不拒绝原假设,可以认为样本数据服从正态分布
 
           

方法2:科尔莫戈罗夫检验(Kolmogorov-Smirnov test)

概念:来分析变量是否符合某种分布或比较两组之间有无显著性差异。 检验单一样本是否来自某一特定分布的方法。

适用范围:

    1)用于检验X的分布G(x)是否服从给定分布F(x),仅适用于连续分布的检验;

    2)检验两组数据是否来自统一分布。

代码:

   1)这里stats.kstest()的第二个参数是Defines the distribution used for calculating the p-value.意思是你想看看你的数据符合啥分布,则将该参数设置为啥分布。

##生成随机数
import numpy as np
np.random.seed(0)
testData = np.random.normal(0,1,100)
 
##利用Kolmogorov-Smirnov test检验testData是否服从正态分布
import scipy.stats as stats
stats.kstest(testData,'norm')
##输出(统计量D的值,P值)=(0.058248638723832402, 0.88658843653019392)
##统计量D的值越接近0就越表明数据和标准正态分布拟合得越好,P值>指定水平,不拒绝原假设,可以认为样本数据服从正态分布。
           

   2)

import numpy as np
chi2 = np.random.chisquare(98, size=100)
norm = np.random.normal(0,1,100)
##检验norm和chi2是否服从同一分布
import scipy.stats as stats
print(stats.ks_2samp(norm, chi2))
##输出Ks_2sampResult(statistic=1.0, pvalue=1.5505547466854487e-45)
           

方法3:安德森-达令检验(Anderson-Darling test)

概念:检验样本数据是否来自特定分布,包括分布:'norm', 'expon', 'gumbel', 'extreme1' or 'logistic'. 

适用范围:它可用於试验分布是否适合,它可以用于建基於最小距离估计程序的参数估计。

代码:

import numpy as np
np.random.seed(0)
data_norm = np.random.normal(0,1,100)
 
##用Anderson-Darling检验生成的数组是否服从正态分布
import scipy.stats as stats
stats.anderson(data_norm, dist='norm')
           

方法4:Lilliefors检验

概念:检验样本数据是否来自正态总体

适用范围:当总体均值和方差未知时,用样本的均值和方差代替后 再用K-S检验法。据说效果不如Anderson-Darling test

代码:

#代码有点问题,后续会修正
##生成1000个服从N(0,1)的随机数
import numpy as np
np.random.seed(0)
norm_Data = np.random.normal(0,1,1000)
#生成100个服从lambda=10的指数分布exp(10)
exp_Data = np.random.exponential(scale=0.1, size=1000) #scale=1/lambda
 
 
from statsmodels.stats.diagnostic import lilliefors
lilliefors(norm_Data)
##输出(统计量的值,P值)=(0.019125294462402076, 0.48168672320192013),P值>指定水平0.05,接受原假设,可以认为样本数据服从正态分布
 
lilliefors(exp_Data)
           

方法5:基于偏度和峰度的检验

概念:偏度是判断样本左边长尾(峰度)还是右边长尾,峰度是判断样本的分布是瘦高还是矮胖。

适用范围:可用于检验样本数据是否来自正态分布(偏度=0,峰度=3),易受异常值影响,不能用于小样本。

代码:

##生成1000个服从N(0,1)的随机数
import numpy as np
np.random.seed(0)
norm_Data = np.random.normal(0,1,1000)
#生成100个服从lambda=10的指数分布exp(10)
exp_Data = np.random.exponential(scale=0.1, size=1000) #scale=1/lambda
 
import scipy.stats as stats
stats.jarque_bera(norm_Data)
##输出(统计量JB的值,P值)=(0.28220016508625245, 0.86840239542814834),P值>指定水平0.05,接受原假设,可以认为样本数据在5%的显著水平下服从正态分布

stats.jarque_bera(exp_Data)
##输出(统计量JB的值,P值)=(1117.2762482645478, 0.0),P值<指定水平0.05,拒绝原假设,认为样本数据在5%的显著水平下不服从正态分布
 
           

参考:

1.https://zhuanlan.zhihu.com/p/51173605

2.https://blog.csdn.net/qq_20207459/article/details/80331805

3.https://www.jianshu.com/p/04cc140e1127

4.https://www.jianshu.com/p/c675e3f67843

继续阅读