当前位置: 首页 > 后端技术 > Python

提示-如何使用二元分类器解决多分类任务?

时间:2023-03-26 11:20:14 Python

二进制问题是我们生活中的常见问题。比如邮件可以分为垃圾邮件和非垃圾邮件,一个人有没有生病,但是除此之外,还会有一些Multivariate的分类问题,比如天气可以分为晴天、阴天、雨天、下雪天等等在。我们通过算法构建的分类器可以分为二分类器和多分类器。前者可以区分两个类别标签,后者可以区分两个以上的类别标签。对于算法,如支持向量机和逻辑回归是严格的二分类算法,而朴素贝叶斯和随机森林等算法可以直接处理多类分类问题。然而,使用二元分类器来处理多分类问题是可行的。下面将以逻辑回归结合鸢尾花数据集为例。使用二元分类器解决多分类问题的OvA和OvO策略可以分为两种策略:one-versus-all(OvA)strategy,也称为one-versus-rest(OvR),简称一对多.一对一(OvO)策略,简称一对一,应该有人用过OvO作为文本表达。用过鸢尾花数据集的小伙伴应该都知道,这个数据集中一共有三种类别标签,分别是setosa、versicolor和virginica,因为一共有三个类别。因此,构造了三个二元分类器,假设山分类器、变量分类器和维度分类器。训练时,将某一类的样本归为一类,将其他类别的样本归为另一类,这样对于未知类别的样本,三个分类器都会有一个判定分数(概率),然后取highestdecisionscore将样本的一个类别作为样本的类别,该方法属于一对多方法。一对一的方法是在任意两类样本之间建立多个二元分类器。原理类似于组队。例如,上述三个标签变量可以由山脉和变量、山脉和维度、变量和维度组成。如果类别为Forn,则所需的分类器数量为$\frac{n(n-1)}{2}$。最后,将决策得分最高的类别作为未知类别样本的最终分类。从上面的介绍也很容易得出两者的优缺点:OvA缺点:因为是一个类别到多个类别(1:N的关系),所以在训练的时候可能会更偏向多类别这边。OvA的优点:假设有n个类别,只需要构建n个分类器。OvO的缺点:在标签类别很多的情况下,需要构建很多二元分类器,构建和训练的过程比较麻烦OvO的优点:每个分类器只需要在包含两个类别的部分数据上进行训练,不需要需要在整个数据集上。两种策略的基本思想都是通过构建多个二元分类器来解决多分类问题。大多数二分类算法都比较适合OvA策略,当然不是全部,也需要根据数据集的特点来确定。接下来,使用逻辑回归对鸢尾花数据集进行建模。因为数据集比较简单,所以只讲这个方法,所以省略分析等操作。手动实施OvA策略。就个人而言,我会习惯将数据集转换为易于观察的DataFrame格式:importpandasasppdfromsklearn.datasetsimportload_irisfeature_names=load_iris().feature_namesdataset_data=pd.DataFrame(load_iris().data,columns=feature_names)dataset_target=pd.DataFrame(load_iris().target,columns=['target'])data=pd.concat([dataset_data,dataset_target],axis=1)数据集共有150个样本,四个特征和一个类别标签:我们使用一对多(OvA策略)结合逻辑回归来解决这个多分类问题。首先介绍一下手动推送的方式。建模过程和二分类一样,但是需要注意OvA策略的思想。首先我们要划分数据集,取7个作为训练集,剩下的3个作为测试集,基础部分就不贴代码了,文末给出完整的代码获取方法文章。OvA的策略是有多少类别就建立多少分类器,所以需要知道所有类别的标签变量,可以使用唯一索引,然后用字典格式存储所有的分类器。#获取标签变量的类别unique_targets=data['target'].unique()'''array([0,1,2])'''#采用OvA策略,三个类别对应三个模型,字典格式storagemodels={}每个分类器都会将一个类别归为一类,剩下的类别归为另一个类别,所以这里暂且假设每次循环与目标相同,标签设置为1,剩下的两个类别classlabel设置为0。为了代码的简洁,使用pipelineflow封装了各个分类器和归一化过程。y_train_copy=y_train.copy()fortargetinunique_targets:#流水线封装模型[target]=make_pipeline(StandardScaler(),LogisticRegression())y_train_list=y_train_copy.tolist()#每次修改训练集的标签,都会当前类别的标签设置为1,其他类别设置为0foriinrange(len(y_train_list)):ify_train_list[i]==target:y_train_list[i]=1else:y_train_list[i]=0y_train=np.array(y_train_list)models[target].fit(X_train,y_train)创建对应的分类器之后,接下来要做的就是应用到测试集上,三个分类器最终得到预测三个标签的概率。test_probs=pd.DataFrame(columns=unique_targets)fortargetinunique_targets:#[:,1]返回属于1的概率,[:,0]是属于0的概率test_probs[target]=models[target].predict_proba(X_test)[:,1]print(test_probs)可以得到关于概率的DataFrame如下:pandas中有一个idxmax()方法可以索引样本中最大值的列索引,其中asample最后是分类别的。predicted_target=test_probs.idxmax(axis=1)'''001021304251......模型错误率:6.67%'''最后通过与原始标签Rate,到此为止就是如何使用二元分类器来实现多类分类问题的手推法。sklearn调用在sklearn中也有类可以实现OvA和OVO策略,比手动push方式更简单方便,即OneVsOneClassifier或OneVsRestClassifier。fromsklearn.multiclassimportOneVsOneClassifier,OneVsRestClassifierOvO=OneVsOneClassifier(make_pipeline(StandardScaler(),LogisticRegression()))OvO.fit(X_train,y_train)ovo_predict=OvO.predict(X_test)你应该熟悉这些库的调用。介绍太多,用对应的方法查看类标签和分类器的个数,3个类别比较聪明,同时构建OvA和OvO策略需要的二元分类器个数为3。print('Categorylabels:%s'%OvO.classes_)print('Numberofclassifiers:%d'%len(OvO.estimators_))'''Categorylabels:[012]Numberofclassifiers:3'''其实在multi_class参数中logistic回归,有ovr(OvA)策略可以选择,但是没有OvO策略。毕竟手推更容易理解一个策略的思路。我们理解了之后,在调用类或者调整参数的时候就知道我们在做什么操作了。综上所述,它是对如何使用二分类算法解决多分类问题的一个概述。.参考链接:[1].https://blog.csdn.net/zm71498...公众号【奶糖猫】回复关键词“多分类”获取文中代码参考