CS_sklearn_2 SVM_2

SVC

本文作为SVM的进阶说明,在上一篇文章的基础上进行提高和探索。

SVC 参数

  先说明一下SVC中一些参数的作用,软间隔体现在这些参数当中
  SVC参数列表
  C: float参数 默认值为1.0
  错误项的惩罚系数。C越大,即对分错样本的惩罚程度越大,因此在训练样本中准确率越高,但是泛化能力降低,也就是对测试数据的分类准确率降低。相反,减小C的话,容许训练样本中有一些误分类错误样本,泛化能力强。对于训练样本带有噪声的情况,一般采用后者,把训练样本集中错误分类的样本作为噪声。

参考文章 Sklearn —SVC 参数与实例

Sample 1 Soft margin

  引入一些包

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap
from sklearn import svm
from sklearn.datasets import make_circles, make_moons, make_blobs,make_classification

  利用plt.subplots()来查看四种不同的数据的分布

n_samples = 100

datasets = [
    make_moons(n_samples=n_samples, noise=0.2, random_state=0),
    make_circles(n_samples=n_samples, noise=0.2, factor=0.5, random_state=1),
    make_blobs(n_samples=n_samples, centers=2, random_state=5),
    make_classification(n_samples=n_samples,n_features = 2,n_informative=2,n_redundant=0, random_state=5)
]

Kernel = ['linear']

fig1,ax1 = plt.subplots(nrows=2, ncols=2,figsize=(10,9))
axes1 = ax1.flatten()
for id,(X,Y) in enumerate(datasets):
    axes1[id].scatter(X[:,0],X[:,1],c=Y,s = 50,cmap="rainbow")
# print(list(enumerate(datasets))[0])
    

在这里插入图片描述

  使用线性分类器进行训练,观察训练结果

# len(datasets)
nrows = len(datasets)
ncols = len(Kernel) + 1

fig2,axes2 = plt.subplots(nrows,ncols,figsize=(10,16))


for id_datasets,(X,Y) in enumerate(datasets):
    # 去掉每一个子图的坐标轴
    axes2[id_datasets,0].set_xticks(())
    axes2[id_datasets,0].set_yticks(())
    axes2[id_datasets,1].set_xticks(())
    axes2[id_datasets,1].set_yticks(())
    
    ax_d = axes2[id_datasets,0]
    if id_datasets == 0:
        ax_d.set_title("Input data")
    ax_d.scatter(X[:,0],X[:,1],c=Y,zorder=10, cmap=plt.cm.Paired,edgecolors='k')
    print(ax)
    for id_kernel,kernel in enumerate(Kernel):
        
        
         
        ax_k = axes2[id_datasets,1]

        if id_datasets == 0:
            ax_k.set_title(kernel)
            
        #建模
        clf = svm.SVC(kernel = kernel,C=1).fit(X,Y)
        score = clf.score(X,Y)
        
        ax_k.scatter(X[:,0],X[:,1],c= Y,zorder = 10,cmap = plt.cm.Paired,edgecolors='k')
        ax_k.scatter(clf.support_vectors_[:,0],clf.support_vectors_[:,1],
                   s=100,facecolors = 'none',zorder=10,edgecolors = 'red')
        
        
        #绘制决策边界,这里加减0.5的是要扩充外边界,防止有白边
        x_min, x_max = X[:, 0].min() - .5, X[:, 0].max() + .5
        y_min, y_max = X[:, 1].min() - .5, X[:, 1].max() + .5
        
 

        XX,YY = np.mgrid[x_min:x_max:200j, y_min:y_max:200j]
        #np.c_,类似于np.vstack的功能
        Z = clf.decision_function(np.c_[XX.ravel(), YY.ravel()]).reshape(XX.shape)
        #填充等高线不同区域的颜色
        ax_k.pcolormesh(XX, YY, Z > 0, cmap=plt.cm.Paired)
        #绘制等高线
        ax_k.contour(XX, YY, Z, colors=['k', 'k', 'k'], linestyles=['--', '-', '--'],
                    levels=[-1, 0, 1])
       
       
            
        
        #为每张图添加分类的分数   
        ax_k.text(0.95, 0.06, ('%.2f' % score).lstrip('0')
                , size=15
                , bbox=dict(boxstyle='round', alpha=0.8, facecolor='white')
                	#为分数添加一个白色的格子作为底色
                , transform=ax_k.transAxes #确定文字所对应的坐标轴,就是ax子图的坐标轴本身
                , horizontalalignment='right' #位于坐标轴的什么方向
               )
   
plt.tight_layout()
plt.show()

在这里插入图片描述

