多类分类器

# 多类分类器

from sklearn.datasets import fetch_openml
minst = fetch_openml('mnist_784',version=1)
X,y = minst["data"],minst["target"]
X_train,X_test,y_train,y_test = X[:60000],X[60000:],y[:60000],y[60000:]
some_digit = X[0]

多类分类器(也称为多项分类器)可以区分两个以上的类。有一些算法(如随机森林分类器或朴素贝叶斯分类器)可以直接处理多个类。也有一些严格的二元分类器(如支持向量机分类器或线性分类器)。
使用二元分类器实现多类分类的策略,比如要创建一个系统将数字图片分为10类(从0到9)

  1. 一种方法是训练10个二元分类器,每个数字一个(0-检测器、1-检测器、2-检测器,以此类推)。然后,当你需要对一张图片进行检测分类时,获取每个分类器的决策分数,哪个分类器给分最高,就将其分为哪个类。这称为一对剩余(OvR)策略,也称为一对多(one-versus-all)。
  2. 另一种方法是为每一对数字训练一个二元分类器:一个用于区分0和1,一个区分0和2,一个区分1和2,以此类推。这称为一对一(OvO)策略。如果存在N个类别,那么这需要训练N×(N-1)/2个分类器。对于MNIST问题,这意味着要训练45个二元分类器!当需要对一张图片进行分类时,你需要运行45个分类器来对图片进行分类,最后看哪个类获胜最多。OvO的主要优点在于,每个分类器只需要用到部分训练集对其必须区分的两个类进行训练。

有些算法(例如支持向量机分类器)在数据规模扩大时表现糟糕。对于这类算法,OvO是一个优先的选择,因为在较小训练集上分别训练多个分类器比在大型数据集上训练少数分类器要快得多。但是对大多数二元分类器来说,OvR策略还是更好的选择。Scikit-Learn可以检测到你尝试使用二元分类算法进行多类分类任务,它会根据情况自动运行OvR或者OvO。现在用sklearn.svm.SVC类来试试SVM分类器:

from sklearn.svm import SVC
svm_clf = SVC()
svm_clf.fit(X_train,y_train)
svm_clf.predict([some_digit])

使用原始目标类0到9(y_train)在训练集上对SVC进行训练,然后做出预测。
在内部,Scikit-Learn实际上训练了45个二元分类器,获得它们对图片的决策分数,然后选择了分数最高的类。
可以通过调用decision_function()方法,查看返回的10个分数,每个类1个,而不再是每个实例返回1个分数:

import numpy as np
some_digit_scores = svm_clf.decision_function([some_digit])
print(some_digit_scores) # 查看10个分数
# [[ 1.72501977  2.72809088  7.2510018   8.3076379  -0.31087254  9.3132482 1.70975103  2.76765202  6.23049537  4.84771048]]
print(np.argmax(some_digit_scores)) # 查看最高分对应的索引,5
print(svm_clf.classes_) #查看所有类别.['0' '1' '2' '3' '4' '5' '6' '7' '8' '9'].当训练分类器时,目标类的列表会存储在classes_属性中,按值的大小排序.本例是刚好索引跟类别一样

强制Scikit-Learn使用一对一或者一对剩余策略,可以使用OneVsOneClassifier或OneVsRestClassifier类。
只需要创建一个实例,然后将分类器传给其构造函数(不必是二元分类器)。
例如,下面这段代码使用OvR策略,基于SVC创建了一个多类分类器:

from sklearn.multiclass import OneVsRestClassifier
ovr_clf = OneVsRestClassifier(SVC())
ovr_clf.fit(X_train,y_train)
ovr_clf.predict([some_digit]) # array(['5'], dtype='

训练SGDClassifier,Scikit-Learn不必运行OvR或者OvO了,因为SGD分类器直接就可以将实例分为多个类。
调用decision_function()可以获得分类器将每个实例分类为每个类的概率列表:让我们看一下SGD分类器分配到的每个类

from sklearn.linear_model import SGDClassifier
sgd_clf = SGDClassifier(random_state=42)
sgd_clf.fit(X_train,y_train)
sgd_clf.predict([some_digit]) # array(['3'], dtype='

对模型进行评估

from sklearn.model_selection import cross_val_score
cross_val_score(sgd_clf,X_train,y_train,cv=3,scoring='accuracy') # array([0.87365, 0.85835, 0.8689 ])

在所有的测试折叠上都超过了85%,这个结果不是太糟,但是依然有提升的空间。例如,将输入进行简单缩放(标准化处理)可以将准确率提到89%以上:

import numpy as np
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train.astype(np.float64))
cross_val_score(sgd_clf,X_train_scaled,y_train,cv=3,scoring='accuracy') # array([0.8983, 0.891 , 0.9018])

 

你可能感兴趣的:(机器学习,多类分类器,机器学习)