多標簽分類
到現在為止,我們看到的模型與數據都是將一條數據分類為一個類別。在某些情況下,我們可能需要分類器為每條數據輸出多個類別。例如,假設有一個人臉識別分類器,如果它在同一張圖片上認出了多張人臉的話,它應該輸出什么呢?顯然,它應該為每個它認出的人臉打上一個標志。
假設這個人臉識別分類器已經被訓練了可以認出3張臉,小明、小紅與小強。當輸入一張圖片時,假設上面有小明與小強,則分類器應該輸出[1, 0, 1]。這種輸出多個二進制標識的分類系統稱為多標簽分類系統(multilabel classification system)。
我們暫時不會深入人臉識別,但是我們可以看一個簡單的例子,作為展示:
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 數組,對每條數據,包含兩個目標類別:第一個表示的是這個手寫數字是不是一個較大的數(7,8,9),第二個類別表示的是它是否是一個奇數。之后我們創建了一個KNeighborsClassifier 實例(KNN支持多標簽分類,當然,不是所有的分類器都支持),然后使用多類別的數組進行訓練。最后我們使用模型做預測,可以看到它輸出了多個類別:
knn_clf.predict([X_train[0]])
>array([[False, True]])
y[0]
>5
可以看到第一條數據是數字5,它分類的結果正確。
我們有多種方法用於評估一個多標簽分類器,使用哪個指標完全取決於項目的需求。例如,其中一個方法是對每個單獨的label衡量它的F1分數(或者任何其他二元分類器里提到的衡量指標),然后對這些分數就平均。如下所示:
y_train_knn_pred = cross_val_predict(knn_clf, X_train, y_multilabel, cv=3) f1_score(y_multilabel, y_train_knn_pred, average="macro") >0.976410265560605
這個的前提是:假設所有的類別都是同等重要到。但是在實際項目中可能並不是這樣的。假設我們的圖片數據中,小明的圖片比小紅與小強的多的多,那么我們可能要給小明的分數更多的權重。一個簡單的方法是:給每個類別的權重等同於這個類別的數據量。使用時只需要在上述代碼中設置 average="weighted" 即可。
多輸出分類
最后要介紹的一種分類任務是多輸出分類(multioutput-multiclass classification,有時候也簡稱multioutput classification)。它其實就是多標簽分類的一般形式,並且每個label都可以是多個類別(也就是說,它包含2種以上可能的值)。
舉個例子,假設我們現在要構造一個系統,用於移除圖片中的噪點。它會輸入一張噪點圖片,然后輸出一張干凈的圖片,以像素強度的像素點矩陣表示(與MNIST圖片表示的方法一樣)。需要注意的是,這個分類器輸出的是多個label(每個像素點一個類別),並且每個label可以有多個值(像素點的像素強度從0到255)。這就是一個multioutput classification system 的例子。
開始我們可以通過給MNIST圖片增加噪點(加到像素點強度中)來創建訓練集與測試集,使用NumPy的randint() 方法。而目標圖片就是原始圖片:
noise = np.random.randint(0, 100, (len(X_train), 784)) X_train_mod = X_train + noise noise = np.random.randintnt(0, 100, (len(X_test), 784)) X_test_mod = X_test + noise y_train_mod = X_train y_test_mod = X_test
我們先看一張測試圖:

左邊是包含噪點的輸入圖,右邊是干凈的目標圖。然后我們訓練一個分類器用於清理這張圖:
knn_clf.fit(X_train_mod, y_train_mod)
clean_digit = knn_clf.predict([X_test_mod[0]])
原圖與預測圖分別如下所示(左邊為預測圖),結果看起來還是很令人滿意的:

至此,我們已經介紹完了分類問題,希望大家現在已經能夠很好地做到以下幾點:
- 如何為分類任務選擇衡量指標
- 選擇合適的precision/recall tradeoff
- 不同分類器之間的對比
- 針對不同的任務構,造表現良好的分類系統
