機器學習4-支援向量機
阿新 • • 發佈:2021-06-10
師兄部落格原文地址
目錄@目錄
主要內容對應周志華西瓜書第六章。
一些問題
- 1、試計算樣本空間中的任意樣本點 到超平面(\(\bm{w}, b\))的距離。
- 設樣本空間中的某樣本點為\(\bm{x}=(x_1, x_2,...,x_n),n\)為樣本空間的維數。
超平面(\(\bm{w}, b\))其法向量為\(\bm{w}\),任取上面一點\(x_0\)有\(\bm{w}^T\bm{x}_0+b=0\)
則\(\bm{x}\)到超平面的距離即為\(\bm{x}\)到\(x_0\)的距離於\(\bm{w}\)方向上的投影。
\(\bm{x}\)到\(x_0\)的距離為:
到平面的距離為為:
\[\frac{|\bm{w}^T(\bm{x}-\bm{x}_0)|}{|\bm{w}|} =\frac{|\bm{w}^T\bm{x}+b|}{|\bm{w}|}\]- 2、試說明支援向量機對噪聲敏感的原因。
- SVM的目的是求出與支援向量有最大化距離的直線,以每個樣本為圓心,該距離為半徑做圓,可以近似認為圓內的點與該樣本屬於相同分類。如果出現了噪聲,那麼這個噪聲所帶來的錯誤分類也將最大化,所以SVM對噪聲是很敏感的。
- 3、試說明支援向量機引入軟間隔的意義。
- 現實任務中往往很難保證所有樣本在特徵空間中線性可分,而且嚴格的分割,其結果也有可能是過分割造成的。
軟間隔允許支援向量機在一些樣本上出錯以達到更好的分類效果。如下圖
如果讓全出的藍色點“出錯”,我們可以得到一個更寬的間隔,有更好的效果。
軟間隔可以減小過擬合以及噪聲的影響。 - 4、試寫出“軟間隔支援向量機”的對偶問題及其KKT條件。
- 軟間隔支援向量機:
則通過拉格朗日乘子法得到的拉格朗日函式如下:
令\(L(\bm{w},b,\bm{\alpha},\bm{\xi},\bm{\mu})\)對\(\bm{w},b,\xi_i\)求偏導可得:
\[\begin{aligned} \bm{w} &=\sum_{i=1}^m\alpha_iy_i \bm{x}_i\\ 0&=\sum_{i=1}^m\alpha_iy_i\\ C&= \alpha_i+\mu_i\tag{2} \end{aligned}\]將(2)式代入(1)式,有原問題的對偶問題:
\[\begin{aligned} \max\limits_{\bm{\alpha}} &\ \sum_{i=1}^m\alpha_i-\frac{1}{2}\sum_{i=1}^m\sum_{j=1}^m\alpha_i\alpha_jy_iy_j\bm{x}_i^T\bm{x}_j\\ s.t. &\ \sum_{i=1}^m\alpha_iy_i=0\\ & \ 0\le\alpha_i\le C,i=1,2,...,m. \end{aligned}\]對應的KKT條件要求:
\[\begin{cases} \alpha_i\ge0,\ \ \mu_i\ge0,\\ y_if(\bm{x}_i)-1+\xi_i\ge0,\\ \alpha_i(y_if(\bm{x}_i)-1+\xi_i)=0,\\ \xi_i\ge0,\ \ \mu_i\xi_i=0 \end{cases}\]- 5、試說明支援向量機引入核函式的意義。
- 不引入核函式的支援向量機只能在原本的空間線性劃分樣本,然而限時任務中在原始空間中很有可能不存在一個能正確劃分兩類樣本的超平面,故可將樣本從原始空間對映到一個更高維的空間去尋找一個合適的劃分超平面。
通過核函式對映到三維空間便線性可分:
LSSVM的Python實現
最小二乘支援向量機使用均方誤差作為軟間隔支援向量機中的替代損失,並修改約束有式:
\[\begin{aligned} \min\limits_{\bm{w},b,\xi} &\ \frac{1}{2}||\bm{w}||^2+\frac{1}{2}\gamma\sum_{i=1}^me^2_i\\ s.t. \ &\ y_i(\bm{w}^T\cdot \phi(\bm{x}_i)+b)\ge1-e_i, i=1,2,...,m \end{aligned} \]拉格朗日對偶為:
\[\begin{aligned} L(\bm{w},b,\bm{\alpha},\bm{e})= &\ \frac{1}{2}||\bm{w}||^2+\frac{1}{2} \gamma\sum_{i=1}^me^2_i\\ &\ +\sum_{i=1}^m\alpha_i(1-e_i-y_i(\bm{w}^T\cdot \phi(\bm{x}_i)+b)) \end{aligned}\]令\(L(\bm{w},b,\bm{\alpha},\bm{e})\)對\(\bm{w},b,e_i\)求偏導可得:
\[\begin{aligned} \bm{w} &=\sum_{i=1}^m\alpha_iy_i\phi(\bm{x}_i)\\ 0&=\sum_{i=1}^m\alpha_iy_i\\ \alpha_i&= \gamma_ie_i\\ 0&=1-e_i-y_i(\bm{w}^T\cdot \phi(\bm{x}_i)+b)\\ \end{aligned}\]通過計算可直接求得\(\bm{\alpha}\)和\(b\):
\[b=(y^T(\Omega+\frac{I}{\gamma})^{-1}y)^{-1}\times y^T(\Omega+\frac{I}{\gamma})^{-1}\vec1\\ \bm{\alpha}=(\Omega+\frac{I}{\gamma})^{-1}\times(\vec1-yb) \]其中:
\[\begin{aligned} \Omega_{ij}&=y_iy_j\phi(x_i)^T\phi(x_j)=y_iy_jK(x_i,x_j)\\ \vec1&=(1,1,...,1)^T \end{aligned}\]模型訓練
def trainLSSVM(kMat, trainY, gamma):
omiga = multiply([email protected], kMat)
rows = omiga.shape[0]
vecOne = ones((rows, 1))
H = omiga + eye(rows)/gamma
b = trainY.T@(linalg.inv(H)@vecOne)/(trainY.T@(linalg.inv(H)@vecOne))
alpha = linalg.inv(H)@(vecOne - trainY@b)
return alpha, b
核函式
def kernelmat(sigma, trainX, testX):
trainRows = trainX.shape[0]
if testX is None:
trainX2 = sum(trainX**2, 0)@ones((1, trainRows))
kMat = trainX2 + trainX2.T - 2*(trainX*trainX.T)
else:
testRows = testX.shape[0]
trainX2 = sum(trainX**2, 0)@ones((1, testRows))
testX2 = sum(testX**2, 0)@ones((1, trainRows))
kMat = trainX2 + testX2.T - 2*(trainX*testX.T)
kMat = -kMat/(sigma**2*2)
kMat = exp(kMat)
return kMat
模型使用
def simLSSVM(trainX, trainY, testX, alpha, b, sigma):
kMat = kernelmat(sigma, trainX, testX)
testY = kMat.T@(multiply(alpha, trainY))
testY = sum(testY, 0) + b
testY = sign(testY)
return testY
關於\(\gamma\)和\(\sigma\)
LSSVM模型在\(\gamma\)和\(\sigma\)確定的情況下是可以通過計算求出解析解的。然而因為有替代損失和核函式的存在,通常LSSVM模型需要優化兩個引數。
這裡以交叉驗證的錯誤率作為目標函式值,使用模擬退火法對其進行優化
交叉驗證
def crossvalidateCost(trainX, trainY, kMat, gamma, sigma, L):
rows = trainY.shape[0]
blockSize = rows/L
costs = zeros((L, 1))
vecIndex = range(0, rows)
vecIndex = mat(vecIndex)
i = 1
for x in costs:
if i == 0:
validation = blockSize*(i-1) + 1 + vecIndex
else:
validation = blockSize * (i - 1) + 1 + mat(range(0, blockSize))
training = setdiff1d(vecIndex, validation)
subK = kMat[training, training]
subX = trainX[training, :]
subY = trainY[training, :]
testX = trainX[validation, :]
trueY = trainY[validation, :]
[alpha, b] = trainLSSVM(subK, subY, gamma)
testY = simLSSVM(subX, subY, testX, alpha, b, sigma)
x = 1 - (sum(testY == trueY)/len(testY))
return mean(costs)
整體框架
# 優化gamma和sigma
gammaOrg = 10
sigmaOrg = 0.45
[gamma, sigma] = SAA(trainX, trainY, gammaOrg, sigmaOrg)
# 訓練模型
kMat = kernelmat(sigma, trainX, testX)
[alpha, b] = trainLSSVM(kMat, trainY, gamma)
# 分類
testY = simLSSVM(trainX, trainY, testX, alpha, b, sigma)
acc = sum(testY == trueY)/len(trueY)