之前提到的是二分类问题,问题结果是0或1这种明显分为两类的。在现实任务中往往遇到的是多分类问题,有些二分类学习方法可以推广到多分类上使用,但是在更多情况下可以使用拆解法,把一个多分类任务分成多个二分类任务解决。
多分类问题的解决思路就是使用拆解法。利用二分类学习器进行多分类问题学习。先对问题进行拆分,再为拆分出来的每一个二分类任务训练一个二分类学习器。最后在进行预测的时候,把这些二分类学习器预测结果进行集成来获得多分类问题最终的结果。
上述解决思路中最关键的就是如何对多分类任务进行拆分,如何对多个分类器进行集成。
最经典的拆分策略有三个:OVO,OVR,MvM。分别是:一对一,一对多,多对多
这次主要介绍一对一和一对多进行多分类任务的拆分。看图理解。
OVO:进行两两配对,比如有c1,c2,c3,c4四个样例,那么如下图一共有6种情况,会训练出6个分类器,在最终测试时,将6种分类器预测到的结果集成得到最终结果。
OVR:每次将一个类的样例作为正例,其他都为反例来训练出N个训练器。在测试时,如果N个分类器预测出的N个结果中只有一个分类器预测到的是正类,那么该分类器预测到的结果就是最终结果。
比如在下图中,4个类的样例有4个分类器,只有第三个预测结果为正类,则取该结果为最终结果。
这次代码中由于数据集中的数据类型杂乱,有字符串和小数,所以使用pandas库结合numpy对数据进行处理。
部分数据集如下图:
在Sklearn机器学习包中,集成了各种各样的数据集,这里引入的是鸢尾花卉(Iris)数据集,它是很常用的一个数据集。鸢尾花有三个亚属,分别是山鸢尾(Iris-setosa)、变色鸢尾(Iris-versicolor)和维吉尼亚(Irisvirginica)。
该数据集一共包含4个特征变量,1个类别变量。共有150个样本,iris是鸢尾植物,这里存储了其萼片和花瓣的长宽,共4个属性,鸢尾植物分三类。
所以在对数据进行处理的过程中,要把最后一列字符串数据通过字典映射为0,1,2三个类别,方便后续处理。
import numpy as np
import pandas as pd
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
#使用pandas库读取函数
def per_read(path):
data=pd.read_csv(path) #pandas读取数据
class_dict={'Iris-setosa':0,'Iris-versicolor':1,'Iris-virginica':2} #字典转换
data['species']=data['species'].map(class_dict) #使用map进行替换
#print(data)
#进行数据分割
x=data.iloc[:,0:-1]
y=data.iloc[:,-1]
x=np.array(x,dtype=np.float)
y = np.array(y, dtype=np.float)
#数据归一化处理
mu=x.mean(0)
std=x.std(0)
x=(x-mu)/std
#分测试集与数据集
x_train,x_test,y_train,y_test=train_test_split(x,y,test_size=0.33)
return x_train,x_test,y_train,y_test
#OVO的计算函数
def ovo(x_train,x_test,y_train,y_test):
log_model=LogisticRegression(solver="lbfgs",multi_class="multinomial")
##self.solver参数决定了我们对逻辑回归损失函数的优化方法,lbfgs是拟牛顿法multi_class="multinomial"是制定使用ovo
log_model.fit(x_train,y_train)
y_predict=log_model.predict(x_test)
print(np.sum(y_predict==y_test)/len(y_test)) #计算预测的准确率
#OVR的计算函数
def ovr(x_train,x_test,y_train,y_test):
log_model=LogisticRegression(solver="lbfgs",multi_class="ovr")
#是用牛顿法进行优化,并指定使用ovr
log_model.fit(x_train,y_train)
y_predict=log_model.predict(x_test)
print(np.sum(y_predict==y_test)/len(y_test))
if __name__=="__main__":
x_train, x_test, y_train, y_test =per_read("F:\comdata\iris.txt")
ovo(x_train, x_test, y_train, y_test)
ovr(x_train, x_test, y_train, y_test)