Python 所有未查看数据的概率值均小于0.5

Python 所有未查看数据的概率值均小于0.5,python,machine-learning,scikit-learn,random-forest,imbalanced-data,Python,Machine Learning,Scikit Learn,Random Forest,Imbalanced Data,我有15个带有二进制响应变量的特性,我对预测概率比0或1类标签更感兴趣。当我使用500棵树、CV、平衡类权重和数据帧中的平衡样本对RF模型进行训练和测试时,我获得了很好的准确性和较好的Brier分数。如图所示,测试数据上类别1的预测概率值介于0到1之间 以下是测试数据的预测概率直方图: 大多数值在0-0.2和0.9到1之间,这非常准确。 但是,当我试图预测看不见的数据的概率值,或者说0或1的值未知的所有数据点,预测的概率值仅在0到0.5之间,对于类1。为什么会这样?这些值不是应该在0.5到1之

我有15个带有二进制响应变量的特性,我对预测概率比0或1类标签更感兴趣。当我使用500棵树、CV、平衡类权重和数据帧中的平衡样本对RF模型进行训练和测试时,我获得了很好的准确性和较好的Brier分数。如图所示,测试数据上类别1的预测概率值介于0到1之间

以下是测试数据的预测概率直方图:

大多数值在0-0.2和0.9到1之间,这非常准确。 但是,当我试图预测看不见的数据的概率值,或者说0或1的值未知的所有数据点,预测的概率值仅在0到0.5之间,对于类1。为什么会这样?这些值不是应该在0.5到1之间吗

以下是看不见数据的预测概率直方图:

我正在使用python中的sklearn RandomforestClassifier。代码如下:

#Read the CSV
df=pd.read_csv('path/df_all.csv')

#Change the type of the variable as needed
df=df.astype({'probabilities': 'int32', 'CPZ_CI_new.tif' : 'category'})

#Response variable is between 0 and 1 having actual probabilities values
y = df['probabilities']

# Separate majority and minority classes
df_majority = df[y == 0]
df_minority = df[y == 1]

# Upsample minority class
df_minority_upsampled = resample(df_minority,
                                 replace=True,  # sample with replacement
                                 n_samples=100387,  # to match majority class
                                 random_state=42)  # reproducible results

# Combine majority class with upsampled minority class
df1 = pd.concat([df_majority, df_minority_upsampled])

y = df1['probabilities']
X = df1.iloc[:,1:138]

#Change interfere values to category
y_01=y.astype('category')

#Split training and testing
X_train, X_valid, y_train, y_valid = train_test_split(X, y_01, test_size = 0.30, random_state = 42,stratify=y)

#Model

model=RandomForestClassifier(n_estimators = 500,
                           max_features= 'sqrt',
                           n_jobs = -1,
                           oob_score = True,
                           bootstrap = True,
                           random_state=0,class_weight='balanced',)
#I had 137 variable, to select the optimum one, I used RFECV
rfecv = RFECV(model, step=1, min_features_to_select=1, cv=10, scoring='neg_brier_score')
rfecv.fit(X_train, y_train)

#Retrained the model with only 15 variables selected
rf=RandomForestClassifier(n_estimators = 500,
                           max_features= 'sqrt',
                           n_jobs = -1,
                           oob_score = True,
                           bootstrap = True,
                           random_state=0,class_weight='balanced',)

#X1_train is same dataframe with but with only 15 varible 
rf.fit(X1_train,y_train)

#Printed ROC metric
print('roc_auc_score_testing:', metrics.roc_auc_score(y_valid,rf.predict(X1_valid)))

#Predicted probabilties on test data
predv=rf.predict_proba(X1_valid)
predv = predv[:, 1]
print('brier_score_training:', metrics.brier_score_loss(y_train, predt))
print('brier_score_testing:', metrics.brier_score_loss(y_valid, predv))

#Output is,
roc_auc_score_testing: 0.9832652130944419
brier_score_training: 0.002380976369884945
brier_score_testing: 0.01669848089917487

#Later, I have images of that 15 variables, I created a data frame out(sample_img) of it and use the same function to predict probabilities. 

IMG_pred=rf.predict_proba(sample_img)
IMG_pred=IMG_pred[:,1]

显示的测试数据结果无效;您执行了一个错误的程序,该程序有两个严重后果,使其无效

这里的错误是,您在分割到训练集和测试集之前执行少数类上采样,但事实并非如此;您应该首先将数据分成训练集和测试集,然后仅对训练数据而不是测试数据执行上采样

这种程序无效的第一个原因是,通过这种方式,由于上采样而产生的一些重复将最终导致训练和测试分离;结果是,使用训练期间已经看到的一些样本对算法进行了测试,这使得测试集的基本要求无效。有关更多详细信息,请参阅中的自己的答案;从那里引述:

我曾经目睹过一个案例,建模者正在努力理解为什么他得到了~100%的测试准确率,远远高于他的培训准确率;原来他的初始数据集充满了重复数据-这里没有类不平衡,但想法是相似的-其中一些重复数据在分割后自然地出现在他的测试集中,当然不是新的或看不见的数据

第二个原因是,这个过程在一个不再代表现实的测试集中显示了有偏差的性能度量:记住,我们希望我们的测试集能够代表真实的看不见的数据,这当然是不平衡的;人为地平衡我们的测试集,声称它有X%的准确度,而这种准确度的很大一部分是由于人为地增加了少数类样本,这是没有意义的,并且会给人以误导性的印象。有关详细信息,请参见中的自己的答案(列车测试拆分的基本原理与此处相同)

第二个原因是,即使您没有执行第一个错误,您的过程仍然是错误的,并且您在分割后继续分别对训练集和测试集进行上采样

简而言之,您应该纠正这个过程,以便首先将训练集和测试集分开,然后仅对训练集进行上采样