针对多分类和多标签问题,虽然深度学习具有较好的表现,但采用传统机器学习方法可以作为对问题深入理解的尝试.
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).
分类器集:
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
sklearn.svm.NuSVC
sklearn.svm.SVC
sklearn.gaussian_process.GaussianProcessClassifier
(setting multi_class = “one_vs_one”)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.tree.DecisionTreeClassifier
sklearn.tree.ExtraTreeClassifier
sklearn.ensemble.ExtraTreesClassifier
sklearn.neighbors.KNeighborsClassifier
sklearn.neighbors.RadiusNeighborsClassifier
sklearn.ensemble.RandomForestClassifier
多标签分类中,二值分类的联合集可以表示为 label binary indicatior 数组形式:每个样本是一个 {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]])
one-vs-rest,也被叫作 one-vs-all,一对多,由 OneVsRestClassifier
实现.
对每一个类别class 拟合一个分类器. 对于每一个分类器,该类别 class 也拟合其它 classes.
特点:
其计算效率较高,只需 N_classes 个分类器.
可解释性好
由于每个类别 class 仅由一个分类器classifier表示,只需利用该分类器即可学习该类的相关信息.
>>> 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])
OneVsRestClassifier
也支持 multilabel 分类问题.
如:Multilabel classification
OneVsOneClassifier
对每一对pair类别 classes 创建一个分类器classifier. 预测时,最多投票votes 被作为预测类别 class.
特点:
>>> 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])
纠错输出编码.
与 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.
>>> 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])
>>> 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]])
对每一个目标值 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]])
链式分类器(Classifier Chain),ClassifierChain
, 是将很多二值分类器组合为一个 multi-label 模型,能够挖掘各 targets 之间的关联性.
对于 N 类的多标签分类问题,N 个二值分类器分别指定一个0 到 N-1 间的整数,表示了在链式分类器中的模型次序order. 依次在训练数据集上训练模型.
在预测时,每个模型的预测结果作为特征,依次传递到下一个模型.
这里,模型的顺序是很重要的.
Jesse Read, Bernhard Pfahringer, Geoff Holmes, Eibe Frank,
“Classifier Chains for Multi-label Classification”, 2009.
[1] - Multiclass and multilabel algorithms