欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

第八十八篇 支持向量机(SVM)

程序员文章站 2022-05-30 19:34:18
...

心得:支持向量机的公式原理理解上还是比较复杂的,本文以流程和原理以及应用方面来进行

一、什么是支持向量机

1. SVM 简介

支持向量机(support vector machines, SVM)是一种二分类模型,它的基本模型是定义在特征空间上的间隔最大的线性分类器,间隔最大使它有别于感知机;转化为一个凸二次规划问题来求解

由简至繁的模型包括:

  1. 当训练样本线性可分时,通过硬间隔最大化,学习一个线性可分支持向量机;
  2. 当训练样本近似线性可分时,通过软间隔最大化,学习一个线性支持向量机;
  3. 当训练样本线性不可分时,通过核技巧和软间隔最大化,学习一个非线性支持向量机;

2. 什么是SVM

用来解决二分类的问题:

  1. “你用一根棍分开它们?要求:尽量在放更多球之后,仍然适用。”
    第八十八篇 支持向量机(SVM)

你会这样去分割
第八十八篇 支持向量机(SVM)
但这样不是最佳的分割方案,如果有更多的球,这种方式的分类有可能会分错,为了减少这种误差,SVM会找到两类球中间的最大间隔如下:
第八十八篇 支持向量机(SVM)

  1. 如果遇到线性不可分的情况,我们该怎样去划分割线呢?
    第八十八篇 支持向量机(SVM)
    我们不可能用一条直线去将它分割开来,这样的分割线不好求解
    第八十八篇 支持向量机(SVM)
    SVM的做饭是吧这些点全部映射到三维空间上,蓝色的球和红色的球权重可能不一,会映射为下图所示的状况,会用一个平面将其进行了切分
    第八十八篇 支持向量机(SVM)

SVM分割超平面原理,以下视频可以更加直接理解超平面分割的方法:
https://www.bilibili.com/video/av33852263/

二、支持向量机的原理以及公式推导

1、线性间隔最大化和支持向量

我们看一个简单的二维空间的例子,O代表正类,X代表负类,样本是线性可分的,但是很显然不只有这一条直线可以将样本分开,而是有无数条,我们所说的线性可分支持向量机就对应着能将数据正确划分并且间隔最大的直线。
第八十八篇 支持向量机(SVM)
间隔就等于两个异类支持向量的差在 w 上的投影,即:
第八十八篇 支持向量机(SVM)
第八十八篇 支持向量机(SVM)

转化为求最小值问题
第八十八篇 支持向量机(SVM)
对偶问题,使用拉格朗日乘子法得到其对偶问题,该问题的拉格朗日函数可以写为:
第八十八篇 支持向量机(SVM)
代入
第八十八篇 支持向量机(SVM)
第八十八篇 支持向量机(SVM)
线性目标函数
第八十八篇 支持向量机(SVM)

2. 非线性支持向量机和核函数

非线性目标函数:
第八十八篇 支持向量机(SVM)
第八十八篇 支持向量机(SVM)
第八十八篇 支持向量机(SVM)

3.核函数的选择

在用SVM处理问题时,如果数据线性不可分,希望通过 将输入空间内线性不可分的数据 映射到 一个高维的特征空间内,使数据在特征空间内是线性可分的,这就是核函数的意义。

  1. 线性核
    优点:
    方案首选,奥卡姆剃刀定律
    简单,可以求解较快一个QP问题
    可解释性强:可以轻易知道哪些feature是重要的

    限制:只能解决线性可分问题

  2. 多项式核
    基本原理:依靠升维使得原本线性不可分的数据线性可分;
    升维的意义:使得原本线性不可分的数据线性可分;

    优点:

    可解决非线性问题
    可通过主观设置幂数来实现总结的预判
    缺点:

    对于大数量级的幂数,不太适用
    比较多的参数要选择
    通常只用在已经大概知道一个比较小的幂数的情况

  3. 高斯核
    优点:
    可以映射到无限维
    决策边界更为多样
    只有一个参数,相比多项式核容易选择

    缺点:
    可解释性差(无限多维的转换,无法算w)
    计算速度比较慢(解一个对偶问题)
    容易过拟合(参数选不好时容易overfitting)

  4. Sigmoid核
    采用Sigmoid函数作为核函数时,支持向量机实现的就是一种多层感知器神经网络,应用SVM方法,隐含层节点数目(它确定神经网络的结构)、隐含层节点对输入节点的权值都是在设计(训练)的过程中自动确定的。而且支持向量机的理论基础决定了它最终求得的是全局最优值而不是局部最小值,也保证了它对于未知样本的良好泛化能力而不会出现过学习现象。

在实战中更多的是:
一般用线性核和高斯核,也就是Linear核与RBF核

  1. 如果Feature的数量很大,跟样本数量差不多,这时候选用LR或者是Linear Kernel的SVM
  2. 如果Feature的数量比较小,样本数量一般,不算大也不算小,选用SVM+Gaussian Kernel
  3. 如果Feature的数量比较小,而样本数量很多,需要手工添加一些feature变成第一种情况

