目录
SVM是通过寻找超平面,用于解决二分类问题的分类算法,核心思想是样本点到超平面的距离越远越好,是对感知机的优化。SVM又分为线性可分支持向量机、线性支持向量机和非线性支持向量机,分别对应着硬间隔、软间隔和应用核函数的支持向量机。本文将详述支持向量机的原理和公式推导
假设函数为,要求函数取的最小值时x的值,我们可以很轻易对函数进行求导,令导数为0,求得。假设有约束条件x>=0,在此我们知道x=0处可以取到最优解,但是如何统一的将有约束条件优化为题转化为无约束条件优化问题进行求解,就需要用到拉格朗日函数。
设有约束的优化问题:
拉格朗日函数可以将以上的有约束问题转化成如下的无约束问题,其中和是拉格朗日乘子:
则问题转化为:
拉格朗日对偶问题:
当和是凸函数,是仿射函数时,(1)式和(2)式具有相同的解
KKT条件:
硬间隔SVM的思想是:能正确分类的点,距离超平面越远越好。点到超平面的距离公式为,假设点都能被正确分类,故而和是同号,进而可写成。距离超平面越远越好可表达为:
且所有的样本点到超平面的距离都要大于最小距离,函数距离可表达为,由于一组和b可以确定一个超平面,一个超平面可以对应无数组和b(就好比和确定的是同一条直线),求出一组 和b即可,故而令=1,最终可得目标函数为:
又由于求 的极大,相当于求 的极小,所以目标函数表示为:
构建拉格朗日函数:
原有的有约束问题转化为无约束问题:
对偶问题:
对拉格朗日函数分别对和b求偏导,同时令偏导等于o,求极小:
将(4)和(5)代入(3):
去掉负号,极大变极小整理得:
可通过SMO算法求得一组使得函数最优化,再通过可得
依据KKT条件:,则,找出一个对应的代入即可得到。(对应的点就是支持向量)
软间隔SVM是在硬间隔SVM的基础上添加松弛变量,每个样本对应一个松弛变量,代表样本点嵌入间隔面的深度,之前的硬间隔不可分体现在不能满足约束条件,将约束条件放松修改为,但是不能是无穷大,如果是无穷大,任意的和b都满足,故而在目标函数上增加惩罚项,目标函数整理如下:
构造拉格朗日函数:
原有的有约束问题转化为无约束问题:
对偶问题:
对拉格朗日函数分别对、b、求偏导,同时令偏导等于o,求极小:
将(7)(8)(9)式代入(6)式:
去掉负号,极大变极小整理得:
(10)(11)(12)式整理:
最终对偶问题为:
仍然可以通过SMO算法求得一组使得函数最优化,、和硬间隔SVM的、的求法一致
当数据线性不可分我们可以通过升维的方式使样本在高维的空间线性可分,如上可知SVM的最优化问题为:
升维的优化问题为:
问题:这样升维带来一些问题,假设用多项式回归进行升维,对于()二维升维的结果是(),共5维,如果是3维数据,升维后就会有19维,以此类推,将会导致维度爆炸。升维后还需要做内积运算,时间(内积运算)和空间(升维之后的数据存储)的消耗将是恐怖的
核函数的思想是不计算的中间结果,令,直接计算出结果,节省时间和空间,优化问题变为:
判别函数:
合页损失函数图像:
我们知道,函数间隔是被正确分类的点,故而当不满足条件时会产生损失,svm的损失函数其实合页损失函数加上L2正则化项:
合页损失函数在代码中的可用来表达,可以通过梯度下降来求解最优解
- from sklearn.datasets import load_iris
- from sklearn.svm import SVC
- import numpy as np
- import matplotlib.pyplot as plt
- from sklearn.model_selection import train_test_split, GridSearchCV
- from sklearn.metrics import accuracy_score
-
- # 加载数据
- iris = load_iris()
- X = iris['data']
- y = iris['target']
-
- # 数据集分割
- X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=666)
- '''
- kernel 核函数,默认高斯核(rbf)
- gamma 对应核函数中的gamma
- C 对应软间隔目标函数中的惩罚项系数C
- coef0 对应核函数中的r,仅对多项式核函数和sigmoid核函数有效
- '''
- svc = SVC()
-
- param_grid = {
- 'C': [1.0, 1.1, 1.2, 2],
- 'kernel': ['linear', 'poly', 'rbf', 'sigmoid'],
- 'decision_function_shape' : ['ovo', 'ovr']
- }
- grid_search = GridSearchCV(svc, param_grid=param_grid, cv=3, n_jobs=-1)
- grid_search.fit(X_train, y_train)
- best_model = grid_search.best_estimator_
-
- print('the best params is {}'.format(grid_search.best_params_))
-
- # 模型评估
- y_predict = best_model.predict(X_test)
- acc = accuracy_score(y_test, y_predict)
- print('accuracy is {}'.format(acc))