警告 scikit-learn中的所有分類器都可以開箱即用進行多分類。除非您想嘗試不同的多類策略,否則無需使用
sklearn.multiclass
模塊。
sklearn.multiclass
模塊通過將 multiclass
和
multilabel
分類問題分解為二分類問題,實現(xiàn)了meta-estimators(元估計)。 multioutput
regression(多輸出回歸)也被支持。
多分類:具有兩個以上類的分類任務。每個樣本只能標記為一個類。
例如,使用從一組水果圖像中提取的特征進行分類,其中每一幅圖像都可能是一個橙子、一個蘋果或一個梨。每個圖像就是一個樣本,并被標記為三個可能的類之一。多類分類的假設是,每個樣本分配給一個標簽并且只有一個標簽--例如,一個樣本不能同時是一個梨和一個蘋果。
有效的 multiclass 的
type_of_target
(y
)
表述是:
包含兩個以上離散值的一維數(shù)組或列向量。三個樣本的向量y
的例子:
>>> import numpy as np
>>> y = np.array(['apple', 'pear', 'apple'])
>>> print(y)
['apple' 'pear' 'apple']
稀疏的binary矩陣, 形狀是
(n_samples, n_classes)
, 每行有一個元素, 每一列代表一個類。這里有一個例子, 一個稀疏的binary矩陣,
對應于三個樣本的y
,
它的列的順序是橙子、蘋果和梨子:
>>> from scipy import sparse
>>> row_ind = np.array([0, 1, 2])
>>> col_ind = np.array([1, 2, 1])
>>> y_sparse = sparse.csr_matrix((np.ones(3), (row_ind, col_ind)))
>>> print(y_sparse)
(0, 1) 1.0
(1, 2) 1.0
(2, 1) 1.0
多標簽分類:分類任務用n_class中
的
x
標簽標記每個樣本,其中x
可以包含0到
n_class
。這可以看作是預測不相互排斥的樣本的屬性。形式上,為每個樣本分配二值化輸出的每個類。正類用1表示,負類用0或-1表示。因此,它可以與運行n_class
二分類任務相媲美,例如使用
sklearn.multioutput.MultiOutputClassifier
。這種方法獨立地處理每個標簽,而多標簽分類器可以同時處理多個類,同時考慮它們之間的相關行為。
例如,與文本文檔或視頻相關的主題預測。這些文件或視頻的主題可以是關于“宗教”、“政治”、“金融”或“教育”其中之一, 也可以是其中的幾個,甚至全部都行 。
多標簽 multilabel
y
的有效表示形式要么是稠密要么是稀疏的二值化矩陣, 形狀是(n_samples, n_classes)
。每一列表示一個類。每一行中的
1
表示樣本被標記的正類。一個關于3個樣本的稠密矩陣y
的例子:
>>> y = np.array([[1, 0, 0, 1], [0, 0, 1, 1], [0, 0, 0, 0]])
>>> print(y)
[[1 0 0 1]
[0 0 1 1]
[0 0 0 0]]
稀疏矩陣形式中相同y
的一個例子:
>>> y_sparse = sparse.csr_matrix(y)
>>> print(y_sparse)
(0, 0) 1
(0, 3) 1
(1, 2) 1
(1, 3) 1
多輸出回歸:預測每個樣本的多個數(shù)值屬性。每個屬性都是一個數(shù)值變量,每個樣本預測的屬性數(shù)大于或等于2。一些支持多輸出回歸的估計器比只運行n_output
估計器的速度更快。
例如,利用在某一地點獲得的數(shù)據(jù),以度為單位預測風速和風向。每個樣本都是在一個地點獲得的數(shù)據(jù),每個樣本的風速和風向都將被輸出。
multioutput 多輸出
y
的一個有效表示是浮點數(shù)組成的形狀是 (n_samples, n_classes)
的稠密矩陣。連續(xù)變量的一種列的合并。3個樣本的
y
示例:
>>> y = np.array([[31.4, 94], [40.5, 109], [25.0, 30]])
>>> print(y)
[[ 31.4 94. ]
[ 40.5 109. ]
[ 25. 30. ]]
多輸出-多類分類(也稱為多任務分類):用一組非二值化屬性標記每個樣本的分類任務。屬性的數(shù)量和類的數(shù)量都大于2。因此,單個估計器處理多個聯(lián)合分類任務。這既是對只考慮二值屬性的多標簽分類任務的推廣,也是對多類分類任務的推廣,其中只考慮一個屬性。
例如,對一組水果圖像的屬性“水果種類”和“顏色”進行分類。屬性“水果種類”有可能的類別有:“蘋果”,“梨”和“橙子”。屬性“顏色”有可能的類別有:“綠色”、“紅色”、“黃色”和“橙色”。每個樣本都是一個水果的圖像,兩個屬性的標簽都是輸出的,每個標簽都是相應屬性的可能類別之一。
多輸出 multioutput
y
的一個有效表示類標簽形狀是(n_samples, n_classes)
的稠密矩陣。一維的多類變量的一種列的合并。3個樣本的
y
示例:
>>> y = np.array([['apple', 'green'], ['orange', 'orange'], ['pear', 'green']])
>>> print(y)
[['apple' 'green']
['orange' 'orange']
['pear' 'green']]
注意,所有處理多輸出-多類(也稱為多任務分類)任務的分類器,都支持將多標簽分類任務作為特例。多任務分類類似于具有不同模型構想的多輸出分類任務。有關更多信息,請參見相關的估值器文檔。
所有scikit-learn分類器都能夠進行多類分類,但是
sklearn.multiclass
提供的 meta-estimators 允許改變它們處理兩個以上類的方式,因為這可能會影響分類器的性能(無論是泛化誤差還是所需的計算資源)。
摘要
以下是 scikit-learn按策略分組支持的分類器總結;如果要使用這些方法之一,則不需要該類中的元估計器,除非您希望使用自定義的多類行為:
固有的多類分類器:
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
One-Vs-One 的多分類:
sklearn.svm.NuSVC
sklearn.svm.SVC
.sklearn.gaussian_process.GaussianProcessClassifier
(setting
multi_class = “one_vs_one”)One-Vs-The-Rest 的多分類:
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
支持多標簽:
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
支持多類多輸出:
警告:目前,
sklearn.metrics
中沒有評估方法能夠支持多輸出多類分類任務。
在多標簽學習中,二分類任務的聯(lián)合集合伴隨標簽的二值化數(shù)組表示:每個樣本是一個形狀為(n_sames,n_class)的數(shù)組的一行, 該行只有兩個值:舉一個例子, 即非零元素,對應于標簽的子集。形如np.array([[1, 0, 0], [0, 1, 1], [0, 0, 0]])
的數(shù)組在第一個樣本中表示屬于標簽0,第二個樣本中表示屬于標簽1和2,在第三個樣本中沒有屬于任何標簽。
通過一組標簽集合來產(chǎn)生多標簽數(shù)據(jù)可能更為直觀。 MultiLabelBinarizer
轉(zhuǎn)換器可用于標簽集合和指示格式集合之間的轉(zhuǎn)換。
>>> 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]])
這種策略,也稱為one-vs-all,是在
OneVsRestClassifier
中實現(xiàn)的。該策略包括為每個類擬合一個分類器。對于每個分類器,將一個類與其他所有類進行分類擬合的。除了它的計算效率(只需要n_classes
個分類器)之外,這種方法的一個優(yōu)點是它的可解釋性。由于每個類都由一個分類器表示,并且只有一個分類器,因此可以通過檢查其對應的分類器來獲得有關該類的知識。這是最常用的策略,也是一個公平的默認選擇。
下面是使用 OVR 進行多類學習的一個例子:
>>> from sklearn import datasets
>>> from sklearn.multiclass import OneVsRestClassifier
>>> from sklearn.svm import LinearSVC
>>> X, y = datasets.load_iris(return_X_y=True)
>>> 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])
OneVsRestClassifier
還支持多標簽分類。要使用此特性,向分類器提供一個指示矩陣,其中單元格[i,j]表示樣本
i 中的第 j 個標簽。
示例 |
---|
多標簽分類 |
OneVsOneClassifier
是對每一對類構造一個分類器。在預測時,選擇得票最多的類別。在票數(shù)相等的兩個類別中,它選擇具有最高總分類置信度的類別,方法是對由底層二分類器計算的對分類置信度進行求和。
由于它需要擬合n_classes * (n_classes - 1) / 2
個分類器,這種方法通常比one-vs-the-rest要慢,原因就在于其復雜度O(n_classes^2)
。然而,這個方法也有優(yōu)點,比如說是在沒有很好的縮放 n_samples
數(shù)據(jù)的核方法中。這是因為每個單獨的學習問題只涉及一小部分數(shù)據(jù),而對于一個one-vs-the-rest,完整的數(shù)據(jù)集將會被使用
n_classes
次。決策函數(shù)是one-versus-one分類器單調(diào)變換的結果。
下面是使用OvO進行多類學習的一個例子:
>>> from sklearn import datasets
>>> from sklearn.multiclass import OneVsOneClassifier
>>> from sklearn.svm import LinearSVC
>>> X, y = datasets.load_iris(return_X_y=True)
>>> 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])
參考
“Pattern Recognition and Machine Learning. Springer”, Christopher M. Bishop, page 183, (First Edition)
基于Output-code的策略與 one-vs-the-rest 和 one-vs-one 的策略有很大的不同。使用這些策略,每個類都表示在歐氏空間中,其中每個維度只能是0或1。換句話說,每個類都由二進制代碼(0和1的數(shù)組)表示。跟蹤每個類的位置/代碼的矩陣稱為代碼簿( code book)。代碼大小是上述空間的維數(shù)。直觀地說,每個類都應該盡可能地用唯一的代碼來表示,并且應該設計一本好的code book來優(yōu)化分類的準確性。在這個實現(xiàn)中,我們只使用[3]中提倡的隨機生成的code book,盡管將來可能會添加更詳細的方法。
在訓練的時候,在 code book 中每位上訓練一個二分類器。在預測時,使用分類器在類空間中投影新的點,并選擇最靠近該點的類。
在 OutputCodeClassifier
中,
code_size
屬性允許用戶控制將要使用的分類器的數(shù)量。它是類別總數(shù)的百分比。
在0到1之間的數(shù)字需要的分類器比 one-vs-the-rest 少。理論上,log2(n_classes) / n_classes
足以明確地表示每個類。然而,在實踐中,由于
log2(n_classes)
比n_class小得多,所以它可能不會帶來很好的準確性。
比 1 大的數(shù)字比 one-vs-the-rest 需要更多的分類器。在這種情況下,一些分類器在理論上會糾正其他分類器的錯誤,因此命名為 “error-correcting” 。然而在實際上這通常不會發(fā)生,因為許多分類器的錯誤通常意義上來說是相關的。error-correcting output codes 和 bagging 有一個相似的作用效果。
下面是使用Output-Codes進行多類學習的一個例子:
>>> from sklearn import datasets
>>> from sklearn.multiclass import OutputCodeClassifier
>>> from sklearn.svm import LinearSVC
>>> X, y = datasets.load_iris(return_X_y=True)
>>> 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])
參考
“Solving multiclass learning problems via error-correcting output codes”, Dietterich T., Bakiri G., Journal of Artificial Intelligence Research 2, 1995. [3] “The error coding method and PICTs”, James G., Hastie T., Journal of Computational and Graphical statistics 7, 1998.
“The Elements of Statistical Learning”, Hastie T., Tibshirani R., Friedman J., page 606 (second-edition) 2008.
多輸出回歸支持 MultiOutputRegressor
可以被添加到任何回歸器中。這個策略包括對每個目標擬合一個回歸器。因為每一個目標可以被一個回歸器精確地表示,通過檢查對應的回歸器,可以獲取關于目標的信息。
因為 MultiOutputRegressor
對于每一個目標可以訓練出一個回歸器,所以它無法利用目標之間的相關度信息。
下面是多輸出回歸的一個例子:
>>> 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]])
多輸出分類支持能夠添加到任何帶有 MultiOutputClassifier
標志的分類器中。這種方法為每一個目標訓練一個分類器。
這就允許產(chǎn)生多目標變量分類器。這種類的目的是擴展評估器用于評估一系列目標函數(shù) (f1,f2,f3…,fn) ,在單個X預測矩陣上訓練以預測一系列響應 (y1,y2,y3…,yn)。
下面是多輸出分類的一個例子:
>>> 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(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]])
Classifier chains(參見ClassifierChain
)是一種將多個二分類器組合成一個能夠利用目標之間相關性的單一多標簽模型的方法。
對于有N個類的多標簽分類問題,N 個二分類器被分配一個介于0到N-1之間的整數(shù)。這些整數(shù)定義了鏈中模型的順序。然后,每個分類器在可用的訓練數(shù)據(jù)和真實的類標簽上訓練, 模型被分配了較小的數(shù)值。
當預測時,真正的標簽將不可用。相反,每個模型的預測被傳遞到鏈中的后續(xù)模型,作為特征使用。
顯然,鏈的順序很重要。鏈中的第一個模型沒有關于其他標簽的信息,而鏈中的最后一個模型具有指示所有其他標簽存在的特性。一般情況下,人們不知道模型在鏈中的最優(yōu)排序,所以通常許多隨機有序鏈是合適的,它們的預測是平均了的。
參考
Jesse Read, Bernhard Pfahringer, Geoff Holmes, Eibe Frank,
“Classifier Chains for Multi-label Classification”, 2009.
回歸鏈(參見RegressorChain
)類似于分類鏈,它是將多個回歸合并成一個能夠利用目標間相關性的單一多目標模型的一種方法。
更多建議: