Friedman test以及后续检验Nemenyi test和Bonferroni-Dunn test

本文讨论了Friedman测试及其后续检验Nemenyi测试和Bonferroni-Dunn测试在算法性能对比中的应用及局限性,并提出了使用Wilcoxon符号秩检验作为替代方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:Friedman test以及后续检验Nemenyi test和Bonferroni-Dunn test

在做算法对比时,往往需要对实验结果进行统计检验。Friedman test是一种常用的检验,用来比较k个算法在N个数据集上的整体表现性能。但Friedman test只能给出k个算法的性能之间是否存在差异的结论,如果存在差异,还需要进行“后续检验”(post-hoc test),以得出哪些算法的性能之间存在统计上的差异,常用的后续检验方法包括Nemenyi test和Bonferroni-Dunn test。

Nemenyi test适用于对比k个算法相互之间的性能(when all classifiers are compared to each other),而Bonferroni-Dunn test适用于将某个算法与其余k-1个算法对比(when all classifiers are compared with a control classifier),二者都是将各个算法平均排名之差与某域值(critical difference, CD)对比,若大于该域值则说明平均排名高的算法统计上优于平均排名低的算法,反之则二者统计上没有差异。

这个域值CD的计算方式如下:

                                                     CD = q_{\alpha} \sqrt{\frac{k(k+1)}{6N}}

其中,k为参加对比的算法个数,N为数据集个数,常用的q_{\alpha}值可通过下表查得,其中表(a)对应Nemenyi test,表(b)对应Bonferroni-Dunn test,#classifiers为算法个数k:

这里重点想谈的是这种统计检验方法存在的问题,注意到由上面公式计算出来的q_{\alpha}一般都大于1,这意味着什么呢?如果在所有数据集上,你所提出的算法一直排名第一,几个对比算法分别一直排名第二、第三、第四……,很明显你所提出的算法优于所有对比算法(就好像你每次考试都是班级第一,肯定比每次都考班级第二的同学优秀,每次考试则对应这里的一个数据集);但是,你所提出的算法与一直排名第二的算法平均排名之差只有1,会小于q_{\alpha},表示二者没有显著差别,这明显有悖于常理。也就是说,这种统计检验方法不仅要求你自己的算法在每个数据集上的排名要靠前,还要求其它对比算法在每个数据集上的排名随机的比较差,这样才能保证对比算法的平均排名都比较低,进而保证你自己的算法与对比算法的平均排名之差大于域值CD。

为了直观起见,我们来计算一下q_{\alpha},看看当数据集个数N大概取多少个时CD值才会小于1。一般来说,论文中对比算法选4到5个,加上我们自己所提的算法k的取值就是5或6,我们计算\alpha=0.05时的CD值,即查表时看q_{0.05}那一行。

k=5时:

对于Nemenyi test来说,至少要当N=38时,

                                                CD=2.728\sqrt{\frac{5 \times 6}{6 \times 38}}\approx 0.9895<1

也就是说至少要在38个数据集上做实验才能避免我说的那种悖论;

对于Bonferroni-Dunn test来说,至少要当N=32时,

                                            CD = 2.498\sqrt{\frac{5 \times 6}{6 \times 32}}\approx 0.9874<1

也就是说至少要在32个数据集上做实验才能避免我说的那种悖论;

k=6时:

对于Nemenyi test来说,至少要当N=57时,

                                           CD=2.850\sqrt{\frac{6 \times 7}{6 \times 57}}\approx 0.9987<1

也就是说至少要在57个数据集上做实验才能避免我说的那种悖论;

对于Bonferroni-Dunn test来说,至少要当N=47时,

                                           CD = 2.576\sqrt{\frac{6 \times 7}{6 \times 47}}\approx 0.9941<1

也就是说至少要在47个数据集上做实验才能避免我说的那种悖论;这里提的悖论指经过统计检验得出每次考第一的同学与每次考第二的同学没有差别的结论,因为从常理角度来看应该是每次考第一的同学比每次考第二的同学要优秀。

但实际上,一般论文中我们也就在10个到20个数据集上做实验而已(也有些文章甚至会仅在5个左右数据集上做实验),那么可以计算如下(Bonferroni-Dunn test更符合我们的应用场景,即对比我们的算法与所选的对比算法之间的关系):

k=5时,对于Bonferroni-Dunn test来说,

                                     N=10:~CD = 2.498\sqrt{\frac{5 \times 6}{6 \times 10}}\approx1.766

                                    N=20:~CD = 2.498\sqrt{\frac{5 \times 6}{6 \times 20}}\approx1.249

k=6时,对于Bonferroni-Dunn test来说,

                                   N=10:~CD = 2.576\sqrt{\frac{6 \times 7}{6 \times 10}}\approx 2.155

                                   N=20:~CD = 2.576\sqrt{\frac{6 \times 7}{6 \times 20}}\approx 1.524

可以看出,当只使用10个数据集时,这个排名之差的域值CD要求还是挺严格的;尤其是k=6N=10时,即使你的算法一直排名第1,对比算法必须平均排名大于3.155=1+2.155才表示你的算法统计上优于对比算法,而此时一共也只有k=6个算法而已啊。

针对Friedman test联合后续检验的以上这种缺陷,我感觉Wilcoxon signed rank test其实更合适于做统计检验用来对比两两之间的性能,在Matlab中可以直接调用signrank函数实现,具体就不谈了,可以查阅signrank的使用方法和以下参考文献。

参考文献(以上所有理论细节均在此文献中):

Janez Demsar,  Statistical Comparisons of Classifiers over Multiple Data Sets, In: JMLR, 2006, 7(1), 1-30.

