《Python数据科学手册》-支持向量机学习笔记

一、支持向量机的由来

'''
支持向量机是有监督学习算法,即可用于分类,也可用于回归。
'''

import numpy as np
import matplotlib.pyplot as plt
from scipy import stats
import seaborn as sns
sns.set()

#一、支持向量机的由来
'''
判别分类的方法:不是为每类数据建模,而是用一条分割线(二维空间中的直线或曲线)
或者流行体(多维空间中的曲线、曲面等概念的推广)将各种类型分开。

这个线性判别分类器尝试画一条将数据分成两部分的直线,构成一个分类模型。
立马会发现一个问题:在这两种类型之间,有不止一条直线可以将它们完美分割。
虽然三种不同的分割器都能完美地判别这些样本,但是选择不同的分割线,可能会使新的数据点(“X”点)分配到不同的标签。
'''

from sklearn.datasets.samples_generator import make_blobs
X, y = make_blobs(n_samples = 50, centers = 2, random_state = 0, cluster_std = 0.60)
plt.scatter(X[:,0], X[:,1], c = y, s = 30, cmap = 'autumn')
plt.show()

xfit = np.linspace(-1, 3.5)
plt.scatter(X[:,0], X[:,1], c = y, s = 30, cmap = 'autumn')
plt.plot([0.6], [2.1], 'x', color = 'red', markeredgewidth = 2, markersize = 10)

for m, b in [(1, 0.65), (0.5, 1.6), (-0.2, 2.9)]:
    plt.plot(xfit, m * xfit + b, '-k')
plt.xlim(-1, 3.5)
plt.show()

结果1:
在这里插入图片描述
结果2:
在这里插入图片描述

二、支持向量机:边界最大化

#二、支持向量机:边界最大化
'''
支持向量机其实就是一个边界最大化评估器,直观解释是:不再画一条细线来区分分类型,而是画一条到最近点边界、有宽度的线条。
'''
xfit = np.linspace(-1, 3.5)
plt.scatter(X[:,0], X[:,1], c = y, s = 20, cmap = 'autumn')
for m, b, d in [(1,0.65,0.33),(0.5,1.6,0.55),(-0.2,2.9,0.2)]:
    yfit = m * xfit + b
    plt.plot(xfit, yfit, '-k')
    plt.fill_between(xfit, yfit - d, yfit + d, edgecolor = 'none', color = '#AAAAAA', alpha = 0.4)
plt.xlim(-1, 3.5)
plt.show()

结果:
在这里插入图片描述

1.拟合支持向量机

1.拟合支持向量机
from sklearn.svm import SVC
model = SVC(kernel = 'linear', C = 1E10)    #该例中,使用线性核函数;C设置为一个很大的数,是为了硬化边界
model.fit(X, y)

'''
为实现更好地可视化效果,创建一个辅助函数画出SVM的决策边界。
这就是两类数据间隔最大的分割线。
图中,正好落在边界线上的点是拟合的关键支撑点,被称为支持向量,支持向量机算法也因此得名。
'''
def plot_svc_decision_function(model, ax = None, plot_support = True):
    """画二维SVC的决策函数"""
    if ax is None:
        ax = plt.gca()
    xlim = ax.get_xlim()
    ylim = ax.get_ylim()

    #创建评估模型的网格
    x = np.linspace(xlim[0], xlim[1], 30)
    y = np.linspace(ylim[0], ylim[1], 30)
    Y, X = np.meshgrid(y,x)
    xy = np.vstack([X.ravel(), Y.ravel()]).T
    P = model.decision_function(xy).reshape(X.shape)

    #画决策边界和边界
    ax.contour(X, Y, P, colors = 'k', levels = [-1, 0, 1], alpha = 0.5, linestyles = ['--', '-', '--'])

    #画支持向量
    if plot_support:
        ax.scatter(model.support_vectors_[:,0],
                   model.support_vectors_[:,1],
                   s = 300, linewidth = 1, facecolors = 'none')
    ax.set_xlim(xlim)
    ax.set_ylim(ylim)

plt.scatter(X[:,0], X[:,1], c = y, s = 20, cmap = 'autumn')
plot_svc_decision_function(model)
plt.show()

print(model.support_vectors_)   #支持向量的坐标

'''
分类器能够成功拟合的关键因素,就是这些支持向量的位置——任何在正确分类一侧远离边界线的点都不会影响拟合效果。
从技术的角度解释的话,因为这些点不会对拟合模型的损失函数产生任何影响,所以只要它们没有跨越边界线,它们的位置和数量就无关紧要。
例如,分别画出数据集前60个点和前120个点的拟合效果,进行对比。
'''
def plot_svm(N = 10, ax = None):
    X, y = make_blobs(n_samples=N, centers = 2, random_state = 0, cluster_std = 0.60)
    X = X[:N]
    y = y[:N]
    model = SVC(kernel = 'linear', C=1E10)
    model.fit(X, y)

    ax = ax or plt.gca()
    ax.scatter(X[:,0], X[:,1], c = y, s = 20, cmap = 'autumn')
    ax.set_xlim(-1,4)
    ax.set_ylim(-1,6)
    plot_svc_decision_function(model, ax)

