Support Vector Machine(SVM)学习笔记(2)

0 声明

本文主要内容来自视频'【2020机器学习全集】菜菜的sklearn完整版,价值4999元的最全机器学习sklearn全集,赶紧收藏_哔哩哔哩_bilibili',课件来自“https://pan.baidu.com/s/1Xl4o0PMA5ysUILeCKvm_2w,提取码:a967”。

1 参数C再理解

对于存在软间隔的数据,需要引入一个松弛系数\zeta增大边际d,让模型能够忍受一小部分训练误差,但是\zeta的引进也可能会使得被分错的样本越来越多。因此需要找出一个”最大边际“与”被分错的样本数量“之间的平衡,这就需要引入系数C作为一个松弛系数\zeta的惩罚项,来惩罚对最大边际的追求。

对于硬间隔数据,决策边界完全由两个支持向量和最小化损失函数(最大化边际)来决定,而决定两条虚线超平面的支持向量是两个标签类别不一致的点,即分别是正样本和负样本。在软间隔情况下的边际依然由支持向量决定,但此刻的支持向量可能就不再是来自两种标签类别的点,而可能是分布在决策边界两边的同类别点。C值会决定究竟是依赖红色点作为支持向量(只追求最大边界),还是要依赖软间隔中,混杂在红色点中的紫色点来作为支持向量(追求最大边界和判断正确的平衡)。如果C值设定比较大,那SVC可能会选择边际较小的,能够更好地分类所有训练点的决策边界,不过模型的训练时间也会更长。如果C的设定值较小,那SVC会尽量最大化边界,尽量将掉落在决策边界另一方的样本点预测正确,决策功能会更简单,但代价是训练的准确度,因为此时会有更多红色的点被分类错误。

因此,引入参数C后,所有可能影响超平面的样本都可能会被定义为支持向量,所以支持向量就不再是所有压在虚线超平面上的点,而是所有可能影响的超平面的位置的那些混杂在彼此的类别中的点了。

2 SVC中的样本不均衡

样本不均衡会产生两个问题,首先,分类模型天生会倾向于多数的类,让多数类更容易被判断正确,少数类被牺牲掉;其次,模型评估指标会失去意义,有时候关注重点就在于少数类,因此着眼于整体判断的指标意义不大。

如果样本中存在数据不均衡,而训练目标又是捕捉数据中的少数类,那么必须先让算法意识到数据标签是不均衡的,通过施加一些惩罚或者改变样本本身,让模型向着捕获少数类的方向建模;然后要改进模型评估指标,使用更加针对于少数类的指标来优化模型。

SVC类中提供了的class_weight来调节样本均衡性,另外,fit方法中也可以设定sample_weight来均衡样本。

2.1 权重调节参数

(1)class_weight参数

可输入字典或者"balanced”,也可不填,默认None 。如果没有给出具体的class_weight,则所有类都被假设为占有相同的权重1,模型会根据数据原本的状况去训练。如果希望改善样本不均衡状况,需要输入形如{"标签的值1":权重1,"标签的值2":权重2}的字典,则参数C将会自动被设为:
标签值为1的C等于权重1 * C,标签值为2的C等于权重2*C。也可以使用“balanced”模式,这个模式使用y的值自动调整与输入数据中的类频率成反比的权重为n_samples/(n_classes * np.bincount(y))

(2) fit方法的sample_weight参数

sample_weight必须输入每个样本在fit时的权重,让权重 * 每个样本对应的C值来迫使分类器强调设定的权重更大的样本。通常是将较大的权重加在少数类的样本上,以迫使模型向着少数类的方向建模。一般而言,class_weight参数与sample_weight参数只需设置一个,如果同时设置了两个参数,则C会同时受到两个参数的影响,即 class_weight中设定的权重 * sample_weight中设定的权重 * C。

2.2 SVC的模型评估指标

当模型着眼于捕捉少数类时,通常会使得相当一部分多数类被判别成为少数类,这会使得成本太高。所以在现实中,往往在寻找捕获少数类的能力和将多数类判错后需要付出的成本的平衡,这就需要引进新的评估指标——混淆矩阵(Confusion Matrix)与ROC曲线。

2.2.1 混淆矩阵

