機器學習 - 基於 Scikit-learn 多類別和多標籤分類算法

多類別分類如果採用GBDT,boost等分類器,邏輯要求較冗繁。在實際應用中建議使用已有算法庫直接處理。省時間省力!

針對多分類和多標籤問題,雖然深度學習具有較好的表現,但採用傳統機器學習方法可以作爲對問題深入理解的嘗試.

sklearn.multiclass 提供了很多機器學習算法,處理 multiclassmultilabel分類問題,主要是將問題轉化爲二值分類(binary classification) 問題. 同時也支持 multitarget迴歸問題.

  • Multiclass 分類: 多類別分類問題,類別classes數大於 2,如,對水果fruit數據集分類,類別有 oranges, apples, pears. Multiclass 分類問題,假設每個樣本僅對應一個標籤 label,如一張 fruit 圖片可能是 apple 或 pear,而不能同時是 apple 和 pear.
  • Mulitlabel 分類: 多標籤分類問題,每個樣本對應着一組標籤 labels. 可以看作是,對一個樣本數據點的屬性預測,屬性間不是互斥關係(mutually exclusive),如文檔document中的相關主題topics. 一篇文章可以是 religion, politics, finance, education 中的任意一個,也可以同時是幾種,也可以是都不是.
  • Multioutput 迴歸: 多輸出迴歸問題,每個樣本對應一組目標值target values. 可以看作是,對每個樣本數據點預測幾個屬性,如某個地點的風向和地震震級預測.
  • Multioutput-multiclass 分類和 Multi-task 分類: 單個估計器estimator 需要處理幾個聯合分類任務. 可以看作是,Multi-label 分類問題和 Multi-class 分類問題的泛化. 輸出是 2d numpy array 或稀疏矩陣 sparse matrix. 標籤 labels 集對於每個輸出可以是不同的,例如,一個樣本的類別標籤可能來自 fruit 標籤集(oranges, apples, pears);而其顏色color 標籤可能來自 color 標籤集(red, green, blue, yellow).

分類器集

1. Multilabel 分類

多標籤分類中,二值分類的聯合集可以表示爲 label binary indicatior 數組形式:每個樣本是一個 {0,1}{0,1}\{0, 1\} 二值向量形式.

例如:np.array([[1, 0, 0], [0, 1, 1], [0, 0, 0]]表示第一個樣本的 label = 0,第二個樣本的 label=2,3,第三個樣本沒有 label.

標籤 label 轉換工具 - MultiLabelBinarizer

from sklearn.preprocessing import MultiLabelBinarizer
>>> y = [[2, 3, 4], [2], [0, 1, 3], [0, 1, 2, 3, 4], [0, 1, 2]]
>>> MultiLabelBinarizer().fit_transform(y)
array([[0, 0, 1, 1, 1],
       [0, 0, 1, 0, 0],
       [1, 1, 0, 1, 0],
       [1, 1, 1, 1, 1],
       [1, 1, 1, 0, 0]])

2. One-Vs-Rest

one-vs-rest,也被叫作 one-vs-all,一對多,由 OneVsRestClassifier 實現.

對每一個類別class 擬合一個分類器. 對於每一個分類器,該類別 class 也擬合其它 classes.

特點:

  • 其計算效率較高,只需 N_classes 個分類器.
  • 可解釋性好 由於每個類別 class 僅由一個分類器classifier表示,只需利用該分類器即可學習該類的相關信息.

2.1 Multiclass learning

>>> from sklearn import datasets
>>> from sklearn.multiclass import OneVsRestClassifier
>>> from sklearn.svm import LinearSVC
>>> iris = datasets.load_iris()
>>> X, y = iris.data, iris.target
>>> OneVsRestClassifier(LinearSVC(random_state=0)).fit(X, y).predict(X)
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 1, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2])

2.2 Multilabel learning

OneVsRestClassifier 也支持 multilabel 分類問題.

如:Multilabel classification

1620uploading.4e448015.gif轉存失敗重新上傳取消

3. One-Vs-One

OneVsOneClassifier 對每一對pair類別 classes 創建一個分類器classifier. 預測時,最多投票votes 被作爲預測類別 class.

特點:

  • 需要 N_classes * (N_classes - 1) / 2 個分類器,其複雜度爲 O(N2classes)O(Nclasses2)O(N_{classes}^2), 相比較於 one-vs-rest,效率較慢.
  • 對於某些覈算法(kernel algorithms) 比較有優勢.

3.1 Multiclass learning

