PCA与LDA的介绍

386 阅读2分钟
  • 为什么要降维:

  1、避免维数灾难,高维情况下容易产生过拟合

  2、特征之间如果存在明显的相关性(也叫共线性),此时就需要降维

  3、降维可以提取数据中的有效信息,去除噪音数据

  4、降维可以降低数据的复杂性,减少模型的训练时间

  5、可以方便对数据进行可视化处理,因为维数很高的话,无法可视化

在machine learning领域,PCA和LDA都可以看成是数据降维的一种方式。

1.PCA介绍

  • 目的:

将原有的d维数据集转换成K维的数据,看k<d;

新生成的K维数据尽可能多的包含原来d维数据的信息

直观看:投影后的投影值尽可能分散。(方差)

  • PCA处理过程:

1.将原始数据按列组成d行n列矩阵X

2.将X的每一样本去中心化,即减去这一行的均值

3.求出协方差矩阵

4.求出协方差矩阵的特征值及对应的特征向量

5.将特征向量按对应特征值大小从上到下按行排列成矩阵,取前m行组成矩阵P

6.Y=PX即为降维到m维后的数据

2.LDA介绍

  • 目的:

降维数据满足两个特征来减少重叠:不同类别数据降维后相互间的差异大,同一类别数据降维后相互间的差异小(最大化类间距离和最小化类內距离)

  • LDA降维流程:

1.计算每个类别的均值ui,全局样本均值u

2.计算类內散度矩阵Sw,全局散度矩阵St,类间散度矩阵Sb

3.对矩阵Sw-1Sb做特征值分解

4.去最大的d‘个特征值所对应的特征向量

5.计算投影矩阵

3.PCA和LDA代码

  • pca代码
import numpy as np 
from scipy.spatial.distance import pdist,squareform

def pca(X, threshold):
  #将X中心化
  X_mean = np.mean(X, axis = 0)
  X_cen = X - X_mean

  #构造散度矩阵并且求解特征值与特征向量
  X_sca = np.dot(X_cen.T, X_cen)
  X_eigenval, X_eigenvect = np.linalg.eig(X_sca)

  #按照阈值排序
  indexs = X_eigenval.argsort()[::-1]
  indexs = indexs[:threshold]
  X_eigenvect_TopK = X_eigenvect[:,indexs]

  #将X投影到特征向量上
  X_proj = np.dot(X_cen, X_eigenvect_TopK)

  #计算重构数据 X * X_proj* X_proj.T
  X_restore = np.dot(X_proj, X_eigenvect_TopK.T) + X_mean
  return X_proj, X_restore


#kernel_pca
def KPCA(X, gamma, k):
    #计算L2距离
    dist_arr = sqdist(X, metric='sqeuclidean')
    dist_mat = squareform(sq_dists)
    
    #计算径向基散度矩阵,并将其归一化
    K_diag = np.exp(-gamma * dist_mat)
    N = X.shape[0]
    one_N = np.ones((N, N))/N
    K = K-one_N.dot(K)-K.dot(one_N)+one_N.dot(K).dot(one_N)
    
    #计算特征值与特征向量
    K_eigenval, K_eigevector = np.linalg.eigh(K)
    K_eigevector_proj = np.column_stack((K_eigevector[:, -i]for i in range(1, 1+k)))
    K_eigenval_proj = [K_eigenval[-i] for i in range(1, k+1)]
    return K_eigevector_proj, K_eigenval_proj

#计算新来的样本的投影
#模型构建完毕后,至于观测样本有关。
def proj_new(X_new, X, gamma, K_eigevector_proj, K_eigenval_proj):
    k = np.exp(-gamma*np.sum((X-X_new)**2, 1))
    return k.dot(K_eigevector_proj/K_eigenval_proj)

  • LDA代码
def lda(data, target, n_dim):
    '''
    :param data: (n_samples, n_features)
    :param target: data class
    :param n_dim: target dimension
    :return: (n_samples, n_dims)
    '''

    clusters = np.unique(target)

    if n_dim > len(clusters)-1:
        print("K is too much")
        print("please input again")
        exit(0)

    #within_class scatter matrix
    Sw = np.zeros((data.shape[1],data.shape[1]))
    for i in clusters:
        datai = data[target == i]
        datai = datai-datai.mean(0)
        Swi = np.mat(datai).T*np.mat(datai)
        Sw += Swi

    #between_class scatter matrix
    SB = np.zeros((data.shape[1],data.shape[1]))
    u = data.mean(0)  #所有样本的平均值
    for i in clusters:
        Ni = data[target == i].shape[0]
        ui = data[target == i].mean(0)  #某个类别的平均值
        SBi = Ni*np.mat(ui - u).T*np.mat(ui - u)
        SB += SBi
    S = np.linalg.inv(Sw)*SB
    eigVals,eigVects = np.linalg.eig(S)  #求特征值,特征向量
    eigValInd = np.argsort(eigVals)
    eigValInd = eigValInd[:(-n_dim-1):-1]
    w = eigVects[:,eigValInd]
    data_ndim = np.dot(data, w)

    return data_ndim

多种降维参考代码:github.com/heucoder/di…

4.PCA与LDA的比较

  • 相似点:

从PCA和LDA的计算过程来看,最后其实都是在求某一个矩阵的特征值,投影矩阵即为该特征值对应的特征向量。

  • 差异:

1.PCA为非监督降维,LDA为有监督降维

2.PCA希望投影后的数据方差尽可能的大,方差越大,则降维后包含的信息越多;LDA则希望投影后相同类别的组内方差小,而组间方差大。LDA能合理运用标签信息,使得投影后的维度具有判别性,不同类别数据尽可能的分开。

3.有标签就尽可能的利用标签的数据(LDA),而对于纯粹的非监督任务,则还是得用PCA进行数据降维。