前言:仅个人小记。参看https://blog.csdn.net/qq_25847123/article/details/108058804。
大部分样本线性可分,总体线性不可分。
某些样本点不能满足函数间隔大于等于 1 1 1 这个约束条件,软间隔策略就是对每个样本点引入一个松弛变量 ξ ≥ 0 \xi\geq 0 ξ≥0。是的函数间隔加上松弛变量是大于等于 1 1 1 的。此时,之前硬间隔最大化中的约束条件更变为
y i ( w ⋅ x i + b ) ≥ 1 − ξ i y_i(\boldsymbol{w}\cdot \boldsymbol{x}_i+b)\geq 1{\color{red}-\xi_i} yi(w⋅xi+b)≥1−ξi
同时,对每个松弛变量 ξ i \xi_i ξi 支付一个代价 ξ i \xi_i ξi。目标函数更变为
1 2 ∣ ∣ w ∣ ∣ 2 + C ∑ i = 1 N ξ i \frac{1}{2}||w||^2{\color{red}+C\sum_{i=1}^N\xi_i} 21∣∣w∣∣2+Ci=1∑Nξi
C C C 成为惩罚参数,取决于实际的应用场景。 C C C 值越大,则对误分类的惩罚越大, C C C 值越小,对误分类的惩罚越小。现在,最小化目标函数意味着:1) 使得 1 2 ∣ ∣ w ∣ ∣ 2 \frac{1}{2}||w||^2 21∣∣w∣∣2 尽量小即间隔尽量大,同时使误分类点的个数尽量小, C C C 是调和二者的系数。
线性不可分的线性支持向量机的学习问题更变为如下凸二次规划问题(原始问题):
max w , b 1 2 ∣ ∣ w ∣ ∣ 2 + C ∑ i = 1 N ξ i s . t . y i ( w x i + b ) ≥ 1 − ξ i , i = [ 1 , N ] ξ i ≥ 0 , i = 1 , 2 , . . . , N \begin{gathered}\max_{\boldsymbol{w},b}\frac{1}{2}||w||^2+{\color{red}C\sum_{i=1}^N\xi_i}\\ \mathsf{s.t.} y_i(\boldsymbol{w}\boldsymbol{x}_i+b)\geq 1{\color{red}-\xi_i},i=[1,N]\\ {\color{red}\xi_i\geq 0},i=1,2,...,N \end{gathered} w,bmax21∣∣w∣∣2+Ci=1∑Nξis.t.yi(wxi+b)≥1−ξi,i=[1,N]ξi≥0,i=1,2,...,N
可以证明 , w \boldsymbol{w} w的解是唯一的,而 b b b可能不唯一,而是存在于一个区间(实际应用中,往往可以直接求出来)。
min α 1 2 ∑ i = 1 N ∑ i = 1 N α i α j y i y j ( x i x j ) − ∑ i = 1 N α i s . t . ∑ i = 1 N α i y i = 1 0 ≤ α i ≤ C , i = 1 , 2 , . . . , N \begin{gathered}\min_{\alpha}\frac{1}{2}\sum_{i=1}^{N}\sum_{i=1}^{N}\alpha_i\alpha_jy_iy_j(\boldsymbol{x}_i\boldsymbol{x}_j)-\sum_{i=1}^N\alpha_i\\ \mathsf{s.t.} \sum_{i=1}^N \alpha_iy_i=1\\ 0\leq \alpha_i{\color{red}\leq C}, i =1,2,...,N \end{gathered} αmin21i=1∑Ni=1∑Nαiαjyiyj(xixj)−i=1∑Nαis.t.i=1∑Nαiyi=10≤αi≤C,i=1,2,...,N
w ∗ = ∑ i = 1 N α i ∗ y i x i b ∗ = y j − ∑ i = 1 N α i ∗ y i ( x i x j ) \begin{gathered} w^*=\sum_{i=1}^N\alpha_i^*y_i\boldsymbol{x}_i\\ b^* = y_j-\sum_{i=1}^N \alpha_i^*y_i(\boldsymbol{x}_i\boldsymbol{x}_j) \end{gathered} w∗=i=1∑Nαi∗yixib∗=yj−i=1∑Nαi∗yi(xixj)
其中, j j j是对应一个 α ∗ \alpha^* α∗的分量 α j ∗ \alpha_j^* αj∗,满足 0 < α j ∗ < C 0<\alpha_j^*{\color{red}
和线性可分SVM的对偶形式的算法代码相比,只有很小的区别。具体地只有四处有区别,已经在代码中通过表述“!!!!”指明。
import matplotlib.pyplot as plt
import cvxopt
import numpy as np
# 软间隔最大化
C=.5 # 这个值逼近0好像会有问题 !!!!
dataset = np.array([[3,3],[4,3],[2.5,3],[2.8,2.6],[1,1],[1,2],[3,3.2]])
labels = np.array([1,1,1,1,-1,-1,-1])
#dataset = np.array([[3,3],[4,3],[1,1]])
#labels = np.array([1,1,-1])
#T = [(3,3,1),(4,3,1),(1,1,-1)] # 数据集,格式为 (x1,x2,y),其中y 为标签,取值-1,+1
n = len(dataset)
P = np.zeros((n,n))
for i in range(n):
for j in range(i+1):
P[i][j] = labels[i]*labels[j]*np.dot(dataset[i],dataset[j])
P[j][i] = P[i][j]
P = cvxopt.matrix(P)
q = cvxopt.matrix([-1.0]*n)
G = np.vstack((-np.identity(n),np.identity(n))) # !!!!!
# G = -np.identity(n)
G = cvxopt.matrix(G)
h = cvxopt.matrix(np.hstack((np.zeros(n),C*np.ones(n)))) #!!!!!
# h = cvxopt.matrix([0.0]*n)
A = cvxopt.matrix([label*1.0 for label in labels],(1,n))
b = cvxopt.matrix([0.0],(1,1))
sol = cvxopt.solvers.qp(P,q,G,h,A,b)
alpha = sol['x']
print(sol['x'])
# 计算分离超平面
w = np.array([0.0,0.0])
for i in range(n):
w += alpha[i]*labels[i]*dataset[i]
alphaPos = 0
for i in range(n):
if alpha[i] > 0 and alpha[i] < C:# !!!!!!
#if alpha[i] > 0:
alphaPos =i
break
t = 0
for i in range(n):
t += alpha[i]*labels[i]*np.dot(dataset[i],dataset[alphaPos])
b = labels[alphaPos]- t
print(w,b)
drawScatterPointsAndLine(dataset,labels,w,b)