SVM 算法

支持向量机

支持向量机(support vector machine,SVM)是非常强大、灵活的有监督学习算法,既可用于分类,也可用于回归。在本节中,我们将介绍支持向量机的原理,并用它解决分类问题。首先还是导入需要用的程序库:

%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
from scipy import stats
#用Seaborn画图
import seaborn as sns; sns.set()


这里将介绍判别分类
方法:不再为每类数据建模,而是用一条分割线(二维空间中的直线或曲线)或者流形体
(多维空间中的曲线、曲面等概念的推广)将各种类型分割开。
下面用一个简单的分类示例来演示,其中两种类型的数据可以被清晰地分割开

%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
from scipy import stats
# 用Seaborn画图
import seaborn as sns; sns.set()
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=50, cmap='autumn');
E:\anaconda3\lib\site-packages\sklearn\utils\deprecation.py:143: FutureWarning: The sklearn.datasets.samples_generator module is  deprecated in version 0.22 and will be removed in version 0.24. The corresponding classes / functions should instead be imported from sklearn.datasets. Anything that cannot be imported from sklearn.datasets is now part of the private API.
  warnings.warn(message, FutureWarning)

在这里插入图片描述

这个线性判别分类器尝试画一条将数据分成两部分的直线,这样就构成了一个分类模型。
对于上图的二维数据来说,这个任务其实可以手动完成。但是我们马上发现一个问题:在
这两种类型之间,有不止一条直线可以将它们完美分割。

xfit = np.linspace(-1, 3.5)
plt.scatter(X[:, 0], X[:, 1], c=y, s=50, 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);

在这里插入图片描述

虽然这三个不同的分割器都能完美地判别这些样本,但是选择不同的分割线,可能会让新
的数据点分配到不同的标签。显然,“画一条分割不同类型
的直线”还不够,我们需要进一步思考。

支持向量机:边界最大化

支持向量机提供了改进这个问题的方法,它直观的解释是:不再画一条细线来区分类
型,而是画一条到最近点边界、有宽度的线条。

xfit = np.linspace(-1, 3.5)
plt.scatter(X[:, 0], X[:, 1], c=y, s=50, 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);

在这里插入图片描述

在支持向量机中,选择边界最大的那条线是模型最优解。支持向量机其实就是一个边界最大化评估器。

1.拟合支持向量机

来看看这个数据的真实拟合结果:用Scikit-Learn 的支持向量机分类器在数据上训练一个
SVM 模型。这里用一个线性核函数,并将参数C 设置为一个很大的数(后面会介绍这些设
置的意义):

from sklearn.svm import SVC # "Support vector classifier"
model = SVC(kernel='linear', C=1E10)
model.fit(X, y)
SVC(C=10000000000.0, kernel='linear')

为了实现更好的可视化分类效果,创建一个辅助函数画出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=50, cmap='autumn')
plot_svc_decision_function(model);

在这里插入图片描述

这就是两类数据间隔最大的分割线。你会发现有一些点正好就在边界线上,在下图 中
用黑圆圈表示。这些点是拟合的关键支持点,被称为支持向量,支持向量机算法也因此得
名。在Scikit-Learn 里面,支持向量的坐标存放在分类器的support_vectors_ 属性中:

model.support_vectors_
array([[0.44359863, 3.11530945],
       [2.33812285, 3.43116792],
       [2.06156753, 1.96918596]])

分类器能够成功拟合的关键因素,就是这些支持向量的位置——任何在正确分类一侧远
离边界线的点都不会影响拟合结果!从技术角度解释的话,是因为这些点不会对拟合模
型的损失函数产生任何影响,所以只要它们没有跨越边界线,它们的位置和数量就都无
关紧要。
例如,可以分别画出数据集前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=50, 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))

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RowYYAzU-1638086107264)(output_13_0.png)]

我们在左图中看到的是前60 个训练样本的模型和支持向量。在右图中,虽然我们画了前
120 个训练样本的支持向量,但是模型并没有改变:左图中的3 个支持向量仍然适用于右
图。这种对远离边界的数据点不敏感的特点正是SVM 模型的优点之一。
如果你正在运行Notebook,可以用IPython 的交互组件动态观察SVM 模型的这个特点:

from ipywidgets import interact, fixed

