PCA主成分分析去噪与降维

写在开头:个人认为还是理论最重要!还是理论最重要!还是理论最重要!重要事情说三遍!
本人最近用到了PCA相关知识,借此进行一定的记录。
同时本文是基于周志华《机器学习》来学习的!相当于也是个读书笔记!

(能力有限,如有不当,敬请谅解)

一、目的

1、降低维数(主要目的)

主成分分析 (Principal Component Analysis,简称 PCA)是最常用的一种降维方法。(具体可见西瓜书,也可以参考下面引用)

2、去噪

PCA也可以用作噪音的过滤,因为任何一个成分的变化影响都远远大于随机噪声的影响的,所以针对于噪声,各种的成分相对不受影响。即可以用主成分来重构原始数据。

3、原理

  • R d \mathbb{R}^{d} 空间中有 m m 个点 : { x 1 , x 2 , . . . , x m } :\{x_1,x_2,...,x_m\} (这些点即可以理解为我们数据的特征,如图片的像素),首先对 x i x_i 数据进行归一化(保证其均值为0)。其中 R d \mathbb{R}^{d} 空间中的坐标基向量均是两两正交的,坐标系基向量为 { w 1 , w 2 , . . . , w d } \{w_1,w_2,...,w_d \}
  • x i = ( x i 1 ; x i 2 ; . . . ; x i d ) R d x_i=(x_{i1};x_{i2};...;x_{id})\in \mathbb{R}^{d} 进行降维压缩得到 z i = ( z i 1 ; z i 2 ; . . . ; z i d ) R d z_i=(z_{i1};z_{i2};...;z_{id'})\in \mathbb{R}^{d'} ( d < d ) (d'<d) 。其中 x i j x_{ij} z i j z_{ij} 分别是样本 x i x_i z i z_i R d \mathbb{R}^{d} R d \mathbb{R}^{d'} 空间下的坐标。
  • x i x_i 得到 z i z_i 的过程可以如下表示: z i j = w j T x i z_{ij}=w_j^Tx_i ;基于 z i z_i 重构 x i x_i 可以表示为: x i ^ = j = 1 d z i j w j \hat{x_i}=\sum_{j=1}^{d'}z_{ij}w_j (基变换,坐标变换)。

所以 x i x_i x i ^ \hat{x_i} 之间的距离表述如下,其中 W T W = I , z i = W T x i \mathbf{W}^{\mathrm{T}} \mathbf{W}=\mathbf{I},\boldsymbol z_i=\mathbf{W}^{\mathrm{T}} \boldsymbol x_i

i = 1 m j = 1 d z i j w j x i 2 2 = i = 1 m W z i x i 2 2 = i = 1 m ( W z i x i ) T ( W z i x i ) = i = 1 m ( z i T W T W z i z i T W T x i x i T W z i + x i T x i ) = i = 1 m ( z i T z i 2 z i T W T x i + x i T x i ) = i = 1 m z i T z i 2 i = 1 m z i T W T x i + i = 1 m x i T x i = i = 1 m z i T z i 2 i = 1 m z i T W T x i +  const  = i = 1 m z i T z i 2 i = 1 m z i T z i +  const  = i = 1 m z i T z i +  const  = i = 1 m tr ( z i z i T ) +  const  = tr ( i = 1 m z i z i T ) +  const  = tr ( i = 1 m W T x i x i T W ) +  const  = tr ( W T ( i = 1 m x i x i T ) W ) +  const  tr ( W T ( i = 1 m x i x i T ) W ) \begin{aligned} \sum^m_{i=1}\left\| \sum^{d'}_{j=1}z_{ij}\boldsymbol{w}_j-\boldsymbol x_i \right\|^2_2&=\sum^m_{i=1}\left\|\mathbf{W}\boldsymbol z_i-\boldsymbol x_i \right\|^2_2\\ &= \sum^m_{i=1} \left(\mathbf{W}\boldsymbol z_i-\boldsymbol x_i\right)^{\mathrm{T}}\left(\mathbf{W}\boldsymbol z_i-\boldsymbol x_i\right)\\ &= \sum^m_{i=1} \left(\boldsymbol z_i^{\mathrm{T}}\mathbf{W}^{\mathrm{T}}\mathbf{W}\boldsymbol z_i- \boldsymbol z_i^{\mathrm{T}}\mathbf{W}^{\mathrm{T}}\boldsymbol x_i-\boldsymbol x_i^{\mathrm{T}}\mathbf{W}\boldsymbol z_i+\boldsymbol x_i^{\mathrm{T}}\boldsymbol x_i \right)\\ &= \sum^m_{i=1} \left(\boldsymbol z_i^{\mathrm{T}}\boldsymbol z_i- 2\boldsymbol z_i^{\mathrm{T}}\mathbf{W}^{\mathrm{T}}\boldsymbol x_i+\boldsymbol x_i^{\mathrm{T}}\boldsymbol x_i \right)\\ &=\sum^m_{i=1}\boldsymbol z_i^{\mathrm{T}}\boldsymbol z_i-2\sum^m_{i=1}\boldsymbol z_i^{\mathrm{T}}\mathbf{W}^{\mathrm{T}}\boldsymbol x_i+\sum^m_{i=1}\boldsymbol x^{\mathrm{T}}_i\boldsymbol x_i\\ &=\sum^m_{i=1}\boldsymbol z_i^{\mathrm{T}}\boldsymbol z_i-2\sum^m_{i=1}\boldsymbol z_i^{\mathrm{T}}\mathbf{W}^{\mathrm{T}}\boldsymbol x_i+\text { const }\\ &=\sum^m_{i=1}\boldsymbol z_i^{\mathrm{T}}\boldsymbol z_i-2\sum^m_{i=1}\boldsymbol z_i^{\mathrm{T}}\boldsymbol z_i+\text { const }\\ &=-\sum^m_{i=1}\boldsymbol z_i^{\mathrm{T}}\boldsymbol z_i+\text { const }\\ &=-\sum^m_{i=1}\operatorname{tr}\left(\boldsymbol z_i\boldsymbol z_i^{\mathrm{T}}\right)+\text { const }\\ &=-\operatorname{tr}\left(\sum^m_{i=1}\boldsymbol z_i\boldsymbol z_i^{\mathrm{T}}\right)+\text { const }\\ &=-\operatorname{tr}\left(\sum^m_{i=1}\mathbf{W}^{\mathrm{T}} \boldsymbol x_i\boldsymbol x_i^{\mathrm{T}}\mathbf{W}\right)+\text { const }\\ &= -\operatorname{tr}\left(\mathbf{W}^{\mathrm{T}}\left(\sum^m_{i=1}\boldsymbol x_i\boldsymbol x^{\mathrm{T}}_i\right)\mathbf{W}\right)+\text { const }\\ &\propto-\operatorname{tr}\left(\mathbf{W}^{\mathrm{T}}\left(\sum^m_{i=1}\boldsymbol x_i\boldsymbol x^{\mathrm{T}}_i\right)\mathbf{W}\right)\\ \end{aligned}
最小化上式得到 W \mathbf{W}

二、代码

1、本文代码是通过加载原始的matlab 中的一个数组文件作为数据集的(数据集可以是任意的数据,但注意最后用plt库绘图时,注意下标的匹配)
2、其中有些地方代码已经注释的很清楚了。
3、若进行降噪即最后重构(restore)即可,若进行降维,那么经过转换后(transform)的即是新的维度下的结果。
4、代码引用了部分搜索到的,不过有些确实找不到了而没有引用!

1、sklearn库方式

# -*- coding: utf-8 -*-
"""
Created on Tue Jan  8 10:39:09 2019

@author: QSY
"""


import matplotlib.pyplot as plt
import scipy.io as sci
from sklearn.decomposition import PCA
import numpy as np

"""Read data from  *.mat including two kinds"""
data_tarin = sci.loadmat('data_train.mat')
# data_test = sci.loadmat('data_test.mat')
data_train_noisy = data_tarin['noiseSignal']
data_train_theory = data_tarin['clearSignal']

#选取数据进行操作
X=data_train_noisy[0:1,:]
#进行行列转换
X=list(map(list, zip(*X)))

#创建横坐标
p=[]
for i in range(434): 
    j=i
    p.append(j)


def ReadReductionofcomponents(X):
    
    pca=PCA(n_components=1)
    pca.fit(X)
    #进行操作转换后的结果
    x_reduction =pca.transform(X)
    
    #进行复原恢复后的结果
    x_restore=pca.inverse_transform(x_reduction)   
    x_restore=x_restore[:,0:1]  
  
    #X仅选择某一列的数据进行操作
    X=np.array(X)
    X=X[:,0:1]
    
    #进行线绘制   
    plt.plot(p, x_restore, color='r', linewidth=0.3, alpha=0.6,label="PCA")
    plt.plot(p, X, color='b', linewidth=0.2, alpha=0.6,label="init")
    plt.legend()#显示图例名字
    #pdf保存
    plt.savefig('1.png')
    plt.show()   
    
ReadReductionofcomponents(X)

2、数学方式

# -*- coding: utf-8 -*-
"""
Created on Tue Jan  8 16:24:57 2019

@author: QSY
"""


import numpy as np
import scipy.io as sci
import matplotlib.pyplot as plt


"""Read data from  *.mat including two kinds"""
data_tarin = sci.loadmat('data_train.mat')
other_data=sci.loadmat('pca.mat')
# data_test = sci.loadmat('data_test.mat')
data_train_noisy = data_tarin['noiseSignal']
data_train_theory = data_tarin['clearSignal']
perfect_data=other_data['U']
#选取数据进行操作
X=data_train_noisy[0:3,:]
X=list(map(list, zip(*X)))

X=perfect_data
#零均值化
def zeroMean(dataMat):      
    #按列求均值,即求各个特征的均值
    meanVal=np.mean(dataMat,axis=0)     
    newData=dataMat-meanVal
    return newData,meanVal
 
def pca(dataMat,n):
    
    newData,meanVal=zeroMean(dataMat)
    covMat=np.cov(newData,rowvar=0)    #求协方差矩阵
    
    eigVals,eigVects=np.linalg.eig(np.mat(covMat))#求特征值和特征向量,特征向量是按列放的,即一列代表一个特征向量
    eigValIndice=np.argsort(eigVals)            #对特征值从小到大排序
    n_eigValIndice=eigValIndice[-1:-(n+1):-1]   #最大的n个特征值的下标
    n_eigVect=eigVects[:,n_eigValIndice]        #最大的n个特征值对应的特征向量
    lowDDataMat=newData*n_eigVect               #低维特征空间的数据
    reconMat=(lowDDataMat*n_eigVect.T)+meanVal  #重构数据
    return lowDDataMat,reconMat

#newData,meanVal=zeroMean(X)
lowDDataMat,reconMat=pca(X,n=1)

p=[]
for i in range(24): 
    j=i#np.log10(i)
    p.append(j)

plt.plot(p, lowDDataMat, color='r', linewidth=0.2, alpha=0.6,label="after PCA")
#plt.plot(p, X, color='b', linewidth=0.2, alpha=0.6,label="init")
plt.legend()#显示图例名字
#pdf保存
plt.savefig('1.pdf')
plt.show()



引用

https://www.cnblogs.com/sweetyu/p/5085798.html
https://www.cnblogs.com/pinard/p/6243025.html

发布了27 篇原创文章 · 获赞 15 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_42192910/article/details/85881257