在我们解决多类线性可分问题的时候,常会遇到单标签二分类问题、单标签多分类问题、多标签算法问题,下面分别讨论。而前面讲的线性分类模型,原则上只能解决二分类问题,但通过一些技巧就可以解决多分类问题。
单标签二分类这种问题是我们最常见的算法问题,主要是指标签(label)的取值只有两种,并且算法中只有一个需要预测的label
;直白来讲就是每个实例的可能类别只有两种(A or B);此时的分类算法其实是在构建一个分类线将数据划分为两个类别。常见的算法:Logistic
、SVM
、KNN
、决策树等。
单标签多分类问题其实是指待预测的label
只有一个,但是label
的取值可能有多种情况;直白来讲就是每个实例的可能类别有 K K K 种( t 1 , t 2 , ⋯ , t k , k ≥ 3 t_1, t_2, \cdots, t_k, k≥3 t1,t2,⋯,tk,k≥3);常见算法:Softmax
、KNN
、决策树等;
在实际的工作中,如果是一个多分类的问题,我们可以将这个待求解的问题转换为二分类算法的延伸,即将多分类任务拆分为若干个二分类任务求解,具体的策略如下:
Multi-Label Machine Learning
(MLL算法)是指预测模型中存在多个 y y y 值,具体分为两类不同情况:
根据多标签业务问题的复杂性,可以将问题分为两大类:
对于这类问题的解决方案可以分为两大类:
详细介绍,请阅读:多标签分类算法原理及代码、多分类及多标签分类算法
OvO
(一对一,One vs One):假如数据 D D D 中有 N N N 个类别,将 N N N 个类别进行两两配对,会得到 N ( N − 1 ) / 2 N(N-1)/2 N(N−1)/2 个二分类器。在预测中,将测试样本输入这 N ( N − 1 ) / 2 N(N-1)/2 N(N−1)/2 个二分类器中得到相应个数的预测结果,然后再将被预测结果数最多的(Voting)作为最终分类结果。
下面举个例子,当有4个类别的时候,首先把类别两两组合(6种组合)。组合完之后,其中一个类别作为正类,另一个作为负类(这个正负只是相对而言,目的是转化为二分类)。然后对每个二分类器进行训练。可以得到6个二分类器。然后把测试样本在6个二分类器上面进行预测。从结果上可以看到,类别1被预测的最多,故测试样本属于类别1。
OvR
(一对其余,One vs Rest): 将一个类别作为正例,其余所有类别作为反例,这样 N N N 个类别可以产生 N N N 个二分类器,将测试样本输入这些二分类器中中得到 N N N 个预测结果,如果仅有一个分类器预测为正类,则将对应的预测结果作为最终预测结果。如果有多个分类器预测为正类,则选择置信度最大的类别作为最终分类结果。
下面举个例子,当有4个类别的时候,每次把其中一个类别作为正类别,其余作为负类别,共有4种组合,对于这4中组合进行分类器的训练,我们可以得到4个分类器。对于测试样本,放进4个分类器进行预测,仅有一个分类器预测为正类,于是取这个分类器的结果作为预测结果,分类器2预测的结果是类别2,于是这个样本便属于类别2。
其实,有人会有疑问,那么预测为负类的分类器就不用管了吗?是的,因为预测为负类的时候有多种可能,无法确定,只有预测为正类的时候才能唯一确定属于哪一类。比如对于分类器3,分类结果是负类,但是负类有类别1,类别2,类别4三种,到底属于哪一种?
OvR
只需训练 N N N 个分类器,而OvO
需训练 N ( N − 1 ) / 2 N(N - 1)/2 N(N−1)/2 个分类器, 因此,OvO
的存储开销和测试时间开销通常比OvR
更大。但在训练时,OvR
的每个分类器均使用全部训练样例,而OvO
的每个分类器仅用到两个类的样例,因此,在类别很多时,OvO
的训练时间开销通常比OvR
更小。至于预测性能,则取决于具体的数据分布,在多数情形下两者差不多。
综上:
补充:
有的地方也会提到一种改进的“一对其余”方式,假设一个多分类问题的类别为 { 1 , 2 , ⋯ , } \{1, 2,\cdots, \} {1,2,⋯,C},则共需要 C C C 个判别函数
f c ( x ; w c ) = w c T x + b c c ∈ { 1 , ⋯ , C } (1) f_c(\pmb{x}; \pmb{w}_c)=\pmb{w}_c^T\pmb{x}+b_c \qquad c\in\{1,\cdots,C\}\tag{1} fc(xxx;wwwc)=wwwcTxxx+bcc∈{1,⋯,C}(1)
对于样本 x \pmb{x} xxx,如果存在一个类别 c c c,相对于所有的其他类别 c ^ ( c ^ ≠ c ) \hat{c}(\hat{c}\not=c) c^(c^=c)有 f c ( x ; w c ) > f c ^ ( x ; w c ^ ) f_c(\pmb{x}; \pmb{w}_c)>f_{\hat{c}}(\pmb{x}; \pmb{w}_{\hat{c}}) fc(xxx;wwwc)>fc^(xxx;wwwc^),那么 x \pmb{x} xxx 属于类别 c。“argmax”方式的预测函数定义为
y = a r g m a x c = 1 C f c ( x ; w c ) (2) y = \overset{C}{\underset{c=1}{argmax}} f_c(\pmb{x}; \pmb{w}_c)\tag{2} y=c=1argmaxCfc(xxx;wwwc)(2)
“一对其余”方式和“一对一”方式都存在一个缺陷:特征空间中会存在一些难以确定类别的区域,而“argmax”方式很好地解决了这个问题。下图给出了用这三种方式进行多分类的示例,其中红色直线表示判别函数 ( ⋅ ) = 0 (⋅) = 0 f(⋅)=0 的直线,不同颜色的区域表示预测的三个类别的区域( w 1 、 w 2 、 w 3 w_1、w_2、w_3 w1、w2、w3)和难以确定类别的区域(‘?’)。在“argmax”方式中,相邻两类 i 和 j 的决策边界实际上是由 ( ; ) − ( ; ) = 0 _(; _) −_ (; _ ) = 0 fi(x;wi)−fj(x;wj)=0 决定,其法向量为 − _ − _ wi−wj。
MvM
是每次将若干个类作为正类,若干个其他类作为反类。显然,OvO
和OvR
是MvM
的特例。MvM
的正、反类构造必须有特殊的设计,不能随意选取。这里介绍一种最常用的MvM
技术"纠错输出码" (Error Correcting Output Codes,简称 ECOC)
ECOC
是将编码的思想引入类别拆分,并尽可能在解码过程中具有容错性。ECOC
工作过程主要分为两步:
编码:对N个类别做M次划分,每次划分将一部分类别划为正类,一部分划为反类,从而形成一个二分类训练集。这样一共产生M个训练集,可训练出M个分类器。
解码:M 个分类器分别对测试样本进行预测,这些预测标记组成一个编码。将这个预测编码与每个类别各自的编码进行比较,返回其中距离最小的类别作为最终预测结果。
类别划分通过"编码矩阵"指定。编码矩阵有多种形式,常见的主要有二元码和三元码。前者将每个类别分别指定为正类和反类,后者在正、反类之外,还可指定"停用类"。图3.5给出了一个示意图,在图 3.5(a) 中,分类器 f 2 f_2 f2 将 C l C_l Cl 类和 C 3 C_3 C3 类的样例作为正例, C 2 C_2 C2 类和 C 4 C_4 C4 类的样例作为反例;在图3.5(b)中,分类器 f 4 f_4 f4 将 C 1 C_1 C1 类和 C 4 C_4 C4 类的样例作为正例, C 3 C_3 C3 类的样例作为反例。在解码阶段,各分类器的预测结果联合起来形成了测试示例的编码,该编码与各类所对应的编码进行比较,将距离最小的编码所对应的类别作为预测结果。
例如在图 3.5(a) 中,若基于欧式距离,预测结果将是 C 3 C_3 C3。也就是一个测试样本,经过分类器 f 1 , f 2 , f 3 , f 4 , f 5 f_1,f_2,f_3,f_4,f_5 f1,f2,f3,f4,f5分别预测成了(-1,-1,+1,-1,+1),与 C 1 C_1 C1 相比较,海明距离为0+1+1+1+0=3,欧式距离为,对 C 2 , C 3 , C 4 C_2,C_3,C_4 C2,C3,C4 都进行比较即可。
利用sklearn
的鸢尾花数据集验证一下,该数据集有 4 个特征属性,3 种分类{‘setosa’, ‘versicolor’, ‘virginica’}
,下面利用 OvR
、OvO
和MvM
三种策略进行多分类的学习及预测:
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.multiclass import OneVsRestClassifier
from sklearn.multiclass import OneVsOneClassifier
from sklearn.multiclass import OutputCodeClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score
# 加载数据
data_iris = datasets.load_iris()
x, y = data_iris.data, data_iris.target
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size = 0.3,random_state = 0)
# 使用multiclass的OvO多分类策略,分类器使用LogisticRegression
model = OneVsOneClassifier(LogisticRegression(C=1.0, tol=1e-6))
model.fit(x_train, y_train)
y_pred = model.predict(x_test)
print(accuracy_score(y_test, y_pred))
# 准确率为:0.9777777777777777
# 使用multiclass的OvR多分类策略,分类器使用LogisticRegression
model = OneVsRestClassifier(LogisticRegression(C=1.0, tol=1e-6))
model.fit(x_train, y_train)
y_pred = model.predict(x_test)
print(accuracy_score(y_test, y_pred))
# 准确率为:0.9555555555555556
# 使用multiclass的ECOC多分类策略,分类器使用LogisticRegression
# 模型对象创建
# code_size: 指定最终使用多少个子模型,实际的子模型的数量=int(code_size*label_number)
# code_size设置为1,等价于ovr子模型个数;
# 设置为0~1, 那相当于使用比较少的数据划分,效果比ovr差;
# 设置为大于1的值,那么相当于存在部分模型冗余的情况
model = OutputCodeClassifier(LogisticRegression(C=1.0, tol=1e-6), code_size=30, random_state=0)
model.fit(x_train, y_train)
y_pred = model.predict(x_test)
print(accuracy_score(y_test, y_pred))
# 准确率为:0.9555555555555556
注意:OvR
、OvO
和MvM
不是逻辑回归专有的,也可以运用与SVM
等只能解决二分类问题的模型上。
softmax
回归其实是逻辑回归的一种变形,逻辑回归模型输出的是两种类别的概率,softmax
回归输出的 K K K 种类别的概率。模型公式如下:
h θ ( x i ) = [ p ( y i = 1 ∣ x i ; θ ) p ( y i = 2 ∣ x i ; θ ) ⋮ p ( y i = k ∣ x i ; θ ) ] = 1 ∑ j = 1 k e θ j T x i [ e θ 1 T x i e θ 2 T x i ⋮ e θ k T x i ] (3) h_{\boldsymbol{\theta}}\left(\boldsymbol{x}_i\right)=\left[\begin{array}{c}{p\left(y_i=1 | \boldsymbol{x}_i ; \boldsymbol{\theta}\right)} \\ {p\left(y_i=2 | \boldsymbol{x}_i ; \boldsymbol{\theta}\right)} \\ {\vdots} \\ {p\left(y_i=k | \boldsymbol{x}_i ; \boldsymbol{\theta}\right)}\end{array}\right]=\frac{1}{\sum_{j=1}^{k} e^{\boldsymbol{\theta}_{j}^{T} \boldsymbol{x}_i}}\left[\begin{array}{c}{e^{\boldsymbol{\theta}_{1}^{T} \boldsymbol{x}_i}} \\ {e^{\boldsymbol{\theta}_{2}^{T} \boldsymbol{x}_i}} \\ {\vdots} \\ {e^{\boldsymbol{\theta}_{k}^{T} \boldsymbol{x}_i}}\end{array}\right]\tag{3} hθ(xi)=⎣⎢⎢⎢⎡p(yi=1∣xi;θ)p(yi=2∣xi;θ)⋮p(yi=k∣xi;θ)⎦⎥⎥⎥⎤=∑j=1keθjTxi1⎣⎢⎢⎢⎢⎡eθ1Txieθ2Txi⋮eθkTxi⎦⎥⎥⎥⎥⎤(3)
参数 θ \pmb{\theta} θθθ 是一个矩阵,矩阵的每一行可以看做是一个类别所对应分类器的参数,总共有 K K K 行,输出的 K K K 个数就表示该类别的概率,总和为1。这样,softmax
回归模型对于一个测试样本,可以得到多个类别对应的概率值,模型选取概率最高的类别作为最终判定结果。详细介绍:Softmax 回归原理与实现
在sklearn
中使用softmax
回归还是调用linear.model.LogisticRegression
,设置一下multi_class
参数即可,内部即会使用softmax
函数计算出每个类别的概率。
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score
# 加载数据
data_iris = datasets.load_iris()
x, y = data_iris.data, data_iris.target
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size = 0.3, random_state = 0)
# 采用softmax回归进行分类
model = LogisticRegression(C=1.0, tol=1e-6, multi_class='multinomial', solver='newton-cg')
model.fit(x_train, y_train)
y_pred = model.predict(x_test)
print(accuracy_score(y_test, y_pred))
# 准确率为:0.9777777777777777
# 输出每个测试样例的类别预测概率
print (model.predict_proba(x_test))
多个二分类器策略和softmax
回归的区别
softmax
回归中对一个测试样本得到的属于各类别的概率和一定为1,而多个二分类器策略中,不管是OvO
、OvR
还是MvM
策略,一个样本在多个二分类器上得到的概率和不一定为 1。因此当分类之间是互斥的情况下(e.g 数字手写识别、动物识别),通常采用softmax
回归;而目标类别不是互斥时(e.g 华语音乐、流行音乐、重金属音乐等)则采用多个二分类器策略进行预测。