前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python快速实战机器学习(5) 支持向量机

Python快速实战机器学习(5) 支持向量机

作者头像
HuangWeiAI
发布2019-11-07 11:42:19
4790
发布2019-11-07 11:42:19
举报
文章被收录于专栏:浊酒清味

引言

机器学习是如今人工智能时代背景下一个重要的领域。这个“Python快速实战机器学习”系列,用Python代码实践机器学习里面的算法,旨在理论和实践同时进行,快速掌握知识。

前面课程:

Python快速实战机器学习(1) 教材准备 Python快速实战机器学习(2) 数据预处理

Python快速实战机器学习(3) 线性分类器

Python快速实战机器学习(4) 逻辑回归

概要

1、初步认识支持向量机;

2、了解松弛变量及其用处;

3、学会使用sklearn调用线性SVM。

支持向量机介绍

1

初步认识

支持向量机的英文是Support Vector Machine,缩写为SVM,在接下来的介绍中我们都用SVM来表示支持向量机。

SVM主要用于解决模二分类问题:如下图中的左图,有红色圆圈以及绿色十字标注的两组数据,我们希望将它们分开。然而将两类数据点分开的直线显然不止一条,图中画出来三条线,看上去都是可以工作的,那么到底哪一条才是最好的分类呢?SVM给了一个要求:我们的优化目标是最大化间隔(margin)。

如上图中右图所示,间隔定义为两个分隔超平面(决策界,图中的两条细线)的距离,那些最靠近超平面的训练样本也被称为支持向量(suppor vectors)。从表面上看,我们优化的对象似乎是这个决策面的方向和位置。但实际上最优决策面的方向和位置完全取决于选择哪些样本作为支持向量,也就是图上面的穿过决策面(Decision boundary)的红色和绿色样本。

2

最大化间隔

最大化决策界的间隔,这么做的原因是间隔大的决策界趋向于含有更小的泛化误差,而间隔小的决策界更容易过拟合。为了更好地理解间隔最大化,我们先认识一下那些和决策界平行的正超平面和负超平面,他们可以表示为

这里为什么取正负1,个人理解是找到一个单位1用来作为一个标准,其实取其他一个数字也是可以的,可能是为了方便就取1了。

用(1)减去(2)可以得到:

对两边同时除以||W||,实现归一化,

这里引入||W||是因为,让等式左边表示成一个距离,大家可以取验证任意一点x到分界线(图中粗虚线)的距离的形式就是带有||W||作为分母的形式,其中,

我们有了间隔的计算公式,好像已经可以开始优化了,但是别忘了分类对于这个问题的限制:

也就是说被分类的两类数据都要在决策面的两边。

到现在为止,我们获得了SVM的一个完整描述,最大化间隔的同时,受到数据要在分界面两边的约束。关于带约束的优化问题,数学界早就开发了一套成熟方法处理,大家可以参考这篇文章:

https://zhuanlan.zhihu.com/p/24638007

松弛变量

虽然我们不想深挖SVM背后的数学概念,但还是有必要简短介绍一下松弛变量(slack variable)。它是由Vladimir Vapnik在1995年引入的,借此提出了软间隔分类(soft-margin)。引入松弛变量的动机是原来的线性限制条件在面对非线性可分数据时需要松弛,这样才能保证算法收敛。

松弛变量值为正,添加到线性限制条件即可:

现在的目标函数变成,

注意1/2||W||是因为最大化2/||W||,等价于最小化1/2||W||,所以我们的目标函数是需要最小化的。使用变量C,我们可以控制错分类的惩罚量。这个概念和正则化相关,如果增大C的值会增加bias而减小模型的方差。我们用一张图来给出C值不同带来的结果:

sklearn训练SVM

我们已经学会了线性SVM的基本概念,下面使用sklearn训练一个模型:

代码语言:javascript
复制
from matplotlib.colors import ListedColormap
import matplotlib.pyplot as plt
import warnings


def versiontuple(v):
    return tuple(map(int, (v.split("."))))


def plot_decision_regions(X, y, classifier, test_idx=None, resolution=0.02):

    # setup marker generator and color map
    markers = ('s', 'x', 'o', '^', 'v')
    colors = ('red', 'blue', 'lightgreen', 'gray', 'cyan')
    cmap = ListedColormap(colors[:len(np.unique(y))])

    # plot the decision surface
    x1_min, x1_max = X[:, 0].min() - 1, X[:, 0].max() + 1
    x2_min, x2_max = X[:, 1].min() - 1, X[:, 1].max() + 1
    xx1, xx2 = np.meshgrid(np.arange(x1_min, x1_max, resolution),
                           np.arange(x2_min, x2_max, resolution))
    Z = classifier.predict(np.array([xx1.ravel(), xx2.ravel()]).T)
    Z = Z.reshape(xx1.shape)
    plt.contourf(xx1, xx2, Z, alpha=0.4, cmap=cmap)
    plt.xlim(xx1.min(), xx1.max())
    plt.ylim(xx2.min(), xx2.max())

    for idx, cl in enumerate(np.unique(y)):
        plt.scatter(x=X[y == cl, 0], 
                    y=X[y == cl, 1],
                    alpha=0.6, 
                    c=cmap(idx),
                    edgecolor='black',
                    marker=markers[idx], 
                    label=cl)

    # highlight test samples
    if test_idx:
        # plot all samples
        if not versiontuple(np.__version__) >= versiontuple('1.9.0'):
            X_test, y_test = X[list(test_idx), :], y[list(test_idx)]
            warnings.warn('Please update to NumPy 1.9.0 or newer')
        else:
            X_test, y_test = X[test_idx, :], y[test_idx]

        plt.scatter(X_test[:, 0],
                    X_test[:, 1],
                    c='',
                    alpha=1.0,
                    edgecolor='black',
                    linewidths=1,
                    marker='o',
                    s=55, label='test set')
代码语言:javascript
复制
from sklearn import datasets
import numpy as np

iris = datasets.load_iris()
X = iris.data[:, [2, 3]]
y = iris.target


from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.3, random_state=0)

from sklearn.preprocessing import StandardScaler

sc = StandardScaler()
sc.fit(X_train)
X_train_std = sc.transform(X_train)
X_test_std = sc.transform(X_test)

X_combined_std = np.vstack((X_train_std, X_test_std))
y_combined = np.hstack((y_train, y_test))

from sklearn.svm import SVC

svm = SVC(kernel='linear', C=1.0, random_state=0)
svm.fit(X_train_std, y_train)


plot_decision_regions(X_combined_std, y_combined,
                      classifier=svm, test_idx=range(105, 150))
plt.xlabel('petal length [standardized]')
plt.ylabel('petal width [standardized]')
plt.legend(loc='upper left')
plt.tight_layout()
# plt.savefig('./figures/logistic_regression.png', dpi=300)
plt.show()

运行结果:

在解决现实的分类问题时,线性逻辑回归和线性SVM通常效果近似。逻辑回归目标是最大化训练集的条件似然,使得它更易受奇异值影响。SVM只关心那些离决策界最近的点(即,支持向量)。另一方面,逻辑回归的优点是易于实现,特别是并行化实现。此外,面对流式数据,逻辑回归的易于更新的特点也很明显。

SVM之所以受欢迎度这么高,另一个重要的原因是它很容易核化(kernelized),能够解决非线性分类问题。我们把这部分内容留到下一课。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-11-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Python与机器学习之路 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档