核化這個概念在很多機器學習方法中都有應用,如SVM,PCA等。在此結合sklearn中的KPCA說說核函數具體怎么來用。
KPCA和PCA都是用來做無監督數據處理的,但是有一點不一樣。PCA是降維,把m維的數據降至k維。KPCA恰恰相反,它是把m維的數據升至k維。但是他們共同的目標都是讓數據在目標維度中(線性)可分,即PCA的最大可分性。
在sklearn中,kpca和pca的使用基本一致,接口都是一樣的。kpca需要指定核函數,不然默認線性核。
首先我們用下面的代碼生成一組數據。
import numpy as np from sklearn.decomposition import PCA, KernelPCA import matplotlib.pyplot as plt import math x=[] y=[] N = 500 for i in range(N): deg = np.random.randint(0,360) if np.random.randint(0,2)%2==0: x.append([6*math.sin(deg), 6*math.cos(deg)]) y.append(1) else: x.append([15*math.sin(deg), 15*math.cos(deg)]) y.append(0) y = np.array(y) x = np.array(x) print('ok')
這些數據可以用下圖來表示
顯然,我們選的正樣本(藍)都落在一個半徑為6的圓上,負樣本(紅)全選在一個半徑為15的圓上。
這樣的數據顯然是線性不可分的。如果我們強行要用線性分類器來做,可以對原始數據做一個kpca處理。
如下代碼:
kpca = KernelPCA(kernel="rbf", n_components=14) x_kpca = kpca.fit_transform(x)
我們用rbf核,指定維度為14(為啥是14,后面說),也就是說吧X(2維)中的數據映射到14維的空間中去。
然后我們用一個線性的SVM分類器來對映射后的數據做一個分類,隨機取80%做訓練集,20%做測試集。
from sklearn import svm clf = svm.SVC(kernel='linear') clf.fit(x_kpca[:0.8*N],y[:0.8*N]) y0 = y[0.8*N:] y1 = clf.predict(x_kpca[0.8*N:]) print(np.linalg.norm(y0-y1, 1))
此時,輸出的是0,也就是說我們預測出的分類與正確的分類完全吻合,沒有一個錯誤。此時分類器在這個數據集上是完全有效的。
綜上所述,通過核化,可以把原本線性不可分的數據映射到高維空間后實現線性可分。
不過這個過程也不完全是那么簡單,我們取不同的維度得到的結果可能相差甚遠,也就是經典的調參問題。
在此,我測試了幾組不同的k取值,得到不同k值條件下分類准確率值。如下圖。
可以看出,不同的k值對結果是有影響的。但不同的數據集可能不一樣,所以需要進行調參。我這個取14就全ok了。