第八十八篇 支持向量机(SVM)
心得:支持向量机的公式原理理解上还是比较复杂的,本文以流程和原理以及应用方面来进行
一、什么是支持向量机
1. SVM 简介
支持向量机(support vector machines, SVM)是一种二分类模型,它的基本模型是定义在特征空间上的间隔最大的线性分类器,间隔最大使它有别于感知机;转化为一个凸二次规划问题来求解
由简至繁的模型包括:
- 当训练样本线性可分时,通过硬间隔最大化,学习一个线性可分支持向量机;
- 当训练样本近似线性可分时,通过软间隔最大化,学习一个线性支持向量机;
- 当训练样本线性不可分时,通过核技巧和软间隔最大化,学习一个非线性支持向量机;
2. 什么是SVM
用来解决二分类的问题:
- “你用一根棍分开它们?要求:尽量在放更多球之后,仍然适用。”
你会这样去分割
但这样不是最佳的分割方案,如果有更多的球,这种方式的分类有可能会分错,为了减少这种误差,SVM会找到两类球中间的最大间隔如下:
- 如果遇到线性不可分的情况,我们该怎样去划分割线呢?
我们不可能用一条直线去将它分割开来,这样的分割线不好求解
SVM的做饭是吧这些点全部映射到三维空间上,蓝色的球和红色的球权重可能不一,会映射为下图所示的状况,会用一个平面将其进行了切分
SVM分割超平面原理,以下视频可以更加直接理解超平面分割的方法:
https://www.bilibili.com/video/av33852263/
二、支持向量机的原理以及公式推导
1、线性间隔最大化和支持向量
我们看一个简单的二维空间的例子,O代表正类,X代表负类,样本是线性可分的,但是很显然不只有这一条直线可以将样本分开,而是有无数条,我们所说的线性可分支持向量机就对应着能将数据正确划分并且间隔最大的直线。
间隔就等于两个异类支持向量的差在 w 上的投影,即:
转化为求最小值问题
对偶问题,使用拉格朗日乘子法得到其对偶问题,该问题的拉格朗日函数可以写为:
代入
线性目标函数
2. 非线性支持向量机和核函数
非线性目标函数:
3.核函数的选择
在用SVM处理问题时,如果数据线性不可分,希望通过 将输入空间内线性不可分的数据 映射到 一个高维的特征空间内,使数据在特征空间内是线性可分的,这就是核函数的意义。
-
线性核
优点:
方案首选,奥卡姆剃刀定律
简单,可以求解较快一个QP问题
可解释性强:可以轻易知道哪些feature是重要的限制:只能解决线性可分问题
-
多项式核
基本原理:依靠升维使得原本线性不可分的数据线性可分;
升维的意义:使得原本线性不可分的数据线性可分;优点:
可解决非线性问题
可通过主观设置幂数来实现总结的预判
缺点:对于大数量级的幂数,不太适用
比较多的参数要选择
通常只用在已经大概知道一个比较小的幂数的情况 -
高斯核
优点:
可以映射到无限维
决策边界更为多样
只有一个参数,相比多项式核容易选择缺点:
可解释性差(无限多维的转换,无法算w)
计算速度比较慢(解一个对偶问题)
容易过拟合(参数选不好时容易overfitting) -
Sigmoid核
采用Sigmoid函数作为核函数时,支持向量机实现的就是一种多层感知器神经网络,应用SVM方法,隐含层节点数目(它确定神经网络的结构)、隐含层节点对输入节点的权值都是在设计(训练)的过程中自动确定的。而且支持向量机的理论基础决定了它最终求得的是全局最优值而不是局部最小值,也保证了它对于未知样本的良好泛化能力而不会出现过学习现象。
在实战中更多的是:
一般用线性核和高斯核,也就是Linear核与RBF核
- 如果Feature的数量很大,跟样本数量差不多,这时候选用LR或者是Linear Kernel的SVM
- 如果Feature的数量比较小,样本数量一般,不算大也不算小,选用SVM+Gaussian Kernel
- 如果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)
训练:
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)
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])
### 属性组合,可以将数据分开
X_ = X[:,0]*X[:,1]
y = X_>0
plt.scatter(X[:,0],X[:,1],c=y)
# 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])
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))
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)
训练:
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"])
高斯分布的核函数预测的数据比较准确
四、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}
下一篇: unity3D学习6
推荐阅读
-
Python SVM(支持向量机)实现方法完整示例
-
Python中使用支持向量机SVM实践
-
Python中支持向量机SVM的使用方法详解
-
Python中使用支持向量机(SVM)算法
-
Python机器学习之SVM支持向量机
-
监督分类:SVM即支持向量机实现遥感影像监督分类(更新:添加机器学习模型存储、大影像划框拼接)
-
支持向量机SVM知识梳理和在sklearn库中的应用
-
Python 深入浅出支持向量机(SVM)算法
-
ML:基于自定义数据集利用Logistic、梯度下降算法GD、LoR逻辑回归、Perceptron感知器、SVM支持向量机、LDA线性判别分析算法进行二分类预测(决策边界可视化)
-
Python机器学习应用之支持向量机的分类预测篇