正态检查相关算法

概念:

正态检验,也被称为正态性检验,是一种统计方法,用于检验一个数据集是否符合正态分布。正态分布,也被称为高斯分布,是一种在自然和社会科学中常见的连续概率分布。

正态性检验的重要性在于许多统计技术都假定数据是正态分布的。如果这个假设不成立,那么这些技术可能会得出错误的结果。例如,t检验和线性回归等参数统计方法都需要数据是正态分布的。

正态性检验的方法有很多种,包括直观的直方图观察、QQ图,也有严格的统计检验方法,例如Kolmogorov-Smirnov检验、Shapiro-Wilk检验、Anderson-Darling检验等。

如果一个数据集通过了正态性检验,那么就可以使用假设数据分布为正态分布的统计方法进行进一步的分析。反之,则需要使用非参数统计方法,或者对数据进行转换使其接近正态分布。

类型

1.Anderson-Darling检验:

Anderson-Darling检验是一种统计假设检验,用于检查一组样本是否来自特定的概率分布。Anderson-Darling检验在统计中是非常有用的,尤其是在检查数据是否遵循正态分布时。

在正态性检验中,Anderson-Darling检验是相对较敏感的检验,因为它对于尾部的偏离更加敏感。也就是说,如果数据的尾部与正态分布的尾部有较大的偏离,那么Anderson-Darling检验会有较大的检验统计量,从而更可能拒绝原假设,即样本数据不是来自正态分布。

Anderson-Darling检验的原假设是样本数据来自指定的分布,对于正态性检验,指定的分布就是正态分布。如果检验结果的p值小于显著性水平(例如0.05),那么我们就拒绝原假设,认为样本数据不是来自正态分布。反之,如果p值大于显著性水平,那么我们就无法拒绝原假设,认为样本数据可能来自正态分布。

算法示例1:

/ 假设我们有一组观测数据  
let data = [1, 2, 3, 4, 5, 6, 7, 8, 9];  
  
// 首先,我们需要对数据进行排序  
data.sort((a, b) => a - b);  
  
// 计算数据的平均值和标准差  
let mean = data.reduce((a, b) => a + b) / data.length;  
let sd = Math.sqrt(data.map(x => Math.pow(x - mean, 2)).reduce((a, b) => a + b) / data.length);  
  
// 计算Anderson-Darling统计量  
let AD = -data.length;  
for(let i = 0; i < data.length; i++) {  
let x = (data[i] - mean) / sd;  
let F = 0.5 * (1 + Math.erf(x / Math.sqrt(2))); // 正态分布的CDF  
AD += (2*i+1) * (Math.log(F) + Math.log(1 - F));  
}  
AD *= -1 / data.length;  
  
// 如果AD统计量小于某个阈值(例如0.05),那么我们可以认为观测数据符合正态分布  
console.log(AD < 0.05);

在这个示例中,我们首先对数组进行排序,然后使用Anderson-Darling检验的公式计算A2统计量。返回的A2值越小,数据越可能符合正态分布。

注意:这个函数假设输入数据已经被归一化为0-1之间,并且遵循正态分布。如果你的数据不满足这些条件,你需要先对数据进行适当的转换或标准化。

算法示例2:

function anderson_darling_test(data: number[]): number {  
    let sorted_data = data.sort((a, b) => a - b);  
    let n = sorted_data.length;  
    let sum = 0;  
  
    for (let i = 0; i < n; i++) {  
        let x = sorted_data[i];  
        let f = jStat.normal.cdf(x, jStat.mean(data), jStat.stdev(data, true));  
        sum += (2 * i + 1) * Math.log(f) + (2 * (n - i) - 1) * Math.log(1 - f);  
    }  
  
    let ad_statistic = -n - sum / n;  
    return ad_statistic;  
}  
  
let data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];  
console.log(anderson_darling_test(data));

这个函数首先将数据排序,然后对每个数据点计算其累积分布函数(CDF)的值(使用jStat.normal.cdf函数)。然后,它将这些值用于计算Anderson-Darling统计量。注意,这个函数需要jStat库,你可以使用npm来安装它:npm install jstat

这只是一个简单的实现,可能无法处理所有可能的边界情况。在实际使用时,你可能需要进行更详尽的错误检查和处理。

2.Ryan-Joiner

Ryan-Joiner检验,也被称为Pearson检验,是一种用于检验数据是否符合正态分布的统计方法。这种检验方法的基本思想是将样本数据与理论正态分布的数据进行比较。

Ryan-Joiner检验通常包括以下步骤:

  1. 将数据从小到大排序。
  2. 计算每个数据值的累积频率。
  3. 将累积频率转换为正态分布的累积频率。
  4. 计算每个数据值与其对应的正态分布值之间的差异。
  5. 通过计算统计量RJ(Ryan-Joiner)来量化这些差异。RJ值越接近1,数据越可能符合正态分布。

但是,和很多统计方法一样,Ryan-Joiner检验也有其局限性。例如,当样本数量较少时,这种检验方法可能会产生误导性的结果。

算法示例1:

import * as math from 'mathjs';  
import * as ss from 'simple-statistics';  
  
let data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; // 这是你的数据  
let n = data.length;  
  
// 第一步:对数据排序  
data.sort((a, b) => a - b);  
  
// 第二步:计算每个数据点的累积分布函数值  
let z = data.map((value) => {  
return math.normal.inv(ss.cumulativeStdNormalProbability((value - ss.mean(data)) / ss.standardDeviation(data)), 0, 1);  
});  
  
// 第三步:计算a值  
let a = [];  
for (let i = 0; i < n; i++) {  
a.push(ss.sum(z.slice(0, i+1)) / ss.sum(z));  
}  
  
// 第四步:计算W值  
let W = 1 - (ss.sum(a.map((value, index) => {  
return value * (z[index] - ss.mean(z));  
})) / ss.sum(z.map(value => {  
return Math.pow(value - ss.mean(z), 2);  
})));  
  
console.log(W); //

以上代码中,ss.cumulativeStdNormalProbability是计算数据点的累积分布函数值,math.normal.inv是计算累积分布函数的逆函数值。

注意,这只是一个简单的Ryan-Joiner检验的实现,实际应用中可能需要考虑更多的细节和优化。如果你需要在生产环境中使用Ryan-Joiner检验,建议你使用成熟的统计软件包,如R或Python的scipy库。

算法示例2:

function ryan_joiner_test(data: number[]): number {  
    let sorted_data = data.sort((a, b) => a - b);  
    let n = sorted_data.length;  
    let rank = jStat.jStat.rank(sorted_data);  
    let expected_rank = rank.map(r => jStat.jStat.normal.inv((r - 0.5) / n));  
    let rj_statistic = jStat.jStat.corrcoeff(expected_rank, sorted_data);  
return rj_statistic;  
}  
  
let data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];  
console.log(ryan_joiner_test(data));

这个函数首先将数据排序,然后计算每个数据点的秩(即在排序后的数据中的位置)。然后,它计算每个秩对应的正态分布的分位数(使用jStat.normal.inv函数)。最后,它计算这些分位数与原始数据的相关系数,得到Ryan-Joiner统计量。

3.Kolmogorov-Smirnov

Kolmogorov-Smirnov检验(简称KS检验),是一种非参数检验方法,由俄国数学家安德雷·尼古拉耶维奇·科尔莫戈罗夫(Andrey Nikolaevich Kolmogorov)和尼古拉·瓦西里耶维奇·斯米尔诺夫(Nikolai Vasilyevich Smirnov)在20世纪30年代提出。

KS检验的主要目的是判断一个随机样本是否符合某一理论分布,或者判断两个随机样本是否来自同一分布。它的优点是完全非参数,对数据的分布形态没有任何要求,适用范围较广。

KS检验的核心是比较实际数据的累积分布函数(CDF)和理论分布的CDF,或者比较两个数据集的CDF。检验统计量D是这两个CDF之间的最大差距。

检验的结果是一个p值,这个p值表示观察到的数据与理论分布(或两个数据集)之间的差距是偶然产生的概率。如果p值小于某个显著性水平(例如0.05),我们就拒绝原假设,认为数据不符合理论分布,或者两个数据集来自不同的分布。

算法示例1:

// 首先,需要安装simple-statistics库  
// 使用npm进行安装:npm install simple-statistics  
  
const ss = require('simple-statistics');  
  
// 假设我们有一组观测数据  
let observed = [1, 2, 3, 4, 5, 6, 7, 8, 9];  
  
// 假设我们期望的是一组均匀分布的数据  
let expected = [1, 2, 3, 4, 5, 6, 7, 8, 9];  
  
// 使用simple-statistics库的cumulativeDistributionFunction函数  
// 来计算观测数据和期望数据的累积分布函数(CDF)  
let observed_cdf = observed.map(ss.cumulativeDistributionFunction(observed));  
let expected_cdf = expected.map(ss.cumulativeDistributionFunction(expected));  
  
// 然后,我们找到观测CDF和期望CDF之间的最大差距  
let max_diff = Math.max(...observed_cdf.map((val, i) => Math.abs(val - expected_cdf[i])));  
  
// 如果最大差距小于某个阈值(例如0.05),那么我们可以认为观测数据符合期望的分布  
console.log(max_diff < 0.05);

这个例子中,我们假设期望的是均匀分布。如果你想要检验观测数据是否符合正态分布,你需要使用正态分布的CDF来替换期望CDF的计算。

需要注意的是,这个例子中的代码只是一个基本的实现,并没有考虑一些细节,例如处理浮点数精度问题、处理数据排序问题等。在实际使用中,可能需要根据实际情况进行一些调整。

算法示例2:

function kolmogorov_smirnov_test(data: number[]): number {  
    // 对数据进行排序  
    let sorted_data = data.sort((a, b) => a - b);  
    let n = sorted_data.length;  
  
    // 计算累积分布函数 (CDF)  
    let cdf = sorted_data.map((value, index) => (index + 1) / n);  
  
    // 计算期望的CDF (对于正态分布)  
    let expected_cdf = sorted_data.map(value => jStat.normal.cdf(value, jStat.mean(data), jStat.stdev(data, true)));  
  
    // 计算Kolmogorov-Smirnov统计量  
    let d = math.max(math.abs(math.subtract(cdf, expected_cdf)));  
  
    return d;  
}  
  
let data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];  
console.log(kolmogorov_smirnov_test(data));

段代码首先对输入数据进行了排序,并计算了每个数据点的累积分布函数(CDF)。然后,它计算了理想情况下(即数据服从正态分布时)的CDF,并计算了这两个CDF之间的最大差值,这就是Kolmogorov-Smirnov统计量。

这只是一个基本的实现,可能无法处理所有可能的边界条件和特殊情况。在实际使用时,你可能需要进行更详尽的错误处理和检查。

原文链接:https://juejin.cn/post/7265946243195994152 作者:流枫_像风一样

(0)
上一篇 2023年8月12日 上午10:26
下一篇 2023年8月12日 上午10:36

相关推荐

发表回复

登录后才能评论