到目前为止,每个样本都只被分配给一个类别。在某些情况下,您可能希望您的分类器为每个样本输出到多个类别上。例如,考虑一个面部识别分类器:如果它同一图片上识别出多个人,它应该做什么?当然,它应该给它识别出的每个人贴上一个标签。说分类器经过训练,辨认出三张面孔,Alice, Bob, 和 Charlie;然后当展示一个Alice和Alice的照片时,它应该输出[1,0,1](意思是“Alice yes, Bob no, Charlie yes”)。这样一个输出多个二元标签的分类系统被称为多标签分类系统[ multilabel classification]。
我们现在还不会进入人脸识别,我们来看一个简单的例子,只是为了便于说明:
from sklearn.neighbors import KNeighborsClassifier
y_train_large = (y_train >= 7)
y_train_odd = (y_train % 2 == 1)
y_multilabel = np.c_[y_train_large, y_train_odd]
knn_clf = KNeighborsClassifier()
knn_clf.fit(X_train, y_multilabel)
这段代码创建了一个y_multilabel数组,它包含两个目标标签(即label):第一个指示数字是否大(7,8或9),第二个表示是否为奇数。下一行创建了一个KNeighborsClassifier实例(它支持多标签分类,但不是所有分类器都支持),我们使用多目标的数组来训练它。现在你可以做一个预测,注意它将输出两个标签:
>>> knn_clf.predict([some_digit])
array([[False, True]], dtype=bool)
它做对了!数字5确实不大(False),也是奇数(True)。
有许多方法可以评估多标签分类器,选择正确的度量标准实际上取决于您的项目。例如,一种方法是为每个单独的标签(或前面讨论的任何其他二元分类器度量)度量F1 score,然后简单地计算平均分数。这段代码计算了所有标签的平均f1 score:
>>> y_train_knn_pred = cross_val_predict(knn_clf, X_train, y_train, cv=3)
>>> f1_score(y_train, y_train_knn_pred, average="macro")
0.96845540180280221
这假设所有的标签都是同等重要的,但可能也并不是这样的。特别是,如果你有更多的Alice的图片,而不是Bob或Charlie,你可能想要给分类器在Alice的照片上的分数增加更多的权重。一个简单的选择是给每个标签一个权重,该权重等于它的support (即:该目标标签的实例数。要做到这一点,只需在前面的代码中设置 average="weighted")。