interact(plot_svm, N=[10,50,100,200,400,1000], ax=fixed(None));
interactive(children=(Dropdown(description='N', options=(10, 50, 100, 200, 400, 1000), value=10), Output()), _…

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

将SVM 模型与核函数组合使用,功能会非常强大。我们在5.6 节介绍基函数回归时介绍过一些核函数。那时,我们将数据投影到多项式和高斯基函数定义的高维空间中,从而实现用线性分类器拟合非线性关系。
在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=50, cmap='autumn')
plot_svc_decision_function(clf, plot_support=False);

在这里插入图片描述

显然,这里需要用非线性判别方法来分割数据。例如,一种简单的投
影方法就是计算一个以数据圆圈(middle clump)为中心的径向基函数:

r = np.exp(-(X ** 2).sum(1))

可以通过三维图来可视化新增的维度——如果你正在运行Notebook,就可以用滑块变换观
察角度:

from mpl_toolkits import mplot3d
from ipywidgets import interact, fixed

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=50, cmap='autumn')
    ax.view_init(elev=elev, azim=azim)
    ax.set_xlabel('x1')
    ax.set_ylabel('x2')
    ax.set_zlabel('r')
    
interact(plot_3D, elev=(-90,90), azip=(-180,180), X=fixed(X), y=fixed(y))
interactive(children=(IntSlider(value=30, description='elev', max=90, min=-90), IntSlider(value=30, descriptio…





<function __main__.plot_3D(elev=30, azim=30, X=array([[-5.61706135e-02, -1.91757887e-02],
       [-3.24732855e-02,  1.85784593e-01],
       [-8.34778451e-02,  1.63126655e-01],
       [ 4.88316811e-03,  6.81508121e-02],
       [ 1.88120125e-01,  1.01202439e-02],
       [-9.24798126e-01,  3.93319002e-01],
       [ 2.98673214e-02,  1.12220257e-01],
       [-9.33903161e-01, -7.25906019e-01],
       [ 1.13785077e-01,  2.41229726e-01],
       [ 6.78684592e-01, -7.63475049e-01],
       [ 7.77233896e-02,  1.06533516e-01],
       [ 5.39739473e-01, -7.93135623e-01],
       [-9.54433932e-02, -2.52511525e-02],
       [-9.67876854e-01, -4.13583329e-01],
       [ 9.94196096e-01, -2.42882635e-01],
       [-1.27347610e-01,  1.04114172e-01],
       [-1.36814783e-01,  8.20177861e-02],
       [-2.09592206e-01, -9.16765257e-01],
       [-1.14597190e-02, -1.17949877e-02],
       [ 7.95014208e-01, -8.13113364e-01],
       [-4.91262045e-02, -4.33910038e-02],
       [-9.22485045e-02,  3.55221030e-02],
       [ 7.84815145e-02, -1.22921933e-01],
       [ 1.76821029e-02,  1.15214114e+00],
       [-1.05900323e+00, -2.53303895e-01],
       [ 2.15163839e-01,  5.80610131e-02],
       [-6.76190117e-02,  4.26077146e-02],
       [-1.67978685e-01, -4.02186472e-02],
       [ 4.28001663e-05, -6.98594415e-02],
       [ 7.77284598e-01,  5.21271083e-01],
       [-9.64379469e-03,  1.95547099e-01],
       [ 2.24306831e-01, -1.04671812e+00],
       [-3.12124595e-02, -1.67838209e-02],
       [ 3.68501771e-01,  1.07950178e+00],
       [-1.57760811e-01, -9.18202668e-02],
       [-3.90698563e-01,  1.06957888e+00],
       [-4.72686618e-02, -5.18980575e-02],
       [-8.26677199e-02,  8.43784712e-02],
       [ 2.63302819e-01, -4.83233738e-02],
       [ 2.12089190e-01, -9.32226929e-02],
       [ 6.24169305e-01,  8.23429663e-01],
       [ 1.63485539e-01, -3.28810918e-02],
       [ 5.41091106e-01,  7.90204843e-01],
       [ 9.28014579e-02, -8.71505013e-01],
       [ 2.67106302e-01, -1.02325022e+00],
       [ 4.16526261e-02, -5.59186555e-02],
       [ 1.09454320e+00,  1.49198601e-02],
       [ 9.00094689e-01, -3.95140378e-01],
       [ 2.72264784e-02, -1.86920081e-01],
       [ 2.21751048e-01,  2.63053069e-02],
       [ 2.27910639e-01, -8.75968297e-02],
       [-8.25540328e-02,  1.57331194e-01],
       [ 5.09785794e-01, -1.09760031e+00],
       [ 9.39007013e-01,  5.36068409e-02],
       [-4.65392116e-01, -8.73931995e-01],
       [-7.24910365e-01, -7.53796011e-01],
       [-1.83318038e-01,  1.02028558e+00],
       [ 1.02214812e-01, -2.58856384e-02],
       [ 6.95003485e-03, -1.24334603e-01],
       [ 1.03549068e+00, -4.02378008e-02],
       [-1.15915425e+00,  2.91307649e-01],
       [-4.34428138e-01,  8.88369780e-01],
       [ 8.41760873e-02,  3.38849398e-02],
       [-1.99128729e-01,  8.41339639e-01],
       [-6.14729381e-01,  7.61142681e-01],
       [-1.12062508e+00,  1.25801406e-02],
       [ 3.98666815e-01, -8.50842819e-01],
       [-8.21165857e-01, -2.80405574e-01],
       [-5.75718279e-01,  9.31872289e-01],
       [-1.02142079e+00,  5.17278493e-01],
       [-4.44518201e-01, -9.24758922e-01],
       [-5.19374699e-02,  1.02721828e-01],
       [ 7.08872958e-01, -4.81867406e-01],
       [-2.33096995e-01, -2.32733908e-02],
       [ 1.31870856e-01, -1.51813572e-01],
       [-1.10660504e+00, -3.31377944e-02],
       [ 1.20969414e-01, -2.15979300e-02],
       [ 4.03106177e-02, -3.63263801e-02],
       [-6.45741599e-03, -3.74165685e-02],
       [ 1.85344268e-01, -3.71446375e-02],
       [-1.01641536e-01, -2.32750499e-02],
       [-9.05201532e-01,  6.16640720e-01],
       [-4.91533549e-02,  2.47194062e-01],
       [ 9.46702602e-01,  2.18737482e-01],
       [ 9.37495115e-01, -5.06247325e-01],
       [-3.81712748e-02,  4.11198862e-03],
       [ 1.01615435e+00,  3.94018604e-01],
       [ 7.19813746e-01,  4.97003099e-01],
       [ 1.72205681e-01,  9.09045304e-01],
       [-6.40769531e-01, -9.46126502e-01],
       [ 4.31144691e-01,  7.89412882e-01],
       [-1.11985695e-01,  1.71534587e-01],
       [-2.12194657e-02,  1.22242578e-01],
       [-7.16770280e-01,  6.99875703e-01],
       [ 6.16124161e-01,  6.46132966e-01],
       [-8.32708000e-01, -6.80375210e-01],
       [-1.31598272e-01,  1.89920315e-01],
       [-6.72098659e-01, -7.19958362e-01],
       [ 1.31784847e-01,  1.33165268e-01],
       [-1.45684274e-01, -8.82333984e-02]]), y=array([1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1,
       1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0,
       0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0,
       0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0,
       0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1], dtype=int64))>

增加新维度之后,数据变成了线性可分状态。如果现在画一个分割平面,例如r = 0.7,即
可将数据分割。
我们还需要仔细选择和优化投影方式;如果不能将径向基函数集中到正确的位置,那么就
得不到如此干净、可分割的结果。通常,选择基函数比较困难,我们需要让模型自动指出
最合适的基函数。
一种策略是计算基函数在数据集上每个点的变换结果,让SVM 算法从所有结果中筛选出
最优解。这种基函数变换方式被称为核变换,是基于每对数据点之间的相似度(或者核函
数)计算的。

这种策略的问题是,如果将N 个数据点投影到N 维空间,当N 不断增大的时候就会出现
维度灾难,计算量巨大。但由于核函数技巧http://bit.ly/2fStZeA
提供的小程序可以隐式
计算核变换数据的拟合,也就是说,不需要建立完全的N 维核函数投影空间!这个核函数
技巧内置在SVM 模型中,是使SVM 方法如此强大的充分条件。
在Scikit-Learn 里面,我们可以应用核函数化的SVM 模型将线性核转变为RBF(径向基函
数)核,设置kernel 模型超参数即可:

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

在这里插入图片描述

通过使用这个核函数化的支持向量机,我们找到了一条合适的非线性决策边界。在机器学
习中,核变换策略经常用于将快速线性方法变换成快速非线性方法,尤其是对于那些可以
应用核函数技巧的模型。

3.SVM优化:软化边界

到目前为止,我们介绍的模型都是在处理非常干净的数据集,里面都有非常完美的决策
边界。但如果你的数据有一些重叠该怎么办呢?例如,有如下所示一些数据:

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=50, cmap='autumn');

在这里插入图片描述

为了解决这个问题,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, 0.1]):
    model = SVC(kernel='linear', C=C).fit(X, y)
    axi.scatter(X[:, 0], X[:, 1], c=y, s=50, 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:.1f}'.format(C), size=14)
