在执行 K 折交叉验证后,我们如何在初始数据集/数据帧中包含预测列?

Posted

技术标签:

【中文标题】在执行 K 折交叉验证后,我们如何在初始数据集/数据帧中包含预测列?【英文标题】:How can we include a prediction column in the initial dataset/dataframe after performing K-Fold cross validation? 【发布时间】:2022-01-14 09:21:23 【问题描述】:

我想使用分类器对我的数据进行 K 折交叉验证。我想将每个样本的预测(或预测概率)列直接包含到初始数据集/数据帧中。有什么想法吗?

from sklearn.metrics import accuracy_score
import pandas as pd
from sklearn.model_selection import KFold

k = 5
kf = KFold(n_splits=k, random_state=None)

acc_score = []
auroc_score = []

for train_index , test_index in kf.split(X):
    X_train , X_test = X.iloc[train_index,:],X.iloc[test_index,:]
    y_train , y_test = y[train_index] , y[test_index]

    model.fit(X_train, y_train)
    pred_values = model.predict(X_test)
    predict_prob = model.predict_proba(X_test.values)[:,1]

    auroc = roc_auc_score(y_test, predict_prob)
    acc = accuracy_score(pred_values , y_test)

    auroc_score.append(auroc)
    acc_score.append(acc)

avg_acc_score = sum(acc_score)/k
print('accuracy of each fold - '.format(acc_score))
print('Avg accuracy : '.format(avg_acc_score))
print('AUROC of each fold - '.format(auroc_score))
print('Avg AUROC : '.format(sum(auroc_score)/k))

鉴于这段代码,我如何开始产生这样的想法:添加一个预测列,或者更好的是,为初始数据集中的每个样本添加预测概率列?

在 10 折交叉验证中,每个示例(样本)将在测试集中仅使用一次,在训练集中使用 9 次。因此,经过 10 次交叉验证后,结果应该是一个数据框,其中我将拥有数据集中所有示例的预测类。每个示例将被分配其初始特征、其标记类以及在交叉验证折叠中计算的预测类,该示例在测试集中使用。

【问题讨论】:

predict_proba 返回一个数组。你希望输出是什么样的?预测类别的概率,还是数据框列中的值列表? 感谢您的帮助,我希望在 K 折交叉过程结束时,我将有一个类似于初始数据集的数据框,但有一个包含所有预测结果的附加列,或者/ 和另外两列包含概率 0 和概率 1 假设我正在执行二进制类分类,并且在数据集的每个原始数据上。这甚至可能吗?我很确定我听说过它。如果您愿意,可以继续向我提问以确保我们在同一页面上,系统会提示我 你能在你的问题中发布一个你想要的例子吗? predict_proba 返回一个概率列表,即[0.6, 0.2, 0.1, 0.1]。您希望该列表出现在您的专栏中吗?请发布一个您正在尝试完成的示例。 @artemis 好的,我确实对我最初的帖子进行了更正。我相信我们现在可以忽略预测概率;这个想法是能够将 K-fold cross-val 的结果报告给初始数据集中的新列;如果它是现在的预测类,那很好;稍后我将通过报告两列以及预测概率的结果来处理它。请参考我的示例,如有任何详细信息,请随时与我联系;对于造成的混乱,我深表歉意。 【参考方案1】:

您可以使用cross_val_predict,参见help page,它基本上会返回您交叉验证的估计值:

from sklearn.datasets import make_classification
from sklearn.model_selection import cross_val_predict, KFold
from sklearn.metrics import accuracy_score
from sklearn import datasets, linear_model
from sklearn.linear_model import LogisticRegression
import pandas as pd
 

X,y = make_classification()
df = pd.DataFrame(X,columns = ["feature:02d".format(i) for i in range(X.shape[1])])
df['label'] = y

df['pred'] = cross_val_predict(LogisticRegression(), X, y, cv=KFold(5))

【讨论】:

【参考方案2】:

您可以使用.loc 方法来完成此操作。 This question 有一个很好的答案来说明如何使用它:df.loc[index_position, "column_name"] = some_value

因此,您发布的代码的编辑版本(我需要数据,并删除了 auc_roc,因为我们没有使用您每次编辑的概率):

from sklearn.metrics import accuracy_score, roc_auc_score
import pandas as pd
from sklearn.model_selection import KFold
from sklearn.datasets import load_breast_cancer
from sklearn.neural_network import MLPClassifier

X,y = load_breast_cancer(return_X_y=True, as_frame=True)
model = MLPClassifier()

k = 5
kf = KFold(n_splits=k, random_state=None)

acc_score = []
auroc_score = []

# Create columns
X['Prediction'] = 1

# Define what values to use for the model
model_columns = [x for x in X.columns if x != 'Prediction']

for train_index , test_index in kf.split(X):
    X_train , X_test = X.iloc[train_index,:],X.iloc[test_index,:]
    y_train , y_test = y[train_index] , y[test_index]

    model.fit(X_train[model_columns], y_train)
    pred_values = model.predict(X_test[model_columns])

    acc = accuracy_score(pred_values , y_test)
    acc_score.append(acc)

    # Add values to the dataframe
    X.loc[test_index, 'Prediction'] = pred_values

avg_acc_score = sum(acc_score)/k
print('accuracy of each fold - '.format(acc_score))
print('Avg accuracy : '.format(avg_acc_score))

# Add label back per question
X['Label'] = y

# Print first 5 rows to show that it works
print(X.head(n=5))

产量

accuracy of each fold - [0.9210526315789473, 0.9122807017543859, 0.9736842105263158, 0.9649122807017544, 0.8672566371681416]
Avg accuracy : 0.927837292345909
   mean radius  mean texture  ...  Prediction  Label
0        17.99         10.38  ...           0      0
1        20.57         17.77  ...           0      0
2        19.69         21.25  ...           0      0
3        11.42         20.38  ...           1      0
4        20.29         14.34  ...           0      0

[5 rows x 32 columns]

(显然模型/值等都是任意的)

【讨论】:

以上是关于在执行 K 折交叉验证后,我们如何在初始数据集/数据帧中包含预测列?的主要内容,如果未能解决你的问题,请参考以下文章

如何在朴素贝叶斯分类器中使用 k 折交叉验证?

在 PyTorch 中使用 DataLoaders 进行 k 折交叉验证

k折交叉验证模型选择方法

R:训练数据集的 k 折交叉验证

如何计算分层 K 折交叉验证的不平衡数据集的误报率?

小白学习之pytorch框架-模型选择(K折交叉验证)欠拟合过拟合(权重衰减法(=L2范数正则化)丢弃法)正向传播反向传播