总人口的相关系数大于人口样本

我创建了两个分类器,一个是提升决策树(BDT),另一个是神经网络(NN),用于将事件分类为信号类或背景类。它们输出一个介于0到1之间的连续概率,表示属于信号类的可能性。我想比较这两种方法,并希望找出它们之间的相关性。

然而,我发现如果我只计算属于背景类的事件的相关系数,或者只计算属于信号类的事件的相关系数,这些相关系数都小于整个数据集的相关系数。我原本以为由于两个分类器是在完全相同的数据集上测试的,总体相关性应该是两个独立相关性的加权平均值。请注意,总数据集包含大约100,000个事件。

在这里,我使用pandas的.corr()函数计算整个数据集的相关性,该函数计算皮尔逊相关系数矩阵:

dfBDT = pd.read_csv("BDTResults.csv")dfNN = pd.read_csv("NNResults.csv")# not defaulted by Event Number by defaultdfBDT = dfBDT.sort_values('EventNumber')dfNN = dfNN.sort_values('EventNumber')# Resets index of sorted dataframe so sorted dataframe index begins at 0dfBDT.reset_index(drop=True, inplace=True)dfNN.reset_index(drop=True, inplace=True)dfscore = pd.concat([dfBDT['score'],dfNN['score']], axis = 1)dfnum = pd.concat([dfBDT['EventNumber'],dfNN['EventNumber']], axis = 1)dfTotal = pd.concat([dfnum,dfscore], axis = 1)dfTotal.columns = ['EventNumberBDT', 'EventNumberNN', 'BDT', 'NN']dfTotal.corr()

这给出了97%的相关性。然后,我对背景事件做了同样的事情,我定义背景事件的类别为0:

BDT_back = (dfBDT.loc[dfBDT['Class'] == 0])['score']BDT_back.reset_index(drop=True, inplace=True)BDT_back_num = (dfBDT.loc[dfBDT['Class'] == 0])['EventNumber']BDT_back_num.reset_index(drop=True, inplace=True)NN_back = (dfNN.loc[dfNN['Class'] == 0])['score']NN_back.reset_index(drop=True, inplace=True)NN_back_num = (dfBDT.loc[dfBDT['Class'] == 0])['EventNumber']NN_back_num.reset_index(drop=True, inplace=True)dfBack = pd.concat([BDT_back_num,NN_back_num,BDT_back,NN_back],                   axis = 1)dfBack.reset_index(drop=True, inplace=True)dfBack.columns = ['EventNumberBDT','EventNumberNN','BDT','NN']dfBack.corr()

这给了我大约96%的相关性。然后,我对信号事件重复上述操作,即将类别=0改为类别=1,我得到的相关性为91%。

然后,如果我尝试重新合并这两个数据框并再次计算总体相关性,我得到的相关性比之前高,达到了98%:

ab = pd.concat([dfBack['BDT'],dfSig['BDT']])ba = pd.concat([dfBack['NN'],dfSig['NN']])abba =pd.concat([ab,ba], axis = 1)abba.corr()

这两个值的不同表明一定是哪里出了问题,但我不知道问题出在哪里。


回答:

归根结底,这取决于基于索引运行的水平合并操作。

未匹配的行

如果两个数据框的行不同,默认执行外连接的concat会在未匹配的索引处(在行数较少的数据框上)生成NaN,这将比拆分前的原始数据框多出更多行。

未匹配的类别

此外,如果Class在两个数据框dfBDTdfNN之间有不同的百分比份额,它们的相应连接将在未匹配的索引处返回NaN

例如,假设dfBDT在类别0和1之间保持60%和40%的比例,而dfNN在类别0和1之间保持50%和50%的比例,其中比较包括:

  • BDT类别0将有更多行比NN类别0
  • BDT类别1将有更少行比NN类别1

在使用pd.concat(..., axis = 1)进行水平连接后,默认外连接how = 'outer',产生的错配将在双方生成NaN。即使你使用how='inner',你也会过滤掉错配,但dfTotal从不过滤掉任何行,而是包括所有行。

排序顺序

在Linux和Windows机器上使用种子可复制的示例进行测试表明,排序很重要,特别是先按Class然后按EventNumber排序很重要。


这可以通过种子随机数据进行可复制的示例来演示。下面的代码重构了你的代码,以避免多次调用pd.concat,而是使用join(将其默认值调整为how='outer')。再往下,这段代码与原始设置等效。

数据

import numpy as npimport pandas as pdnp.random.seed(2292020)dfBDT = pd.DataFrame({'EventNumber': np.random.randint(1, 15, 500),                      'Class': np.random.randint(0, 1, 500),                      'score': np.random.randn(500)                     })dfNN = pd.DataFrame({'EventNumber': np.random.randint(1, 15, 500),                     'Class': np.random.randint(0, 1, 500),                     'score': np.random.randn(500)                    })

代码

dfBDT = dfBDT.sort_values(['Class', 'EventNumber']).reset_index(drop=True)    dfNN = dfNN.sort_values(['Class', 'EventNumber']).reset_index(drop=True)  # 所有行(无过滤)dfTotal = (dfBDT.reindex(['EventNumber', 'score'], axis='columns')                .join(dfNN.reindex(['EventNumber', 'score'], axis='columns'),                      rsuffix = '_')                .set_axis(['EventNumberBDT', 'BDT', 'EventNumberNN', 'NN'],                           axis='columns', inplace = False)                .reindex(['EventNumberBDT','EventNumberNN','BDT','NN'],                          axis='columns'))    dfTotal.corr()# 两个过滤后的数据框类别(0表示背景,1表示信号)df_list = [(dfBDT.query('Class == {}'.format(i))                 .reindex(['EventNumber', 'score'], axis='columns')                 .join(dfNN.query('Class == {}'.format(i))                           .reindex(['EventNumber', 'score'], axis='columns'),                       rsuffix = '_')                 .set_axis(['EventNumberBDT', 'BDT', 'EventNumberNN', 'NN'],                           axis='columns', inplace = False)                 .reindex(['EventNumberBDT','EventNumberNN','BDT','NN'],                          axis='columns')           ) for i in range(0,2)]dfSub = pd.concat(df_list)dfSub.corr()

输出 (注意它们返回不同的结果)

dfTotal.corr()#                 EventNumberBDT  EventNumberNN       BDT        NN# EventNumberBDT        1.000000       0.912279 -0.024121  0.115754# EventNumberNN         0.912279       1.000000 -0.039038  0.122905# BDT                  -0.024121      -0.039038  1.000000  0.012143# NN                    0.115754       0.122905  0.012143  1.000000dfSub.corr()#                 EventNumberBDT  EventNumberNN       BDT        NN# EventNumberBDT        1.000000       0.974140 -0.024121  0.120102# EventNumberNN         0.974140       1.000000 -0.026026  0.122905# BDT                  -0.024121      -0.026026  1.000000  0.025548# NN                    0.120102       0.122905  0.025548  1.000000

Related Posts

使用LSTM在Python中预测未来值

这段代码可以预测指定股票的当前日期之前的值,但不能预测…

如何在gensim的word2vec模型中查找双词组的相似性

我有一个word2vec模型,假设我使用的是googl…

dask_xgboost.predict 可以工作但无法显示 – 数据必须是一维的

我试图使用 XGBoost 创建模型。 看起来我成功地…

ML Tuning – Cross Validation in Spark

我在https://spark.apache.org/…

如何在React JS中使用fetch从REST API获取预测

我正在开发一个应用程序,其中Flask REST AP…

如何分析ML.NET中多类分类预测得分数组?

我在ML.NET中创建了一个多类分类项目。该项目可以对…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注