混淆矩阵是二分类问题的多维衡量指标体系,在样本不平衡时极其有用。在混淆矩阵中,将少数类认为是正例,多数类认为是负例。在决策树,随机森林这些普通的分类算法里,即是说少数类是1,多数类是0。在SVM里,就是说少数类是1,多数类是-1。普通的混淆矩阵,一般使用{0,1}来表示。下面是一个混淆矩阵的例子:


混淆矩阵中,永远是真实值在前,预测值在后。其实可以很容易看出,11和00的对角线就是全部预测正确的,01和10的对角线就是全部预测错误的。基于混淆矩阵,有六个不同的模型评估指标,这些评估指标的范围都在[0,1]之间,所有以11和00为分子的指标都是越接近1越好,所以以01和10为分子的指标都是越接近0越好。

(1)Accuracy(准确率)

Accuracy =\frac{11+00}{11+10+01+00}

准确率Accuracy就是所有预测正确的所有样本除以总样本,通常来说越接近1越好。

(2)Precision(精确度)

Precision =\frac{11}{11+01}

精确度Precision表示所有被预测为是少数类的样本中,真正的少数类所占的比例。精确度越高,代表捕捉正确的少数类越多,对少数类的预测越精确。精确度越低,则代表误伤了过多的多数类。它是”将多数类判错后所需付出成本“的衡量。

(3)Recall(召回率)

 Recall =\frac{11}{11+10}

召回率Recall表示所有真实为1的样本中,被预测正确的样本所占的比例。召回率越高,代表捕捉出了越多的少数类,召回率越低,代表没有捕捉出足够的少数类。如果希望不计一切代价找出少数类,那就会追求高召回率。

(3)F1-meassure

注意召回率和精确度的分子是相同的(都是11),只是分母不同,因此召回率Recall和精确度Precision是此消彼长的,两者之间的平衡代表了捕捉少数类的需求和尽量不要误伤多数类的需求的平衡。究竟要偏向于哪一方,取决于业务需求:究竟是误伤多数类的成本更高,还是无法捕捉少数类的代价更高。为了同时兼顾精确度和召回率,创造了两者的调和平均数作为考量两者平衡的综合性指标,称之为F1-measure。两个数之间的调和平均倾向于靠近两个数中比较小的那一个数,因此追求尽量高的F1-measure 能够保证精确度和召回率都比较高。F1-measure在[0,1]之间分布,越接近1越好。

F1-measure =\frac{2}{\frac{1}{ Precision }+\frac{1}{Recall }}=\frac{2 Precision \cdot Recall }{Precision + Recall }

(4)False Negative Rate(假负率)

其数值等于 1 - Recall,用于衡量所有真实为1的样本中,被错误判断为0的部分。

(5)Specificity (特异度)

 Specificity=\frac{00}{01+00}

特异度(Specificity)表示所有真实为0的样本中,被正确预测为0的样本所占的比例。特异度衡量了一个模型将多数类判断正确的能力。

(6)False Positive Rate(假正率)

F P R=\frac{01}{01+00}

假正率等于1 - specificity,表示一个模型将多数类判断错误的能力。假正率其实类似于Precision的反向指标,Precision衡量有多少个少数点被判断正确,而假正率FPR衡量有多少个多数点被判断错误,性质是十分类似的。
2.2.2 sklearn中的评价指标

 2.3 ROC曲线

在追求较高的Recall的时候,Precision会下降,就是说随着更多的少数类被捕捉出来,会有更多的多数类被判断错误。如果想要知道随着Recall的逐渐增加,模型将多数类判断错误的能力如何变化,FPR假正率是合适的选择。另外,因为Precision无法判断这些被判断错误的多数类在全部多数类中究竟占多大的比例,所以无法在提升Recall的过程中顾及到模型整体的Accuracy。而以假正率FPR为横坐标,不同阈值下的召回率Recall为纵坐标绘制而成的曲线就用于衡量模型在尽量捕捉少数类的时候,误伤多数类的情况如何变化,该曲线被称为The Receiver Operating Characteristic Curve,简称为ROC曲线,中文称为受试者操作特性曲线。

补充:所谓的阈值,其实就是在二分类问题的概率/距离临界值,当样本被预测出的概率/距离高于临界值时,该样本被分为一类,当样本被预测出的概率低于临界值时,该样本被分为另外一类。显然,阈值不同,混淆矩阵也不一样,相应的准确率Accuracy,精确度Precision,召回率Recall,精确度和召回率的平衡指标F1-measure,特异度Specificity,以及假正率FPR等都不一样。而ROC曲线就是以假正率FPR为横坐标,不同阈值下的召回率Recall为纵坐标绘制而成的曲线。