Sample 2 样本不均衡

  对于分类问题,永远都逃不过的一个痛点就是样本不均衡问题。样本不均衡是指在一组数据集中,标签的一类天生占有很大的比例,但我们有着捕捉出某种特定的分类的需求的状况。比如,我们现在要对潜在犯罪者和普通人进行 分类,潜在犯罪者占总人口的比例是相当低的,也许只有2%左右,98%的人都是普通人,而我们的目标是要捕获 出潜在犯罪者。这样的标签分布会带来许多问题。
  首先,分类模型天生会倾向于多数的类,让多数类更容易被判断正确,少数类被牺牲掉。因为对于模型而言,样本量越大的标签可以学习的信息越多,算法就会更加依赖于从多数类中学到的信息来进行判断。如果我们希望捕获少数类,模型就会失败。其次,模型评估指标会失去意义。这种分类状况下,即便模型什么也不做,全把所有人都当 成不会犯罪的人,准确率也能非常高,这使得模型评估指标accuracy变得毫无意义,根本无法达到我们的“要识别 出会犯罪的人”的建模目的。
  所以现在,我们首先要让算法意识到数据的标签是不均衡的,通过施加一些惩罚或者改变样本本身,来让模型向着
  捕获少数类的方向建模。然后,我们要改进我们的模型评估指标,使用更加针对于少数类的指标来优化模型。
  要解决第一个问题,我们在逻辑回归中已经介绍了一些基本方法,比如上采样下采样。但这些采样方法会增加样本的总数,对于支持向量机这个样本总是对计算速度影响巨大的算法来说,我们完全不想轻易地增加样本数量。况 且,支持向量机中地决策仅仅决策边界的影响,而决策边界又仅仅受到参数C和支持向量的影响,单纯地增加样本 数量不仅会增加计算时间,可能还会增加无数对决策边界无影响的样本点。因此在支持向量机中,我们要大力依赖 我们调节样本均衡的参数:SVC类中的class_weight和接口fit中可以设定的sample_weight。
  在逻辑回归中,参数class_weight默认None,此模式表示假设数据集中的所有标签是均衡的,即自动认为标签的 比例是1:1。所以当样本不均衡的时候,我们可以使用形如{“标签的值1”:权重1,“标签的值2”:权重2}的字典来 输入真实的样本标签比例,来让算法意识到样本是不平衡的。或者使用”balanced“模式,直接使用 n_samples/(n_classes * np.bincount(y))作为权重,可以比较好地修正我们的样本不均衡情况。

SVC的参数:class_weight
  可输入字典或者"balanced”,可不填,默认None 对SVC,将类i的参数C设置为class_weight [i] * C。如果没有给出 具体的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))

SVC的接口fit的参数:sample_weight
  数组,结构为 (n_samples, ),必须对应输入fit中的特征矩阵的每个样本
每个样本在fit时的权重,让权重 * 每个样本对应的C值来迫使分类器强调设定的权重更大的样本。通常,较大的权 重加在少数类的样本上,以迫使模型向着少数类的方向建模

  通常来说,这两个参数我们只选取一个来设置。如果我们同时设置了两个参数,则C会同时受到两个参数的影响, 即 class_weight中设定的权重 * sample_weight中设定的权重 * C

  我们接下来就来看看如何使用这个参数。
  首先,我们来自建一组样本不平衡的数据集。我们在这组数据集上建两个SVC模型,一个设置有class_weight参 数,一个不设置class_weight参数。我们对两个模型分别进行评估并画出他们的决策边界,以此来观察 class_weight带来的效果。

  首先导入一些包

import numpy as np
import matplotlib.pyplot as plt
from sklearn import svm
from sklearn.datasets import make_blobs

  构造两个样本不均衡数据,centers表示两个数据的中心点,clusters_std 表示两个类别的方差,一般方差越大样本越分散

class_1 = 500
class_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)
print(X.shape) #(550,2)

  样本可视化

plt.scatter(X[:,0],X[:,1],c = y,s = 10 ,cmap = "rainbow")

在这里插入图片描述
  使用线性分类器,惩罚系数为1,不设定class_weight

#不设定class_weight
clf = svm.SVC(kernel = 'linear',C=1.0)
clf.fit(X,y)

  设定class_weight

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

  给两个模型分别打分看看,这个分数是accuracy准确度,做样本均衡之后,我们的准确率下降了,没有样本均衡的准确率更高

print(clf.score(X,y)) #0.9418181818181818
print(wclf.score(X,y)) #0.9127272727272727

  画出图像

plt.figure(figsize=(13,10))
# plt.scatter(X[:,0],X[:,1],c=y,cmap = "rainbow",s = 10)
red = plt.scatter(X[:,0][y == 1],X[:,1][y == 1],c='red',s = 10,label = 'xx')
darkviolet = plt.scatter(X[:,0][y == 0],X[:,1][y == 0],c='darkviolet',s = 10,label = 'bb')

ax = plt.gca()

xlim = ax.get_xlim()
ylim = ax.get_ylim()

xx = np.linspace(xlim[0],xlim[1],30)
yy = np.linspace(ylim[0],ylim[1],30)
YY,XX = np.meshgrid(yy,xx)
xy = np.vstack([XX.ravel(),YY.ravel()]).T
print(xy)
Z_clf = clf.decision_function(xy).reshape(XX.shape)
a = ax.contour(XX,YY,Z_clf,colors = 'black',levels=[0], alpha=0.5, linestyles=['-'])


Z_wclf = wclf.decision_function(xy).reshape(XX.shape)
b = ax.contour(XX, YY, Z_wclf, colors='red', levels=[0], alpha=0.5, linestyles=['-'])

#第三步:画图例
# legend() 只能有一个,下面那个会覆盖上面那个legend
plt.legend([a.collections[0], b.collections[0],red,darkviolet], 
           ["non weighted", "weighted","small","more"],
           loc="upper right")


plt.show()

在这里插入图片描述

   如果都使用高斯径向基核函数
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值