[ML] 機器學習基石:第十一講 Linear Models for Classification

ML:基礎學習
課程:機器學習基石
簡介:第十一講 Linear Models for Classification


Error 比較

y=1
err0/1(s,y)=[sign(ys)1]errSQR(s,y)=(ys1)2errCE(s,y)=ln(1+eys)errSCE(s,y)=log2(1+eys)
為了方便會將 errCE(s,y) 調整為 errSCE(s,y),如右下圖
對於任意 yss=wTx
err0/1(s,y)errSCE(s,y)=1ln2errCE(s,y){Ein0/1(w)EinSCE(w)=1ln2EinCE(w)Eout0/1(w)EoutSCE(w)=1ln2EoutCE(w) Eout0/1(w)Ein0/1(w)+Ω0/11ln2EinCE(w)+Ω0/1 故當 EinCE(w) 變小時,也意味著 Eout0/1(w) 變小
linear regression 也可用同樣的方法得證之

實際運用方法

PLA linear regression logistic regression
優點 線性可分時,很有效率 最簡單最佳化 簡單最佳化
缺點 無法得知是否線性可分,得使用 pocket 但效率與 logistic 差不多 |ys| 太大,err 太過寬鬆 ys 太大,err 太過寬鬆
實務上會使用 linear regression 設定 w0,然後再使用 logistic regression 最佳化

Stochastic Gradient

logistic Regression 更新公式如下,那麼有辦法改成像 PLA 一樣,看見一個 (xn,y) 就更新一次嗎?
Double subscripts: use braces to clarify
換個想法,平均是否跟期望值很接近,那麼用隨機抽點的方法再平均抽出來的點,是否也是 ok 的?
wEin(w)=εrandom nwerr(w,xn,yn)werr(w,xn,yn)=werr(w)+zero mean "noise"
演算法
  1. 將原先的梯度 werr(w) 改為 stochastic gradient werr(w,xn,yn) 
  2.  經過足夠的次數
    •  平均 werr(w) 平均 werr(w,xn,yn)
  3.  優缺點
    • 優點:簡單快速,可用在 online 學習
    • 缺點:不夠穩定,因可能一下走對,一下走錯
SGD logistic regression
Double subscripts: use braces to clarify
SGD 與 PLA 相似處,如上
  • SGD 可視為 soft PLA,錯多少就更新多少
  • η=1 時,Double subscripts: use braces to clarify 又很大,兩者可視為一樣
實際經驗運用的方式
  • 停止條件 => 跑夠多次,因若還 check gradient 就回到原先較沒效率的方式
  • 經驗 η=0.1,若 x 範圍適當
Python 原始碼
  1. import matplotlib.pyplot as plt
  2. import numpy as np
  3. import operator
  4. import math
  5. import random
  6. # 網路上找的 dataset 可以線性分割
  7. rawData = [
  8. ((-0.4, 0.3), -1),
  9. ((-0.3, -0.1), -1),
  10. ((-0.2, 0.4), -1),
  11. ((-0.1, 0.1), -1),
  12. ((0.9, -0.5), 1),
  13. ((0.7, -0.9), 1),
  14. ((0.8, 0.2), 1),
  15. ((0.4, -0.6), 1),
  16. ((0.2, 0.6), -1),
  17. ((-0.5, -0.5), -1),
  18. ((0.7, 0.3), 1),
  19. ((0.9, -0.6), 1),
  20. ((-0.1, 0.2), -1),
  21. ((0.3, -0.6), 1),
  22. ((0.5, 0.1), -1), ]
  23. # 加入 x0
  24. dataset = [((1,) + x, y) for x, y in rawData]
  25. # 內積
  26. def dot(*v):
  27. return sum(map(operator.mul, *v))
  28. # 計算向量長度
  29. def vlen(v):
  30. square = map(operator.mul, v, v)
  31. return sum(square) ** (1/2)
  32. # 取 thita
  33. def thita(v):
  34. return 1 / ( 1 + math.exp( -v ))
  35. # 計算梯度
  36. def gradient(w, dataset):
  37. setsV = []
  38. for x, y in dataset:
  39. setsV.append( map(operator.mul, [thita(-y*dot(w, x)) * (y)] * len(x), x) )
  40. sum = [0] * len(x)
  41. for v in setsV:
  42. sum = map(operator.add, sum, v)
  43. sum = map(operator.truediv, sum, [1]*len(x))
  44. return list(sum)
  45. # 更新 w
  46. def update(w, n, g):
  47. u = map(operator.mul, [n] * len(g), g)
  48. w = map(operator.add, w, u)
  49. return list(w)
  50. # 用 w 畫圖
  51. def plotfig(w):
  52. # 畫圖
  53. fig = plt.figure()
  54. # numrows=1, numcols=1, fignum=1
  55. ax1 = fig.add_subplot(111)
  56. xx = list(filter(lambda d: d[1] == -1, dataset))
  57. ax1.scatter([x[0][1] for x in xx], [x[0][2] for x in xx],
  58. s=100, c='b', marker="x", label='-1')
  59. oo = list(filter(lambda d: d[1] == 1, dataset))
  60. ax1.scatter([x[0][1] for x in oo], [x[0][2] for x in oo],
  61. s=100, c='r', marker="o", label='1')
  62. l = np.linspace(-2, 2)
  63. # w0 + w1x + w2y = 0
  64. # y = -w0/w2 - w1/w2 x
  65. if w[2]:
  66. a, b = -w[1] / w[2], -w[0] / w[2]
  67. ax1.plot(l, a * l + b, 'b-')
  68. else:
  69. ax1.plot([-w[0] / w[1]] * len(l), l, 'b-')
  70. plt.legend(loc='upper left', scatterpoints=1)
  71. plt.show()
  72. # SGD Logistic Regression演算法實作
  73. def SGD_logisticRegression(dataset):
  74. # 初始化 w
  75. w = [0] * 3
  76. t = 0
  77. n = 0.1
  78. max_number = 1000
  79. while True:
  80. g = gradient(w, [random.choice(dataset)])
  81. print("g {:.5f} => {}: {}".format(vlen(g), t, tuple(w)))
  82. w = update(w, n, g)
  83. t += 1
  84. if t > max_number:
  85. break
  86. return w
  87. # 主程式
  88. def main():
  89. # 執行
  90. w = SGD_logisticRegression(dataset)
  91. plotfig(w)
  92. if __name__ == '__main__':
  93. main()
  94.  
SGD 並不限定 logistic,例:也可用在 linear regression 上,Double subscripts: use braces to clarify

多類別分類


One-Versus-All (OVA)

如下,但若出現在中間區域或重疊的部分,又該如何決定呢?
那改為可能性表示呢?例如用 logistic regression 選出最大可能性
且因為 θ 為 monotonic 的,所以只需比較 w[k]Tx 大小
演算法
  1. kyy 表示有多少類別
    • 利用 logistic regression,得到 w[k]
      邊跑邊重新定義資料即可
      D[k]={(xn,yn=2[yn=k]1)}n=1N
  2. 回傳最大的可能性 g(x)=argmaxky(w[k]Tx)
優缺點
  • 優點:非常有效率,可平行處理,可搭配類似 logistic 的方法
  • 缺點:因 1 對多,資料容易不平衡,會出現一直說同一個答案的解法
計算效率
若有 K-class,大小為 N
需學習 K 個 logistic regressioin,每個大小皆為 N

One versus One (OVO)

演算法
  1.  (k,l)y×y
    • 利用 linear binary classification 得到 w[k,l]
      邊跑邊重新定義資料即可
      D[k,l]={(xn,yn=2[yn=k]1):yn=k or yn=l}
  2. 回傳最多票數 g(x)={w[k,l]Tx}
優缺點
  • 優點:穩定有效率,因資料變小,可搭配任何二元分類的方法
  • 缺點:使用 C2Kw[k,l],需要更多的空間、預測時間更長、更多的訓練
計算效率
若有個二元分類的方法,需用 N3 時間計算大小為 N 的資料
有 K-class 的資料時,假設每個類別的大小皆為 N/K,若 K = 10 那麼需花多少時間?
T=(2NK)3×C2K=(8N31000)×45=925N3
若是 OVA 呢?
T=N3×K=10N3
所以在這種情況 OVA 比 OVO 沒效率

留言