Kernelized Principal Component Analysis.

主成分分析是一种线性降维方法,如果原始数据是线性不可分的,则降维后的数据仍然是线性不可分的。

核主成分分析(kernelized principal component analysis,KPCA)是一种非线性降维方法。其基本思想是先通过核方法把原始的线性不可分数据映射到高维空间,使其在高维空间线性可分;再通过主成分分析将其线性降维到低维空间,并在该低维空间中仍然线性可分。

KPCA的基本流程是对于维度为dd的原始样本空间中的样本点xRd,引入映射ϕ将其投影到维度为d的高维特征空间z=ϕ(x)Rd,再在特征空间中实施PCA方法,得到降维结果y=WzRk

1. 直接求解KPCA

KPCA中对样本点xRd引入映射ϕ投影到高维特征空间z=ϕ(x)Rd。映射ϕ通常不显式给出,而是定义核函数计算高维特征空间中的内积:

κ(xi,xj)=ϕ(xi)Tϕ(xj)

常用的核函数包括:

进一步引入矩阵KRn×n,其中第(i,j)个元素κ(xi,xj)表示样本xixj映射到高维空间后的特征相似度。选定核函数后,矩阵K可以由原始空间的输入样本XRn×d直接计算得到。

对于PCA,计算过程依赖于样本的协方差矩阵S=XTXRd×d,协方差矩阵衡量样本的不同特征之间的相似度。对于KPCA,样本映射到高维空间中的协方差矩阵为S=ϕ(X)Tϕ(X)Rd×d,由于映射ϕ通常是未知的,因此协方差矩阵无法直接计算。

另一方面,注意到矩阵K=ϕ(X)ϕ(X)T已经得到,该矩阵衡量不同样本之间的相似度。下面寻找矩阵S和矩阵K对应的特征向量和特征值之间的关系。假设矩阵K具有特征向量uRn和特征值λ(矩阵K可以进行特征值分解),

Ku=λu ϕ(X)ϕ(X)Tu=λu

上式两端左乘ϕ(X)T

ϕ(X)Tϕ(X)ϕ(X)Tu=λϕ(X)Tu Sϕ(X)Tu=λϕ(X)Tu

由上式可以看出,矩阵S具有特征向量ϕ(X)TuRd和特征值λ

由于PCA要求矩阵S的特征向量是归一化的,而ϕ(X)Tu不满足;因此对其归一化:

v=1||ϕ(X)Tu||ϕ(X)Tu=1uTϕ(X)ϕ(X)Tuϕ(X)Tu=1uTλuϕ(X)Tu=1λϕ(X)Tu

对于KPCA,降维结果可以由矩阵S的前k个最大特征值对应的特征向量vRd×k表示为:

Y=ϕ(X)v=1λϕ(X)ϕ(X)Tu=1λKu

上式表明,求解KPCA的过程可以避开对协方差矩阵S进行特征值分解,只需要对矩阵K进行特征值分解即可。

值得一提的是,对于PCA通常对数据进行归一化处理,即减去所有样本数据的平均值。对于KPCA,无法显式地对高维映射后的数据ϕ(X)进行处理,因此选择对矩阵K=ϕ(X)ϕ(X)T进行预处理。

记单位矩阵InRn×n和全1矩阵1nRn×1,则中心矩阵(centering matrix) H=In1N1n1Tn可以表示样本矩阵ϕ(X)的中心化过程:

ϕ(˜X)=ϕ(HX)=(In1N1n1Tn)ϕ(X)

则中心化的矩阵K表示为:

˜K=ϕ(˜X)ϕ(˜X)T=(In1N1n1Tn)ϕ(X)ϕ(X)T(In1N1n1Tn)T=(In1N1n1Tn)K(In1N1n1Tn)T

综上所述,KPCA的一般步骤如下:

  1. 给定输入样本XRn×d和降维维度k;
  2. 选定核函数,计算核矩阵KRn×n
  3. 对矩阵K进行中心化:˜K=(In1N1n1Tn)K(In1N1n1Tn)T;
  4. 对矩阵˜K进行特征值分解;
  5. 选择前k个最大特征值λ对应的特征向量uRn×k;
  6. 降维:Y=1λKu

2. 根据表示定理求解KPCA

KPCA可以表示为高维特征空间的线性模型y=WzRk。根据表示定理,线性模型的参数WRk×d的最优解可以表示为所有样本的线性组合

W=Ni=1αizi=Ni=1αiϕ(xi)

则其第j维的投影向量wjRd可以表示成:

wj=Ni=1αjiϕ(xi)=Zαj

其中αj=(αj1,αj2,,αjN)RN

根据主成分分析的结果,投影向量wj应满足:

(Ni=1ϕ(xi)ϕ(xi)T)wj=λjwj

由于Ni=1ϕ(xi)ϕ(xi)T=Ni=1zizTi=ZZTwj=Zαj,上式可以表示为:

ZZTZαj=λjZαj

一般情况下,我们不清楚映射ϕ的具体形式,因此引入核函数:

κ(xi,xj)=ϕ(xi)Tϕ(xj),K=ZTZ

则原式进一步表示为:

ZKαj=Zλjαj

若下式满足,则上式自动满足:

Kαj=λjαj

αjK的特征向量。取K最大的k个特征向量α1,α2,,αk,则原始样本x投影后的第j维坐标yj为:

yj=wTjϕ(x)=Ni=1αjiϕ(xi)Tϕ(x)=Ni=1αjiκ(xi,x)

3. 实现KPCA

① KPCA from scratch

由上述介绍,KPCA的一般步骤如下:

  1. 给定输入样本XRn×d和降维维度k;
  2. 选定核函数,计算核矩阵KRn×n
  3. 对矩阵K进行中心化:˜K=(In1N1n1Tn)K(In1N1n1Tn)T;
  4. 对矩阵˜K进行特征值分解;
  5. 选择前k个最大特征值λ对应的特征向量uRn×k;
  6. 降维:Y=1λKu
def kernel(xi, xj, gamma=1):
    return np.exp(-gamma**2*np.sum((xi-xj)**2))

def KPCA(data, k):
    n, d = data.shape
    K = np.zeros([n, n])
    # 计算核函数
    for i in range(n):
        for j in range(n):
            K[i, j] = kernel(data[i], data[j])
    # K矩阵归一化
    H = np.eye(n)-np.ones([n,n])/n # (n, n)
    K = H.dot(K).dot(H.T) # (n, n)
    # 计算特征值和特征向量
    eig_values, eig_vectors = np.linalg.eig(K)
    # 选择前k个最大的特征值标号
    index = np.argsort(-eig_values)[:k]
    # 选择对应的特征向量(主方向)
    KPCA_vectors = eig_vectors[index, :] # (k, n)
    # 降维
    KPCA_vectors /= np.expand_dims(np.sqrt(eig_values[index]),axis=-1)
    reduced_data = np.dot(K, KPCA_vectors.T) # (n, k)
    return reduced_data

② KPCA from sklearn

KPCA也可以通过sklearn库快速实现:

from sklearn.datasets import load_digits
from sklearn.decomposition import KernelPCA
import matplotlib.pyplot as plt

digits = load_digits()
X_kpca = KernelPCA(n_components=2, kernel="rbf", gamma=1).fit_transform(digits.data)

plt.figure(figsize=(10, 5))
plt.scatter(X_kpca[:, 0], X_kpca[:, 1], c=digits.target,label="KernelPCA")
plt.legend()
plt.show()