【机器学习入门】推导超级详细,一文讲清楚支持向量机(SVM)【从原理到代码】

支持向量机(SVM)是机器学习中非常经典的一个模型,所以我就把这个作为第二个深入学习的机器学习模型,然后发现居然还挺难的(调包侠流下无能泪水)。
参考了很多博客,但是大部分博客都是讲一部分,要么数学部分比较详细,要么后面的推导部分比较详细,本篇汇集了百家之长,其中我也尽量详细通俗给出了我的一些理解,特在此记录一下。
其中可能存在一些错误,或者有些地方我也理解的不到位,在这些地方我都给出了参考博客,可以参考这些博客。

1.原理部分

1.1.SVM

首先直接抛出SVM的核心假设:SVM面向二分类,假设一组点为线性可分,也就是可以一个被超平面分为两部分。SVM要找的就是这样的超平面,这个超平面使得正类和负类相距此平面最近的点和最远,最近的点被称为支持向量,也可以理解找到一个平面,使得两类中在这个平面的垂直方向的最短的距离最大(最小值最大问题),这样来了一个新样本,那么就可以以更大的概率分类正确。
如下图,SVM就是要找到中间那条线(实际是n维的一个超平面),把两部分样本分开。

1.2.优化目标

基于目标,可以写出优化方程: m a x ( 2 d ) max(2d) max(2d),其中d就是作为支持向量的点到超平面的距离,2d就是最短的支持向量距离(垂直于超平面方向)。
在空间 R n R^n Rn中,点到超平面的距离可以表达为:
w T x + b ∣ ∣ w ∣ ∣ \frac{w^Tx+b}{||w||} ∣∣w∣∣wTx+b其中, w , x w,x w,x都是 n × 1 n×1 n×1向量, x x x是移项后表达式的所有参数,在二维中,该式子表示为 a x + b y + c a 2 + b 2 \frac{ax+by+c}{\sqrt{a^2+b^2}} a2+b2 ax+by+c,对应于上面就是 w T = ( a , b ) , x T = ( x , y ) w^T=(a,b),x^T=(x,y) wT=(a,b),xT=(x,y),本质是一样的。
知道了表达式后,就可以对上面提到的 d d d进行转化,假设超平面为 w T x + b = 0 w^Tx+b=0 wTx+b=0,如下:
m a x ( 2 d ) = > m a x ( 2 ∣ w T x + b ∣ ∣ ∣ w ∣ ∣ ) max(2d)\\=>max(2\frac{|w^Tx+b|}{||w||}) max(2d)=>max(2∣∣w∣∣wTx+b)因为 w , b w,b w,b同时放缩不会影响到超平面,也不会影响d的值,所以通过适当的放缩,该式子可表达为 m a x ( 2 1 ∣ ∣ w ∣ ∣ ) max(2\frac{1}{||w||}) max(2∣∣w∣∣1),这有利于后续的优化,进一步转化:
m a x ( 2 1 ∣ ∣ w ∣ ∣ ) = > m i n ( ∣ ∣ w ∣ ∣ 2 ) = > m i n ( ∣ ∣ w ∣ ∣ 2 2 ) max(2\frac{1}{||w||})\\=>min(\frac{||w||}{2})\\=>min(\frac{||w||^2}{2}) max(2∣∣w∣∣1)=>min(2∣∣w∣∣)=>min(2∣∣w2)最后一步是为了去掉根号,方便计算,其中 ∣ ∣ w ∣ ∣ = w T w ||w||=w^Tw ∣∣w∣∣=wTw
任意一点到超平面的距离其实也可以表达为 y i ( w T x + b ) ∣ ∣ w ∣ ∣ \frac{y_i(w^Tx+b)}{||w||} ∣∣w∣∣yi(wTx+b),因为 y i ( w T x + b ) y_i(w^Tx+b) yi(wTx+b) y = ± 1 y=±1 y=±1,始终与 ( w T x + b ) (w^Tx+b) (wTx+b)同号,因此 y i ( w T x + b ) = ∣ ( w T x + b ) ∣ y_i(w^Tx+b)=|(w^Tx+b)| yi(wTx+b)=(wTx+b),上面提到了 ∣ ( w T x + b ) ∣ = 1 |(w^Tx+b)|=1 (wTx+b)=1,那么对于所有的向量,距离超平面的函数距离都要大于等于1(函数距离就是分子|(w^Tx+b)|,除了 ∣ ∣ w ∣ ∣ ||w|| ∣∣w∣∣之后是几何距离),存在:
y i ( w T x + b ) ≥ 1 y_i(w^Tx+b)≥1 yi(wTx+b)1此时可列出目标和约束条件:
m i n ( ∣ ∣ w ∣ ∣ 2 2 ) s . t .    y i ( w T x + b ) ≥ 1 min(\frac{||w||^2}{2})\\ s.t.\;y_i(w^Tx+b)≥1 min(2∣∣w2)s.t.yi(wTx+b)1

1.3.数学知识补充

1.3.1.拉格朗日和kkt

下面介绍拉格朗日乘子和kkt。求解优化目标时,如果约束条件是等式,那么可以使用拉格朗日乘子法转为不带约束条件的优化,形如:
m i n ( f ( x ) ) s . t .    φ i ( x ) = 0 , i = 1 , 2 , . . . , n min(f(x))\\ s.t.\; φ_i(x)=0,i=1,2,...,n min(f(x))s.t.φi(x)=0,i=1,2,...,n上式可化为
L ( x , λ ) = f ( x ) + ∑ i = 1 n λ i φ i ( x ) L(x,λ)=f(x)+∑_{i=1}^{n}λ_iφ_i(x) L(x,λ)=f(x)+i=1nλiφi(x)此时令 L L L x x x分别求偏导,解得的结果是极小值的必要条件(也就是可能是,也有可能不是),可以用于验证一个点是否是,如果为极值点那么一定满足上式。