三、支持向量机的应用

1. sklearn 线性分割

import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

from sklearn.svm import SVC
import sklearn.datasets as datasets

###生成数据
X,y = datasets.make_blobs(n_samples=100,centers=2) #centers 代表分为两类
plt.scatter(X[:,0],X[:,1],c=y)

第八十八篇 支持向量机(SVM)
训练:

svc = SVC(kernel="linear")

svc.fit(X,y)

# 权重
svc.coef_
# 截距
svc.intercept_

w1,w2 = svc.coef_[0]
b = svc.intercept_

画出分割线:

# 0 = w1*x + w2*y +b
# y = -w1*x/w2 - b/w2

w = -w1/w2
b_ = -b/w2

plt.scatter(X[:,0],X[:,1],c=y,cmap=plt.cm.PuOr)

x = np.linspace(-10,2,50)

plt.plot(x,x*w+b_)

### 画出支持向量点
plt.scatter(support_ver[:,0],support_ver[:,1],color='purple',s=100)

第八十八篇 支持向量机(SVM)

2. sklearn 非线性分割

import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

from sklearn.svm import SVC

X = np.random.randn(300,2)
plt.scatter(X[:,0],X[:,1])

第八十八篇 支持向量机(SVM)

### 属性组合,可以将数据分开
X_ = X[:,0]*X[:,1]
y = X_>0
plt.scatter(X[:,0],X[:,1],c=y)

第八十八篇 支持向量机(SVM)

# rbf 符合高斯分布
svc = SVC(kernel="rbf")
svc.fit(X,y)

### 生成测试数据
x1 = np.linspace(-3,3,100) #100个横坐标
y1 = np.linspace(-3,3,100) #100个纵坐标
X1,Y1 = np.meshgrid(x1,y1) #10000个坐标,其中一个横坐标对应100个纵坐标
X_test = np.concatenate([X1.reshape(-1,1),Y1.reshape(-1,1)],axis=-1)
plt.scatter(X_test[:,0],X_test[:,1])

第八十八篇 支持向量机(SVM)

y_ = svc.predict(X_test)

#散点图
#plt.figure(figsize=(6,6))
#plt.scatter(X_test[:,0],X_test[:,1],c=y_)

# 求划分的距离
d_ = svc.decision_function(X_test)
plt.figure(figsize=(6,6))

plt.contourf(X1,Y1,d_.reshape(100,100))

第八十八篇 支持向量机(SVM)

3. sklearn 回归分割

import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

from sklearn.svm import SVR
X = np.linspace(0,3*np.pi,50).reshape(-1,1)
X_test = np.linspace(0,3*np.pi,128).reshape(-1,1)
y = np.sin(X)
plt.scatter(X,y)

第八十八篇 支持向量机(SVM)
训练:

svr_linear = SVR(kernel="linear")

svr_rbf = SVR(kernel="rbf")

svr_poly = SVR(kernel="poly")

svr_linear.fit(X,y)

svr_rbf.fit(X,y)

svr_poly.fit(X,y)

#预测
y1 = svr_linear.predict(X_test)

y2 = svr_rbf.predict(X_test)

y3 = svr_poly.predict(X_test)

#画图
plt.scatter(X,y)
plt.plot(X_test,y1)
plt.plot(X_test,y2)
plt.plot(X_test,y3)
plt.legend(["linear","rbf","poly"])

高斯分布的核函数预测的数据比较准确
第八十八篇 支持向量机(SVM)

四、SVC人脸识别

原文地址: https://blog.csdn.net/jasonzhoujx/article/details/81905923

准备数据

下载数据
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)

降维,训练找出最佳参数

#使用预处理来提取更有意义的特征。这里使用主成份分析来提取150个基本元素,然后将其提供给支持向量机分类器。
#将这个预处理和分类器打包成管道

from sklearn.svm import SVC
from sklearn.decomposition import PCA
from sklearn.pipeline import make_pipeline
pca = PCA(n_components=150, whiten=True, random_state=42)
svc = SVC(kernel='rbf', class_weight='balanced')
model = make_pipeline(pca, svc)

#为了测试分类器的训练效果,将数据集分解成训练集和测试集进行交叉检验
from sklearn.cross_validation import train_test_split
x_train, x_test, y_train, y_test = train_test_split(faces.data, faces.target, random_state=42)

#用网络搜索交叉检验来寻找最优参数组合。通过不断调整C(松弛变量)和参数gamma(控制径向基函数核的大小),确定最优模型
from sklearn.grid_search 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)

grid.fit(x_train, y_train)
print(grid.best_params_)

#输出结果:
{'svc__C': 10, 'svc__gamma': 0.001}