目录
SVM概念
线性SVM是基于感知机发展而来的一种二分类模型,有别于感知机中使用误分类点到分离超平面的距离作为损失函数(最小化误分类点到超平面的距离),SVM使用最大化函数间隔作为优化目标(最大化正确分类样本到分离超平面的距离,这样分分离超平面是最中间的那个超平面,泛化性最好的)。
公式
李航统计学习解释
其中函数间隔定义为:,即感知机的损失函数,在感知机中,使用
表示点到分离超平面的距离,
可以表示分类错误的程度。但是由于W和b成比例改变时,分割的超平面并没有改变,但是函数间隔确是原来的比例倍数,由此启示可以在法向量上加一个约束,使得间隔是确定的,因此引入几何间隔。
几何间隔定义为:,(实际上感觉就是点到超平面的距离,这里是正确分类点到超平面的距离)。
优化目标:使得几何间隔最大化,成为硬间隔最大化。
求解:
机器大西瓜解释:
- 点到分离超平面的距离:
- 正确分类的两种情况(正确分类并且缩放后,实际因该是以0为阈值):
- 间隔:两个正确分类的最近(可能大于1,但是决定分离超平面的只有最近的)的异类到分离超平面之和:
,形式近似于几何间隔。
- 优化目标:找到使间隔最大的分离超平面,即最大化
,最小化
。
求解
求出上式后,使用拉格朗日乘子法进行求解。
对偶问题
原始问题本质是先求满足条件的拉格朗日乘子使取得最大值(x的函数,确定拉格朗日乘子),然后求关于W,B的最小值(确定w,b),求得最后的最小值优化。极大极小。
对偶问题是先求W,B的最小值(用表示确定w,b),然后求关于拉格朗日乘子的最大值,通过求解拉格朗日乘子确定W,B。用拉格朗日乘子表示W,B。极小极大。
SVM求解最优化的原始问题描述为:找到使间隔最大的分离超平面,即最大化,最小化
。
即,约束条件:
勒格朗日乘子法:
本质是最小化 最大,由
对偶问题就是先最小化,然后最大化。
软间隔最大化
不是所有都满足线性的关系,因此在约束条件上加上一个松弛变量,松弛变量的系数就是惩罚系数C。C越大表示对误分类惩罚越大(越容易过拟合)C越小则惩罚越小(越容易欠拟合),
svm的另一种解释:损失函数(合页损失函数(hinge))
优缺点及比较
训练数据要选择好,选择具有代表性的数据(此处理解为在间隔附近的)
非线性SVM(拥有核函数的)
使用隐式的非线性变换将输入空间映射到线性可分的特征空间,从而进行求解。
核函数有高斯核函数(RBF)
可优化参数
代码
# -*- coding: utf-8 -*-
"""
Created on Sun Mar 29 14:06:17 2020
@author: dabing
"""
from sklearn.svm import SVC, LinearSVC
from sklearn.model_selection import GridSearchCV
from sklearn.datasets import load_iris
from sklearn import preprocessing
#加载数据集,x为矩阵float64,y为标签int32(未经过one-hot编码)
X, y = load_iris(return_X_y=True)
#数据预处理,max-min归一化,必须归一化,内部计算
max_min_scale = preprocessing.MinMaxScaler()
max_min_scale.fit(X)
X = max_min_scale.transform(X)
#-----------------------------------------------线性SVM
'''
Similar to SVC with parameter kernel='linear'但它是用liblinear而不是libsvm来实现的,
因此它在惩罚函数和损失函数的选择上具有更大的灵活性,
并且应该更好地扩展到大量的样本。
使用one-rest
'''
'''
与其他正则化系数相反,最大化间隔函数
C:惩罚系数,即对误差的宽容度。c越高,说明越不能容忍出现误差,容易过拟合。C越小,容易欠拟合。C过大或过小,泛化能力变差
欠拟合需要调大,过拟合需要调小。
#'''
linear_SVM = LinearSVC(C=2, penalty='l2', loss='hinge', tol=1e-3)
linear_SVM.fit(X,y)
accuracy = linear_SVM.score(X,y)
print(accuracy)
#网格搜索
param_grid ={
'C': [0.1, 0.5, 1.0, 1.5, 2.0],
'penalty': ['l2'],
'tol': [1e-3,1e-4,1e-5,1e-6]
}
garid_search = GridSearchCV(LinearSVC(loss='hinge'), param_grid, scoring='accuracy', cv = 5)
garid_search.fit(X,y)
print(garid_search.cv_results_['mean_test_score'])
print(garid_search.best_params_)
print(garid_search.best_score_)
#----------------------------------非线性SVM,具有核函数
# https://blog.csdn.net/qq_16953611/article/details/82414129
'''
kernel='linear'时,为线性核,C越大分类效果越好,但有可能会过拟合(defaul C=1)
kernel='rbf'时(default),为高斯核,gamma值越小,分类界面越连续;gamma值越大,分类界面越“散”,分类效果越好,但有可能会过拟合。
核函数系数,只对 rbf,poly,sigmod有效。默认为1/n_features
decision_function_shape='ovr'时,为one v rest,即一个类别与其他类别进行划分,
decision_function_shape='ovo'时,为one v one,即将类别两两之间进行划分,用二分类的方法模拟多分类的结果。
gamma是选择RBF函数作为kernel后,该函数自带的一个参数。隐含地决定了数据映射到新的特征空间后的分布,
gamma越大,支持向量越少,gamma值越小,支持向量越多。支持向量的个数影响训练与预测的速度。
这里面大家需要注意的就是gamma的物理意义,大家提到很多的RBF的幅宽,它会影响每个支持向量对应的高斯的作用范围,从而影响泛化性能。
我的理解:如果gamma设的太大,会很小,很小的高斯分布长得又高又瘦, 会造成只会作用于支持向量样本附近,对于未知样本分类效果很差,
存在训练准确率可以很高,(如果让无穷小,则理论上,高斯核的SVM可以拟合任何非线性数据,但容易过拟合)而测试准确率不高的可能,就是通常说的过训练;
而如果设的过小,则会造成平滑效应太大,无法在训练集上得到特别高的准确率,也会影响测试集的准确率。
'''
kernal_SVM = SVC(kernel='linear', tol=1e-3)
kernal_SVM.fit(X,y)
print(kernal_SVM.score(X,y))
#网格搜索
param_grid ={
'C': [0.1, 0.5, 1.0, 1.5, 2.0],
'tol': [1e-3,1e-4,1e-5,1e-6]
}
garid_search = GridSearchCV(SVC(kernel='linear'), param_grid, scoring='accuracy', cv = 5)
garid_search.fit(X,y)
print(garid_search.cv_results_['mean_test_score'])
print(garid_search.best_params_)
print(garid_search.best_score_)
#--------SCV非线性
kernal_SVM = SVC(kernel='rbf', tol=1e-3)
kernal_SVM.fit(X,y)
print(kernal_SVM.score(X,y))
#网格搜索
param_grid ={
'C': [0.1, 0.5, 1.0, 1.5, 2.0],
'tol': [1e-3,1e-4,1e-5,1e-6]
}
garid_search = GridSearchCV(SVC(kernel='rbf',gamma='scale'), param_grid, scoring='accuracy', cv = 5)
garid_search.fit(X,y)
print(garid_search.cv_results_['mean_test_score'])
print(garid_search.best_params_)
print(garid_search.best_score_)
面试常见问题:
- 简述SVM
- SVM主要特点
- 解释间隔最大化
- 解释支持向量
- SVM的推导
- 为什么要引入对偶问题
- SVM的优缺点
- SVM的应用领域
- 如何选择核函数
- RBF的有点
- 核函数选取与数据量的关系
- 如何调节乘法银子
- 如何防止SVM过拟合
- 简述SVM和LR的区别
- https://blog.csdn.net/run_fly001/article/details/88363804?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task