多類別分類如果採用GBDT,boost等分類器,邏輯要求較冗繁。在實際應用中建議使用已有算法庫直接處理。省時間省力!
針對多分類和多標籤問題,雖然深度學習具有較好的表現,但採用傳統機器學習方法可以作爲對問題深入理解的嘗試.
sklearn.multiclass
提供了很多機器學習算法,處理 multiclass
和 multilabel
分類問題,主要是將問題轉化爲二值分類(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).
分類器集:
- **Inherently multiclass:
sklearn.naive_bayes.BernoulliNB
sklearn.tree.DecisionTreeClassifier
sklearn.tree.ExtraTreeClassifier
sklearn.ensemble.ExtraTreesClassifier
sklearn.naive_bayes.GaussianNB
sklearn.neighbors.KNeighborsClassifier
sklearn.semi_supervised.LabelPropagation
sklearn.semi_supervised.LabelSpreading
sklearn.discriminant_analysis.LinearDiscriminantAnalysis
sklearn.svm.LinearSVC
(setting multi_class=”crammer_singer”)sklearn.linear_model.LogisticRegression
(setting multi_class=”multinomial”)sklearn.linear_model.LogisticRegressionCV
(setting multi_class=”multinomial”)sklearn.neural_network.MLPClassifier
sklearn.neighbors.NearestCentroid
sklearn.discriminant_analysis.QuadraticDiscriminantAnalysis
sklearn.neighbors.RadiusNeighborsClassifier
sklearn.ensemble.RandomForestClassifier
sklearn.linear_model.RidgeClassifier
sklearn.linear_model.RidgeClassifierCV
- Multiclass as One-Vs-One:
sklearn.svm.NuSVC
sklearn.svm.SVC
sklearn.gaussian_process.GaussianProcessClassifier
(setting multi_class = “one_vs_one”)
- Multiclass as One-Vs-All:
sklearn.ensemble.GradientBoostingClassifier
sklearn.gaussian_process.GaussianProcessClassifier
(setting multi_class = “one_vs_rest”)sklearn.svm.LinearSVC
(setting multi_class=”ovr”)sklearn.linear_model.LogisticRegression
(setting multi_class=”ovr”)sklearn.linear_model.LogisticRegressionCV
(setting multi_class=”ovr”)sklearn.linear_model.SGDClassifier
sklearn.linear_model.Perceptron
sklearn.linear_model.PassiveAggressiveClassifier
- Support multilabel:
sklearn.tree.DecisionTreeClassifier
sklearn.tree.ExtraTreeClassifier
sklearn.ensemble.ExtraTreesClassifier
sklearn.neighbors.KNeighborsClassifier
sklearn.neural_network.MLPClassifier
sklearn.neighbors.RadiusNeighborsClassifier
sklearn.ensemble.RandomForestClassifier
sklearn.linear_model.RidgeClassifierCV
- Support multiclass-multioutput:
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 分類問題.
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 空間內的點,然後根據該點與數據類別點的最近距離,選擇最近的預測類別.
OutputCodeClassifier
的 code_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. 依次在訓練數據集上訓練模型.
在預測時,每個模型的預測結果作爲特徵,依次傳遞到下一個模型.
這裏,模型的順序是很重要的.