ML:基礎技法學習
Package:scikit-learn
課程:
機器學習技法
簡介:第五講 Kernel Logistic Regression
SVM as Regularized Model
- large margin fewer hyperplanes L2 regularization of short W
- soft margin special
- larger C or C smaller less regularization
regularized LogReg approximate SVM
從
Linear Models for Classification 得知
若 ,當縮小 時,相當於也是在做分類
而從圖中看來
故 L2-regularized logistic regression 其實就相當於在做 soft margin SVM
Platt's Model
可視需求代入,像是 Kernel SVM 如上推導
該怎麼做,才能將 SVM 轉換為機率的表示呢?
簡單的想法如下圖
- 若像左邊一樣,最後再將結果用 logistic function 轉換,但這就喪失了 LogReg 的 maximum likelihood 的意義了
- 若像右邊一樣,先用 SVM 跑出初始值,再代入 LogReg,但這跟直接跑 LogReg 所得到的解是差不多的,所以 SVM 幾乎無任何作用,non-linear 也無法使用,像 kernel SVM 也無法應用在此
所以若改為先跑完 SVM,再運用 LogReg 修正一下呢?
看起來可行,而且其實就是利用 A 調整 ,利用 A & B 調整
或是將 SVM 視為一種特別的轉換 ,從多維轉換至一維,再進行處理
骨子裡仍可使用 SVM 的各種方法,也就是 可視需求代入,像是 Kernel SVM
- 這不是 Z 空間中最好的 LogReg 解,只是還不錯的解,需用 KLR 得最好解
- 若 夠好,通常
假如 ,表示 SVM 在亂做,不然怎麼會完全反向
- 若 夠好,通常
- 與原本 SVM 的邊界不一定一樣,因為 做了平移
- 如何解 LogReg
Kernel Logistic Regression (KLR)
Representer Theorem
claim: for any L2-regularized linear model
optimal
最佳化 必是 的線性組合
令
&
希望證得
反證法
假設存在
err 的值,不因 而變
矛盾,因 err 固定,而 為最佳解,那麼在 為何 還可以比 更小
故最佳化 必是 的線性組合
因無限制條件,可利用 GD/SGD/... 求解
- 兩種不同的角度
- KLR = linear model of
- ,一種特別的 regularizer
- 可視同 與 轉換過的資料 作內積
- kernel 作用在 轉換 與 regularizer
- KLR = linear model of
- 藏在 kernel 中,且為 L2 regularizer
-
- import matplotlib.pyplot as plt
- import numpy as np
-
- from sklearn.svm import SVC
-
-
- # kernel logistic regression
- class KLR:
- def __init__(self):
- pass
-
-
- # 高斯 kernel
- def kernel_rbf(self, xn, xm):
- kv = np.exp(-self.gamma * (np.linalg.norm(xn-xm)**2))
- return kv
-
-
- # 產生 kernel matrix
- def kernelMatrix(self, x):
- m = []
- for xn in x:
- row = [self.kernel_rbf(xn, xm) for xm in x]
- m.append(row)
-
- return np.array(m)
-
-
- # error function
- # lamda/N B^T K B + 1/N log(...)
- def errFuc(self, x, y):
- sum = 0
- for n in range(self.N):
- sum += np.log(1+np.exp(-y[n] * np.dot(self.beta,self.K[:,n])))
- return self.lambda_/self.N * np.dot(self.beta, self.K).dot(self.beta) + sum/self.N
-
-
- # 梯度方程式
- def gradFuc(self, x, y):
- err = np.array([0] * self.N)
- for n in range(self.N):
- val = y[n] * np.dot(self.beta, self.K[:,n])
- temp = -y[n] * self.K[:,n] / (1 + np.exp(val))
- err = np.add(err, temp)
-
- val = self.lambda_/self.N * 2 * np.dot(self.K, self.beta) + 1/self.N * err
-
- return val
-
-
- # 訓練
- def fit(self, x, y, gamma=0.5, lambda_=0.1, n=1, max_number=1000):
- # 初始化
- y[y==0] = -1
- self.N = len(y)
- self.beta = [1] * self.N
- self.gamma = gamma
- self.lambda_ = lambda_
- self.x = x
- self.K = self.kernelMatrix(x)
-
- t = 0
- while True:
- g = self.gradFuc(x, y)
- self.beta = self.beta - n*g
- err = self.errFuc(x,y)
-
- # print('{:4d} n:{:.3f} err : {}'.format(t, n, err))
- t += 1
- if t > max_number or err < 0.01:
- break
-
-
- # 預測結果
- # w = sigma(b_n z_n)
- # g = sigma(b_n kernel(x_n,x))
- def predict(self, X):
- k = []
- for x in X:
- m = []
- for xn in self.x:
- m.append(self.kernel_rbf(xn, x))
- k.append(m)
- k = np.array(k).T
- p = np.dot(np.array(self.beta), k)
- return p
-
-
- # 訓練資料
- 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.0
-
- # exp(-2|x-x'|^2)
- gamma = 2
- classifiers = {"Platt's Model": SVC(kernel='rbf', gamma=gamma, C=C, probability=True),
- 'KLR': KLR(),
- }
- # 多少分類器
- n_classifiers = len(classifiers)
-
- # 產生 meshgrid,共 100x100 的點
- XX1, XX2 = np.mgrid[-3:3:200j, -4:4:200j]
- # 打平合併
- Xfull = np.c_[XX1.ravel(), XX2.ravel()]
-
- # 因是 dict 所以顯示不一定照順序
- for index, (name, classifier) in enumerate(classifiers.items()):
- # 訓練資料
- classifier.fit(X, Y)
-
- # 得到機率
- if name == "Platt's Model":
- # 取 1 的機率值,因接近 1 則機率越大,若取 0 會相反
- probas = classifier.predict_proba(Xfull)[:, 1]
- elif name == 'KLR':
- probas = classifier.predict(Xfull)
-
- plt.subplot(n_classifiers, 1, index + 1)
- # 調整之間的空白高度
- plt.subplots_adjust(hspace=.6)
-
- # 重新排列結果,符合 XX1
- probas = probas.reshape(XX1.shape)
- # 畫圖,contour 不填滿顏色,contourf 填滿顏色
- im = plt.contourf(XX1, XX2, probas, cmap="winter")
- # 依圖畫出 colorbar
- plt.colorbar(im)
-
- # 畫出所有點
- plt.scatter(X[:, 0], X[:, 1], c=Y, cmap=plt.cm.Paired)
-
- # 標題
- plt.title("{}".format(name))
-
- plt.show()
參考
sklearn.svm.SVC
sklearn.kernel_ridge.KernelRidge
留言
張貼留言