Text(0.5, 1.0, 'C = 0.1')

在这里插入图片描述

案例:人脸识别

我们用人脸识别案例来演示支持向量机的实战过程。这里用Wild 数据集中带标记的人脸
图像,里面包含了数千张公开的人脸照片。Scikit-Learn 内置了获取照片数据集的功能:

from sklearn.datasets import fetch_lfw_people
faces = fetch_lfw_people(min_faces_per_person=60)
print(faces.target_names)
print(faces.images.shape)
['Ariel Sharon' 'Colin Powell' 'Donald Rumsfeld' 'George W Bush'
 'Gerhard Schroeder' 'Hugo Chavez' 'Junichiro Koizumi' 'Tony Blair']
(1348, 62, 47)
fig, ax = plt.subplots(3, 5)
for i, axi in enumerate(ax.flat):
    axi.imshow(faces.images[i], cmap='bone')
    axi.set(xticks=[], yticks=[],
            xlabel=faces.target_names[faces.target[i]])

在这里插入图片描述

每个图像包含[62×47]、接近3000 像素。虽然可以简单地将每个像素作为一个特征,但
是更高效的方法通常是使用预处理器来提取更有意义的特征。这里使用主成分分析(详情
请参见5.9 节)来提取150 个基本元素,然后将其提供给支持向量机分类器。可以将这个
预处理器和分类器打包成管道:

