ML:基礎技法學習
Package:scikit-learn
課程:
機器學習技法
簡介:第四講 soft-margin SVM (support vector machine)
建議的 Library
soft-margin SVM primal
QP of 個變數, 個條件
從
第一講得知
從
Pocket 得知,希望得到最小的錯誤總數
將兩者合併,並加入 C 參數,控制 trade-off
看是以 large margin 為主,還是 noise tolerance
可再簡化為
不是 linear,所以不再是 QP
而且也無法分辨錯誤的距離大小
若改成記錄違反 margin 的距離呢?並用此取代計數錯誤的數目
當 ,距離可為
可以以後面那項為代表,以 表示離 有多遠,可得
有 跟 ,共 個變數,再加上 個
並有兩個絛件,各有 個
soft-margin SVM dual
QP of 個變數, 個條件
利用 Lagrange multipliers,隱藏限制條件,此處將 用 & 取代
當 會發現
- 違反限制條件時,會導致
-
又因 針對 取 max 的緣故, 越大越好
-
又因
針對 取 max 的緣故, 越大越好
- 使得
- 符合限制條件時,會導致
又因 針對 取 max 的緣故, 與 兩者至少有一個必須為 0
-
又因
針對 取 max 的緣故, 與 兩者至少有一個必須為 0
- 使得
故此式子與原本的求解一樣,如下,只是限制條件被隱藏到 max 中
此時 仍在式子最外面,如何把它跟裡面的 交換呢?
這樣才能初步得到 2N 個變數的式子
任取一個 with ,因取 max 一定比任意還大,可得下式
那如果對 取 max,也不影響此等式,如下
比較直覺的想法,就像是「從最大的一群中取最小」一定 「從最小的一群中取最大」
目前的關係稱作 weak duality
但這還不夠,最好是 strong duality,才能初步得到 2N 個變數的式子
幸運的是,在 QP 中,只要滿足以下條件,便是 strong duality
- convex primal (原來的問題為 convex)
- feasible primal (原來的問題有解的,也就是線性可分)
- linear constraints (限制條件為線性的)
對於 SVM 滿足這些條件並不困難,故解以下的式子,如同解原本的式子
但如何把內部的 拿掉呢?
內部的問題,當最佳化時,必定符合
從以上的這些條件,可得
將限制條件移出
可得
求 共 個變數
限制條件 有 個,加上 ,共
與 Hard margin 只差在 有上限限制
Kernel soft-margin SVM
任意 ,則 =0 (by KKT)
但 來自 , 又來自 ,無法求解
利用另一條件,任意 ,則 (by KKT)
故當 ,則
同時滿足兩個條件的為 free SV,可得
仍會有 overfit 的風險,需小心選取
的意義
兩組 complementary slackness
-
-
- 即是違反的值
- 可視情況用在資料的解析上,何者有幫助、何者無幫助、何者可能有 noise
Model Selection
利用
validation 選擇合適的參數
橫軸為 C,縱軸為 , 對於 SVM 非常常用
為資料個數
假設擁有 N 個資料
當選擇的資料 ,其對應的 ,即是非 SV
也就是說即使被挑去做 validation 也不影響最佳化結果
而 non-SV 分類必為正確,故其
錯誤的定義是跟 0 的差值,畢竟對於 sign 而言,只要大過 0 或小過 0 即可
所以此時的 未取 sign,而放縮過的 ()
不是 0,就是 1,故
所以
下圖為 SV 的個數,但可看出並無法用來挑選最佳 model
因上面的式子只是表達其錯誤上限,實際上的錯誤還是未知
實際上是用來排除不合理的 model,再進行 的計算

- import numpy as np
- import matplotlib.pyplot as plt
- from sklearn import svm
- from sklearn.model_selection import cross_val_score
-
- # 訓練資料
- X = np.c_[(.4, -.7),
- (-1.5, -1),
- (-1.4, -.9),
- (-1.3, -1.2),
- (-1.1, -.2),
- (-1.2, -.4),
- (-.5, 1.2),
- (-1.5, 2.1),
- (1, 1),
- # --
- (1.3, .8),
- (1.2, .5),
- (.2, -2),
- (.5, -2.4),
- (.2, -2.3),
- (0, -2.7),
- (1.3, 2.1)].T
- Y = np.r_[[0] * 8 + [1] * 8]
-
- # C 越大表示越無法容忍錯誤
- C = 1
- # fit 表示訓練
- # x^Tx'
- g_svm_linear = svm.SVC(kernel='linear', C=C).fit(X, Y)
- # (5+10x^Tx')^3
- g_svm_poly = svm.SVC(kernel='poly', degree=3, coef0=5, gamma=10, C=C).fit(X, Y)
- # exp(-2|x-x'|^2)
- g_svm_rbf = svm.SVC(kernel='rbf', gamma=2, C=C).fit(X, Y)
-
- # title for the plots
- titles = ['linear kernel => $\mathbf{x}^T\mathbf{x}\'$',
- 'polynomial kernel => $(5+10\mathbf{x}^T\mathbf{x}\')^3$',
- 'Gaussian kernel => $e^{(-2|\mathbf{x}-\mathbf{x}\'|^2)}$',]
-
- # 產生 meshgrid,共 200x100 的點
- XX1, XX2 = np.mgrid[-2:2:200j, -3:3:100j]
-
- for i, g_svm in enumerate([g_svm_linear, g_svm_poly, g_svm_rbf]):
- # 5-Fold Cross Validation
- scores = cross_val_score(g_svm, X, Y, cv=5)
- # 平均埴
- m = scores.mean()
- # 標準差
- sd = scores.std()
-
- plt.subplot(3, 1, i + 1)
- # 調整之間的空白高度
- plt.subplots_adjust(hspace=.6)
-
- # 代進值,得到距離
- # 回傳判斷結果
- YY = g_svm.predict(np.c_[XX1.ravel(), XX2.ravel()])
- # 重新排列結果,符合 XX1
- YY = YY.reshape(XX1.shape)
-
- # 畫圖,contour 不填滿顏色,contourf 填滿顏色
- plt.contourf(XX1, XX2, YY, cmap=plt.cm.bone, alpha=0.5)
-
- # 得到 free SV 的距離
- margin = max(g_svm.decision_function(g_svm.support_vectors_))
- # 只取足夠距離的 free SV
- index0 = g_svm.decision_function(X[g_svm.support_[Y[g_svm.support_]==0]])+margin<0.1
- index1 = g_svm.decision_function(X[g_svm.support_[Y[g_svm.support_]==1]])-margin<0.1
- index = np.r_[index0, index1]
-
- # 畫出所有點
- plt.scatter(X[:, 0], X[:, 1], c=Y, cmap=plt.cm.Paired)
- # 將 free support vector 標示出來
- plt.scatter(g_svm.support_vectors_[index, 0], g_svm.support_vectors_[index, 1], color='g', linewidths=3, linestyle='-', s=100, facecolors='none')
-
-
- # 回傳距離
- YY = g_svm.decision_function(np.c_[XX1.ravel(), XX2.ravel()])
- # 重新排列結果,符合 XX1
- YY = YY.reshape(XX1.shape)
- # 畫出界線
- plt.contour(XX1, XX2, YY, colors=['k', 'k', 'k'], linestyles=['--', '-', '--'], levels=[-margin, 0, margin])
- # 標題
- plt.title('{} Accuracy: {:0.2f}$\pm${:0.2f}'.format(titles[i],m,sd*3))
-
- plt.show()
參考
sklearn.svm.SVC
留言
張貼留言