机器学习--SVM支持向量机

支持向量机的直观理解

支持向量机是监督学习算法的一种,有时也被称为大间距分类器。法广泛的应用于工业界和学术界。
接下来将用一个例子来说明:
在这里插入图片描述
如图,对于这样一个数据集,其中既有正样本,也有负样本,可以看出这个数据集是线性可分的,也就是,存在一条直线把正负样本分开。当然,这样的直线有很多条 ,比如:
在这里插入图片描述
这些直线都可以将正负样本分开,但是绿线和粉线多多少少看起来不是很自然,所以支持向量机的作用就是在这些直线中选择这个黑色的决策边界。之所以选择黑线,是因为其决策界和训练样本之间有更大的最短距离,如图:
在这里插入图片描述
但是,有时数据集会出现一些异常点,如下图:
在这里插入图片描述
如果为了将样本用最大间距分开,最终就会得到这条粉线,但是仅仅基于一个异常点和样本,就将决策界从黑线变成粉线,显然是不明智的。所以支持向量机为了应对这种情况,会进行正则化参数C,C的作用类似于1/λ,当C不是很大的时候,它可以忽略掉一些异常点的影响,得到更好的决策边界。
上述描述的只是其中一种情况,还有一种需要通过使用高级数的多项式模型来解决无法用直线进行分隔的分类问题,如图:
在这里插入图片描述
为了用SVM找出一个非线性的决策边界,我们首先要实现高斯核函数。我可以把高斯核函数想象成一个相似度函数,用来测量一对样本的距离
这里用sklearn自带的svm中的核函数即可。
在这里插入图片描述

代码实现

一.线性分类
1.导入数据,可视化画出散点图,根据y的0和1区分颜色。其中,大多数SVM的库会自动帮你添加额外的特征 x 0已经 θ 0,所以无需手动添加。

mat = loadmat('./data/ex6data1.mat')
print(mat.keys())
# dict_keys(['__header__', '__version__', '__globals__', 'X', 'y'])
X = mat['X']
y = mat['y']

def plotData(X, y):
    plt.figure(figsize=(8,5))
    plt.scatter(X[:,0], X[:,1], c=y.flatten(), cmap='rainbow')  #X第0列为x坐标,第1列为y坐标,c颜色按照y的0和1来区分。根据'rainbow'对应数字颜色
    plt.xlabel('X1')
    plt.ylabel('X2')
    plt.legend()
plotData(X, y)
plt.show()

在这里插入图片描述
2.画出网格线和边界线,通过改变C值,观察边界线的变化。
其中:
np.r_是按列连接两个矩阵,就是把两矩阵上下相加,要求列数相等。
np.c_是按行连接两个矩阵,就是把两矩阵左右相加,要求行数相等。

def plotBoundary(clf, X):   #clf是指训练好的模型(已经求好theta)
    '''plot decision bondary'''
    x_min, x_max = X[:,0].min()*1.2, X[:,0].max()*1.1
    y_min, y_max = X[:,1].min()*1.1,X[:,1].max()*1.1
    xx, yy = np.meshgrid(np.linspace(x_min, x_max, 500),
                         np.linspace(y_min, y_max, 500))
    Z = clf.predict(np.c_[xx.ravel(), yy.ravel()]) 
    Z = Z.reshape(xx.shape)
    plt.contour(xx, yy, Z)
#定义SVM的C值,然后根据X和y训练两个模型,包含在clfs中
models = [svm.SVC(C, kernel='linear') for C in [1, 100]]
clfs = [model.fit(X, y.ravel()) for model in models]    #flatten是返回一份拷贝,对原始矩阵没影响。ravel对原始有影响
#调用定义的函数画出边界线图
title = ['SVM Decision Boundary with C = {} (Example Dataset 1'.format(C) for C in [1, 100]]
for model,title in zip(clfs,title): 
    plt.figure(figsize=(8,5))
    plotData(X, y)
    plotBoundary(model, X)
    plt.title(title)
    plt.show()

在这里插入图片描述
在这里插入图片描述
可以从上图看到,当C比较小时模型对误分类的惩罚增大,比较严格,误分类少,间隔比较狭窄。

当C比较大时模型对误分类的惩罚增大,比较宽松,允许一定的误分类存在,间隔较大。
二.非线性分类
(1)数据二
1.导入数据,可视化画出散点图。

mat = loadmat('./data/ex6data2.mat')    
X2 = mat['X']
y2 = mat['y']
plotData(X2, y2)
plt.show()

在这里插入图片描述
2.计算高斯核函数

def gaussKernel(x1, x2, sigma):
    return np.exp(- ((x1 - x2) ** 2).sum() / (2 * sigma ** 2))

gaussKernel(np.array([1, 2, 1]),np.array([0, 4, -1]), 2.)  # 0.32465246735834974

3.通过高斯核函数画出边界图。

sigma = 0.1
gamma = np.power(sigma,-2.)/2
modle = svm.SVC(C=1, kernel='rbf', gamma=gamma)  #
clf = modle.fit(X2, y2.flatten())
plotData(X2, y2)
plotBoundary(modle, X2)  #这里用modle或clf都行,只要之前用modle.fit训练过就行了。
plt.show()

在这里插入图片描述
(2)数据三
1.导入数据,可视化画出散点图。

mat3 = loadmat('data/ex6data3.mat')
X3, y3 = mat3['X'], mat3['y']
Xval, yval = mat3['Xval'], mat3['yval']	#指测试验证集,用于计算f1score来评估模型好坏
plotData(X3, y3)
plt.show()

在这里插入图片描述
2.接下来选一个合适的C和sigma做准备

Cvalues = (0.01, 0.03, 0.1, 0.3, 1., 3., 10., 30.)
sigmavalues = Cvalues
best_pair, best_score = (0, 0), 0
	#找到最适C和sigma
for C in Cvalues:
    for sigma in sigmavalues:
        gamma = np.power(sigma,-2.)/2
        model = svm.SVC(C=C,kernel='rbf',gamma=gamma)
        model.fit(X3, y3.flatten())
        this_score = model.score(Xval, yval)
        if this_score > best_score:
            best_score = this_score
            best_pair = (C, sigma)
#打印出找到的结果
print('best_pair={}, best_score={}'.format(best_pair, best_score))
# best_pair=(1.0, 0.1), best_score=0.965	

3.#用得到的参数训练模型,画出边界线

model = svm.SVC(C=1., kernel='rbf', gamma = np.power(.1, -2.)/2)
model.fit(X3, y3.flatten())
plotData(X3, y3)
plotBoundary(model, X3)
plt.show()

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值