自動的網(wǎng)站制作智慧軟文網(wǎng)站
文章目錄
- 前言
- 分析
- 數(shù)據(jù)集線性可分情況下的支持向量機
- 原始問題凸優(yōu)化包解法
- 對偶問題凸優(yōu)化包解法
- 數(shù)據(jù)集線性不可分情況下的線性支持向量機與軟間隔最大化
前言
- 在支持向量機中,理論邏輯很簡單:最大化最小的幾何間隔。但是實際編寫代碼過程中有一個小點需要注意??偸前讯诸惖念悇e分為
0
和1
,這樣就導(dǎo)致我的目標(biāo)函數(shù)跟算法描述的就不一樣,所以求解結(jié)果就不正確。 - 同時還有第二個要注意的就是凸優(yōu)化包
cvxpy
中各種運算的表示方法,比如凸優(yōu)化中常見的二次方程的表示,變量的默認(rèn)形狀等,要查看官方文檔才能熟悉。變量的默認(rèn)形狀為列向量。
參考:
- 李航:統(tǒng)計學(xué)習(xí)方法
- CVXPY
分析
支持向量機算法中,我們的訓(xùn)練數(shù)據(jù)除了是兩種類別以外,類別的編號也有要求,分別是1
、-1
,只有這樣,我們才能求每個樣本所對應(yīng)的函數(shù)間隔 D = y i ( w x i + b ) D=y_i(wx_i+b) D=yi?(wxi?+b)和幾何間隔 D = y i w x i + b ∥ w ∥ 2 D=y_i\frac{wx_i+b}{\|w\|_2} D=yi?∥w∥2?wxi?+b?,在這種類別標(biāo)簽的情況下,預(yù)測值 w x i + b wx_i+b wxi?+b與真實值 y i y_i yi?之間的乘積才有意義。
預(yù)測與真實相同,乘積才會是大于0的;預(yù)測與真實相反,乘積就是小于0的。只有這樣后面的目標(biāo)函數(shù)最大化幾何間隔才有意義。
重新表述一下可分?jǐn)?shù)據(jù)集上支持向量機的目標(biāo)函數(shù)和約束條件:
max λ s.t. y i w x i + b ∥ w ∥ 2 ≥ λ \begin{align*} &\textbf{max}&\lambda \\ &\textbf{s.t.} &y_i\frac{wx_i+b}{\|w\|_2}\ge\lambda \end{align*} ?maxs.t.?λyi?∥w∥2?wxi?+b?≥λ?
如果我們使用類別標(biāo)簽為0
,1
,那么當(dāng)錯誤分類時,幾何間隔為0
,無法指導(dǎo)參數(shù)修改。所以必須要使用1
,-1
。
數(shù)據(jù)集線性可分情況下的支持向量機
此時有兩種求法,一種是用原始算法,直接用cvxpy
函數(shù)包求解原始的這個凸優(yōu)化問題,并把問題變?yōu)橄率鲂问?#xff1a;
max t ∥ w ∥ 2 s.t. y i ( w x i + b ) ≥ t \begin{align*} &\textbf{max}&\frac{t}{\|w\|_2} \\ &\textbf{s.t.} &y_i{(wx_i+b)}\ge t \end{align*} ?maxs.t.?∥w∥2?t?yi?(wxi?+b)≥t?
由于通過同比例放大w,b
可以實現(xiàn)條件中左邊的乘積大小的任意變換,所以我們修改t
為 1 1 1。上述凸優(yōu)化問題就變?yōu)?#xff1a;
min ∥ w ∥ 2 s.t. y i ( w x i + b ) ≥ 1 \begin{align*} &\textbf{min}&{\|w\|_2} \\ &\textbf{s.t.} &y_i{(wx_i+b)}\ge 1 \end{align*} ?mins.t.?∥w∥2?yi?(wxi?+b)≥1?
第二種方法就是將原始問題使用拉格朗日乘子法變換為對偶問題,將加入條件和拉格朗日乘子的拉格朗日函數(shù)進行求導(dǎo),并將求導(dǎo)得到的關(guān)系式帶入拉格朗日函數(shù),這樣就可以得到對偶問題。
原始問題凸優(yōu)化包解法
import numpy as np
import cvxpy as cp
#生成符合要求的樣本數(shù)據(jù)
np.random.seed(3)
train_x=np.random.randn(2,2)
weight_x=np.random.randn(2)
bias_x=np.random.randn(1)
train_y=np.where(train_x@weight_x+bias_x<0,-1,1).reshape(2,-1)
print(train_x,train_y)
#求解對偶凸優(yōu)化問題
w=cp.Variable(2)
b=cp.Variable(1)
obj=cp.Minimize(1/2*cp.sum_squares(w))
cons=[train_y[0]*(train_x@w+b)[0]>=1,train_y[1]*(train_x@w+b)[1]>=1]
prob=cp.Problem(obj,cons)
result=prob.solve()
#輸出拉格朗日乘子的和最優(yōu)化的目標(biāo)函數(shù)值以及權(quán)重w
print(f'w.value,result,b.value:{w.value,result,b.value}')
結(jié)果如下:
[[ 1.78862847 0.43650985][ 0.09649747 -1.8634927 ]] [[-1][ 1]]
w.value,result,b.value:(array([-0.41507783, -0.56418804]), 0.24529887505030906, array([-0.01130633]))
對偶問題凸優(yōu)化包解法
本例子中我們使用了小規(guī)模的數(shù)據(jù),只有兩個樣本,所以這兩個樣本肯定都是支持向量,也就是對應(yīng)的拉格朗日乘子都不為0,對于大規(guī)模樣本數(shù)據(jù)的情況,如果不在分界面上,那么對應(yīng)的拉格朗日乘子為0,也就不是支持向量。拉格朗日乘子不為0的肯定就是支持向量。
import numpy as np
import cvxpy as cp
#生成符合要求的樣本數(shù)據(jù)
np.random.seed(3)
train_x=np.random.randn(2,2)
weight_x=np.random.randn(2)
bias_x=np.random.randn(1)
train_y=np.where(train_x@weight_x+bias_x<0,-1,1).reshape(2,-1)
print(train_x,train_y)
#求解對偶凸優(yōu)化問題
alpha=cp.Variable(2)
obj=cp.Minimize(1/2*cp.quad_form(alpha,(train_x@train_x.T)*(train_y@train_y.T))-cp.sum(alpha))
cons=[alpha>=0,train_y.T@alpha>=0,train_y.T@alpha<=0]
prob=cp.Problem(obj,cons)
result=prob.solve()
#輸出拉格朗日乘子的和最優(yōu)化的目標(biāo)函數(shù)值以及權(quán)重w
print(f'alpha.value,result,w:{alpha.value,result,np.array(alpha.value.reshape(2,-1)*train_y*train_x).sum(axis=0)}')
#檢驗支持向量機求出的分離面是否與這兩個樣本之間的連線垂直
w=np.array(alpha.value.reshape(2,-1)*train_y*train_x).sum(axis=0)
np.array(train_x[0,:]-train_x[1,:]).reshape(1,-1)@np.array([-w[1]/w[0],1]).reshape(2,-1)
結(jié)果如下:
[[ 1.78862847 0.43650985][ 0.09649747 -1.8634927 ]] [[-1][ 1]]
alpha.value,result,w:(array([0.24529888, 0.24529888]), -0.24529887505030898, array([-0.41507783, -0.56418804]))
array([[-4.4408921e-16]])
至于參數(shù)b,我們可以通過支持向量所對應(yīng)的等式求出。
我們可以觀察一下原始問題與對偶問題的解答是否一致。
數(shù)據(jù)集線性不可分情況下的線性支持向量機與軟間隔最大化
軟間隔顧名思義就是給原來的間隔留下一點寬容量,給那些不容易分正確的留一點余地。同時對于這些余地進行懲罰所得到的分割面,以上面線性可分的數(shù)據(jù)做演示。
import numpy as np
import cvxpy as cp
#生成符合要求的樣本數(shù)據(jù)
np.random.seed(3)
train_x=np.random.randn(2,2)
weight_x=np.random.randn(2)
bias_x=np.random.randn(1)
train_y=np.where(train_x@weight_x+bias_x<0,-1,1).reshape(2,-1)
print(train_x,train_y)
#求解對偶凸優(yōu)化問題
w=cp.Variable(2)
b=cp.Variable(1)
softgap=cp.Variable(2)
obj=cp.Minimize(1/2*cp.sum_squares(w)+100*cp.sum(softgap))
cons=[train_y[0]*(train_x@w+b)[0]>=1-softgap[0],train_y[1]*(train_x@w+b)[1]>=1-softgap[1],softgap>=0]
prob=cp.Problem(obj,cons)
result=prob.solve()
#輸出拉格朗日乘子的和最優(yōu)化的目標(biāo)函數(shù)值以及權(quán)重w
print(f'w.value,result,b.value,softgap.value:{w.value,result,b.value,softgap.value}')
結(jié)果如下:
[[ 1.78862847 0.43650985][ 0.09649747 -1.8634927 ]] [[-1][ 1]]
w.value,result,b.value,softgap.value:(array([-0.41507783, -0.56418804]), 0.24529887505030906, array([-0.01130633]), array([-2.90746355e-22, 1.53881391e-22]))
可以看出在線性可分的的情況下軟間隔不起作用。
那么我們制造一些線性不可分的數(shù)據(jù),來測試一下。
import numpy as np
import cvxpy as cp
#生成符合要求的樣本數(shù)據(jù)
np.random.seed(3)
train_x=np.array([[0,0],[1,0],[2,0]])
train_y=np.array([-1,1,-1]).reshape(3,-1)
print(train_x,train_y)
#求解對偶凸優(yōu)化問題
w=cp.Variable(2)
b=cp.Variable(1)
softgap=cp.Variable(3)
obj=cp.Minimize(1/2*cp.sum_squares(w)+0.1*cp.sum(softgap))
cons=[train_y[0]*(train_x@w+b)[0]>=1-softgap[0],train_y[1]*(train_x@w+b)[1]>=1-softgap[1],train_y[2]*(train_x@w+b)[2]>=1-softgap[2],softgap>=0]
prob=cp.Problem(obj,cons)
result=prob.solve()
#輸出拉格朗日乘子的和最優(yōu)化的目標(biāo)函數(shù)值以及權(quán)重w
print(f'w.value,result,b.value,softgap.value:{w.value,result,b.value,softgap.value}')
結(jié)果如下:
[[0 0][1 0][2 0]] [[-1][ 1][-1]]
w.value,result,b.value,softgap.value:(array([9.07653476e-18, 0.00000000e+00]), 0.2, array([-1.]), array([ 8.59013373e-23, 2.00000000e+00, -8.59013423e-23]))