前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >机器学习13:多分类学习

机器学习13:多分类学习

作者头像
用户5473628
发布2019-08-08 15:51:30
5K0
发布2019-08-08 15:51:30
举报
文章被收录于专栏:MiningAlgorithmsMiningAlgorithms

多分类学习

目录:

一、多分类拆分策略:

1,一对一(OVO)

2,一对其余(OVR)

3,多对多(MvM)

二、算法分类:单、多标签 -> 二分类、多分类

1, 单标签二分类算法

2, 单标签多分类算法

3, 多标签算法

三、code

一、多分类拆分策略:单标签多分类问题

有些情况下,二分类学习方法可以推广到多分类问题中;但是多数情况下需要基于一定的策略,利用二分类学习器解决多分类问题。

对多分类任务的经典拆分策略包含三种:一对一(onevs one);一对其余(one vs rest);多对多(manyvs many)。

1,一对一(OVO):

将n个类别两两配对,从而产生n(n-1)/2个二分类任务,也即产生n(n-1)/2个二分类学习器,产生n(n-1)/2个分类结果,最终的多分类结果通过投票产生。其中单个二分类学习器就是对Ci和Cj进行分类的二分类学习器。

2,一对其余(OVR):

每次将一个类的样例作为正例,所有其他类的样例作为反例来训练n个分类器。

在测试时若仅有一个分类器的预测为正例,则把该分类器对应的预测类别标记作为最终的分类结果;若有多个分类器预测为正例,则通常考虑各分类器的预测置信度,选择置信度最大的类别标记作为分类结果,例如:逻辑回归算法对 n 个数据集训练出 n 个模型,将待预测的样本传入这n 个模型中,所得概率最高的那个模型对应的样本类型即认为是该预测样本的类型。

可见,OVO需要训练n(n-1)/2个分类器,而OVR只需训练n个分类器,因此OVO的存储开销和预测时间开销通常比OVR更大。但在训练时OVR的每个分类器均使用全部训练样例,而OVO的单个分类器仅使用两个类别的样例,因此,在类别很多时,OVO的训练时间开销通常比OVR更小。预测性能的表现则取决于具体的数据分布,多数情况下两者差别不大。

3,多对多(MvM):

每次将若干个类作为正类,若干个其他类作为反类。从这个角度来看,OVO和OVR是MOM的特例。

其中,MVM最常用的是纠错输出码(Error Correcting Output Codes,ECOC)。ECOC是将编码思想引入类别拆分,并尽可能在解码过程中具有容错性。

ECOC分为两步:

1),编码:将N个类别做M次划分,每次将一部分作为正例,其余作为反例,学习到M个分类器;

2),解码:新样本提交给M个分类器,得到M个结果,组成一个编码,将其和每个类别各自的编码进行比较,距离最小的类别作为最终结果

一般来讲,对同一个学习任务,ECOC编码越长,纠错能力越强。然而,编码越长,意味着所需训练的分类器越多,计算、存储开销都会增大;对于有限类别,可能的组合数目有限,码长超过一定范围后就失去了意义。

二、算法分类:单、多标签 -> 二分类、多分类

1, 单标签二分类算法:

每个样例可能类别只有两种(正例、反例),此时的分类算法其实是在构建一个分类线将数据划分为两个类别,常见的算法:Logistic、SVM等

2, 单标签多分类算法:

每个样例的可能类别有K种,例如:一种花可能是牡丹花、兰花、荷花等等。常见算法有:softmax、纠错码机制等。

3, 多标签算法: 常见算法有:KNN、decision tree等

解决多标签问题的技术:转换问题为多分类问题;调整多分类算法适应多标签问题;Ensemble 方法。

转换策略:

1),Binary Relevance (二值相关):多标签问题转换为多个分类问题。

2),Classifier Chains (分类器串联):

黄色区域为输入空间,白色区域代表学习目标。该方法和Binary relevance很相似,区别在于:考虑了标签之间的相关性。

3),Label Powerset (标签集合):

相同颜色表示对应的标签一致,因此可以讲他们看成同一类。转化成多分类问题。缺点:当数据集很大时,类别数目非常多,会增加模型复杂度,导致精确度降低。

4),标签排序(calibrated label ranking):

学习从示例到预先定义的标签集的排名的映射。迄今为止,标签排名的现有方法隐式地在一个基础(实用)尺度上运行,而这个尺度并没有被校准,因为它没有一个自然的“零点”。我们的扩展提出了一种概念上新颖的技术,用于通过成对比较方法将通常的学习扩展到多标记场景,这种设置以前不适合成对分解技术。这种方法的关键思想是引入一种人工校准标签,在每个示例中,它将相关标签与无关标签分离开来。该技术可以被视为成对偏好学习和传统相关性分类技术的组合,其中训练单独的分类器来预测标签是否相关。

三、code:

1,多分类拆分策略:一对一(OVO)、一对其余(OVR)

code:1,OVR:LogisticRegression()默认使用OvR;2,ovo

代码语言:javascript
复制
# 1,OVR: LogisticRegression()默认使用OvR
import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets
from matplotlib.colors import ListedColormap
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
%matplotlib inline

iris = datasets.load_iris()
X = iris.data
y = iris.target
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=666)

log_reg_ovr = LogisticRegression()
log_reg_ovr.fit(X_train, y_train)
score_ovr = log_reg_ovr.score(X_test, y_test)
print(score_ovr)