>>> from sklearn import datasets
>>> from sklearn.multiclass import OneVsOneClassifier
>>> from sklearn.svm import LinearSVC
>>> iris = datasets.load_iris()
>>> X, y = iris.data, iris.target
>>> OneVsOneClassifier(LinearSVC(random_state=0)).fit(X, y).predict(X)
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2])

4. Error-Correcting Output-Codes

糾錯輸出編碼.

與 one-vs-rest 和 one-vs-one 是完全不同的策略.

糾錯輸出編碼中,每一個類別class 都是 Euclidean 空間表示,每一維是 0 或 1. 將每一個類別class 表示爲二值0或1編碼的形式.

表示了每一類編碼的矩陣爲 codebook. 編碼 code 的長度即爲Euclidean空間的維度.

每一類class 都是由唯一的編碼code 來表示的.

好的 codebook 設計應該是能取得最有的分類精度.

這裏僅是採用隨機生成的 codebook - [The error coding method and PICTs] 論文所提出.

在 fitting 時,二值分類器是 對 codebook 內的每個字節bit 進行擬合.

在 prediction 時,分類器用於得到樣本的類別class 空間內的點,然後根據該點與數據類別點的最近距離,選擇最近的預測類別.

OutputCodeClassifiercode_size 參數可以自定義分類器數量. 其值小於等於 N_classes.

Solving multiclass learning problems via error-correcting output codes. The error coding method and PICTs.

4.1 Multiclass learning

>>> from sklearn import datasets
>>> from sklearn.multiclass import OutputCodeClassifier
>>> from sklearn.svm import LinearSVC
>>> iris = datasets.load_iris()
>>> X, y = iris.data, iris.target
>>> clf = OutputCodeClassifier(LinearSVC(random_state=0),
...                            code_size=2, random_state=0)
>>> clf.fit(X, y).predict(X)
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1,
       1, 2, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 1, 1, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2])

5. Multioutput regression

>>> from sklearn.datasets import make_regression
>>> from sklearn.multioutput import MultiOutputRegressor
>>> from sklearn.ensemble import GradientBoostingRegressor
>>> X, y = make_regression(n_samples=10, n_targets=3, random_state=1)
>>> MultiOutputRegressor(GradientBoostingRegressor(random_state=0)).fit(X, y).predict(X)
array([[-154.75474165, -147.03498585,  -50.03812219],
       [   7.12165031,    5.12914884,  -81.46081961],
       [-187.8948621 , -100.44373091,   13.88978285],
       [-141.62745778,   95.02891072, -191.48204257],
       [  97.03260883,  165.34867495,  139.52003279],
       [ 123.92529176,   21.25719016,   -7.84253   ],
       [-122.25193977,  -85.16443186, -107.12274212],
       [ -30.170388  ,  -94.80956739,   12.16979946],
       [ 140.72667194,  176.50941682,  -17.50447799],
       [ 149.37967282,  -81.15699552,   -5.72850319]])

6. Multioutput classification

對每一個目標值 target 擬合一個分類器.

>>> from sklearn.datasets import make_classification
>>> from sklearn.multioutput import MultiOutputClassifier
>>> from sklearn.ensemble import RandomForestClassifier
>>> from sklearn.utils import shuffle
>>> import numpy as np
>>> X, y1 = make_classification(n_samples=10, n_features=100, n_informative=30, n_classes=3, random_state=1)
>>> y2 = shuffle(y1, random_state=1)
>>> y3 = shuffle(y1, random_state=2)
>>> Y = np.vstack((y1, y2, y3)).T
>>> n_samples, n_features = X.shape # 10,100
>>> n_outputs = Y.shape[1] # 3
>>> n_classes = 3
>>> forest = RandomForestClassifier(n_estimators=100, random_state=1)
>>> multi_target_forest = MultiOutputClassifier(forest, n_jobs=-1)
>>> multi_target_forest.fit(X, Y).predict(X)
array([[2, 2, 0],
       [1, 2, 1],
       [2, 1, 0],
       [0, 0, 2],
       [0, 2, 1],
       [0, 0, 2],
       [1, 1, 0],
       [1, 1, 1],
       [0, 0, 2],
       [2, 0, 0]])

7. Classifier Chain

鏈式分類器(Classifier Chain),ClassifierChain, 是將很多二值分類器組合爲一個 multi-label 模型,能夠挖掘各 targets 之間的關聯性.

對於 N 類的多標籤分類問題,N 個二值分類器分別指定一個0 到 N-1 間的整數,表示了在鏈式分類器中的模型次序order. 依次在訓練數據集上訓練模型.

在預測時,每個模型的預測結果作爲特徵,依次傳遞到下一個模型.

這裏,模型的順序是很重要的.

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章