机器学习——支持向量机

简介: 机器学习——支持向量机

关于支持向量机的一些基础知识:支持向量机SVM(Support Vector Machine)笔记 ,这篇文章总结得很好,视频讲解可以查看b站上面的b板推导。


以下内容是使用代码看看效果


%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
from scipy import stats
# use seaborn plotting defaults
import seaborn as sns; sns.set()


SVM基本模型:Hard Margin问题


#随机来点数据
# datasets.samples_generator是sklearn工具包中的数据生成函数
# cluster_std代表数据的离散程度,random_state代表随机状态
# n_samples代表指定样本数目,centers代表数据簇的个数
# 以下代码构建了50个数据点,要进行二分类任务
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')


<matplotlib.collections.PathCollection at 0x20c4d56e588>

image.png


进数据进行二分类,用直线将数据分割开,但是如何找到最合适的决策边界?


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);

image.png


根据SVM的原理,需要找出最宽的边界

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);

image.png

  • 让我们看一下实际拟合该数据的结果:我们将使用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, break_ties=False, cache_size=200, class_weight=None,
    coef0=0.0, decision_function_shape='ovr', degree=3, gamma='scale',
    kernel='linear', max_iter=-1, probability=False, random_state=None,
    shrinking=True, tol=0.001, verbose=False)


为了更好地可视化此处发生的情况,让我们创建一个快速便捷的函数,该函数将为我们绘制SVM决策边界,示例代码如下:


# 绘图函数
def plot_svc_decision_function(model, ax=None, plot_support=True):
    """Plot the decision function for a 2D SVC"""
    if ax is None:
        ax = plt.gca()
    xlim = ax.get_xlim()
    ylim = ax.get_ylim()
    # 用svm自带的decision_function函数唉绘图
    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);

image.png

  • 这条线就是我们希望得到的决策边界啦


  • 观察发现有3个点做了特殊的标记,它们恰好都是边界上的点


  • 它们就是我们的support vectors(支持向量)


  • 在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=200, 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))

image.png

  • 左边是60个点的结果,右边的是120个点的结果
  • 观察发现,只要支持向量没变,其他的数据怎么加无所谓!


核函数变换


  • 首先我们先用线性的核来看一下在下面这样比较难的数据集上还能分了吗?
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);

image.png


显然在二维特征空阿金中做得不好,但如果映射到高维空间中,效果如下:


#加入了新的维度r
from mpl_toolkits import mplot3d
r = np.exp(-(X ** 2).sum(1))
# 可以想象一下在三维中把环形数据集进行上下拉伸
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('x')
    ax.set_ylabel('y')
    ax.set_zlabel('r')
plot_3D(elev=45, azim=45, X=X, y=y)

image.png


自定义了一个新的维度,两类数据点就很容易分开了,这就是核函数变换的基本思想


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);
#加入高斯核函数
clf = SVC(kernel='rbf', C=1E6)
clf.fit(X, y)
# 对比之下,可以将两者区分开来
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');

image.png


两者的对比如上所示,其中核函数参数选择常用的高斯核函数‘rbf’,其他参数保持不变,可以看见解决了线性不可分的问题


kernel{‘linear’, ‘poly’, ‘rbf’, ‘sigmoid’, ‘precomputed’},

default=’rbf’ Specifies the kernel type to be used in the algorithm.

It must be one of ‘linear’, ‘poly’, ‘rbf’, ‘sigmoid’, ‘precomputed’ or

a callable. If none is given, ‘rbf’ will be used. If a callable is

given it is used to pre-compute the kernel matrix from data matrices;

that matrix should be an array of shape (n_samples, n_samples).


使用这种核支持向量机,我们学习一个合适的非线性决策边界。这种核变换策略在机器学习中经常被使用!


SVM参数选择:Soft Margin问题


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)
# 选择了两个松弛因子c进行对比试验,分别是10和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)

image.png


可以看见,


c=10时,对分类结果较为严格,以分类为前提,再去找最宽的决策边界


而c=0.1时,并不要求分类完全正确,选择的是可以容忍某些错误


gamma参数

