跳转至

检验样本分布的正态性

在对数据进行处理前,有时需要判断数据是否呈正态分布。本文介绍了定量检验正态性的两种方法:Shapiro-Wilk test 和距离熵。

Shapiro-Wilk 检验正态性

Shapiro-Wilk test 是一种在频率上统计检验中检验正态性的方法。该检验的零检验是样本 \(x_1,\cdots ,x_n\)来自于一个正态分布的母体。这个检验的统计量是:

\[ W = \frac{(\sum_{i=1}^{n}a_{i}x_{(i)})^2}{\sum_{i=1}^{n}(x_i-\bar{x})^2} \]

其中:

  1. \(x_{(i)}\) 用括号包含下标索引 \(i\) 的;\(x_{(i)}\) 是第 \(i\) 阶统计量,即样本中的第 \(i\) 个最小数,注意不要与 \(x_i\) 混淆!
  2. \(\overline {x}=(x_{1}+\cdots +x_{n})/n\)是样本的平均值。
  3. 常量 \(a_i\)通过下面的公式得出:
\[ (a_1,\dots ,a_n)=\frac{m^{T}V^{-1}}{\sqrt{(m^{T}V^{-1}V^{-1}m)}}, m=(m_1,\dots ,m_n)^T \]

其中 \(m_1,\dots ,m_n\)是从一个标准的正态分布随机变量上采样的有序独立同分布的统计量的期望值。V 是这些有序统计量的协方差。

这个统计检验的假设是样本来自于一个正态母体,因此,一方面,如果 p 值小于选择的显著度水平(通常设为 0.05),那么在更大概率下我们应该拒绝零假设,数据的证据显示我们的样本不是来自一个正态分布母体。另一方面,如果 p 值比选择的显著度水平大,那么我们没有证据拒绝零假设,数据来自于一个正态分布。

Python 实现:

Python
import numpy as np
from scipy import stats
np.random.seed(0)
x = np.random.randn(1, 1000)
print(stats.shapiro(x[0]))
# (0.9985557794570923, 0.5914123058319092)
# 输出(统计量 W 的值,P 值)
# W 的值越接近 1 就越表明数据和正态分布拟合得越好
# P 值>指定水平,不拒绝原假设,可以认为样本数据服从正态分布
# 不适合样本>5000 的情况

距离熵

距离熵 (metric entropy) :用非参的高斯核密度估计出样本点 \(x_t\) 对应的分布函数,与标准正态分布密度函数相减并计算差值的平方和:

\[ metric\_ entropy = \sum_{t=1}^N\left(D_h\left(x, m_t\right)-N\left(0,1, m_t\right)\right)^2 \]

其中:

  1. \(D_h\left(x, x_t\right)\) 表示基于样本 \(x\) 计算得到的核密度估计概率密度函数在 \(m_t\) 处的取值。

  2. \(m_t = \min \left(x_t\right)+\frac{\max \left(x_t\right)-\min \left(x_t\right)}{N} t\)\(N\left(0,1, m_t\right)\) 表示标准正态分布密度函数对应 \(m_t\)处的取值。

  3. 若样本点完全服从正态分布,那么 \(metric\_ entropy = 0\)

以某日的两只股票为例,分别绘制当日的分钟收盘价折线图与标准化后的分钟收益率的直方图,如下图所示。当日内收益率出现极端值时,高斯核密度估计与标准正态分布的差距较大,计算出的距离熵也较大。上图中的股票价格变化较为平稳,距离熵为\(0.13\),下图中的股票价格在少数分钟出现突变,距离熵为\(0.87\)

nos

Python 实现:

Python
def metric_entropy(array):
    # 使用高斯核密度估计出样本点 $x_t$ 对应的分布函数
    kernel_density = stats.gaussian_kde(array)
    # 计算样本点的最小值和最大值
    x_min = array.min()
    x_max = array.max()
    # 生成等差数列,用于计算距离熵
    # 第一个数字是 x_min + (x_max - x_min) / len(array),最后一个数字是 x_max,一共有 len(array) 个数字
    m_list = np.linspace(start = x_min, stop = x_max, num=len(array)+1)[1:]
    # 计算高斯核密度估计的概率密度值
    D_list = kernel_density(m_list)
    # 计算正态分布的概率密度值
    N_list = stats.norm.pdf(m_list)
    # 计算距离熵
    metric_entropy = sum((D_list - N_list)**2)

评论