2.4 SVM中的概率预测

为了求解ROC曲线,需要实现概率的求解。sklearn提供了两种方式求解概率:重要参数probability,方法decision_function。

(1)decision_function

decision_function返回输入特征矩阵中每个样本到划分数据集超平面的距离。在SVM中利用超平面来判断样本的分类,本质上来说,当两个点的距离是相同的符号的时候,越远离超平面的样本点归属于某个标签类的概率就很大。所以,到超平面的距离一定程度上反映了样本归属于某个标签类的可能性。decision_function返回的值也因此被认为是SVM中的置信度(confidence)。

(2)probability

置信度终归不是概率,它没有边界,可以无限大,大部分时候也不是以百分比或者小数的形式呈现,而SVC的判断过程又不像决策树一样可以求解出一个比例。为了解决这个矛盾,SVC还有一个重要参数probability。在fit之前将probability设置为true,SVC的接口predict_proba和predict_log_proba将生效。值得注意的是,在二分类过程中,decision_function只会生成一列距离,样本的类别由距离的符号来判断,但是predict_proba会生成两个类别分别对应的概率。

2.5 sklearn中的ROC曲线和AUC面积

ROC曲线通常都是凸型的。对于一条凸型ROC曲线来说,曲线越靠近左上角越好,越往下越糟糕,曲线如果在虚线的下方,则证明模型完全无法使用。但是它也有可能是一条凹形的ROC曲线。对于一条凹型ROC曲线来说,应该越靠近右下角越好,凹形曲线代表模型的预测结果与真实情况完全相反,那也不算非常糟糕,只要手动将模型的结果逆转,就可以得到一条左上方的弧线了。最糟糕的就是,无论曲线是凹形还是凸型,曲线位于图像中间,和虚线非常靠近。
 

为了将ROC曲线反映的效果数字化,引入了AUC面积的概念——AUG面积代表了ROC曲线下方的面积,这个面积越大,代表ROC曲线越接近左上角,模型就越好。

(1)sklearn.metrics.roc_curve

y_true : 数组,形状 = [n_samples],真实标签;
y_score : 数组,形状 = [n_samples],置信度分数,可以是正类样本的概率值,或置信度分数,或者decision_function返回的距离;
pos_label : 整数或者字符串, 默认None,表示被认为是正类样本的类别。

FPR:返回值,假正率;

Recall:返回值,召回率;

thresholds:返回值,阈值,可以是距离,也可以是概率。

(2)sklearn.metrics.roc_auc_score
y_true : 数组,形状 = [n_samples],真实标签;
y_score : 数组,形状 = [n_samples],置信度分数,可以是正类样本的概率值,或置信度分数,或者decision_function返回的距离。

2.6 利用ROC曲线找出最佳阈值

ROC曲线反映的是recall增加的时候FPR如何变化,也就是当模型捕获少数类的能力变强的时候,会误伤多数类的情况是否严重。一个最优的模型能够在捕获少数类的能力变强的时候,尽量不误伤多数类,也就是说,随着recall的变大,FPR的大小越小越好。所以希望找到的最优点,其实是Recall和FPR差距最大的点,这个点,又叫做约登指数。确定该点对应的概率或者距离之后,让这个距离/概率以上的点,都为正类,让这个距离/概率以下的点都为负类,这种模型就是最好的。从找出的最优阈值点来看,这个点其实是图像上离左上角最近的点,离中间的虚线最远的点,也是ROC曲线的转折点。如果没有时间进行计算,或者横坐标比较清晰的时候,就可以观察转折点来找到最佳阈值。

3 SVC处理多分类问题

SVC处理多分类是一个比二分类问题更加复杂的问题,这里不作展开,只介绍基本的思路。大概思路是将多分类问题转化为二分类问题,按照转化方式不同,可以分为两种模式,一种叫做“一对一”模式(one vs one),一种叫做“一对多”模式(one vs rest)。在ovo模式下,标签中的所有类别会被两两组合,每两个类别之间建一个SVC模型,每个模型生成一个决策边界,分别进行二分类;在ovr模式下,标签中所有的类别会分别与其他类别进行组合,建立n_class个模型,每个模型生成一个决策边界,分别进行二分类。