链接:https://www.jmlr.org/papers/volume7/demsar06a/demsar06a.pdf

<think>好的,我现在需要帮助用户解决如何在编程中实现同组两两比较检验的问题。首先,我得理解用户的需求。用户提到的是“同组两两比较检验”,可能是指同一数据集中多个组之间的两两比较,比如在多组独立样本的非参数检验之后进行的比较,例如Nemenyi检验Bonferroni校正法。用户可能已经了解了一些统计学方法,但需要具体的编程实现步骤。 接下来,我需要回忆相关的统计方法。常见的多组比较方法有方差分析(ANOVA),但如果是非参数的情况,可能会使用Kruskal-Wallis检验,之后进行两两比较。这时候,Bonferroni校正是常用的方法,用来调整显著性水平,避免多重比较带来的误差。此外,还有Nemenyi检验,适用于非参数的情况,尤其是在Friedman检验后的比较。 然后,我需要考虑如何在编程中实现这些方法。用户可能使用的是Python或R,但根据用户提供的示例中有Python代码,可能更倾向于Python。不过,SPSS的实现也可能被提及,但用户的问题明确提到编程实现,所以可能主要用Python或R。 首先,对于参数检验的情况,比如ANOVA后的Tukey HSD检验,Python中可以使用statsmodels库。对于非参数的情况,比如Kruskal-Wallis后的Dunn检验,可能需要使用scipy.stats,但需要注意这些库是否直接支持两两比较。如果没有现成的函数,可能需要手动实现,比如使用Mann-Whitney U检验并进行Bonferroni校正。 接下来,我需要整理步骤。例如,对于非参数的情况,步骤可能包括:1. 进行Kruskal-Wallis检验确定组间差异;2. 生成所有可能的两两组合;3. 对每对使用Mann-Whitney U检验;4. 应用Bonferroni校正调整p值;5. 输出结果。 在Python中,可以使用itertools来生成组合,scipy.stats进行检验,然后乘以比较次数来校正p值。同时,需要提醒用户注意,Bonferroni校正可能过于保守,可以考虑其他方法如Holm-Bonferroni。 另外,用户提供的引用中提到了SPSS的实现,可能用户也想知道如何在SPSS中操作,但问题明确是编程实现,所以可能简要提到,但重点放在Python或R的代码上。 还需要考虑示例代码的正确性,比如使用scipy的kruskalmannwhitneyu函数,然后进行循环p值调整。同时,需要解释代码的步骤,让用户能够理解每一步的作用。 可能还需要提到其他方法,比如Nemenyi检验,但可能没有现成的Python实现,需要手动计算或使用其他库,如scikit-posthocs。这里可能需要建议安装第三方库。 最后,需要生成相关问题,例如如何选择校正方法,不同方法的区别,如何处理数据不满足正态性等。这些问题可以帮助用户进一步探索。 总结来说,回答的结构应该是先介绍两两比较的概念应用场景,然后分参数非参数情况给出步骤代码示例,最后提供相关问题注意事项。</think>### 同组两两比较检验的编程实现方法 #### 1. **方法概述** 同组两两比较检验(Pairwise Comparison)用于分析多组数据中任意两组之间的显著性差异,常见于方差分析(ANOVA)或非参数检验(如Kruskal-Wallis检验)后。常用方法包括: - **参数检验**:Tukey HSD(适用于方差分析后的多重比较) - **非参数检验**:Dunn检验Nemenyi检验(需结合Bonferroni校正控制误差率)[^2] #### 2. **实现步骤** ##### (1) 参数检验(以Tukey HSD为例) **Python示例**(使用`statsmodels`库): ```python import pandas as pd import statsmodels.stats.multicomp as mc # 假设数据格式为:groups是分组标签,values是观测值 data = pd.DataFrame({'group': ['A','A','B','B','C','C'], 'value': [1,2,3,4,5,6]}) # 执行Tukey HSD检验 tukey = mc.MultiComparison(data['value'], data['group']) result = tukey.tukeyhsd(alpha=0.05) print(result.summary()) ``` ##### (2) 非参数检验(以Dunn检验为例) **Python示例**(使用`scikit-posthocs`库): ```python import scipy.stats as stats import scikit_posthocs as sp # 生成多组数据(示例) data = [[1,2,3], [4,5,6], [7,8,9]] # 先执行Kruskal-Wallis检验 h_stat, p_value = stats.kruskal(*data) if p_value < 0.05: # 执行Dunn检验Bonferroni校正) dunn_result = sp.posthoc_dunn(data, p_adjust='bonferroni') print(dunn_result) ``` ##### (3) 手动实现Bonferroni校正 若需自定义实现(如Mann-Whitney U检验的两两比较): ```python import itertools from scipy.stats import mannwhitneyu import numpy as np groups = {'A': [1,2,3], 'B': [4,5,6], 'C': [7,8,9]} pairs = list(itertools.combinations(groups.keys(), 2)) adjusted_alpha = 0.05 / len(pairs) # Bonferroni校正 for pair in pairs: u_stat, p = mannwhitneyu(groups[pair[0]], groups[pair[1]]) print(f"{pair[0]} vs {pair[1]}: p={p:.4f}, 显著性={p < adjusted_alpha}") ``` #### 3. **关键点说明** - **多重比较校正**:Bonferroni校正通过调整显著性阈值($\alpha/n$,$n$为比较次数)降低假阳性风险[^1]。 - **非参数方法选择**:若数据不满足正态性或方差齐性,优先使用Dunn检验Nemenyi检验[^2]。 - **编程工具**:Python中`scikit-posthocs`库封装了多种两两比较方法,R语言中`PMCMRplus`包更全面。
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值