但是如果约束条件条件包含不等式约束,此时可以使用kkt条件,kkt条件使用的情形如下:
m i n ( f ( x ) ) s . t .    φ i ( x ) = 0 , i = 1 , 2 , . . . , n g j ( x ) ≤ 0 , j = 1 , 2 , . . . , m min(f(x))\\ s.t.\;φ_i(x)=0,i=1,2,...,n\\ g_j(x)≤0,j=1,2,...,m min(f(x))s.t.φi(x)=0,i=1,2,...,ngj(x)0,j=1,2,...,m此时,再写出拉格朗日函数:
L ( x , λ , β ) = f ( x ) + ∑ i = 1 n λ i φ i ( x ) + ∑ i = 1 m β j g j ( x ) L(x,λ,β)=f(x)+∑_{i=1}^{n}λ_iφ_i(x)+∑_{i=1}^{m}β_jg_j(x) L(x,λ,β)=f(x)+i=1nλiφi(x)+i=1mβjgj(x)
上式称为原始问题,需要进一步转化,下面介绍拉格朗日对偶性,这也是比较难理解的地方。
约束 β ≥ 0 \beta≥0 β0,此时因为 g ( x ) ≤ 0 g(x)≤0 g(x)0,那么 ∑ i = 1 m β j g j ( x ) ≤ 0 ∑_{i=1}^{m}β_jg_j(x)≤0 i=1mβjgj(x)0,因此 L ( x , λ , β ) ≤ f ( x ) L(x,λ,\beta)≤f(x) L(x,λ,β)f(x) f ( x ) f(x) f(x)为求解目标,为了使得 L ( x , λ , β ) L(x,λ,β) L(x,λ,β)趋向于 f ( x ) f(x) f(x),那么要求 m a x ( L ( x , λ , β ) ) max(L(x,λ,β)) max(L(x,λ,β)),即 max ⁡ β ≥ 0 , λ ( L ( x , λ , β ) ) \max\limits_{β≥0,λ}(L(x,λ,β)) β0,λmax(L(x,λ,β))
该式只是对 λ , β λ,β λ,β进行约束,而 g ( x ) g(x) g(x)是要约束 x x x才能满足 g ( x ) ≤ 0 g(x)≤0 g(x)0,因此 g ( x ) > 0 g(x)>0 g(x)>0可能成立,从而使得:
max ⁡ β ≥ 0 , λ ( L ( x , λ , β ) ) = { f ( x ) , ∀    g j ( x ) ≤ 0 [ f ( x ) , + ∞ ] , ∃    g j ( x ) > 0 \max\limits_{β≥0,λ}(L(x,λ,β))=\left\{ \begin{array}{cc} f(x),{\forall}\;g_j(x)≤0 & \\ [f(x),+∞],{\exists}\;g_j(x)>0 \end{array} \right. β0,λmax(L(x,λ,β))={f(x),gj(x)0[f(x),+],gj(x)>0
(这里有一个问题就是:为什么不满足约束的时候不考虑h(x)≠0?这一点我也不是很清楚,参考的几篇博客并没有提到,也有可能是我没理解到位吧!)
也就是无论如何 max ⁡ β ≥ 0 , λ ( L ( x , λ , β ) ) \max\limits_{β≥0,λ}(L(x,λ,β)) β0,λmax(L(x,λ,β))的下限都是 f ( x ) f(x) f(x),也就是求解目标,那么只要再对其求 m i n min min min ⁡ x max ⁡ β ≥ 0 , λ ( L ( x , λ , β ) ) \min\limits_{x}\max\limits_{β≥0,λ}(L(x,λ,β)) xminβ0,λmax(L(x,λ,β)),那么原始问题可转化为原始代价函数
J d = m i n ( f ( x ) ) = min ⁡ x max ⁡ β ≥ 0 , λ ( L ( x , λ , β ) ) J_d=min(f(x))=\min\limits_{x}\max\limits_{β≥0,λ}(L(x,λ,β)) Jd=min(f(x))=xminβ0,λmax(L(x,λ,β))最后补充一点,**max(.)**为凸函数,**min(.)为凹函数,与括号内的.***形式无关,这和下面进一步转化有关。(证明参见

1.3.2.对偶方法

对于原函数,构造一个新的函数,也就是将 L ( x , λ , β ) L(x,\lambda,\beta) L(x,λ,β)前面的 m i n min min m a x max max顺序反一反,条件不变,得到一个新函数:
min ⁡ x ( L ( x , λ , β ) ) = min ⁡ x ( f ( x ) + ∑ i = 1 n λ i φ i ( x ) + ∑ i = 1 m β j g j ( x ) ) \min\limits_{x}(L(x,\lambda,\beta))=\min\limits_{x}(f(x)+∑_{i=1}^{n}λ_iφ_i(x)+∑_{i=1}^{m}β_jg_j(x)) xmin(L(x,λ,β))=xmin(f(x)+i=1nλiφi(x)+i=1mβjgj(x))该函数满足下式:
min ⁡ x ( L ( x , λ , β ) ) = { min ⁡ x ( f ( x ) ) , ∀    g j ( x ) ≤ 0 [ − ∞ , min ⁡ x ( f ( x ) ) ] , ∃    g j ( x ) > 0 \min\limits_{x}(L(x,λ,β))=\left\{ \begin{array}{cc} \min\limits_{x}(f(x)),{\forall}\;g_j(x)≤0 & \\ [-∞,\min\limits_{x}(f(x))],{\exists}\;g_j(x)>0 \end{array} \right. xmin(L(x,λ,β))={xmin(f(x)),gj(x)0[,xmin(f(x))],gj(x)>0
(这里有个问题:我感觉满足条件的时候βg(x)s∈[-∞,0],不满足的时候是[-∞,+∞],所以满足的时候最小值为什么是f(x)最小值?这部分来自博客)。
可见最大值都是 f ( x ) f(x) f(x),那么类似上面取 m a x max max
J p = max ⁡ β ≥ 0 , λ min ⁡ x ( L ( x , λ , β ) ) J_p=\max\limits_{β≥0,λ}\min\limits_{x}(L(x,λ,β)) Jp=β0,λmaxxmin(L(x,λ,β))假设 J d , J p J_d,J_p Jd,Jp对应的极值(极小值和极大值)分别是 d ∗ 和 p ∗ d^*和p^* dp,那么满足:
d ∗ ≥ p ∗ d^*≥p^* dp根据Slater定理,如果问题为问题(凹问题可以转为凸问题),那么** p ∗ = d ∗ p^*=d^* p=d,此时称为强对偶性**(与之对应的是弱对偶性,满足的是上面的不等式)。

1.4.优化目标转化

下面回到原问题上来,原优化问题如:
m i n ( ∣ ∣ w ∣ ∣ 2 2 ) s . t .    y i ( w T x + b ) − 1 ≥ 0 min(\frac{||w||^2}{2})\\ s.t.\;y_i(w^Tx+b)-1≥0 min(2∣∣w2)s.t.yi(wTx+b)10上面的不等式约束是≥0,要满足标准kkt,转为下式:
m i n ( ∣ ∣ w ∣ ∣ 2 2 ) s . t .    − ( y i ( w T x + b ) − 1 ) ≤ 0 min(\frac{||w||^2}{2})\\ s.t.\;-(y_i(w^Tx+b)-1)≤0 min(2∣∣w2)s.t.(yi(wTx+b)1)0写出拉格朗日函数
L ( w , b , β ) = ∣ ∣ w ∣ ∣ 2 2 − ∑ i = 1 m β i [ y i ( w T x i + b ) − 1 ] L(w,b,β)=\frac{||w||^2}{2}-∑_{i=1}^{m}β_i[y_i(w^Tx_i+b)-1] L(w,b,β)=2∣∣w2i=1mβi[yi(wTxi+b)1]
该问题为原始问题,满足 β > 0 β>0 β>0(kkt条件),转为原始代价函数
J d = m i n ( f ( w ) ) = min ⁡ w , b max ⁡ β ≥ 0 ( L ( w , b , β ) ) J_d=min(f(w))=\min\limits_{w,b}\max\limits_{β≥0}(L(w,b,β)) Jd=min(f(w))=w,bminβ0max(L(w,b,β))该函数为凸函数 m i n min min),转为对偶问题
min ⁡ w , b max ⁡ β ≥ 0 ( L ( w , b , β ) ) = max ⁡ β ≥ 0 min ⁡ w , b ( L ( w , b , β ) ) \min\limits_{w,b}\max\limits_{β≥0}(L(w,b,β))=\max\limits_{β≥0}\min\limits_{w,b}(L(w,b,β)) w,bminβ0max(L(w,b,β))=β0maxw,bmin(L(w,b,β))写出完整的表达式:
max ⁡ β ≥ 0 min ⁡ w , b ( L ( w , b , β ) ) = max ⁡ β ≥ 0 min ⁡ w , b ( ∣ ∣ w ∣ ∣ 2 2 − ∑ i = 1 m β i [ y i ( w T x i + b ) − 1 ] ) \max\limits_{β≥0}\min\limits_{w,b}(L(w,b,β))=\max\limits_{β≥0}\min\limits_{w,b}(\frac{||w||^2}{2}-∑_{i=1}^{m}β_i[y_i(w^Tx_i+b)-1]) β0maxw,bmin(L(w,b,β))=β0maxw,bmin(2∣∣w2i=1mβi[yi(wTxi+b)1])先求里面部分,分别对 w , b w,b w,b求偏导,得到下式:
{ ∂ L ∂ w = w − ∑ i = 1 m y i x i β i ∂ L ∂ b = − ∑ i = 1 m y i β i \left\{ \begin{array}{cc} \frac{\partial L}{\partial w}=w-∑_{i=1}^{m}y_ix_iβ_i \\ \frac{\partial L}{\partial b}=-∑_{i=1}^{m}y_iβ_i \end{array} \right. {wL=wi=1myixiβibL=i=1myiβi
分别令其为0,得到:
w = ∑ i = 1 m y i x i β i ∑ i = 1 m y i β i = 0 w=∑_{i=1}^{m}y_ix_iβ_i\\ ∑_{i=1}^{m}y_iβ_i=0 w=i=1myixiβii=1myiβi=0注意:这里的 x i , w x_i,w xi,w都是一个向量。
带入原式,变为:
max ⁡ β ≥ 0 ( 1 2 w T w − ∑ i = 1 m β i [ y i ( w T x i + b ) − 1 ] ) = max ⁡ β ≥ 0 ( 1 2 w T w − ∑ i = 1 m β i y i w T w − b ∑ i = 1 m β i y i + ∑ i = 1 m β i ) = max ⁡ β ≥ 0 ( 1 2 w T ∑ i = 1 m y i x i β i − w T ∑ i = 1 m y i x i β i + ∑ i = 1 m β i ) = max ⁡ β ≥ 0 ( ∑ i = 1 m β i − 1 2 w T ∑ i = 1 m y i x i β i ) \max\limits_{β≥0}(\frac{1}{2}w^Tw-∑_{i=1}^{m}β_i[y_i(w^Tx_i+b)-1])\\ =\max\limits_{β≥0}(\frac{1}{2}w^Tw-∑_{i=1}^{m}β_iy_iw^Tw-b∑_{i=1}^{m}β_iy_i+∑_{i=1}^{m}β_i)\\ =\max\limits_{β≥0}(\frac{1}{2}w^T∑_{i=1}^{m}y_ix_iβ_i-w^T∑_{i=1}^{m}y_ix_iβ_i+∑_{i=1}^{m}β_i)\\ =\max\limits_{β≥0}(∑_{i=1}^{m}β_i-\frac{1}{2}w^T∑_{i=1}^{m}y_ix_iβ_i) β0max(21wTwi=1mβi[yi(wTxi+b)1])=β0max(21wTwi=1mβiyiwTwbi=1mβiyi+i=1mβi)=β0max(21wTi=1myixiβiwTi=1myixiβi+i=1mβi)=β0max(i=1mβi21wTi=1myixiβi)上面是带入了 w w w,然后进行化简得到。下面要进一步带入 w T w^T wT,这个就是 w w w的转置,注意维度的变化:
max ⁡ β ≥ 0 ( ∑ i = 1 m β i − 1 2 w T ∑ i = 1 m y i x i β i ) = max ⁡ β ≥ 0 ( ∑ i = 1 m β i − 1 2 ∑ j = 1 m β j T x j T y j T ∑ i = 1 m y i x i β i ) = max ⁡ β ≥ 0 ( ∑ i = 1 m β i − 1 2 ∑ i , j = 1 m β j β i y j y i x j T x i ) \max\limits_{β≥0}(∑_{i=1}^{m}β_i-\frac{1}{2}w^T∑_{i=1}^{m}y_ix_iβ_i)\\ =\max\limits_{β≥0}(∑_{i=1}^{m}β_i-\frac{1}{2}∑_{j=1}^{m}β_j^Tx_j^Ty_j^T∑_{i=1}^{m}y_ix_iβ_i)\\ =\max\limits_{β≥0}(∑_{i=1}^{m}β_i-\frac{1}{2}∑_{i,j=1}^{m}β_jβ_iy_jy_ix_j^Tx_i) β0max(i=1mβi21wTi=1myixiβi)=β0max(i=1mβi21j=1mβjTxjTyjTi=1myixiβi)=β0max(i=1mβi21i,j=1mβjβiyjyixjTxi)此时问题被转化为了
max ⁡ β ≥ 0 ( ∑ i = 1 m β i − 1 2 ∑ i , j = 1 m β j β i y j y i x j T x i ) s . t .    ∑ i = 1 m y i β i = 0 \max\limits_{β≥0}(∑_{i=1}^{m}β_i-\frac{1}{2}∑_{i,j=1}^{m}β_jβ_iy_jy_ix_j^Tx_i)\\ s.t. \;∑_{i=1}^{m}y_iβ_i=0 β0max(i=1mβi21i,j=1mβjβiyjyixjTxi)s.t.i=1myiβi=0

1.5.SMO求解β​

【推荐】知乎,主要是介绍SMO,在α的介绍部分比较容易理解
上面的转化得到了一个关于 β β β的优化函数,下面介绍利用SMO算法求解 β β β
SMO算法类似于坐标上升算法,假设存在要求 m i n ( f ( x 1 , x 2 ) ) min(f(x_1,x_2)) min(f(x1,x2)),首先固定 x 1 x_1 x1(将其看做一个常数),然后计算关于 x 2 x_2 x2的偏导,然后可以得到此时对应的最优 x 2 x_2 x2,然后固定 x 2 x_2 x2,求解 x 1 x_1 x1,不断迭代直到收敛。
SMO的思路大致类似,每次选取尽量少的变量来优化。回到SVM问题中,在上面得到了需要求解的函数:
max ⁡ β ≥ 0 ( ∑ i = 1 m β i − 1 2 ∑ i , j = 1 m β j β i y j y i x j T x i ) s . t .    ∑ i = 1 m y i β i = 0 \max\limits_{β≥0}(∑_{i=1}^{m}β_i-\frac{1}{2}∑_{i,j=1}^{m}β_jβ_iy_jy_ix_j^Tx_i)\\ s.t. \;∑_{i=1}^{m}y_iβ_i=0 β0max(i=1mβi21i,j=1mβjβiyjyixjTxi)s.t.i=1myiβi=0这是一个关于 β β β的函数, β β β是一个 n × 1 n\times 1 n×1的向量,并且存在约束条件,直接求解复杂度很高,SMO将其分解为多个二次规划问题求解,每次针对其中两个 β = < β i , β j > β=<β_i,β_j> β=<βi,βj>进行优化,大大减少了运算量。

1.5.1.不限制β

首先抛开对于β的限制,选取需要优化的两个参数记为 β 1 , β 2 β_1,β_2 β1,β2,剩下的若干 β β β固定,作为常数处理。
为了简便表达,这里设 k i , j k_{i,j} ki,j上面的 x i T x j x_i^Tx_j xiTxj,容易得到 k i , j = k j , i k_{i,j}=k_{j,i} ki,j=kj,i,同时设 h i , j = β j β i y j y i x j T x i = β j β i y j y i k i , j h_{i,j}=β_jβ_iy_jy_ix_j^Tx_i=β_jβ_iy_jy_ik_{i,j} hi,j=βjβiyjyixjTxi=βjβiyjyiki,j,满足 h i , j = h j , i h_{i,j}=h_{j,i} hi,j=hj,i(这是为了方便查看带入的规则)。
记优化目标为 W ( β ) W(β) W(β),把与 β 1 , β 2 β_1,β_2 β1,β2有关的提取出来,其他记为 C C C,可得:
W ( β 1 , β 2 ) = ∑ i = 1 m β i − 1 2 ∑ i , j = 1 m h i , j = β 1 + β 2 − 1 2 h 1 , 1 − 1 2 h 1 , 2 − 1 2 h 1 , 1 − 1 2 h 2 , 2 − 1 2 ∑ i = 3 m h i , 1 − 1 2 ∑ i = 3 m h 1 , i − 1 2 ∑ i = 3 m h i , 2 − 1 2 ∑ i = 3 m h 2 , i + C = β 1 + β 2 − h 1 , 2 − 1 2 h 1 , 1 − 1 2 h 2 , 2 − ∑ i = 3 m h 1 , i − ∑ i = 3 m h 2 , i + C W(β_1,β_2)=∑_{i=1}^{m}β_i-\frac{1}{2}∑_{i,j=1}^{m}h_{i,j}\\ =β_1+β_2-\frac{1}{2}h_{1,1}-\frac{1}{2}h_{1,2}-\frac{1}{2}h_{1,1}-\frac{1}{2}h_{2,2}-\\ \frac{1}{2}∑_{i=3}^{m}h_{i,1}-\frac{1}{2}∑_{i=3}^{m}h_{1,i}-\frac{1}{2}∑_{i=3}^{m}h_{i,2}-\frac{1}{2}∑_{i=3}^{m}h_{2,i}+C\\ =β_1+β_2-h_{1,2}-\frac{1}{2}h_{1,1}-\frac{1}{2}h_{2,2}-∑_{i=3}^{m}h_{1,i}-∑_{i=3}^{m}h_{2,i}+C W(β1,β2)=i=1mβi21i,j=1mhi,j=β1+β221h1,121h1,221h1,121h2,221i=3mhi,121i=3mh1,i21i=3mhi,221i=3mh2,i+C=β1+β2h1,221h1,121h2,2i=3mh1,ii=3mh2,i+C带入 h i , j h_{i,j} hi,j得到:
β 1 + β 2 − 1 2 k 1 , 1 α 1 2 − 1 2 k 2 , 2 α 2 2 − 1 2 k 1 , 2 α 1 α 2 − ∑ i = 3 m k 1 , i β 1 β i y 1 y i − ∑ i = 3 m k 2 , i β 2 β i y 2 y i + C β_1+β_2-\frac{1}{2}k_{1,1}α_1^2-\frac{1}{2}k_{2,2}α_2^2-\frac{1}{2}k_{1,2}α_1α_2-∑_{i=3}^{m}k_{1,i}β_1β_iy_1y_i-∑_{i=3}^{m}k_{2,i}β_2β_iy_2y_i+C β1+β221k1,1α1221k2,2α2221k1,2α1α2i=3mk1,iβ1βiy1yii=3mk2,iβ2βiy2yi+C进一步,因为对于每个 ∑ i = 3 m ∑_{i=3}^{m} i=3m,其中的 β 1 , β 1 , y 1 , y 2 β_1,β_1,y_1,y_2 β1,β1,y1,y2都是一样的,所以可以提取出来,得到:
β 1 + β 2 − 1 2 k 1 , 1 α 1 2 − 1 2 k 2 , 2 α 2 2 − 1 2 k 1 , 2 α 1 α 2 − β 1 y 1 ∑ i = 3 m k 1 , i β i y i − β 2 y 2 ∑ i = 3 m k 2 , i β i y i + C β_1+β_2-\frac{1}{2}k_{1,1}α_1^2-\frac{1}{2}k_{2,2}α_2^2-\frac{1}{2}k_{1,2}α_1α_2-β_1y_1∑_{i=3}^{m}k_{1,i}β_iy_i-β_2y_2∑_{i=3}^{m}k_{2,i}β_iy_i+C β1+β221k1,1α1221k2,2α2221k1,2α1α2β1y1i=3mk1,iβiyiβ2y2i=3mk2,iβiyi+C
β 1 , β 2 β_1,β_2 β1,β2是满足一定约束条件的,即 ∑ i = 1 m y i β i = 0 ∑_{i=1}^{m}y_iβ_i=0 i=1myiβi=0,设 y 1 β 1 + y 2 β 2 = γ y_1β_1+y_2β_2=γ y1β1+y2β2=γ,那么存在:
β 1 = y 1 ( γ − β 2 y 2 ) β_1=y_1(γ-β_2y_2) β1=y1(γβ2y2)设:
v 1 = ∑ i = 3 m k 1 , i β i y i v 2 = ∑ i = 3 m k 2 , i β i y i v_1=∑_{i=3}^{m}k_{1,i}β_iy_i\\v_2=∑_{i=3}^{m}k_{2,i}β_iy_i v1=i=3mk1,iβiyiv2=i=3mk2,iβiyi带入 β 1 β_1 β1后,那么此时 W ( β 1 , β 2 ) W(β_1,β_2) W(β1,β2)就变为了关于 β 2 β_2 β2的函数,注意 y i 2 = 1 y_i^2=1 yi2=1,如下:
W ( β 2 ) = y 1 ( γ − β 2 y 2 ) + β 2 − 1 2 k 1 , 1 ( γ − β 2 y 2 ) 2 − 1 2 k 2 , 2 β 2 2 − k 1 , 2 β 2 ( γ − β 2 y 2 ) y 2 − v 1 ( γ − β 2 y 2 ) − v 2 y 2 β 2 + C W(β_2)=y_1(γ-β_2y_2)+β_2-\frac{1}{2}k_{1,1}(γ-β_2y_2)^2\\ -\frac{1}{2}k_{2,2}β_2^2-k_{1,2}β_2(γ-β_2y_2)y_2-v1(γ-β_2y_2)-v_2y_2β_2+C W(β2)=y1(γβ2y2)+β221k1,1(γβ2y2)221k2,2β22k1,2β2(γβ2y2)y2v1(γβ2y2)v2y2β2+C然后对 β 2 β_2 β2求导:
∂ W ∂ β 2 = − y 1 y 2 + y 2 2 − k 1 , 1 y 2 ( γ − β 2 y 2 ) − k 2 , 2 α 2 − k 1 , 2 γ y 2 − 2 k 1 , 2 β 2 + v 1 y 2 − v 2 y 2 = ( 2 k 1 , 2 − k 1 , 1 − k 2 , 2 ) β 2 + ( k 1 , 1 − k 1 , 2 ) γ y 2 + y 2 ( v 1 − v 2 ) − y 2 ( y 1 − y 2 ) \frac{\partial W}{\partial β_2}=-y_1y_2+y_2^2-k_{1,1}y_2(γ-β_2y_2)-k_{2,2}α_2-k_{1,2}γy_2-2k_{1,2}β_2+v_1y_2-v_2y_2\\ =(2k_{1,2}-k_{1,1}-k_{2,2})β_2+(k_{1,1}-k_{1,2})γy_2+y_2(v_1-v_2)-y_2(y_1-y_2) β2W=y1y2+y22k1,1y2(γβ2y2)k2,2α2k1,2γy22k1,2β2+v1y2v2y2=(2k1,2k1,1k2,2)β2+(k1,1k1,2)γy2+y2(v1v2)y2(y1y2)下面的步骤将消除 γ γ γ,计算出更新后的值 β n e w β^{new} βnew和原来的值 β o l d β^{old} βold的关系,这和更新参数有关。
首先可以知道,对于一个输入样本 x x x,其预测值为 f ( x ) = w T x + b f(x)=w^Tx+b f(x)=wTx+b,带入前面计算出的 w w w(在问题求解部分)可得:
f ( x j ) = ∑ i = 1 m y i β i x i T x j + b = ∑ i = 1 m y i β i k i , j + b f(x_j)=∑_{i=1}^{m}y_iβ_ix_i^Tx_j+b\\=∑_{i=1}^{m}y_iβ_ik_{i,j}+b f(xj)=i=1myiβixiTxj+b=i=1myiβiki,j+b可以发现这个式子和前面的 v 1 , v 2 v_1,v_2 v1,v2形式类似,带入 x 1 x_1 x1,可得 f ( x 1 ) = ∑ i = 1 m y i β i k i , 1 + b f(x_1)=∑_{i=1}^{m}y_iβ_ik_{i,1}+b f(x1)=i=1myiβiki,1+b,用 f ( x ) f(x) f(x)的形式表达出 v 1 , v 2 v_1,v_2 v1,v2
v 1 = f ( x 1 ) − y 1 β 1 o l d k 1 , 1 − y 2 β 2 o l d k 2 , 1 − b v 2 = f ( x 2 ) − y 1 β 1 o l d k 2 , 1 − y 2 β 2 o l d k 2 , 2 − b v_1=f(x_1)-y_1β_1^{old}k_{1,1}-y_2β_2^{old}k_{2,1}-b\\ v_2=f(x_2)-y_1β_1^{old}k_{2,1}-y_2β_2^{old}k_{2,2}-b v1=f(x1)y1β1oldk1,1y2β2oldk2,1bv2=f(x2)y1β1oldk2,1y2β2oldk2,2b这里是 β o l d β^{old} βold是因为这是基于已知的预测值的,所以是上一次的参数,也就是旧参数。
替换掉前面求导得到的式子 v 1 − v 2 v_1-v_2 v1v2
v 1 − v 2 = f ( x 1 ) − f ( x 2 ) + ( k 1 , 1 + k 2 , 2 − 2 k 1 , 2 ) β 2 o l d y 2 + γ ( k 1 , 2 − k 1 , 1 ) v1-v2=f(x_1)-f(x_2)+(k_{1,1}+k_{2,2}-2k_{1,2})β_2^{old}y_2+γ(k_{1,2}-k_{1,1}) v1v2=f(x1)f(x2)+(k1,1+k2,22k1,2)β2oldy2+γ(k1,2k1,1)带入得:
∂ W ∂ β 2 = ( 2 k 1 , 2 − k 1 , 1 − k 2 , 2 ) β 2 n e w + ( k 1 , 1 − k 1 , 2 ) γ y 2 + y 2 ( f ( x 1 ) − f ( x 2 ) + ( k 1 , 1 + k 2 , 2 − 2 k 1 , 2 ) β 2 o l d y 2 + γ ( k 1 , 2 − k 1 , 1 ) ) − y 2 ( y 1 − y 2 ) = ( 2 k 1 , 2 − k 1 , 1 − k 2 , 2 ) β 2 n e w − ( 2 k 1 , 2 − k 1 , 1 − k 2 , 2 ) β 2 o l d + y 2 ( ( f ( x 1 ) − y 1 ) − ( f ( x 2 ) − y 2 ) ) \frac{\partial W}{\partial β_2}=(2k_{1,2}-k_{1,1}-k_{2,2})β_2^{new}+(k_{1,1}-k_{1,2})γy_2\\ +y_2(f(x_1)-f(x_2)+(k_{1,1}+k_{2,2}-2k_{1,2})β_2^{old}y_2+γ(k_{1,2}-k_{1,1}))-y_2(y_1-y_2)\\ =(2k_{1,2}-k_{1,1}-k_{2,2})β_2^{new}-(2k_{1,2}-k_{1,1}-k_{2,2})β_2^{old}+y_2((f(x_1)-y_1)-(f(x_2)-y_2)) β2W=(2k1,2k1,1k2,2)β2new+(k1,1k1,2)γy2+y2(f(x1)f(x2)+(k1,1+k2,22k1,2)β2oldy2+γ(k1,2k1,1))y2(y1y2)=(2k1,2k1,1k2,2)β2new(2k1,2k1,1k2,2)β2old+y2((f(x1)y1)(f(x2)y2))
e i = f ( x i ) − y i , K = 2 k 1 , 2 − k 1 , 1 − k 2 , 2 e_i=f(x_i)-y_i,K=2k_{1,2}-k_{1,1}-k_{2,2} ei=f(xi)yi,K=2k1,2k1,1k2,2
∂ W ∂ β 2 = K β 2 n e w − K β 2 o l d + y 2 ( e 1 − e 2 ) \frac{\partial W}{\partial β_2}=Kβ_2^{new}-Kβ_2^{old}+y_2(e_1-e_2) β2W=Kβ2newKβ2old+y2(e1e2)要满足极值点,那么 ∂ W ∂ β 2 = 0 \frac{\partial W}{\partial β_2}=0 β2W=0,得到:
β 2 n e w = β 2 o l d − y 2 ( e 1 − e 2 ) / K β_2^{new}=β_2^{old}-y_2(e_1-e_2)/K β2new=β2oldy2(e1e2)/K因为 β 1 n e w = y 1 ( γ − β 2 n e w y 2 ) β_1^{new}=y_1(γ-β_2^{new}y_2) β1new=y1(γβ2newy2),而 γ = β 2 o l d y 1 + β 1 o l d y 2 γ=β_2^{old}y_1+β_1^{old}y_2 γ=β2oldy1+β1oldy2,由此可以解出新的 β 1 n e w β_1^{new} β1new

1.5.2.β裁剪

下面要对β进行裁剪,也就是考虑限制 β β β
实际的 β β β是有范围的,限定为 0 ≤ β ≤ C 0≤β≤C 0βC C C C表示软间隔常数。
因为 β 1 y 1 + β 2 y 2 = γ β_1y_1+β_2y_2=γ β1y1+β2y2=γ,这个关系始终成立,无论是 β n e w β^{new} βnew还是 β o l d β^{old} βold,又因为 y = ± 1 y=±1 y=±1,下面分两种情况讨论 y 1 , y 2 y_1,y_2 y1,y2的情况并分析 β 2 n e w β_2^{new} β2new约束条件:

  1. y 1 y 2 < 0 y_1y_2<0 y1y2<0
    此时存在 β 2 − β 1 β_2-β_1 β2β1为常数,那么 β 2 n e w − β 1 n e w = β 2 o l d − β 1 o l d β_2^{new}-β_1^{new}=β_2^{old}-β_1^{old} β2newβ1new=β2oldβ1old,那么存在:
    0 ≤ β 1 n e w = β 2 n e w − ( β 2 o l d − β 1 o l d ) ≤ C = > m a x ( 0 , β 2 o l d − β 1 o l d ) ≤ β 2 n e w ≤ m i n ( C , C + ( β 2 o l d − β 1 o l d ) ) 0≤β_1^{new}=β_2^{new}-(β_2^{old}-β_1^{old})≤C\\ =>max(0,β_2^{old}-β_1^{old})≤β_2^{new}≤min(C,C+(β_2^{old}-β_1^{old})) 0β1new=β2new(β2oldβ1old)C=>max(0,β2oldβ1old)β2newmin(C,C+(β2oldβ1old))
  2. y 1 y 2 > 0 y_1y_2>0 y1y2>0
    此时存在 β 2 + β 1 β_2+β_1 β2+β1为常数,那么 β 2 n e w + β 1 n e w = β 2 o l d + β 1 o l d β_2^{new}+β_1^{new}=β_2^{old}+β_1^{old} β2new+β1new=β2old+β1old,那么存在:
    0 ≤ β 1 n e w = ( β 2 o l d + β 1 o l d ) − β 2 n e w ≤ C = > m a x ( 0 , ( β 2 o l d + β 1 o l d ) − C ) ≤ β 2 n e w ≤ m i n ( C , β 2 o l d + β 1 o l d ) 0≤β_1^{new}=(β_2^{old}+β_1^{old})-β_2^{new}≤C\\=>max(0,(β_2^{old}+β_1^{old})-C)≤β_2^{new}≤min(C,β_2^{old}+β_1^{old}) 0β1new=(β2old+β1old)β2newC=>max(0,(β2old+β1old)C)β2newmin(C,β2old+β1old)
    若计算得到的 β 2 n e w β_2^{new} β2new超出了这个范围,那么就置为对应的边界值,记上界为 H H H,下界为 L L L,那么 β β β的更新可以写为:
    β n e w = { H ,              β n e w > H β n e w ,      L ≤ β n e w ≤ L L ,              β n e w < L β^{new}=\left\{ \begin{array}{cc} H,\;\;\;\;\;\;β^{new}>H \\ β^{new},\;\;L≤β^{new}≤L\\ L,\;\;\;\;\;\;β^{new}<L \end{array} \right. βnew= H,βnewHβnew,LβnewLL,βnewL到这里,就可以完成对一对参数的更新。

1.5.3.b的更新

b b b是超平面的偏置,每次更新参数后,也要改变 b b b
根据一开始的假设,若一个点为支持向量,存在 y ( w T x + b ) = 1 y(w^Tx+b)=1 y(wTx+b)=1,两边同乘以 y i y_i yi并移项,得到 b = y − w T x b=y-w^Tx b=ywTx,进一步带入 w T w^T wT,得到:
b j = y j − ∑ i = 1 m y i β i k i , j b_j=y_j-∑_{i=1}^{m}y_iβ_ik_{i,j} bj=yji=1myiβiki,j带入 j = 1 j=1 j=1得到:
b 1 n e w = y 1 − ∑ i = 1 m y i β i k i , 1 = y 1 − ∑ i = 3 m y i β i k i , 1 − y 1 β 1 n e w k 1 , 1 − y 2 β 2 n e w k 1 , 2 = y 1 − f ( x 1 ) + y 1 β 1 o l d k 1 , 1 + y 2 β 2 o l d k 2 , 1 + b 1 o l d − y 1 β 1 n e w k 1 , 1 − y 2 β 2 n e w k 1 , 2 = − e 1 + y 1 k 1 , 1 ( β 1 o l d − β 1 n e w ) + y 2 k 1 , 2 ( β 2 o l d − β 2 n e w ) + b o l d b_1^{new}=y_1-∑_{i=1}^{m}y_iβ_ik_{i,1}\\ =y_1-∑_{i=3}^{m}y_iβ_ik_{i,1}-y_1β_1^{new}k_{1,1}-y_2β_2^{new}k_{1,2}\\ =y_1-f(x_1)+y_1β_1^{old}k_{1,1}+y_2β_2^{old}k_{2,1}+b_1^{old}-y_1β_1^{new}k_{1,1}-y_2β_2^{new}k_{1,2}\\ =-e_1+y_1k_{1,1}(β_1^{old}-β_1^{new})+y_2k_{1,2}(β_2^{old}-β_2^{new})+b^{old} b1new=y1i=1myiβiki,1=y1i=3myiβiki,1y1β1newk1,1y2β2newk1,2=y1f(x1)+y1β1oldk1,1+y2β2oldk2,1+b1oldy1β1newk1,1y2β2newk1,2=e1+y1k1,1(β1oldβ1new)+y2k1,2(β2oldβ2new)+bold同理可得 b 2 b_2 b2
b 2 n e w = − e 2 + y 1 k 1 , 2 ( β 1 o l d − β 1 n e w ) + y 2 k 2 , 2 ( β 2 o l d − β 2 n e w ) + b o l d b_2^{new}=-e_2+y_1k_{1,2}(β_1^{old}-β_1^{new})+y_2k_{2,2}(β_2^{old}-β_2^{new})+b^{old} b2new=e2+y1k1,2(β1oldβ1new)+y2k2,2(β2oldβ2new)+bold由KKT条件可知,当 β i β_i βi满足 0 < β i ≤ C 0<β_i≤C 0βiC时,此时该点为支持向量,此时可用上式计算,满足 b n e w = b 1 n e w = b 2 n e w b^{new}=b_1^{new}=b_2^{new} bnew=b1new=b2new。否则当 β i = 0 β_i=0 βi=0,两个乘子都在边界上,且两者边界大小不一致,此时 b 1 , b 2 b_1,b_2 b1,b2中间的值就是和KKT条件一致的阈值,SMO选取中间点作为新的阈值,即 b n e w = ( b 1 n e w + b 2 n e w ) / 2 b^{new}=(b_1^{new}+b_2^{new})/2 bnew=(b1new+b2new)/2,总之都是两个的均值。(这里不是很理解,感觉大致意思就是如果两个点都满足满足KKT条件,那么距离中间的超平面距离一定是一样的,所以大小一致,否则要更新?)

简单说一下利用松弛变量证明KKT条件(β和点是否为支持向量的关系)的思路(详细可以参考博客),针对不等式约束,通过添加正数因子将其转为等式约束
β g ( w ) ≤ 0 = > β ( g ( w ) + a 2 ) = 0 β ≥ 0 g ( w ) = y i ( w T x + b ) − 1 βg(w)≤0=>β(g(w)+a^2)=0\\ \beta≥0\\ g(w)=y_i(w^Tx+b)-1 βg(w)0=>β(g(w)+a2)=0β0g(w)=yi(wTx+b)1这个式子会出现在拉格朗日乘子中,求导后可以得到两个有关的公式:
∂ L ∂ a = 2 β a = 0 ∂ L ∂ β = g ( w ) + a 2 = 0 \frac{\partial L}{\partial a}=2βa=0\\ \frac{\partial L}{\partial β}=g(w)+a^2=0 aL=2βa=0βL=g(w)+a2=0要求极值,因此令其为0,可得 β a = 0 βa=0 βa=0,此时有两种情况,分别是 a = 0 a=0 a=0 β = 0 β=0 β=0

  1. a = 0 , β ≠ 0 a=0,β≠0 a=0,β=0,此时 g ( w ) = 0 g(w)=0 g(w)=0,而 g ( w ) = 0 g(w)=0 g(w)=0就表示该点为支持向量。

  2. a ≠ 0 , β = 0 a≠0,β=0 a=0,β=0,此时 g ( w ) < 0 g(w)<0 g(w)<0,不是支持向量。

因为 0 ≤ β ≤ C 0≤β≤C 0βC,因此就可以看做若 0 < β ≤ C 0<β≤C 0<βC,也就是不等于0,那么点为支持向量,否则不是支持向量,这也是KKT条件之一。

1.6.线性不可分

前面叙述的前提条件都是线性可分,但是实际情况中很多时候不存在线性可分的结果,那么此时就需要改进原函数使其能够适应这种异常情况。
此部分参考,知乎的详细说明
有两种不可分情况:样本线性不可分和问题线性不可分,前者是由于采样导致,后者是问题本身决定,解决方案分别是软间隔支持向量机(惩罚项)和广义线性化(核函数)

1.6.1软间隔支撑向量机

未解决样本线性不可分的问题,这种向量机允许少数样本点在支持向量之间,通过加入松弛项 γ \gamma γ来优化求解:
y i ( w T x + b ) ≥ 1 − γ i y_i(w^Tx+b)≥1-γ_i yi(wTx+b)1γi当然,这个值一定是越小越好,因此优化目标可写为:
m i n ( 1 2 ∣ ∣ w ∣ ∣ + C ∑ i = 1 m γ i ) s . t .    y i ( w T x + b ) ≥ 1 − γ i min(\frac{1}{2}||w||+C∑_{i=1}^{m}γ_i)\\ s.t. \;y_i(w^Tx+b)≥1-γ_i min(21∣∣w∣∣+Ci=1mγi)s.t.yi(wTx+b)1γi
这个 C C C就是惩罚的系数, C ∑ i = 1 m γ i C∑_{i=1}^{m}γ_i Ci=1mγi为惩罚项,

  1. C C C越大,那么松弛变量的影响更加倾向于0,那么最终的结果越接近标准的线性支持向量机
  2. C C C越小,松弛变量可以有较大的影响,此时对于不在支持向量间的点有更高的容忍度。

1.6.2.广义线性化

这一篇写的比较好,举了一些例子
广义线性化主要是将特征映射到更高的维度,解决在根本上无法线性可分的问题,解决方法就是核函数

可以知道, S V M SVM SVM的求解目标如下:
max ⁡ β ≥ 0 ( ∑ i = 1 m β i − 1 2 ∑ i , j = 1 m β j β i y j y i x j T x i ) s . t .    ∑ i = 1 m y i β i = 0 \max\limits_{β≥0}(∑_{i=1}^{m}β_i-\frac{1}{2}∑_{i,j=1}^{m}β_jβ_iy_jy_ix_j^Tx_i)\\ s.t. \;∑_{i=1}^{m}y_iβ_i=0 β0max(i=1mβi21i,j=1mβjβiyjyixjTxi)s.t.i=1myiβi=0核函数主要是对 x T x x^Tx xTx部分进行替换,核函数需要满足:
φ ( x i ) φ ( x j ) = K ( x i , x j ) φ(x_i)φ(x_j)=K(x_i,x_j) φ(xi)φ(xj)=K(xi,xj)这个表达式左边的意思就是对两个点分别升维后进行点积操作,而右边的 K K K就是核函数,是一个关于 x i , x j x_i,x_j xi,xj的函数。这就相当于可以直接由原来未升维的点 x i , x j x_i,x_j xi,xj得到点积的结果,这样可以大大减少计算量。
常用的核函数有下面几种:

最常用的就是高斯核,这个是一个 n n n维的超圆,但是计算量比较大。(详细的介绍

2.代码

下面是代码实现的部分,我实现了一个比较简单的版本(没考虑更复杂的核函数等),这里我先看了一遍知乎老哥的实现,然后全程自己写了一遍,最后调试通过了,应该没什么大问题。
下面的左边是初始的优化目标,右边是迭代30轮候的,可以看到基本不变化,也就是收敛了。
在这里插入图片描述
下面是对于训练样本的预测,其中加大的双环表示支持向量,绿色的和红色的支持向量应该距离中间的分类超平面有着相同距离。
在这里插入图片描述
有个问题是迭代次数设置多了,画出来的超平面有问题,我猜可能是过拟合?不是很清楚,有知道的可以评论区告诉我。
最后给出完整的代码,注释非常详细,大家可以自行体味。

# 尝试复现SVM
import numpy as np
from matplotlib import pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False

def load_data():
    np.random.seed(0)
    x1= np.random.uniform(1,6,(50)).reshape(-1,1)
    np.random.seed(100)
    x2= np.random.uniform(8,15,(50)).reshape(-1,1)
    np.random.seed(100)
    y1=1.5*x1+10
    y2=1.9*x2-7
    np.random.seed(200)
    y1 += np.random.uniform(1, 3, (50)).reshape(-1,1)
    np.random.seed(300)
    y2 += np.random.uniform(2, 10, (50)).reshape(-1,1)
    tmp1 = np.hstack((x1,y1,np.ones(50).reshape(-1,1)))
    tmp2 = np.hstack((x2,y2,-np.ones(50).reshape(-1,1)))
    data = np.vstack((tmp1,tmp2))
    idx_list = np.random.choice(100,100,replace=False)
    ans = np.zeros((100,3))
    for i,idx in enumerate(idx_list):
        ans[i]=data[idx]
    return ans[:,:-1],ans[:,-1]

class MySVM():
    def fit(self,x,y,epochs,C): # 训练
        y = y.reshape(-1,1)
        samples = x.shape[0] # 样本数,也就是m
        features = x.shape[1] # 特征数
        print('输入共%d个特征,样本数为%d'%(features,samples))
        beta = np.zeros((samples,1)) # β
        b = 0 # b
        target = np.ones((1, samples)) @ beta
        for i in range(samples):
            for j in range(samples):
                target -= 1 / 2 * beta[i] * beta[j] * y[i] * y[j] + x[i] @ x[j].T
        print('初始优化目标:%.2f' % (target))
        for epoch in range(epochs):
            print('epoch:',epoch+1)
            for i in range(samples): # 每次选取i和另一个数j作为更新数对
                while True:
                    j = np.random.choice(samples,1,replace=False)[0] # 随机选择两个要更新的
                    if j!=i:
                        break
                # print('当前优化,i=%d,j=%d'%(i,j))
                w_T = (beta * y).T @ x  # w^T=∑βyx=(βyx).T,β、y都是列向量,所以转置
                # print(w_T.shape) # (1,2)
                # 下面计算β_j^{new},把公式的2对应j,i对应1
                k_i_i = x[i]@x[i].T
                k_i_j = x[i]@x[j].T
                k_j_j = x[j]@x[j].T
                K = 2*k_i_j-k_i_i-k_j_j # 计算系数k
                fx_i = w_T@x[i].T+b
                fx_j = w_T@x[j].T+b
                e_i = fx_i-y[i]
                e_j = fx_j-y[j]
                beta_old_i = beta[i]
                beta_old_j = beta[j]
                beta_new_j = beta_old_j-y[j]*(e_i-e_j)/K
                # 裁剪beta_new_j
                if y[i]==y[j]: # 同号
                    L = max(0,beta_old_i+beta_old_j-C)
                    H = min(C,beta_old_i+beta_old_j)
                    if beta_new_j<L:
                        beta_new_j=L
                    elif beta_new_j>H:
                        beta_new_j=H
                else:
                    L = max(0, beta_old_j - beta_old_i)
                    H = min(C, C + beta_old_j - beta_old_i)
                    if beta_new_j < L:
                        beta_new_j = L
                    elif beta_new_j > H:
                        beta_new_j = H
                # 因为β_1^{old}y_1+β_2^{old}y_2=β_1^{new}y_1+β_2^{new}y_2=γ => β_1^{new}=y_1(γ-β_2^{new}y_2)
                # 可以基于此解出beta_new_i,因为上面的裁剪,可以保证下面解出来的一定在[0,C]之间
                gamma = (beta_old_i*y[i]+beta_old_j*y[j])
                beta_new_i = y[i]*(gamma-beta_new_j*y[j])
                # 更新参数b
                b_new_i = -e_i+y[i]*k_i_i*(beta_old_i-beta_new_i)+y[j]*k_i_j*(beta_old_j-beta_new_j)+b
                b_new_j = -e_j+y[i]*k_i_j*(beta_old_i-beta_new_i)+y[j]*k_j_j*(beta_old_j-beta_new_j)+b
                # b = (b_new_i+b_new_j)/2 # 一开始写的,发现好像不对,对照了参考博客
                if beta[i] > 0:
                    b = b_new_i
                elif beta[j] > 0:
                    b = b_new_j
                else:
                    b = (b_new_i+b_new_j)/2
                beta[i]=beta_new_i
                beta[j]=beta_new_j
            # 计算优化目标
            target = np.ones((1,samples))@beta
            for i in range(samples):
                for j in range(samples):
                    target-=1/2*beta[i]*beta[j]*y[i]*y[j]+x[i]@x[j].T
            print('优化目标:%.2f'%(target))
        # print(beta)
        self.beta = beta
        self.w_T = w_T
        self.b = b

    def predict(self,x):
        pred = np.sign(self.w_T@x.T+self.b).reshape(-1,1)
        return pred

if __name__ == '__main__':
    X,y = load_data() # 产生数据
    svm = MySVM()
    svm.fit(X,y,epochs=30,C=0.6) # C不知道怎么设置,随便设置一个,参考了博客
    res=svm.predict(X)
    cnt = 0
    for i in range(X.shape[0]):
        if res[i] != y[i]:
            cnt+=1
    print("预测错误%d个"%(cnt))

    # 对每个数据点绘制,标出特殊的
    beta = svm.beta
    for i in range(X.shape[0]):
        if res[i]==-1:
            plt.scatter(X[i,0],X[i,1],marker='^',s=20,color='g',facecolors='none')
            if beta[i]>0.0001: # 支持向量
                plt.scatter(X[i,0],X[i,1],marker='^',s=100,color='g',facecolors='none')
        else:
            plt.scatter(X[i,0],X[i,1],marker='o',s=20,color='r',facecolors='none')
            if beta[i]>0.0001: # 支持向量
                plt.scatter(X[i,0],X[i,1],marker='o',s=100,color='r',facecolors='none')
    # 解出两个在截距,也就是交于x1和x2
    w_T = svm.w_T[0]
    b=svm.b
    b1 = -b/w_T[0] # x1轴
    b2 = -b/w_T[1] # x2轴
    k = -b2/b1 # y=kx+b,b就是b2
    x = np.linspace(min(X[:,0]),max(X[:,0]),1000)
    y = k*x+b2
    plt.plot(x,y,linestyle='--')
    plt.show()

总结一下,机器向量机的数学推导相对来说确实比较繁琐,好几个地方没有看懂,翻了很多博客才大概理解,有的地方我感觉也没有完全参透,在以后的学习中再慢慢体味吧!
下面是主要的参考博客:
1.知乎:SVM的推导和求解,但是感觉前面的推导有点冗余
2.CSDN,也是详解,前面的数学部分整理的很详细,后面的相对不够详细
3.微信,相对简略,省略了很多,前面的讲解比较好
4.知乎,主要是SMO部分,比较详细
5.CSDN,主要是介绍SMO,在α的介绍部分比较容易理解,有代码实现

  • 31
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值