当类别更多的时候,无论是ovr还是ovo模式需要的决策边界都会越来越多,模型也会越来越复杂,不过ovo模式下的模型计算会更加复杂,因为ovo模式中的决策边界数量增加更快,但相对的,ovo模型也会更加精确。ovr模型计算更快,但是效果往往不是很好。在硬件可以支持的情况下,还是建议选择ovo模式。sklearn的参数decision_function_shape决定究竟使用哪一种分类模式,可输入“ovo","ovr",默认”ovr",二分类时,尽管选用ovr模式。

4 实例介绍

4.1 一个设置权重平衡数据的实例

from sklearn import svm
from sklearn.datasets import make_blobs

class_1_ = 7
class_2_ = 4
centers_ = [[0.0, 0.0], [1,1]]
clusters_std = [0.5, 1]
X, y = make_blobs(n_samples=[class_1_, class_2_],
                  centers=centers_,
                  cluster_std=clusters_std,
                  random_state=0, shuffle=False)

wclf = svm.SVC(kernel='linear', class_weight={1: 10}) # 设定权重
wclf.fit(X, y)
wclf.score(X, y)

4.2 混淆矩阵应用实例

from sklearn.metrics import confusion_matrix as CM, precision_score as P, recall_score as R
import pandas as pd
from sklearn import svm
from sklearn.datasets import make_blobs

class_1 = 500 #类别1有500个样本
class_2 = 50 #类别2只有50个
centers = [[0.0, 0.0], [2.0, 2.0]] #设定两个类别的中心
clusters_std = [1.5, 0.5] #设定两个类别的方差,通常来说,样本量比较大的类别会更加松散
X, y = make_blobs(n_samples=[class_1, class_2],
                  centers=centers,
                  cluster_std=clusters_std,
                  random_state=0, shuffle=False)
clf_proba = svm.SVC(kernel="linear",C=1.0,probability=True).fit(X,y)

prob = pd.DataFrame(clf_proba.predict_proba(X))  #生成的各类标签下的概率
prob.columns = ["0","1"]
for i in range(prob.shape[0]):
    if prob.loc[i,"1"] > 0.5:
        prob.loc[i,"pred"] = 1
    else:
        prob.loc[i,"pred"] = 0
prob["y_true"] = y

print(CM(prob.loc[:,"y_true"],prob.loc[:,"pred"],labels=[1,0]))
print(P(prob.loc[:,"y_true"],prob.loc[:,"pred"],labels=[1,0]))
print(R(prob.loc[:,"y_true"],prob.loc[:,"pred"],labels=[1,0]))

4.3 一个ROC曲线和AUC面积应用实例

from sklearn.metrics import roc_curve
from sklearn.metrics import roc_auc_score as AUC
from sklearn.datasets import make_blobs
import matplotlib.pyplot as plt

class_1 = 500  # 类别1有500个样本
class_2 = 50  # 类别2只有50个
centers = [[0.0, 0.0], [2.0, 2.0]]  # 设定两个类别的中心
clusters_std = [1.5, 0.5]  # 设定两个类别的方差,通常来说,样本量比较大的类别会更加松散
X, y = make_blobs(n_samples=[class_1, class_2],
                  centers=centers,
                  cluster_std=clusters_std,
                  random_state=0, shuffle=False)
FPR, recall, thresholds = roc_curve(
    y, clf_proba.decision_function(X), pos_label=1)
maxindex = (recall - FPR).tolist().index(max(recall - FPR))  # 求解最佳阈值
print(thresholds[maxindex])  # 选取最佳阈值,可以是概率,也可以是距离,这里是距离

# 计算AUC面积
area = AUC(y, clf_proba.decision_function(X))
print(area)

plt.figure()
plt.plot(FPR, recall, color='red',
         label='ROC curve (area = %0.2f)' % area)
plt.plot([0, 1], [0, 1], color='black', linestyle='--')
plt.scatter(FPR[maxindex], recall[maxindex], c="black", s=30)
plt.xlim([-0.05, 1.05])
plt.ylim([-0.05, 1.05])
plt.xlabel('False Positive Rate')
plt.ylabel('Recall')
plt.title('Receiver operating characteristic example')
plt.legend(loc="lower right")
plt.show()

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

syphomn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值