数据降维-核化线性降维(kernelized PCA)

主要是在传统的PCA中加入了kernel。传统的PCA使用的是线性变换,为此(Schoelkopf et al. 1998)在传统的PCA中引进了kernel的技巧,本文的主要参考文献为MLAPP,参考的是第14章的第四小节,算法如下:数据降维-核化线性降维(kernelized PCA)_第1张图片

这个算法,和传统的pca差不多,主要步骤3和8主要是做特征空间的中心化,因为pca处理的是中心化后的数据,推断步骤如下:数据降维-核化线性降维(kernelized PCA)_第2张图片 

详细细节可以查看MLAPP这本书。

代码如下:

from matplotlib import cm
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
np.random.seed(1234)
from scipy.spatial.distance import  pdist,squareform,cdist
fig=plt.figure()
ax=fig.gca(projection="3d")
#三组数据的均值
mean_list=([0,1,2],[4,3,5],[7,8,9])
#三组数据的方差
cov=np.array([[2,0,0],[0,1,0],[0,0,3]],dtype=np.float32)
#用来控制方差大小的参数
cita=[0.5,0.8,0.5]
sample=list()
for mean,cita in zip(mean_list,cita):
    #采样出三组数据
    data=np.random.multivariate_normal(mean,cov=cita*cov,size=100)
    sample.append(data)
label=["blue","orange","green"]
for P,label in zip(sample,label):
    ax.scatter(P[:,0],P[:,1],P[:,2],label=label,c=label)
ax.legend()
plt.show()
class KernelPCA:
    def __init__(self,bandwidth,dim):
        #定义核函数的带宽
        self.bandwidth=bandwidth
        #定义隐变量的维数
        self.dim=dim
    def fit(self,train_X):
        self.size_train=train_X.shape[0]
        self.train_X=train_X
        dist=squareform(pdist(self.train_X))
        K=self.rbf_kernel(dist)
        self.one=np.ones((self.size_train,1),dtype=np.float32)
        O=self.one.dot(self.one.T)/self.size_train
        #K~
        K_hat=K-O.dot(K)-K.dot(O)+O.dot((K.dot(O)))
        D,U=np.linalg.eig(K_hat)
        D=np.reshape(D,(self.size_train,))
        self.V=U[:,:self.dim]/D[:self.dim]
    def predict(self,data):
        pred_size=data.shape[0]
        O_x=np.ones((pred_size,1)).dot(self.one.T)/self.size_train
        K_x=self.rbf_kernel(cdist(data,self.train_X))
        #K~*
        K_h=K_x-O_x.dot(K_x)-K_x.dot(O_x)+O_x.dot(K_x.dot(O_x))
        z=K_h.dot(self.V)
        return z
    def rbf_kernel(self,X):
        return np.exp(-X/(self.bandwidth**2))
kp=KernelPCA(1,2)
#将三组数据连接起来
data=np.concatenate((sample[0],sample[1],sample[2]),axis=0)
kp.fit(data)
z=kp.predict(data)
a,b,c=np.split(z,3,axis=0)
latent_list=[a,b,c]
colors=["blue","orange","green"]
for z,color in zip(latent_list,colors):
    plt.scatter(z[:,0],z[:,1],c=color)
plt.show()

原始的三组数据如图:

数据降维-核化线性降维(kernelized PCA)_第3张图片

带宽为1,经过映射后为:

数据降维-核化线性降维(kernelized PCA)_第4张图片

当然你可以调节不同的带宽值,带宽为4时:

数据降维-核化线性降维(kernelized PCA)_第5张图片

 

 

 

你可能感兴趣的:(数据降维,MLAPP)