在sklearn工具包中,σ对应着gamma参数值,来控制模型的复杂程度。gamma值越大,模型复杂度越高;gamma值越小,模型复杂度越低。


X, y = make_blobs(n_samples=100, centers=2,
                  random_state=0, cluster_std=1.1)
fig, ax = plt.subplots(1, 2, figsize=(16, 6))
fig.subplots_adjust(left=0.0625, right=0.95, wspace=0.1)
for axi, gamma in zip(ax, [10, 0.1]):
    model = SVC(kernel='rbf', gamma=gamma).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('gamma = {0:.1f}'.format(gamma), size=14)

image.png

可见,


左图的模型复杂,gamma值大,出现了过拟合现象;相对之下,右图的模型比较简单,效果更好


SVM人脸识别实例


具体可以参考官方提供:API文档


  • 数据读入
# 读取数据集
from sklearn.datasets import fetch_lfw_people
# 限制每个人的样本数至少为60
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]])

image.png

  • 每个图的大小是 [62×47]
  • 在这里我们就把每一个像素点当成了一个特征,但是这样特征太多了,用PCA降维一下吧!
  • 数据降维及划分
from sklearn.svm import SVC
#from sklearn.decomposition import RandomizedPCA
from sklearn.decomposition import PCA
from sklearn.pipeline import make_pipeline
# 降维到150维。基本模型实例化
pca = PCA(n_components=150, whiten=True, random_state=42)
svc = SVC(kernel='rbf', class_weight='balanced')
# 然后再使用svm建模
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=40)


  • svm模型训练

使用grid search cross-validation来选择我们的参数,网络参数选择,决策树中有提及到参数的选择方法


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


  • 结果预测
model = grid.best_estimator_
yfit = model.predict(Xtest)
# yfit.shape
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);

image.png


结果中,如果是用红色标注的名称就表示是不正常的预测名字


如果想得到各项具体评估指标可以使用classification_report函数


from sklearn.metrics import classification_report
print(classification_report(ytest, yfit, target_names=faces.target_names))
precision    recall  f1-score   support
     Ariel Sharon       0.50      0.50      0.50        16
     Colin Powell       0.69      0.81      0.75        54
  Donald Rumsfeld       0.83      0.85      0.84        34
    George W Bush       0.94      0.88      0.91       136
Gerhard Schroeder       0.72      0.85      0.78        27
      Hugo Chavez       0.81      0.72      0.76        18
Junichiro Koizumi       0.87      0.87      0.87        15
       Tony Blair       0.85      0.76      0.80        37
         accuracy                           0.82       337
        macro avg       0.78      0.78      0.78       337
     weighted avg       0.83      0.82      0.82       337


  • 精度(precision) = 正确预测的个数(TP)/被预测正确的个数(TP+FP)
  • 召回率(recall)=正确预测的个数(TP)/预测个数(TP+FN)
  • F1 = 2精度召回率/(精度+召回率)
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');

image.png


这样显示出来能帮助我们查看哪些人更容易弄混,对角线上的数值表示将一个人正确预测成他自己的样本个数。以Ariel为例,有8个样本预测成功,而有6个样本是被误认为Colin,1个样本被误认为Donald