fig, ax = plt.subplots(1, 2, figsize = (16,6))
fig.subplots_adjust(left = 0.0625, right = 0.95, wspace = 0.1)
for axi, N in zip(ax, [60,120]):
    plot_svm(N, axi)
    axi.set_title('N = {0}'.format(N))
plt.show()

结果1:
在这里插入图片描述
结果2:

[[0.44359863 3.11530945]
 [2.33812285 3.43116792]
 [2.06156753 1.96918596]]

结果3:
在这里插入图片描述

2.超越线性边界:核函数SVM模型

#2.超越线性边界:核函数SVM模型
'''
将SVM模型与核函数组合使用,功能会非常强大。
这里,将数据投影到多项式和高斯基函数定义的高维空间中,从而实现线性分类器拟合非线性关系。
为应用核函数,引入一些非线性可分额数据。
'''
from sklearn.datasets.samples_generator import make_circles
X, y = make_circles(100, factor = .1, noise = .1)
clf = SVC(kernel = 'linear').fit(X,y)
plt.scatter(X[:,0], X[:, 1], c = y, s = 20, cmap = 'autumn')
plot_svc_decision_function(clf, plot_support = False)
plt.show()

'''
显然,这里需要用非线性判别方法来分割数据。
将数据投影到高维空间的一种简单的投影方法,是计算一个以数据圆圈为中心的径向基函数。
通过三维图来可视化新增的维度。
'''

r = np.exp(-(X ** 2).sum(1))
from mpl_toolkits import mplot3d
def plot_3D(elev = 30, azim = 30, X = X, y = y):
    ax = plt.subplot(projection = '3d')
    ax.scatter3D(X[:,0], X[:,1], r, c = y ,s = 20, cmap = 'autumn')
    ax.view_init(elev = elev, azim = azim)
    ax.set_xlabel('x')
    ax.set_ylabel('y')
    ax.set_zlabel('r')

import ipywidgets
from ipywidgets import interact, fixed
interact(plot_3D,elev = [-90,90],azip = (-180,180),X = fixed(X),y = fixed(y))
plt.show()

'''
增加新维度后,数据变成线性可分的。如果现在画一个分割平面,例如r=0.7,即可将数据分割。
还需要仔细选择和优化投影方式,如果不能将径向基函数集中到正确位置,就得不到干净、可分割的结果。
选择基函数比较困难,需要让模型自动指出最适合的基函数。

一种策略是,计算基函数在数据集上每个点的变换结果,让SVM算法从所有结果中筛选出最优解。
这种基函数变换方式被称为核变换,是基于每对数据点之间的相似度(或者核函数)计算的。

这种策略的问题是,如果将N个数据点投影到N维空间,当N不断增大的时候就会出现维度灾难,计算量巨大。
但是由于核函数技巧提供的小程序可以隐式计算和变幻数据的拟合,不需要建立完全的N维核函数投影空间。
'''

clf = SVC(kernel = 'rbf', C = 1E6)
clf.fit(X, y)
plt.scatter(X[:,0], X[:,1], c = y, s = 20, cmap = 'autumn')
plot_svc_decision_function(clf)
plt.scatter(clf.support_vectors_[:,0], clf.support_vectors_[:,1], s = 300, lw = 1, facecolors = 'none')
plt.show()

结果1:
在这里插入图片描述
结果2:
在这里插入图片描述

3.SVM优化:软化边界

#3.SVC优化:软化边界
'''
到目前为止,介绍的模型都是在处理非常干净的数据集,里面都有非常完美的决策边界。但是,当数据有一些重叠时,应该软化边界。

'''
X, y = make_blobs(n_samples=100, centers=2, random_state=0,cluster_std=1.2)
plt.scatter(X[:,0], X[:,1], c = y, s = 20, cmap = 'autumn')
plt.show()

'''
SVM实现一些修正因子来“软化”边界。为了取得更好的拟合效果,它允许一些点位于边界线之内。
边界线的硬度可以通过设置超参数进行控制,通常是C。
如果C很大,边界就会很硬,数据点便不能在边界内“生存”;
如果C很小,边界线比较软,有一些数据就可以穿越边界线。
'''

X, y = make_blobs(n_samples=100,centers=2, random_state=0,cluster_std=0.8)
fig, ax = plt.subplots(1, 2, figsize = (16,6))
fig.subplots_adjust(left = 0.0625, right = 0.95, wspace = 0.1)

for axi, C in zip(ax,[10,0.1]):
    model = SVC(kernel = 'linear', C = C).fit(X,y)
    axi.scatter(X[:,0], X[:,1], c = y, s = 20, cmap = 'autumn')
    plot_svc_decision_function(model, axi)
    axi.scatter(model.support_vectors_[:,0],
                model.support_vectors_[:,1],
                s = 300, lw = 1, facecolors = 'none')
    axi.set_title('C = {0}'.format(C),size = 14)
plt.show()
"""
参数C的最优值视数据集的具体情况而定,通过交叉检验或者类似的程序进行计算
"""

结果1:
在这里插入图片描述
结果2:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值