[ML] 機器學習技法:第五講 Kernel Logistic Regression

ML:基礎技法學習
Package:scikit-learn
課程:機器學習技法
簡介:第五講 Kernel Logistic Regression

SVM as Regularized Model

minb,w  12wTw+Cn=1Nmax(1yn(wTzn+b),0)
soft-margin SVM primal
minb,w,ξ  12wTw+Cn=1Nξnsubject to  yn(wTxn+b)1ξn and ξn0 for all n(xn,yn) 違反時,ξn=1yn(wTzn+b)
(xn,yn) 合法時,ξn=0
故可改寫為 ξn=max(1yn(wTzn+b),0)

minb,w  12wTw+Cn=1Nmax(1yn(wTzn+b),0) 仔細觀察,可發現這就是 L2 regularization 的變形而已
  • large margin fewer hyperplanes L2 regularization of short W
  • soft margin special err^
  • larger C or C smaller λ less regularization

regularized LogReg approximate SVM

  • linear score s=wTzn+b
  • err0/1(s,y)=[ys0]
  • err^SVM(s,y)=max(1ys,0)
  • errSCE(s,y)=log2(1+eys)
Linear Models for Classification 得知
errerr0/1,當縮小 err 時,相當於也是在做分類
而從圖中看來
ys+yserrSVM(s,y)0ys(ln 2)errSCE(s,y)0 故 L2-regularized logistic regression 其實就相當於在做 soft margin SVM

Platt's Model

g(x)=θ(A(wSVMTΦ(x)+bSVM)+B)=θ(A(SVαnynK(xn,x)+bSVM)+B)=θ(SVAαnynK(xn,x)+AbSVM+B)minA,B  1Nn=1Nlog(1+eyn(A(wSVMTΦ(x)+bSVMΦSVM(xn))+B)) ΦSVM(xn) 可視需求代入,像是 Kernel SVM 如上推導
該怎麼做,才能將 SVM 轉換為機率的表示呢?
簡單的想法如下圖
  • 若像左邊一樣,最後再將結果用 logistic function 轉換,但這就喪失了 LogReg 的 maximum likelihood 的意義了
  • 若像右邊一樣,先用 SVM 跑出初始值,再代入 LogReg,但這跟直接跑 LogReg 所得到的解是差不多的,所以 SVM 幾乎無任何作用,non-linear 也無法使用,像 kernel SVM 也無法應用在此
所以若改為先跑完 SVM,再運用 LogReg 修正一下呢?
g(x)=θ(A(wSVMTΦ(x)+bSVM)+B) 看起來可行,而且其實就是利用 A 調整 wSVM,利用 A & B 調整 bSVM
或是將 SVM 視為一種特別的轉換 ΦSVM(x),從多維轉換至一維,再進行處理
骨子裡仍可使用 SVM 的各種方法,也就是 ΦSVM(x) 可視需求代入,像是 Kernel SVM
  • 這不是 Z 空間中最好的 LogReg 解,只是還不錯的解,需用 KLR 得最好解
  • wSVM 夠好,通常 A>0
    假如 A<0,表示 SVM 在亂做,不然怎麼會完全反向
  • bSVM 夠好,通常 B0
  • 與原本 SVM 的邊界不一定一樣,因為 B 做了平移
  • 如何解 LogReg
    • GD
    • SGD
    • 甚至更簡單的方法,因為只有兩個變數

Kernel Logistic Regression (KLR)

Representer Theorem
claim: for any L2-regularized linear model
minw  λNwTw+1Nn=1Nerr(yn,wTzn) optimal w=n=1Nβnzn
最佳化 w 必是 zn 的線性組合
w=w+w
wspan(zn) & wspan(zn)
希望證得 w=0
反證法
假設存在 w
err(yn,wTzn)=err(yn,(w+w)Tzn)=err(yn,wTzn+wTzn0)=err(yn,wTzn) err 的值,不因 w 而變
wTw=(w+w)T(w+w)=wTw+2wTw+wTw=wTw+wTw>wTw 矛盾,因 err 固定,而 w 為最佳解,那麼在 wTw 為何 w 還可以比 w 更小
故最佳化 w 必是 zn 的線性組合
minβ  Ein(β)=minβ  λNn=1Nm=1NβnβmK(xn,xm)+1Nn=1Nln(1+eynm=1NβmK(xm,xn))=minβ  λNβTKβ+1Nn=1Nln(1+eynβTK(:,n)) 因無限制條件,可利用 GD/SGD/... 求解 Ein(β)=λN2KTβ+1Nn=1NynK(:,n)1+eynβTK(:,n)
根據 機器學習基石:第十講 Logistic Regression & 機器學習基石:第十四講 Regularization 可得
L2-regularized logistic regression
minw  Ein(w)=minw  λNwTw+Ein(w)=minw  λNwTw+1Nn=1Nln(1+eynwTzn)(w=n=1Nβnzn) minβ  Ein(β)=minβ  λN(n=1Nβnzn)Tn=1Nβnzn+1Nn=1Nln(1+eyn(m=1Nβmzm)Tzn)=minβ  λNn=1Nm=1NβnznTβmzm+1Nn=1Nln(1+eyn(n=1NβmzmTzn))(znTzm=K(xn,xm))=minβ  λNn=1Nm=1NβnβmznTzm+1Nn=1Nln(1+eyn(n=1NβmK(xm,xn)))=minβ  λNn=1Nm=1NβnβmK(xn,xm)+1Nn=1Nln(1+eyn(n=1NβmK(xm,xn)))=minβ  λNn=1Nm=1NβnβmK(xn,xm)+1Nn=1Nln(1+eynm=1NβmK(xm,xn))=minβ  λNβTKβ+1Nn=1Nln(1+eynβTK(:,n))Ein(β)=λN2KTβ+1Nn=1N11+eynβTK(:,n)eynβTK(:,n)(ynK(:,n))=λN2KTβ+1Nn=1NynK(:,n)1+eynβTK(:,n)
  • 兩種不同的角度
    • KLR = linear model of β
      • n=1Nm=1NβnβmK(xn,xm)=βTKβ,一種特別的 regularizer
      •  m=1NβmK(xm,xn) 可視同 β 與 轉換過的資料 作內積
      • kernel 作用在 轉換 與 regularizer
    • KLR = linear model of w
      • 藏在 kernel 中,且為 L2 regularizer
  • β
    • 長度為 N,同資料個數
    • βn 通常不為 0,與 αn 相反

程式碼

  1. import matplotlib.pyplot as plt
  2. import numpy as np
  3.  
  4. from sklearn.svm import SVC
  5.  
  6.  
  7. # kernel logistic regression
  8. class KLR:
  9. def __init__(self):
  10. pass
  11. # 高斯 kernel
  12. def kernel_rbf(self, xn, xm):
  13. kv = np.exp(-self.gamma * (np.linalg.norm(xn-xm)**2))
  14. return kv
  15. # 產生 kernel matrix
  16. def kernelMatrix(self, x):
  17. m = []
  18. for xn in x:
  19. row = [self.kernel_rbf(xn, xm) for xm in x]
  20. m.append(row)
  21.  
  22. return np.array(m)
  23. # error function
  24. # lamda/N B^T K B + 1/N log(...)
  25. def errFuc(self, x, y):
  26. sum = 0
  27. for n in range(self.N):
  28. sum += np.log(1+np.exp(-y[n] * np.dot(self.beta,self.K[:,n])))
  29. return self.lambda_/self.N * np.dot(self.beta, self.K).dot(self.beta) + sum/self.N
  30. # 梯度方程式
  31. def gradFuc(self, x, y):
  32. err = np.array([0] * self.N)
  33. for n in range(self.N):
  34. val = y[n] * np.dot(self.beta, self.K[:,n])
  35. temp = -y[n] * self.K[:,n] / (1 + np.exp(val))
  36. err = np.add(err, temp)
  37.  
  38. val = self.lambda_/self.N * 2 * np.dot(self.K, self.beta) + 1/self.N * err
  39.  
  40. return val
  41. # 訓練
  42. def fit(self, x, y, gamma=0.5, lambda_=0.1, n=1, max_number=1000):
  43. # 初始化
  44. y[y==0] = -1
  45. self.N = len(y)
  46. self.beta = [1] * self.N
  47. self.gamma = gamma
  48. self.lambda_ = lambda_
  49. self.x = x
  50. self.K = self.kernelMatrix(x)
  51. t = 0
  52. while True:
  53. g = self.gradFuc(x, y)
  54. self.beta = self.beta - n*g
  55. err = self.errFuc(x,y)
  56. # print('{:4d} n:{:.3f} err : {}'.format(t, n, err))
  57. t += 1
  58. if t > max_number or err < 0.01:
  59. break
  60. # 預測結果
  61. # w = sigma(b_n z_n)
  62. # g = sigma(b_n kernel(x_n,x))
  63. def predict(self, X):
  64. k = []
  65. for x in X:
  66. m = []
  67. for xn in self.x:
  68. m.append(self.kernel_rbf(xn, x))
  69. k.append(m)
  70. k = np.array(k).T
  71. p = np.dot(np.array(self.beta), k)
  72. return p
  73.  
  74. # 訓練資料
  75. X = np.c_[(.4, -.7),
  76. (-1.5, -1),
  77. (-1.4, -.9),
  78. (-1.3, -1.2),
  79. (-1.1, -.2),
  80. (-1.2, -.4),
  81. (-.5, 1.2),
  82. (-1.5, 2.1),
  83. (1, 1),
  84. # --
  85. (1.3, .8),
  86. (1.2, .5),
  87. (.2, -2),
  88. (.5, -2.4),
  89. (.2, -2.3),
  90. (0, -2.7),
  91. (1.3, 2.1)].T
  92. Y = np.r_[[0] * 8 + [1] * 8]
  93.  
  94. # C 越大表示越無法容忍錯誤
  95. C = 1.0
  96.  
  97. # exp(-2|x-x'|^2)
  98. gamma = 2
  99. classifiers = {"Platt's Model": SVC(kernel='rbf', gamma=gamma, C=C, probability=True),
  100. 'KLR': KLR(),
  101. }
  102. # 多少分類器
  103. n_classifiers = len(classifiers)
  104.  
  105. # 產生 meshgrid,共 100x100 的點
  106. XX1, XX2 = np.mgrid[-3:3:200j, -4:4:200j]
  107. # 打平合併
  108. Xfull = np.c_[XX1.ravel(), XX2.ravel()]
  109.  
  110. # 因是 dict 所以顯示不一定照順序
  111. for index, (name, classifier) in enumerate(classifiers.items()):
  112. # 訓練資料
  113. classifier.fit(X, Y)
  114. # 得到機率
  115. if name == "Platt's Model":
  116. # 取 1 的機率值,因接近 1 則機率越大,若取 0 會相反
  117. probas = classifier.predict_proba(Xfull)[:, 1]
  118. elif name == 'KLR':
  119. probas = classifier.predict(Xfull)
  120. plt.subplot(n_classifiers, 1, index + 1)
  121. # 調整之間的空白高度
  122. plt.subplots_adjust(hspace=.6)
  123. # 重新排列結果,符合 XX1
  124. probas = probas.reshape(XX1.shape)
  125. # 畫圖,contour 不填滿顏色,contourf 填滿顏色
  126. im = plt.contourf(XX1, XX2, probas, cmap="winter")
  127. # 依圖畫出 colorbar
  128. plt.colorbar(im)
  129. # 畫出所有點
  130. plt.scatter(X[:, 0], X[:, 1], c=Y, cmap=plt.cm.Paired)
  131. # 標題
  132. plt.title("{}".format(name))
  133.  
  134. plt.show()

參考

sklearn.svm.SVC
sklearn.kernel_ridge.KernelRidge

留言