最近在考虑要发Paper,在模型的性能比较中,除了采用Precision/Recall的比较之外,为了进一步验证论文中的选择是存在可证明性的,因此考虑了使用F-test对多种模型算法进行统计显著性检验。

常见的模型评估与方法

  • 误分率(misclassification rate),即准确度。
  • 精确率(precision)和召回率(recall)
  • 计算F1
  • ROC曲线,ROC_AUC
  • k-fold cross-validation

以上这些方法都能为模型的评估和选择提供有利的帮助,但是有时候会存在几个模型精度相差不多,无法科学的评判选择的情况。此时,为了更进一步的检验其显著性,统计显著性检验的方法就起到很好的的作用。

常用的显著性检验方法

Student's t-test

通过小样本来对总体均值或者总体之间均值的差异的推断通常使用t检验
\[假设X_1,X_2,...,X_n 遵循独立的分布 N(\mu,\sigma^2),i.e. 样本数量为n ,均值为 \mu ,方差为\sigma^2 .\\随机变量 \frac{\overline{X}-\mu}{\sigma/\sqrt{n}} 有一个标准的正态分布。由于总体方差未知,可以通过样本方差来估计,但是对于小样本,\\ \frac{\overline{X}-\mu}{S/\sqrt{n}}不再服从正态分布,而是服从 Student's t-distribution(n-1).\\其中,样本方差为 S^2 = \frac{1}{n-1}\sum_{i=1}^n(X_i-\overline{X})^2.得到的统计量t:\\t=\frac{\overline{X}-\mu}{S/\sqrt{n}}\\随着n的增大,S逐渐趋近于\sigma,而t分布也越来越接近正态分布。\]
一般常用双总体t检验,two-sample t-test 。 来检验总体的均值的差异是否显著。

检验统计量为:
\[t=\frac{\overline{X_1}-\overline{X_2}}{\sqrt{\frac{(n_1-1)S_1^2+(n_2-1)S_2^2}{(n_1+n_2-2)}(\frac{1}{n_1}+\frac{1}{n_2})}}\]

F-test

从两研究总体中随机抽取样本,要对这两个样本进行比较的时候,首先要判断两总体方差是否相同,即方差齐性。若两总体方差相等,则直接用t检验,若不等,可采用t'检验或变量变换或秩和检验等方法。

其中要判断两总体方差是否相等,就可以用F检验。

实现

该实验背景是根据某个工业场景,选择了一些通用模型进行训练。将数据集按照class进行分层采样成5子样本。分别使用7种不同的模型对5个子样本进行训练和检测识别。经过实验后得到一些实验数据,发现存在几种模型的precision和recall相差不多,此时在没有检测速度比较的的情况,如何科学地表达这几种模型的表现力。即统计显著性检验。

f-test具体的实现如下:

def F_test(sample, mean_list, modify_std_list):
    """
    统计显著性检验
    :param mean_list:
    :param modify_std_list:
    :return:
    """
    statistic_list = []
    pvalue_list = []
    type_list = []
    model1_list = []
    model2_list = []
    result = {}
    cout = 1
    # 统计显著性检验
    for i in range(len(Model)):
        for j in range(len(Model)):

            (statistic, pvalue) = stats.ttest_ind_from_stats(mean1=mean_list[i], std1=modify_std_list[i], nobs1=5,
                                                             mean2=mean_list[j],
                                                             std2=modify_std_list[j], nobs2=5)
            if pvalue < 0.05:
                type_list.append("Reject NULL hypothesis - Significant differences exist between groups.")
            else:
                type_list.append("Accept NULL hypothesis - No significant difference between groups.")

            model1_list.append(Model[i])
            model2_list.append(Model[j])
            statistic_list.append(statistic)
            pvalue_list.append(pvalue)

            print(
                "第 {} 对比检验组合:第 {} 个 mean:{},第 {} 个 modify_std:{}".format(cout, i, mean_list[i], j,
                                                                         modify_std_list[j]))
            print("------------第{}次迭代完成!----------".format(cout))
            cout += 1
    result = {"model1": model1_list, "model2": model2_list,
              "pvalue": pvalue_list, "statistic": statistic_list,
              "result": type_list}
    pd.DataFrame(result).to_csv('result.csv', index=False)
    return result

热力图可视化:

def plt_show(result):
    """
    可视化
    :param result:
    :return:
    """
    df = pd.read_csv('result.csv')
    print(df['pvalue'])
    # 将表格数据转化成矩阵图
    df = df.pivot("model1", 'model2', "pvalue")
    print(df)
    f, ax = plt.subplots(figsize=(9, 7))
    # grid_kws = {"height_ratios": (.9, .05), "hspace": .5}
    ax = sns.heatmap(df, ax=ax, vmin=0, vmax=0.05, cmap="GnBu", square=False,
                     xticklabels=['M1', 'M2', 'M3', 'M4', 'M5', 'M6', 'M7'],
                     yticklabels=['M1', 'M2', 'M3', 'M4', 'M5', 'M6', 'M7'],
                     center=df.loc['Faster RCNN+InceptionV2', 'SSD+MobileNetV1'],
                     annot=True, fmt='.2g', annot_kws={'size': 10, 'color': 'black', "ha": 'center', "va": 'center'})

    label_y = ax.get_yticklabels()
    plt.setp(label_y, rotation=360, horizontalalignment='right')
    label_x = ax.get_xticklabels()
    plt.setp(label_x, rotation=360, horizontalalignment='right')
    plt.xlabel('Model')  # 设置坐标名称
    plt.ylabel('Model')
    plt.savefig("f-test.jpg")
    plt.show()

最后的结果:(以上只存放了一些主要代码~)

在热力图中,如果p值大于0.05,表示两个模型之间的显著性差异不大,反之,显著性差异比较大,有很大不同。

最后希望自己的论文能够顺利地成功发表!哈哈~

01-01 21:16