多元分类支持向量机是用于处理多类别分类问题的方法。常见的二元分类支持向量机直接处理两类分类问题,但在实际应用中,我们经常需要处理多于两类的情况。对于这种问题,我们通常采用以下两种策略将多元分类问题转化为二元分类问题:
这里的投票是指,**每一个二元分类器对于一个未知样本的预测结果都可以看作是对目标类别的一次投票。**每个分类器预测未知样本属于两个类别中的哪一个,预测结果即为对该类别的投票。在所有的二元分类器中,得票最多的类别则被判定为未知样本的类别。
举个例子,假设我们有3个类别A、B和C,根据一对一策略,我们构建了3个分类器:A vs B,B vs C,A vs C。对于一个未知样本:
那么A得票2次,B和C各得票1次。在这个投票过程中,得票最多的A就是最终的类别结果。
这两种策略都有各自的优势和缺点。一对剩余的优势是只需要训练 个分类器,但在类别不平衡的情况下,性能可能会变差。而一对一的优势是每个分类器只需要在部分训练集上进行训练,所以每个训练过程比较快,但需要训练更多的分类器。在实际应用中可以根据具体情况选择最适合的策略。
一对剩余(One-vs-the-rest, OvR)是一种常用的多类分类策略,主要步骤如下:
构造 个分类器:对于 个类别,我们构造出 个支持向量机二元分类器。第 个分类器的目标是区分第 类和其他所有的类别。
训练分类器:对于第 个分类器,我们将所有第 类的样本标签设为1,其他类别的样本标签设为-1,然后进行训练。训练过程中,我们尝试找到最优的划分超平面,目标函数和二元分类SVM一样,如下所示:
满足以下约束:
这里 是超平面的法向量, 是超平面的截距, 是样本数量, 为第 个样本, 为第 个样本的标签, 为一个预先设定的惩罚系数,和二元分类SVM目标函数中的 一样,用于处理不可分情况。
预测:对于一个未知的样本点 ,我们将其输入到这 个分类器中,得到 个预测结果。最后类别的预测选取得分最高的分类器对应的类别。
这种方法的好处在于训练的复杂度仅与类别数量线性相关,而且各分类器之间的训练可以并行进行,节省了训练时间。一方面,这种方法可能导致不平衡的分类器性能,因为类别不平衡问题可能会在二分类问题中得到放大。
"一对一"是一种在支持向量机(Support Vector Machine, SVM)进行多元分类时的常用策略。这种策略也被称为"one-vs-one"或"all-pairs"策略。
在进行多元分类的时候,我们经常会遇到一个问题,那就是传统的二元分类算法(如SVM)无法直接应用于多元问题,因为它们仅仅可以做出两种类别间的决策。
"一对一"策略旨在解决这个问题。它的基本思想很简单:
对于给定的 个类别,为每一对类别训练一个二元分类器。当共有 个类别时,这意味着我们需要训练 个这样的分类器。对于每个分类器,我们把来自其两个类别的样本视为正负两类,忽略其它类别的样本。
在分类阶段,所有的 个分类器都会被用来对样本进行分类,每个分类器所作的决策被视为一种"投票",投票给它判定的类别。最后,每个样本都会被分配给得票最多的类别。
从这个角度来看,一对一策略实际上是一个"集成学习"的策略,把许多简单的二元分类器的决策综合起来,得到一个多元分类器。这种策略在许多实际问题中已被证明是非常有效的,尤其是在那些类别之间的区分度比较明显的数据集上。
要评估支持多元分类支持向量机的准确率,我们可以使用混淆矩阵(Confusion Matrix)来计算各种分类指标,如准确率、精确率、召回率和F1得分。
假设我们的多元分类支持向量机模型有两个类别,分别为正例(Positive)和反例(Negative)。
具体可见准确性评价指标的分类问题。
1from sklearn import svm, datasets
2from sklearn.model_selection import GridSearchCV, train_test_split
3from sklearn.metrics import accuracy_score
4import matplotlib.pyplot as plt
5import numpy as np
6
7# 加载鸢尾花数据集,并且只取前两个特征
8iris = datasets.load_iris()
9X = iris.data[:, :2]
10y = iris.target
11
12# 切分训练集和测试集
13X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
14
15# 设定搜索的参数
16parameters = {'kernel':['linear', 'rbf'], 'C':[1,2,4,8], 'gamma':[0.125, 0.25, 0.5 ,1, 2, 4]}
17
18# 执行网格搜索
19svc = svm.SVC()
20clf = GridSearchCV(svc, parameters)
21clf.fit(X_train, y_train)
22
23# 打印最优参数
24print("best params: " + str(clf.best_params_))
25
26# 用最优参数生成模型
27svc_best = svm.SVC(kernel=clf.best_params_['kernel'], C=clf.best_params_['C'], gamma=clf.best_params_['gamma'])
28svc_best.fit(X_train, y_train)
29
30# 在测试集上预测并评估
31y_pred = svc_best.predict(X_test)
32print("Accuracy score: ", accuracy_score(y_test, y_pred))
33
34# 生成网格数据
35x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
36y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
37h = (x_max / x_min)/100
38xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h))
39
40# 预测网格点的标签
41Z = svc_best.predict(np.c_[xx.ravel(), yy.ravel()])
42Z = Z.reshape(xx.shape)
43
44plt.contourf(xx, yy, Z, cmap=plt.cm.coolwarm, alpha=0.8)
45plt.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.coolwarm)
46plt.xlabel('Sepal length')
47plt.ylabel('Sepal width')
48plt.xlim(xx.min(), xx.max())
49plt.title('SVC with ' + clf.best_params_['kernel'] + ' kernel')
50plt.show()
1from sklearn import svm, datasets
2from sklearn.model_selection import GridSearchCV, train_test_split
3from sklearn.metrics import accuracy_score
4import matplotlib.pyplot as plt
5import numpy as np
6
7# 加载鸢尾花数据集,并且只取前两个特征
8iris = datasets.load_iris()
9X = iris.data[:, :2]
10y = iris.target
11
12# 切分训练集和测试集
13X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
14
15# 设定搜索的参数
16parameters = {'kernel':['linear', 'rbf'], 'C':[1,2,4,8], 'gamma':[0.125, 0.25, 0.5 ,1, 2, 4]}
17
18# 执行网格搜索
19svc = svm.SVC()
20clf = GridSearchCV(svc, parameters)
21clf.fit(X_train, y_train)
22
23# 打印最优参数
24print("best params: " + str(clf.best_params_))
25
26# 用最优参数生成模型
27svc_best = svm.SVC(kernel=clf.best_params_['kernel'], C=clf.best_params_['C'], gamma=clf.best_params_['gamma'])
28svc_best.fit(X_train, y_train)
29
30# 在测试集上预测并评估
31y_pred = svc_best.predict(X_test)
32print("Accuracy score: ", accuracy_score(y_test, y_pred))
33
34# 生成网格数据
35x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
36y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
37h = (x_max / x_min)/100
38xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h))
39
40# 预测网格点的标签
41Z = svc_best.predict(np.c_[xx.ravel(), yy.ravel()])
42Z = Z.reshape(xx.shape)
43
44plt.contourf(xx, yy, Z, cmap=plt.cm.coolwarm, alpha=0.8)
45plt.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.coolwarm)
46plt.xlabel('Sepal length')
47plt.ylabel('Sepal width')
48plt.xlim(xx.min(), xx.max())
49plt.title('SVC with ' + clf.best_params_['kernel'] + ' kernel')
50plt.show()
输出结果:
1best params: {'C': 1, 'gamma': 0.125, 'kernel': 'linear'}
2Accuracy score: 0.9
1best params: {'C': 1, 'gamma': 0.125, 'kernel': 'linear'}
2Accuracy score: 0.9
优点:
缺点: