[ML] 機器學習技法:第三講 Kernel SVM

ML:基礎技法學習
Package:scikit-learn
課程:機器學習技法
簡介:第三講 Kernel SVM (support vector machine)

dual SVM model

minα   12αTQDα(1N×1)Tαsubject to   yTα=0αn0,for n=1,2,,N qn,m=ynymznTzm inner product in Rd~
znTzm=Φ(xn)TΦ(xm)

如何簡化 znTzm=Φ(xn)TΦ(xm) ?將 Φ(xn)TΦ(xm) 簡化為 K(xn,xm)

Kernel Hard-Margin SVM Algorithm


General Polynomial Kernel

KQ(x,x)=(ζ+γxTx)Q   with γ>0,ζ0
先從二次轉換來看
假設 Φ2(x)=(1,x1,x2,,xd,x12,x1x2,,x1xd,x2x1,x22,,x2xd,,xd2)
為求化簡,故同時包含 x1x2 & x2x1,即使兩者是完全一樣的
展開 轉換與內積可得
Φ2(x)TΦ2(x)=1+di=1xixi+i=1dj=1dxixjxixj=1+di=1xixi+i=1dxixij=1dxjxj=1+xTx+(xTx)(xTx) 可看到原本若轉換後再內積需要花 O(d~)=O(d2) 的時間,但展開後只需花原本維度的 O(d)

定義 轉換 Φ kernel function: KΦ(x,x)Φ(x)TΦ(x)
Φ2KΦ2(x,x)=1+(xTx)+(xTx)2
利用此特性,可將各個參數皆轉換與 ϕ 有關,如下
  • qn,m=ynymznTzm=ynymK(xn,xm)
  • SV(xs,ys) 取出一個
    b=yswTzs=ys(n=1Nαnynzn)Tzs=ysn=1NαnynznTzs=ysn=1NαnynK(xn,xs)
  • 最佳方程式可得
    gSVM(x)=sign(wTΦ(x)+b)=sign((n=1Nαnynzn)TΦ(x)+b)=sign(n=1NαnynznTΦ(x)+b)=sign(n=1NαnynΦ(xn)TΦ(x)+b)=sign(n=1NαnynK(xn,x)+b)
故計算效率已與 d~ 無關

那如何再小修一下 轉換 ϕ,加入 2γγγ>0 不然開根號會為虛數
Φ2(x)=(1,2γx1,,2γxd,γx12,γx1x2,,,γxd2)K2(x,x)=1+2γxTx+(xTx)2

那理論上 1 也可以替換為變數 ζζ0 不然開根號會為虛數
ζ 可為 0 是因為它不影響轉換,但 γ 為 0 會只剩下常數項,跟原來的目的完全違背
故可得到一簡單的算式
Φ2(x)=(ζ,2ζγx1,,2ζγxd,γx12,γx1x2,,,γxd2)K2(x,x)=ζ2+2ζγxTx+(γxTx)2=(ζ+γxTx)2 此結論可推廣至高次項,也只是略調整係數,故
KQ(x,x)=(ζ+γxTx)Q   with γ>0,ζ0
因使用 Polynomial Kernel,故稱作 Polynomial SVM
事實上調整 kernel 就等同在調整 margin definition
因 kernel 隱含映射的函數,不同的映射函數,即使對應到同樣的 R2xnzn 的位置也都不一樣
如下圖,SV 的點完全不同
因有最大化 margin 的限制,故即使是十次方,表示仍可接受,甚至 margin 為 0.1
Linear Kernel 就是最原本的線性轉換,K1(x,x)=(0+1xTx)1
記住,若 Linear Kernel 已足夠好,那就無需往下做,越簡單越準確

Infinite Dimensional Transform (Gaussian SVM)

K(x,x)=eγxx2   with γ>0Φ(x)=eγxTx(1,21γ1!(x1,x2,,xd),22γ2!(x12,x1x2,,xd2),23γ3!(x13,x12x2,,xd3),2iγi!(x1i,x1i1x2,,xdi),)
K(x,x)=eγxx2=eγ(xTx2xTx+xTx)=eγxTxeγxTxeγ2xTxby Taylor=eγxTxeγxTxi=0(2γxTx)ii!=i=0eγxTxeγxTx(2γxTx)ii!=i=0eγxTxeγxTx2iγi!2iγi!(xTx)i=i=02iγi!eγxTx2iγi!eγxTx(n=1dxnxn)i=eγxTxeγxTxi=02iγi!2iγi!(n=1dxnxn)i=eγxTxeγxTx(1+21γ1!21γ1!n1=1dxn1xn1+22γ2!22γ2!n1=1dxn1xn1n2=1dxn2xn2+23γ3!23γ3!n1=1dxn1xn1n2=1dxn2xn2n3=1dxn3xn3+)=eγxTxeγxTx(1+21γ1!21γ1!n1=1dxn1xn1+22γ2!22γ2!n1=1dn2=1dxn1xn2xn1xn2+23γ3!23γ3!n1=1dn2=1dn3=1dxn1xn2xn3xn1xn2xn3+)=eγxTxeγxTx(1+21γ1!21γ1!(x1,x2,,xd)(x1,x2,,xd)+22γ2!22γ2!(x12,x1x2,,xd2)(x12,x1x2,,xd2)+23γ3!23γ3!(x13,x12x2,,xd3)(x13,x12x2,,xd3)+)=Φ(x)TΦ(x)Φ(x)=eγxTx(1,21γ1!(x1,x2,,xd),22γ2!(x12,x1x2,,xd2),23γ3!(x13,x12x2,,xd3),2iγi!(x1i,x1i1x2,,xdi),) 可以看到其實就是各個次項的組合,從 0次項直到無限次項皆包含在內
gSVM(x)=sign(SVαnynK(xn,x)+b)=sign(SVαnyneγxxn2+b)
如上,解其實就是在 SV 上的高斯函數的線性組合
因為此特性也叫做 Radial Basis Function (RBF) kernel
能做無限多維,又有 maximum margin 限制,是否就很美好呢?不
γ 選太大時,仍會有 overfit 的風險
甚至無限大時就等同於 Kγ(x,x)=(x==x),完全跟訓練點一樣才會為 1

Kernel 比較

  • Kernel 代表著兩者之間的相似性,因為是內積
  • Linear Kernel
    • K(x,x)=xTx
    • 優點
      • 安全
      • 快速,使用特別的 QP solver
      • 可被解釋
    • 缺點
      • 若不是 線性可分 無法分類
  • Polynomial Kernel
    • K(x,x)=(ζ+γxTx)Q
    • Q 若很低次,有時候回到原本的 primal 解法,用特別的 solver,還比較快
    • 優點
      • 比 linear 限制少一點,不需要 線性可分
      • 透過 Q 表示限制轉換空間的維度
    • 缺點
      • 數值範圍太大會影響電腦處理
        |ζ+γxTx|
        小於 1 時,Q 比較大會近乎 0
        大於 1 時,Q 比較大會是很大的值 
      • 參數太多
  • Gaussian Kernel
    • K(x,x)=eγxx2
    • 優點
      • 最強大
      • 數值範圍比 polynomial 好
      • 參數只有一個
    • 缺點
      • 無法解釋在做什麼
      • 計算慢
      • 容易 overfit

Mercer's condition

可自定 kernel,只要 Kernel Matrix 滿足條件,以下為充要條件
  • symmetric
  • let kij=K(xi,xj),此 Kernel Matrix 必定是半正定
    K=[Φ(x1)TΦ(x1)Φ(x1)TΦ(x2)Φ(x1)TΦ(xN)Φ(x2)TΦ(x1)Φ(x2)TΦ(x2)Φ(x1)TΦ(xN)Φ(xN)TΦ(x1)Φ(xN)TΦ(x2)Φ(x1)TΦ(xN)]=[z1z2zN]T[z1z2zN]=ZZT
假設 K 為有效的 kernel function
kij=K(xi,xj)=Φ(xi)TΦ(xj)=Φ(xj)TΦ(xi)=K(xj,xi)=kji 內積兩者交換,值不變,故必定是對稱的
而對於任意向量 z
zTKz=izijkijzj=ijzikijzj=ijziΦ(xi)TΦ(xj)zj=ijzikΦk(xi)Φk(xj)zj=ijkziΦk(xi)Φk(xj)zj=kiziΦk(xi)jzjΦk(xj)=k(iziΦk(xi))20

程式碼

參數定義
  1. import numpy as np
  2. import matplotlib.pyplot as plt
  3. from sklearn import svm
  4.  
  5. # 訓練資料
  6. X = np.c_[(.4, -.7),
  7. (-1.5, -1),
  8. (-1.4, -.9),
  9. (-1.3, -1.2),
  10. (-1.1, -.2),
  11. (-1.2, -.4),
  12. (-.5, 1.2),
  13. (-1.5, 2.1),
  14. (1, 1),
  15. # --
  16. (1.3, .8),
  17. (1.2, .5),
  18. (.2, -2),
  19. (.5, -2.4),
  20. (.2, -2.3),
  21. (0, -2.7),
  22. (1.3, 2.1)].T
  23. Y = [0] * 8 + [1] * 8
  24.  
  25. # C 越大表示越無法容忍錯誤,故設定一很大的值 for hard margin
  26. C = 1e10
  27. # fit 表示訓練
  28. # x^Tx'
  29. g_svm_linear = svm.SVC(kernel='linear', C=C).fit(X, Y)
  30. # (5+10x^Tx')^3
  31. g_svm_poly = svm.SVC(kernel='poly', degree=3, coef0=5, gamma=10, C=C).fit(X, Y)
  32. # exp(-0.3|x-x'|^2)
  33. g_svm_rbf = svm.SVC(kernel='rbf', gamma=.3, C=C).fit(X, Y)
  34.  
  35. # title for the plots
  36. titles = ['linear kernel => $\mathbf{x}^T\mathbf{x}\'$',
  37. 'polynomial kernel => $(5+10\mathbf{x}^T\mathbf{x}\')^3$',
  38. 'Gaussian kernel => $e^{(-0.3|\mathbf{x}-\mathbf{x}\'|^2)}$',]
  39.  
  40. # 產生 meshgrid,共 200x100 的點
  41. XX1, XX2 = np.mgrid[-2:2:200j, -3:3:100j]
  42.  
  43. for i, g_svm in enumerate([g_svm_linear, g_svm_poly, g_svm_rbf]):
  44. plt.subplot(3, 1, i + 1)
  45. # 調整之間的空白高度
  46. plt.subplots_adjust(hspace=.6)
  47. # 代進值,得到距離
  48. # 回傳判斷結果
  49. YY = g_svm.predict(np.c_[XX1.ravel(), XX2.ravel()])
  50. # 重新排列結果,符合 XX1
  51. YY = YY.reshape(XX1.shape)
  52.  
  53. # 畫圖,contour 不填滿顏色,contourf 填滿顏色
  54. plt.contourf(XX1, XX2, YY, cmap=plt.cm.bone, alpha=0.5)
  55.  
  56. # 畫出所有點
  57. plt.scatter(X[:, 0], X[:, 1], c=Y, cmap=plt.cm.Paired)
  58. # 將 support vector 標示出來
  59. plt.scatter(g_svm.support_vectors_[:, 0], g_svm.support_vectors_[:, 1], color='g', linewidths=3, linestyle='-', s=100, facecolors='none')
  60.  
  61. # 得到 SV 的距離
  62. margin = np.mean(abs(g_svm.decision_function(np.c_[g_svm.support_vectors_[:, 0],g_svm.support_vectors_[:, 1]])))
  63. # 回傳距離
  64. YY = g_svm.decision_function(np.c_[XX1.ravel(), XX2.ravel()])
  65. # 重新排列結果,符合 XX1
  66. YY = YY.reshape(XX1.shape)
  67. # 畫出界線
  68. plt.contour(XX1, XX2, YY, colors=['k', 'k', 'k'], linestyles=['--', '-', '--'], levels=[-margin, 0, margin])
  69. # 標題
  70. plt.title(titles[i])
  71.  
  72. plt.show()

參考

支持向量机(三)核函数
sklearn.svm.SVC

留言