from sklearn.svm import SVC
# from sklearn.decomposition import RandomizedPCA
from sklearn.decomposition import PCA as RandomizedPCA
from sklearn.pipeline import make_pipeline

pca = RandomizedPCA(n_components=150, whiten=True, random_state=42)
svc = SVC(kernel='rbf', class_weight='balanced')
model = make_pipeline(pca, svc)

为了测试分类器的训练效果,将数据集分解成训练集和测试集进行交叉检验:

from sklearn.model_selection import train_test_split
Xtrain, Xtest, ytrain, ytest = train_test_split(faces.data, faces.target,
    random_state=42)
Xtrain
array([[107.333336, 107.333336, 108.666664, ..., 109.      ,  96.333336,
         99.      ],
       [ 90.666664,  63.      ,  57.666668, ..., 216.33333 , 218.      ,
        218.      ],
       [134.66667 , 124.333336, 129.      , ..., 158.      , 165.      ,
        171.66667 ],
       ...,
       [ 73.333336,  53.333332,  48.666668, ...,  40.666668,  71.333336,
         80.666664],
       [ 52.      ,  94.333336, 121.333336, ..., 252.      , 251.66667 ,
        250.33333 ],
       [157.66667 , 141.66667 , 133.      , ...,  12.      ,  11.      ,
          8.333333]], dtype=float32)

通过不断调整参数C(控制边界线的硬
度)和参数gamma(控制径向基函数核的大小),确定最优模型:

from sklearn.model_selection import GridSearchCV
param_grid = {'svc__C': [1, 5, 10, 50],
            'svc__gamma': [0.0001, 0.0005, 0.001, 0.005]}
grid = GridSearchCV(model, param_grid)
%time grid.fit(Xtrain, ytrain)
print(grid.best_params_)
Wall time: 31.7 s
{'svc__C': 10, 'svc__gamma': 0.001}

最优参数最终落在了网格的中间位置。如果它们落在了边缘位置,我们可能就需要扩展网
格搜索范围,确保最优参数可以被搜索到。
有了交叉检验的模型,现在就可以对测试集的数据进行预测了:

model = grid.best_estimator_
yfit = model.predict(Xtest)

将一些测试图片与预测图片进行对比

fig, ax = plt.subplots(4, 6)
for i, axi in enumerate(ax.flat):
    axi.imshow(Xtest[i].reshape(62, 47), cmap='bone')
    axi.set(xticks=[], yticks=[])
    axi.set_ylabel(faces.target_names[yfit[i]].split()[-1],
                        color='black' if yfit[i] == ytest[i] else 'red')
fig.suptitle('Predicted Names; Incorrect Labels in Red', size=14);

在这里插入图片描述

在这个小样本中,我们的最优评估器只判断错了一张照片(最后一行中布什的照片被误判
为布莱尔)。我们可以打印分类效果报告,它会列举每个标签的统计结果,从而对评估器
的性能有更全面的认识:

from sklearn.metrics import classification_report
print(classification_report(ytest, yfit,target_names=faces.target_names))
                   precision    recall  f1-score   support

     Ariel Sharon       0.65      0.73      0.69        15
     Colin Powell       0.80      0.87      0.83        68
  Donald Rumsfeld       0.74      0.84      0.79        31
    George W Bush       0.92      0.83      0.88       126
Gerhard Schroeder       0.86      0.83      0.84        23
      Hugo Chavez       0.93      0.70      0.80        20
Junichiro Koizumi       0.92      1.00      0.96        12
       Tony Blair       0.85      0.95      0.90        42

         accuracy                           0.85       337
        macro avg       0.83      0.84      0.84       337
     weighted avg       0.86      0.85      0.85       337
from sklearn.metrics import confusion_matrix
mat = confusion_matrix(ytest, yfit)
sns.heatmap(mat.T, square=True, annot=True, fmt='d', cbar=False,
            xticklabels=faces.target_names,
            yticklabels=faces.target_names)
plt.xlabel('true label')
plt.ylabel('predicted label');

在这里插入图片描述

这幅图可以帮助我们清晰地判断哪些标签容易被分类器误判。
真实环境中的人脸识别问题的照片通常不会被切割得这么整齐(即使像素相同),两类人
脸分类机制的唯一差别其实是特征选择:你需要用更复杂的算法找到人脸,然后提取图片
中与像素化无关的人脸特征。这类问题有一个不错的解决方案,就是用OpenCV(http://
opencv.org)配合其他手段,包括最先进的通用图像和人脸图像的特征提取工具,来获取
人脸特征数据。

支持向量机总结

前面已经简单介绍了支持向量机的基本原则。支持向量机是一种强大的分类方法,主要有四点理由。

  • 模型依赖的支持向量比较少,说明它们都是非常精致的模型,消耗内存少。
  • 一旦模型训练完成,预测阶段的速度非常快。
  • 由于模型只受边界线附近的点的影响,因此它们对于高维数据的学习效果非常好——即使训练比样本维度还高的数据也没有问题,而这是其他算法难以企及的。
  • 与核函数方法的配合极具通用性,能够适用不同类型的数据。但是,SVM 模型也有一些缺点。
  • 随着样本量N 的不断增加,最差的训练时间复杂度会达到 O [ N 3 ] {O[N^3]} O[N3];经过高效处理后,也只能达到 O [ N 2 ] {O[N^2]} O[N2]。因此,大样本学习的计算成本会非常高。
  • 训练效果非常依赖于边界软化参数C 的选择是否合理。这需要通过交叉检验自行搜索;当数据集较大时,计算量也非常大。
  • 预测结果不能直接进行概率解释。这一点可以通过内部交叉检验进行评估(具体请参见SVC 的probability 参数的定义),但是评估过程的计算量也很大。

由于这些限制条件的存在,我通常只会在其他简单、快速、调优难度小的方法不能满足需求时,才会选择支持向量机。但是,如果你的计算资源足以支撑SVM 对数据集的训练和交叉检验,那么用它一定能获得极好的效果。

SVM在弱学习器中的性能一直十分优越,但在如今这个时代,建议使用更好的算法。以集成算法为主,如随机森林,XGBoost之类的。在kaggle里基本基本都是集成算法,哈哈。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

ACxz

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

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

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

打赏作者

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

抵扣说明:

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

余额充值