目录
相关文章
|
5月前
|
机器学习/深度学习 算法 数据挖掘
PYTHON银行机器学习:回归、随机森林、KNN近邻、决策树、高斯朴素贝叶斯、支持向量机SVM分析营销活动数据|数据分享-2
PYTHON银行机器学习:回归、随机森林、KNN近邻、决策树、高斯朴素贝叶斯、支持向量机SVM分析营销活动数据|数据分享
|
5月前
|
机器学习/深度学习 Python
PYTHON银行机器学习:回归、随机森林、KNN近邻、决策树、高斯朴素贝叶斯、支持向量机SVM分析营销活动数据|数据分享-4
PYTHON银行机器学习:回归、随机森林、KNN近邻、决策树、高斯朴素贝叶斯、支持向量机SVM分析营销活动数据|数据分享
|
5月前
|
机器学习/深度学习 人工智能 算法
探索机器学习中的支持向量机(SVM)算法
【5月更文挑战第27天】在数据科学和人工智能的领域中,支持向量机(SVM)是一种强大的监督学习模型,它基于统计学习理论中的VC维理论和结构风险最小化原理。本文将详细介绍SVM的工作原理、核心概念以及如何在实际问题中应用该算法进行分类和回归分析。我们还将讨论SVM面临的挑战以及如何通过调整参数和核技巧来优化模型性能。
|
2月前
|
机器学习/深度学习 算法
【机器学习】SVM面试题:简单介绍一下SVM?支持向量机SVM、逻辑回归LR、决策树DT的直观对比和理论对比,该如何选择?SVM为什么采用间隔最大化?为什么要将求解SVM的原始问题转换为其对偶问题?
支持向量机(SVM)的介绍,包括其基本概念、与逻辑回归(LR)和决策树(DT)的直观和理论对比,如何选择这些算法,SVM为何采用间隔最大化,求解SVM时为何转换为对偶问题,核函数的引入原因,以及SVM对缺失数据的敏感性。
59 3
|
2月前
|
机器学习/深度学习 运维 算法
深入探索机器学习中的支持向量机(SVM)算法:原理、应用与Python代码示例全面解析
【8月更文挑战第6天】在机器学习领域,支持向量机(SVM)犹如璀璨明珠。它是一种强大的监督学习算法,在分类、回归及异常检测中表现出色。SVM通过在高维空间寻找最大间隔超平面来分隔不同类别的数据,提升模型泛化能力。为处理非线性问题,引入了核函数将数据映射到高维空间。SVM在文本分类、图像识别等多个领域有广泛应用,展现出高度灵活性和适应性。
96 2
|
2月前
|
机器学习/深度学习 算法
【机器学习】支持向量机SVM、逻辑回归LR、决策树DT的直观对比和理论对比,该如何选择(面试回答)?
文章对支持向量机(SVM)、逻辑回归(LR)和决策树(DT)进行了直观和理论上的对比,并提供了在选择这些算法时的考虑因素,包括模型复杂度、损失函数、数据量需求、对缺失值的敏感度等。
43 1
|
5月前
|
机器学习/深度学习 算法 Python
PYTHON银行机器学习:回归、随机森林、KNN近邻、决策树、高斯朴素贝叶斯、支持向量机SVM分析营销活动数据|数据分享-1
PYTHON银行机器学习:回归、随机森林、KNN近邻、决策树、高斯朴素贝叶斯、支持向量机SVM分析营销活动数据|数据分享
PYTHON银行机器学习:回归、随机森林、KNN近邻、决策树、高斯朴素贝叶斯、支持向量机SVM分析营销活动数据|数据分享-1
|
4月前
|
机器学习/深度学习 算法 Windows
【阿旭机器学习实战】【34】使用SVM检测蘑菇是否有毒--支持向量机
【阿旭机器学习实战】【34】使用SVM检测蘑菇是否有毒--支持向量机
|
5月前
|
机器学习/深度学习 数据采集 算法
深入理解并应用机器学习算法:支持向量机(SVM)
【5月更文挑战第13天】支持向量机(SVM)是监督学习中的强分类算法,用于文本分类、图像识别等领域。它寻找超平面最大化间隔,支持向量是离超平面最近的样本点。SVM通过核函数处理非线性数据,软间隔和正则化避免过拟合。应用步骤包括数据预处理、选择核函数、训练模型、评估性能及应用预测。优点是高效、鲁棒和泛化能力强,但对参数敏感、不适合大规模数据集且对缺失数据敏感。理解SVM原理有助于优化实际问题的解决方案。
|
5月前
|
机器学习/深度学习 人工智能 算法
探索机器学习中的支持向量机(SVM)算法
【5月更文挑战第6天】在数据科学和人工智能的广阔天地中,支持向量机(SVM)以其强大的分类能力与理论深度成为机器学习领域中的一个闪亮的星。本文将深入探讨SVM的核心原理、关键特性以及实际应用案例,为读者提供一个清晰的视角来理解这一高级算法,并展示如何利用SVM解决实际问题。
181 7
下一篇
无影云桌面