前言
提醒:
文章内容为方便作者自己后日复习与查阅而进行的书写与发布,其中引用内容都会使用链接表明出处(如有侵权问题,请及时联系)。
其中内容多为一次书写,缺少检查与订正,如有问题或其他拓展及意见建议,欢迎评论区讨论交流。
文章目录
代码抄录
from sklearn.datasets import load_iris
from sklearn.decomposition import KernelPCA
import numpy as np
import matplotlib.pyplot as plt
from scipy.spatial.distance import pdist, squareform
def sigmiod(x,coef=0.25):
x=np.dot(x,x.T)
return np.tanh(coef*x+1)
def linear(x):
x=np.dot(x,x.T)
return x
def rbf(x,gamma=15):
sq_dists=pdist(x,'sqeuclidean')
mat_sq_dists=squareform(sq_dists)
return np.exp(-gamma*mat_sq_dists)
def kpca(data,n_dims=2,kernel=rbf):
K=kernel(data)
N=K.shape[0]
one_n=np.ones((N,1))/N
eig_values,eig_vector=np.linalg.eig(K)
idx=eig_values.argsort()[::-1]
eigval=eig_values[idx][:n_dims]
eigvector=eig_vector[:,idx][:,:n_dims]
eigval=eigval**0.5
vi=eigvector/eigval.reshape(-1,n_dims)
data_n=np.dot(K,vi)
return data_n
if __name__=='__main__':
data=load_iris().data
Y=load_iris().target
data_1=kpca(data,kernel=rbf)
sklearn_kpca=KernelPCA(n_components=2,kernel='rbf',gamma=15)
data_2=sklearn_kpca.fit_transform(data)
plt.figure(figsize=(10,6))
plt.subplot(121)
plt.title('My KPCA')
plt.scatter(data_1[:,0],data_1[:,1],c=Y)
plt.subplot(122)
plt.title('Sklearn KPCA')
plt.scatter(data_2[:,0],data_2[:,1],c=Y)
plt.show()
代码分析
数据集介绍
使用sklearn函数库中自带的数据 “from sklearn.datasets import load_iris”
X X X为数据的特征,形状为(150,4):有150条数据,每条数据有4个特征。
Y Y Y为数据的标签,形状为(150,):有150条,三类标签(“setosa”, “versicolor”, 和 “virginica”)。
以下为 X X X与 Y Y Y的表格(只显示了前四组):
sigmiod(x,coef=0.25)
def sigmiod(x,coef=0.25):
x=np.dot(x,x.T)
return np.tanh(coef*x+1)
sigmoid函数通常用于激活函数,尤其是在神经网络中。它的数学形式是:
注意到导数与原函数关系:
其数学图像为:
源代码没有使用传统的sigmoid函数,而是使用了双曲正切函数(tanh):
注意到导数与原函数关系:
其数学图像为:
def linear(x)
def linear(x):
x=np.dot(x,x.T)
return x
代码展示的结果为:
( X X X是一个 m × n m\times n m×n的矩阵,结果 f ( x ) f(x) f(x)是一个 m × m m\times m m×m的矩阵)
rbf(x,gamma=15)
def rbf(x,gamma=15):
sq_dists=pdist(x,'sqeuclidean')
mat_sq_dists=squareform(sq_dists)
return np.exp(-gamma*mat_sq_dists)
- sq_dists=pdist(x,‘sqeuclidean’);mat_sq_dists=squareform(sq_dists)
pdist()计算矩阵 X X X中所有成对数据点之间的平方欧几里得距离,squareform()将这些距离转换成对称的距离矩阵
得到矩阵 m × m m\times m m×m的 D D D矩阵:
( D i j D_{ij} Dij表示矩阵 X X X中第 i i i行和第 j j j行对应的数据点之间的平方欧几里得距离
- np.exp(-gamma*mat_sq_dists)
返回值为:
- 关于径向基函数(Radial Basis Function,RBF),常作为核函数,用于机器学习和数据科学中的核方法。以下是该函数的数学表达:
设 X X X是一个 m × n m\times n m×n的矩阵,其中每一行代表一个 n − n- n−维数据点。
关于核主成分析
核主成分分析(Kernel Principal Component Analysis, KPCA)是主成分分析(PCA)的非线性扩展。它通过使用核技巧(kernel trick)将数据映射到更高维的特征空间,在线性空间中进行PCA,从而有效处理非线性数据结构。以下是KPCA的详细步骤:
1. 核技巧
核技巧的核心思想是通过一个非线性映射 ϕ \phi ϕ 将原始数据从输入空间映射到一个更高维甚至是无限维的特征空间。在这个特征空间中,数据可能呈现线性结构。
2. 选择核函数
常用的核函数包括:
- 线性核: K ( x , y ) = x ⋅ y K(x, y) = x \cdot y K(x,y)=x⋅y
- 多项式核: K ( x , y ) = ( x ⋅ y + c ) d K(x, y) = (x \cdot y + c)^d K(x,y)=(x⋅y+c)d
- 高斯核(RBF核): K ( x , y ) = exp ( − ∥ x − y ∥ 2 2 σ 2 ) K(x, y) = \exp(-\frac{\|x - y\|^2}{2\sigma^2}) K(x,y)=exp(−2σ2∥x−y∥2)
- sigmoid核: K ( x , y ) = tanh ( α x ⋅ y + c ) K(x, y) = \tanh(\alpha x \cdot y + c) K(x,y)=tanh(αx⋅y+c)
3. 构建核矩阵
对于给定的数据集 { x 1 , x 2 , … , x n } \{x_1, x_2, \ldots, x_n\} {x1,x2,…,xn},计算核矩阵 K K K,其中 K i j = K ( x i , x j ) K_{ij} = K(x_i, x_j) Kij=K(xi,xj)。
4. 中心化核矩阵
为了确保数据在特征空间中是中心化的,需对核矩阵进行中心化。中心化后的核矩阵 K ′ K' K′ 由以下公式获得:
K ′ = K − 1 n K − K 1 n + 1 n K 1 n K' = K - 1_n K - K 1_n + 1_n K 1_n K′=K−1nK−K1n+1nK1n
其中 1 n 1_n 1n是一个 n × n n \times n n×n的全1矩阵。
中心化详细推导步骤
给定数据集 { x 1 , x 2 , … , x n } \{x_1, x_2, \ldots, x_n\} {x1,x2,…,xn},其核矩阵为 K K K,其中
K i j = K ( x i , x j ) K_{ij} = K(x_i, x_j) Kij=K(xi,xj)
1. 计算平均值向量
首先,计算核矩阵的平均值:
K ˉ i = 1 n ∑ j = 1 n K i j \bar{K}_i = \frac{1}{n} \sum_{j=1}^{n} K_{ij} Kˉi=n1∑j=1nKij
K ˉ j = 1 n ∑ i = 1 n K i j \bar{K}_j = \frac{1}{n} \sum_{i=1}^{n} K_{ij} Kˉj=n1∑i=1nKij
K ˉ = 1 n 2 ∑ i = 1 n ∑ j = 1 n K i j \bar{K} = \frac{1}{n^2} \sum_{i=1}^{n} \sum_{j=1}^{n} K_{ij} Kˉ=n21∑i=1n∑j=1nKij
2. 中心化公式
中心化后的核矩阵 K ′ K' K′的每个元素为:
K i j ′ = K i j − K ˉ i − K ˉ j + K ˉ K'_{ij} = K_{ij} - \bar{K}_i - \bar{K}_j + \bar{K} Kij′=Kij−Kˉi−Kˉj+Kˉ
3. 矩阵形式
使用矩阵运算,可以将上述过程表示为:
K ′ = K − 1 n K − K 1 n + 1 n K 1 n K' = K - 1_n K - K 1_n + 1_n K 1_n K′=K−1nK−K1n+1nK1n
其中,
1
n
1_n
1n 是一个
n
×
n
n \times n
n×n 的全1矩阵,矩阵乘法的结果是对每一行或每一列进行平均。
解释
- 1 n K 1_n K 1nK和 K 1 n K 1_n K1n的作用是计算出每一行和每一列的均值。
- 1 n K 1 n 1_n K 1_n 1nK1n 计算整个矩阵的均值。
- 通过这些步骤,确保数据在新的特征空间中是零均值的。
通过这种方式,中心化后的核矩阵 K ′ K' K′ 在特征空间中确保数据的均值为零,从而支持后续的特征分析。
5. 特征分解
对中心化后的核矩阵 K ′ K' K′进行特征值分解,得到特征值和特征向量:
K ′ v = λ v K'v = \lambda v K′v=λv
特征向量 (v) 对应于特征空间中的主成分。
6. 投影到主成分空间
选择前 k k k个最大的特征值对应的特征向量,将数据投影到这个新的特征空间中。
优势
- 捕捉非线性结构: KPCA可以发现原始数据中的非线性模式。
- 灵活性: 通过选择不同的核函数,可以适应不同的数据分布。
应用
KPCA常用于降维、特征提取、模式识别和数据预处理,在图像处理、基因数据分析等领域有广泛应用。
通过核技巧,KPCA提供了一种强大的非线性降维方法,能够处理复杂结构的数据。
关于抄录代码中定义的sigmiod(x,coef=0.25),linear(x),rbf(x,gamma=15) 三个函数其实就是定义了三个核函数,在代码中,原作者仅仅使用了rbf(x,gamma=15)。同时,在传统的KPCA中会用到核矩阵去中心化,抄录代码中原作者并没有用到。
kpca(data,n_dims=2,kernel=rbf)
def kpca(data,n_dims=2,kernel=rbf):
K=kernel(data)
N=K.shape[0]
one_n=np.ones((N,1))/N
eig_values,eig_vector=np.linalg.eig(K)
idx=eig_values.argsort()[::-1]
eigval=eig_values[idx][:n_dims]
eigvector=eig_vector[:,idx][:,:n_dims]
eigval=eigval**0.5
vi=eigvector/eigval.reshape(-1,n_dims)
data_n=np.dot(K,vi)
return data_n
- K=kernel(data)
其中, ∥ d a t a [ i ] − d a t a [ j ] ∥ ∥data[i]−data[j]∥ ∥data[i]−data[j]∥是数据点 d a t a [ i ] data[i] data[i]和 d a t a [ j ] data[j] data[j]之间的欧几里得距离。- one_n=np.ones((N,1))/N
原作者并没有使用这一语句,估计是要做去中心化,但没有做。- eig_values,eig_vector=np.linalg.eig(K)
idx=eig_values.argsort()[::-1]
eigval=eig_values[idx][:n_dims]
eigvector=eig_vector[:,idx][:,:n_dims]
特征值分解,进行排序,进行查找。
可参考PCA:学习日记_241021_主成分分析(PCA)- eigval=eigval**0.5
vi=eigvector/eigval.reshape(-1,n_dims)
data_n=np.dot(K,vi)
假设特征向量为 V V V和特征值为 λ \lambda λ:
特征向量集合 V n = [ v 1 , v 2 , … , v n _ d i m s ] V_n = [v_1, v_2, \ldots, v_{n\_dims}] Vn=[v1,v2,…,vn_dims]
特征值集合 λ n = [ λ 1 , λ 2 , … , λ n _ d i m s ] \lambda_n = [\lambda_1, \lambda_2, \ldots, \lambda_{n\_dims}] λn=[λ1,λ2,…,λn_dims]
归一化的特征向量:
V i = [ v 1 λ 1 , v 2 λ 2 , … , v n _ d i m s λ n _ d i m s ] V_i = \left[\frac{v_1}{\sqrt{\lambda_1}}, \frac{v_2}{\sqrt{\lambda_2}}, \ldots, \frac{v_{n\_dims}}{\sqrt{\lambda_{n\_dims}}}\right] Vi=[λ1 v1,λ2 v2,…,λn_dims vn_dims]
将数据投影到新的特征空间:
data n = K ⋅ V i \text{data}_n = K \cdot V_i datan=K⋅Vi
python中自带函数实现KPCA
sklearn_kpca=KernelPCA(n_components=2,kernel='rbf',gamma=15)
遗留问题
- 关于核函数的具体含义与具体意义,,