思考:输入到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