【发布时间】:2022-01-12 11:19:27
【问题描述】:
很抱歉,如果这是一篇很长的帖子,但我有一些与混淆矩阵度量和交叉验证相关的问题,我真的需要帮助。
这张来自 Sklearn CV link 的图片显示我们的整个数据集应该被分成训练和测试。然后,训练集再次分成验证部分,我们在 k-1 折叠中训练我们的模型并在剩余的折叠中验证(重复这 k 次)。最后,我们从一开始就使用测试集测试我们的模型。
在我的问题中,我有一个包含42372 样本的不平衡二元分类问题的数据集。 3615属于1类,其余为0类。
由于我的数据集不平衡,我使用StratifiedShuffleSplit 和5 folds,得到了这个:
结果,使用MLPClassfier 我得到了以下混淆矩阵:
从该矩阵中可以看出,我的一半数据集用于测试 (19361+19+1782+28 = 21190)。
在这之后,我改变了CV策略,并尝试了StratifiedKfold:
而且,作为混淆矩阵,我得到了这个:
从第二个混淆矩阵可以看出,我的整个数据集都用于测试 (38644+113+3329+286 = 42372)。
所以,这是我的问题:
1 - 我是否需要将整个数据拆分为训练/测试(例如,使用 train_test_split),然后提供 CV 迭代器(KFold、StratifiedKFold、StratifiedShuffleSplit 等)仅 与火车部分?或者我应该将我的整个数据输入到迭代器中,然后他们将完成将其拆分为训练/测试并将此训练再次拆分为训练和验证的工作?
2 - 关于我尝试的 CV 策略,为什么 StratifiedShuffleSplit 使用了一半的数据?为什么StratifiedKFold 使用所有数据?这些简历中的任何一个是错误的吗?两者都错还是都正确?我在这里缺少什么?
编辑:生成混淆矩阵的原始代码我发现here。我刚刚对其进行了一些修改以满足我的需要,如下所示:
import itertools
import time as time
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Patch
# from sklearn.model_selection import StratifiedKFold
from sklearn.model_selection import StratifiedShuffleSplit
from sklearn.neural_network import MLPClassifier
from sklearn.metrics import confusion_matrix
n_splits = 5 # Num of Folds
stratshufkfold = StratifiedShuffleSplit(n_splits=n_splits, random_state=0)
# stratshufkfold = KFold(n_splits=n_splits)
def generate_confusion_matrix(cnf_matrix, classes, normalize=False, title='Matriz de Confusão'):
if normalize:
cnf_matrix = cnf_matrix.astype('float') / cnf_matrix.sum(axis=1)[:, np.newaxis]
print("Matriz de confusão normalizada")
else:
print('Matriz de confusão, sem normalização')
plt.imshow(cnf_matrix, interpolation='nearest', cmap=plt.get_cmap('Blues'))
plt.title(title)
plt.colorbar()
tick_marks = np.arange(len(classes))
plt.xticks(tick_marks, classes)
plt.yticks(tick_marks, classes)
fmt = '.2f' if normalize else 'd'
thresh = cnf_matrix.max() / 2.
for i, j in itertools.product(range(cnf_matrix.shape[0]), range(cnf_matrix.shape[1])):
plt.text(j, i, format(cnf_matrix[i, j], fmt), horizontalalignment="center",
color="white" if cnf_matrix[i, j] > thresh else "black")
plt.tight_layout()
plt.ylabel('Real')
plt.xlabel('Predito')
return cnf_matrix
def plot_confusion_matrix(predicted_labels_list, y_test_list):
cnf_matrix = confusion_matrix(y_test_list, predicted_labels_list)
np.set_printoptions(precision=2)
# Plot non-normalized confusion matrix
plt.figure()
generate_confusion_matrix(cnf_matrix, classes=class_names, title='Matriz de confusão, sem normalização')
plt.show()
# Plot normalized confusion matrix
plt.figure()
generate_confusion_matrix(cnf_matrix, classes=class_names, normalize=True, title='Matriz de confusão normalizada')
plt.show()
def evaluate_model_MLP(x, y):
predicted_targets = np.array([])
actual_targets = np.array([])
global t_inicial_MLP
global t_final_MLP
t_inicial_MLP = time.time()
for train_ix, test_ix in stratshufkfold.split(x, y):
train_x, train_y, test_x, test_y = x[train_ix], y[train_ix], x[test_ix], y[test_ix]
# Fit
classifier = MLPClassifier(activation='relu', batch_size=56, solver='sgd').fit(train_x, train_y)
predicted_labels = classifier.predict(test_x)
predicted_targets = np.append(predicted_targets, predicted_labels)
actual_targets = np.append(actual_targets, test_y)
t_final_MLP = time.time()
return predicted_targets, actual_targets
predicted_target_MLP, actual_target_MLP = evaluate_model_MLP(x, y)
plot_confusion_matrix(predicted_target_MLP, actual_target_MLP)
acuracia_MLP = accuracy_score(actual_target_MLP, predicted_target_MLP)
【问题讨论】:
-
对于第一点,第一个选项是要走的路。对于您的第二个问题,imo,如果不查看您的代码,很难说出发生了什么。因此,我建议添加一段代码,以使您的示例可重现。
-
@amiola 我已经用代码编辑了帖子。我唯一无法分享的是数据库。但正如我所说,这是一个形状为
(42372, 1036)的二元分类问题,其中第一个3615样本属于1类,其余样本属于0类。
标签: python scikit-learn cross-validation confusion-matrix