具有交叉验证的不同混淆矩阵
Different Confusion Matrix with Cross-Validation
很抱歉,如果这很长 post,但我有一些与混淆矩阵指标和交叉验证相关的问题,我真的需要帮助。
这张来自 Sklearn CV link 的图片表明我们的整个数据集应该分为训练和测试。然后,训练集再次被分成验证部分,我们以 k-1 次训练我们的模型并在剩余的一次中验证(重复 k 次)。最后,我们从一开始就用测试集测试我们的模型。
在我的问题中,我有一个不平衡二进制 classification 问题的数据集,样本为 42372
。 3615
属于class1
,其余为class0
.
由于我的数据集不平衡,我使用 StratifiedShuffleSplit
和 5 folds
,得到这个:
结果,使用 MLPClassfier
我得到以下混淆矩阵:
正如您从该矩阵中看到的那样,我的数据集有一半用于测试 (19361+19+1782+28 = 21190
)。
之后,我改变了CV策略,并尝试了StratifiedKfold
:
而且,作为混淆矩阵,我得到了这个:
从第二个混淆矩阵可以看出,我的整个数据集都用于测试 (38644+113+3329+286 = 42372
)。
所以,这是我的问题:
1 - 我是否需要将整个数据拆分为 train/test(例如,使用 train_test_split
),然后提供 CV 迭代器(KFold
、StratifiedKFold
、 StratifiedShuffleSplit
,等等)只有火车部分?或者我应该将我的全部数据输入迭代器,它们将完成将其拆分为 train/test 并将这列火车再次拆分为火车和验证的工作?
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)
如评论中所述,对于第一个问题,第一个选项是要走的路。即,通过 train_test_split
拆分整个数据集,然后在 训练集 .
上调用所选交叉验证器对象的方法 .split()
对于第二点,问题隐藏在StratifiedKFold
和StratifiedShuffleSplit
的一些默认参数背后,以及参数n_splits
.
的略微不同的含义上
关于 StratifiedKFold
,参数 n_splits
确定 折叠数 您根据 documentation.因此,强加 n_splits=5
意味着模型将在 4 倍(训练集的 80%)上训练,并在每个可能的组合上测试一次(训练集的 20%)。
关于StratifiedShuffleSplit
,参数n_splits
指定了重新洗牌和分裂的迭代次数。另一方面,参数 train_size
(连同 test_size
)定义了折叠的大小(相对于训练集的大小)。特别是,根据 docs,默认设置定义为,如果指定其中的 none,则 train_size=0.9
(训练集的 90%)和 test_size=0.1
(10训练集的百分比)。
因此在 StratifiedShuffleSplit
构造函数中指定 test_size
- 例如 - 应该可以解决您的问题:
stratshufkfold = StratifiedShuffleSplit(n_splits=n_splits, random_state=0, test_size=0.2)
很抱歉,如果这很长 post,但我有一些与混淆矩阵指标和交叉验证相关的问题,我真的需要帮助。
这张来自 Sklearn CV link 的图片表明我们的整个数据集应该分为训练和测试。然后,训练集再次被分成验证部分,我们以 k-1 次训练我们的模型并在剩余的一次中验证(重复 k 次)。最后,我们从一开始就用测试集测试我们的模型。
在我的问题中,我有一个不平衡二进制 classification 问题的数据集,样本为 42372
。 3615
属于class1
,其余为class0
.
由于我的数据集不平衡,我使用 StratifiedShuffleSplit
和 5 folds
,得到这个:
结果,使用 MLPClassfier
我得到以下混淆矩阵:
正如您从该矩阵中看到的那样,我的数据集有一半用于测试 (19361+19+1782+28 = 21190
)。
之后,我改变了CV策略,并尝试了StratifiedKfold
:
而且,作为混淆矩阵,我得到了这个:
从第二个混淆矩阵可以看出,我的整个数据集都用于测试 (38644+113+3329+286 = 42372
)。
所以,这是我的问题:
1 - 我是否需要将整个数据拆分为 train/test(例如,使用 train_test_split
),然后提供 CV 迭代器(KFold
、StratifiedKFold
、 StratifiedShuffleSplit
,等等)只有火车部分?或者我应该将我的全部数据输入迭代器,它们将完成将其拆分为 train/test 并将这列火车再次拆分为火车和验证的工作?
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)
如评论中所述,对于第一个问题,第一个选项是要走的路。即,通过 train_test_split
拆分整个数据集,然后在 训练集 .
.split()
对于第二点,问题隐藏在StratifiedKFold
和StratifiedShuffleSplit
的一些默认参数背后,以及参数n_splits
.
关于
StratifiedKFold
,参数n_splits
确定 折叠数 您根据 documentation.因此,强加n_splits=5
意味着模型将在 4 倍(训练集的 80%)上训练,并在每个可能的组合上测试一次(训练集的 20%)。关于
StratifiedShuffleSplit
,参数n_splits
指定了重新洗牌和分裂的迭代次数。另一方面,参数train_size
(连同test_size
)定义了折叠的大小(相对于训练集的大小)。特别是,根据 docs,默认设置定义为,如果指定其中的 none,则train_size=0.9
(训练集的 90%)和test_size=0.1
(10训练集的百分比)。 因此在StratifiedShuffleSplit
构造函数中指定test_size
- 例如 - 应该可以解决您的问题:stratshufkfold = StratifiedShuffleSplit(n_splits=n_splits, random_state=0, test_size=0.2)