def plot_decision_boundary(model, axis):  # 绘制决策边界  
    x0, x1 = np.meshgrid(
        np.linspace(axis[0], axis[1], int((axis[1]-axis[0])*100)).reshape(-1,1),
        np.linspace(axis[2], axis[3], int((axis[3]-axis[2])*100)).reshape(-1,1)
    )
    X_new = np.c_[x0.ravel(), x1.ravel()]
    
    y_predict = model.predict(X_new)
    zz = y_predict.reshape(x0.shape)    
    custom_cmap = ListedColormap(['#EF9A9A','#FFF59D','#90CAF9'])    
    plt.contourf(x0, x1, zz, linewidth=5, cmap=custom_cmap)

plot_decision_boundary(log_reg, axis=[4, 8.5, 1.5, 4.5])
plt.scatter(X[y==0, 0], X[y==0, 1])  # 可视化时只能在同一个二维平面内体现两种特征
plt.scatter(X[y==1, 0], X[y==1, 1])
plt.scatter(X[y==2, 0], X[y==2, 1])
plt.show()


# 2,OVO:
log_reg_ovo = LogisticRegression(multi_class='multinomial', solver='newton-cg')  # multinomial:指 OvO 方法
log_reg_ovo.fit(X_train, y_train)
score_ovo = log_reg_ovo.score(X_test, y_test)
print(score_ovo)

plot_decision_boundary(log_reg2, axis=[4, 8.5, 1.5, 4.5])
plt.scatter(X[y==0, 0], X[y==0, 1])
plt.scatter(X[y==1, 0], X[y==1, 1])
plt.scatter(X[y==2, 0], X[y==2, 1])
plt.show()

2,算法分类:单标签二分类算法、单标签多分类算法、多标签算法

code: 1,OVO; 2,OVR;3,Error-Correcting:纠错码机制;4,多标签分类。

代码语言:javascript
复制
import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets
from sklearn.multiclass import OneVsOneClassifier
from sklearn.multiclass import OneVsRestClassifier
from sklearn.multiclass import OutputCodeClassifier
from sklearn.svm import LinearSVC
from sklearn.metrics import accuracy_score
from sklearn.datasets import make_multilabel_classification
from sklearn.svm import SVC
from sklearn.preprocessing import LabelBinarizer
from sklearn.decomposition import PCA
from sklearn.cross_decomposition import CCA

iris = datasets.load_iris()  # 加载数据
X, y = iris.data, iris.target  # 获取X和y

# 1,OVO:
clf = OneVsOneClassifier(LinearSVC(random_state=0))  # 模型构建
clf.fit(X, y)  # 模型训练

# 2,OVR:
clf = OneVsRestClassifier(LinearSVC(random_state=0)) # 模型构建
clf.fit(X, y)

# 3,Error-Correcting:纠错码机制
clf = OutputCodeClassifier(LinearSVC(random_state=0), code_size=2, random_state=0)  # code_size: 指定最终使用多少个子模型,实际的子模型的数量=code_size*label_number
clf.fit(X, y)            # 模型构建
print(clf.predict(X))    # 输出预测结果值
print("准确率:%.3f" % accuracy_score(y, clf.predict(X)))

k = 1
for item in clf.estimators_:  # 模型属性输出
    print("第%d个模型:" % k, end="")
    print(item)
    k += 1
print(clf.classes_)

# 4,多标签分类:
def plot_hyperplane(clf, min_x, max_x, linestyle, label):
    # 画图
    w = clf.coef_[0]
    a = -w[0] / w[1]
    xx = np.linspace(min_x - 5, max_x + 5)  
    yy = a * xx - (clf.intercept_[0]) / w[1]
    plt.plot(xx, yy, linestyle, label=label)

def plot_subfigure(X, Y, subplot, title):    # 将X进行降维操作,变成两维的数据
    X = PCA(n_components=2).fit_transform(X)
    min_x = np.min(X[:, 0])
    max_x = np.max(X[:, 0])

    min_y = np.min(X[:, 1])
    max_y = np.max(X[:, 1])

    classif = OneVsRestClassifier(SVC(kernel='linear'))
    classif.fit(X, Y)

    plt.subplot(2, 2, subplot)
    plt.title(title)

    zero_class = np.where(Y[:, 0])
    one_class = np.where(Y[:, 1])
    plt.scatter(X[:, 0], X[:, 1], s=40, c='gray')
    plt.scatter(X[zero_class, 0], X[zero_class, 1], s=160, edgecolors='b',
               facecolors='none', linewidths=2, label='Class 1')
    plt.scatter(X[one_class, 0], X[one_class, 1], s=80, edgecolors='orange',
               facecolors='none', linewidths=2, label='Class 2')

    plot_hyperplane(classif.estimators_[0], min_x, max_x, 'r--',
                    'Boundary\nfor class 1')
    plot_hyperplane(classif.estimators_[1], min_x, max_x, 'k-.',
                    'Boundary\nfor class 2')
    plt.xticks(())
    plt.yticks(())

    plt.xlim(min_x - .5 * max_x, max_x + .5 * max_x)
    plt.ylim(min_y - .5 * max_y, max_y + .5 * max_y)
    if subplot == 1:
        plt.xlabel('First principal component')
        plt.ylabel('Second principal component')
        plt.legend(loc="upper left")


plt.figure(figsize=(8, 6))

X, Y = make_multilabel_classification(n_classes=2, n_labels=1,
                                      allow_unlabeled=False, # 该参数控制是否有类别缺省的数据,False表示没有
                                      random_state=1)

plot_subfigure(X, Y, 1, "With unlabeled samples + CCA")

plt.subplots_adjust(.04, .02, .97, .94, .09, .2)
plt.show()

Reference:

《西瓜书》

https://www.jianshu.com/p/20dbe1c1ba67

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-05-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 MiningAlgorithms 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档