我正在尝试理解如何为我的多标签分类问题制作混淆矩阵和ROC曲线。我正在构建一个神经网络。以下是我的类别:
mlb = MultiLabelBinarizer()ohe = mlb.fit_transform(as_list)# 遍历所有可能的类别标签并显示它们for (i, label) in enumerate(mlb.classes_): print("{}. {}".format(i + 1, label))[INFO] class labels:1. class12. class23. class34. class45. class56. class6
我的标签已转换:
ohearray([[0, 1, 0, 0, 1, 1], [0, 1, 1, 1, 1, 0], [1, 1, 1, 0, 1, 0], [0, 1, 1, 1, 0, 1],...]]
训练数据:
array([[[[ 1.93965047e+04, 8.49532852e-01], [ 1.93965047e+04, 8.49463479e-01], [ 1.93965047e+04, 8.49474722e-01], ...,
模型:
model.compile(loss="binary_crossentropy", optimizer=opt,metrics=["accuracy"])H = model.fit(trainX, trainY, batch_size=BS, validation_data=(testX, testY), epochs=EPOCHS, verbose=1)
我能够得到百分比,但对于如何计算混淆矩阵或ROC曲线,或者获取分类报告,我有点迷茫…以下是百分比:
proba = model.predict(testX)idxs = np.argsort(proba)[::-1][:2]for i in proba: print ('\n') for (label, p) in zip(mlb.classes_, i): print("{}: {:.2f}%".format(label, p * 100))class1: 69.41%class2: 76.41%class3: 58.02%class4: 63.97%class5: 48.91%class6: 58.28%class1: 69.37%class2: 76.42%class3: 58.01%class4: 63.92%class5: 48.88%class6: 58.26%
如何做到这一点,最好能提供一个例子?
回答:
从v0.21版本开始,scikit-learn包含了多标签混淆矩阵;以下是根据文档为5个类别调整的示例:
import numpy as npfrom sklearn.metrics import multilabel_confusion_matrixy_true = np.array([[1, 0, 1, 0, 0], [0, 1, 0, 1, 1], [1, 1, 1, 0, 1]])y_pred = np.array([[1, 0, 0, 0, 1], [0, 1, 1, 1, 0], [1, 1, 1, 0, 0]])multilabel_confusion_matrix(y_true, y_pred)# result:array([[[1, 0], [0, 2]], [[1, 0], [0, 2]], [[0, 1], [1, 1]], [[2, 0], [0, 1]], [[0, 1], [2, 0]]])
通常的classification_report
也适用:
from sklearn.metrics import classification_reportprint(classification_report(y_true, y_pred))# result precision recall f1-score support 0 1.00 1.00 1.00 2 1 1.00 1.00 1.00 2 2 0.50 0.50 0.50 2 3 1.00 1.00 1.00 1 4 0.00 0.00 0.00 2 micro avg 0.75 0.67 0.71 9 macro avg 0.70 0.70 0.70 9weighted avg 0.67 0.67 0.67 9 samples avg 0.72 0.64 0.67 9
关于ROC曲线,你可以从文档中的绘制多标签问题ROC曲线示例中获取一些想法(不过我不是很确定这个概念本身是否非常有用)。
混淆矩阵和分类报告需要硬类预测(如示例所示);ROC曲线需要以概率形式的预测。
要将你的概率预测转换为硬类别,你需要一个阈值。现在,通常(且隐式地),这个阈值被设为0.5,即如果y_pred > 0.5
,预测为1,否则预测为0。然而,这并非总是如此,这取决于具体问题。一旦你设定了这样的阈值,你就可以通过列表推导轻松地将你的概率预测转换为硬类别;这是一个简单的示例:
import numpy as npy_prob = np.array([[0.9, 0.05, 0.12, 0.23, 0.78], [0.11, 0.81, 0.51, 0.63, 0.34], [0.68, 0.89, 0.76, 0.43, 0.27]])thresh = 0.5y_pred = np.array([[1 if i > thresh else 0 for i in j] for j in y_prob])y_pred# result:array([[1, 0, 0, 0, 1], [0, 1, 1, 1, 0], [1, 1, 1, 0, 0]])