Locality Preserving Projections.

局部保留投影(Locality Preserving Projection, LPP)算法是一种线性降维方法。对于高维空间中的样本$X \in \Bbb{R}^{N \times D}$,LPP寻找一个投影矩阵$A \in \Bbb{R}^{D \times d}$,从而构造低维空间的降维结果$Y=XA \in \Bbb{R}^{N \times d}$。

LPP在降维时考虑了样本点之间的相对位置关系。构造一个关系矩阵$W \in \Bbb{R}^{N \times N}$衡量任意两个样本点之间的距离。关系矩阵$W$构造如下:

\[W_{ij} = \begin{cases} e^{-\frac{||x_i-x_j||^2}{t}}, & j\neq i, j \in \text{KNN}(i) \\ 0, & \text{otherwise} \end{cases}\]

直观地,当点$j$与点$i$距离比较近时,使用径向基函数衡量两者的相对位置关系;并且对点$i$只考虑最接近的$k$个点(使用kNN实现)。定义$W_{ii}=0$是为了后续推导方便。

关系矩阵$W$的构造过程为:

def cal_pairwise_dist(X):
    #返回任意两个点之间的欧式距离
    N,D = np.shape(X)
    tile_xi = np.tile(np.expand_dims(X,1),[1,N,1]) # [N,N,D]
    tile_xj = np.tile(np.expand_dims(X,axis=0),[N,1,1]) # [N,N,D]
    dist = np.sum((tile_xi-tile_xj)**2,axis=-1)  # [N,N]
    return dist
    
def rbf(dist, t = 1.0):
    #径向基函数
    return np.exp(-(dist/t))

def cal_rbf_dist(data, n_neighbors = 10, t = 1):
    #计算关系矩阵
    dist = cal_pairwise_dist(data)
    N = dist.shape[0]
    rbf_dist = rbf(dist, t)
    W = np.zeros([N, N])
    for i in range(N):
        #跳过与样本点与自身的关系
        index_ = np.argsort(dist[i])[1:1 + n_neighbors]
        W[i, index_] = rbf_dist[i, index_]
        W[index_, i] = rbf_dist[index_, i]
    return W

LPP的优化目标函数如下:

\[\sum_{i,j} (y_i-y_j)^2W_{ij}\]

如果样本点$j$与点$i$的距离比较接近,则$W_{ij}$比较大,通过最小化上述目标使得降维后$y_j$与$y_i$比较接近。如果样本点$j$与点$i$的距离比较远,则$W_{ij}=0$,不再限制降维后$y_j$与$y_i$的关系。

目标函数可进一步写作:

\[\begin{aligned} \sum_{i,j} (y_i-y_j)^2W_{ij} &= \sum_{i,j} (y_i^TW_{ij}y_i+y_j^TW_{ij}y_j-2y_i^TW_{ij}y_j) \\ &= 2\sum_{i,j} y_i^TW_{ij}y_i-2\sum_{i,j}y_i^TW_{ij}y_j \\ &= 2\sum_{i} y_i^T(\sum_{j}W_{ij})y_i-2\sum_{i,j}y_i^TW_{ij}y_j \\ &(\text{记}D_{ii} = \sum_{j}W_{ij}) \\ &= 2(\sum_{i} y_i^TD_{ii}y_i-\sum_{i,j}y_i^TW_{ij}y_j) \end{aligned}\]

记$D=\text{diag}(D_{ii})\in \Bbb{R}^{N \times N}$。首先考虑降维维度是$1$的情况,即$A=a\in \Bbb{R}^{D \times 1}$,则目标函数写作矩阵形式:

\[Y^T(D-W)Y =Y^TLY= a^TX^TLXa\]

其中$L=D-W\in \Bbb{R}^{N \times N}$是样本的拉普拉斯矩阵。

引入约束$Y^TDY=a^TX^TDXa=1$,通过将$Y^TDY$固定为常数,使得当样本的相对关系比较接近时($D$比较接近),降维结果也比较接近($Y$比较接近)。

LPP的优化问题写作:

\[\begin{aligned} \mathop{\min}_a \quad & a^TX^TLXa \\ \text{s.t.} \quad & a^TX^TDXa=1 \end{aligned}\]

构造拉格朗日函数:

\[L=a^TX^TLXa + \lambda(1-a^TX^TDXa)\]

对上式求极值,得:

\[2X^TLXa -2\lambda X^TDXa = 0\]

整理得:

\[(X^TDX)^{-1}X^TLXa = \lambda a\]

因此$a$为矩阵$(X^TDX)^{-1}X^TLX$的最小特征值对应的特征向量。

一般地,当$d>1$时,降维矩阵$A$为矩阵$(X^TDX)^{-1}X^TLX$的$d$个最小的特征值对应的特征向量组成的矩阵。

LPP的实现过程如下:

def lpp(X, n_dims = 2, n_neighbors = 30, t = 1.0):
    N = X.shape[0]
    W = cal_rbf_dist(X, n_neighbors, t)

    #计算矩阵D和L
    D = np.zeros_like(W)
    for i in range(N):
        D[i,i] = np.sum(W[i])
    L = D - W

    #计算矩阵特征值
    XTDX = np.dot(np.dot(X.T, D), X)
    XTLX = np.dot(np.dot(X.T, L), X)
    eig_val, eig_vec = np.linalg.eig(np.dot(np.linalg.pinv(XDXT), XLXT))

    #特征值从小到大排序
    sort_index_ = np.argsort(np.abs(eig_val))
    eig_val = eig_val[sort_index_]

    #舍弃太小的特征值
    j = 0
    while eig_val[j] < 1e-6:
        j+=1
    sort_index_ = sort_index_[j:j+n_dims]
    eig_val_picked = eig_val[j:j+n_dims]

    #根据特征值对应的特征向量构造降维矩阵A
    A = eig_vec[:, sort_index_]

    #降维
    Y = np.dot(X, A)
    return Y