1. 主成分分析

优点:降低数据的复杂性,识别最重要的多个特征。

缺点:不一定需要,且可能损失有用信息。

使用数据类型:数值型数据

2. 在NumPy中实现PCA

将数据转换成前K个主成分的伪码:

去除平均值(让样本矩阵中心化,即每一个维度减去该维度的均值,使每一维度上的均值为0)

计算协方差矩阵

计算协方差矩阵的特征值和特征向量

将特征值从大到小排序

保留最上面的K个特征向量

将数据转换到上述K个特征向量构建的新空间中

补充阅读:协方差矩阵

(1)一个维度上方差的定义:

(2)协方差的定义:

方差是协方差的一个特例,X与其自身的协方差就是X的方差。

分母为n-1是因为随机变量的数学期望未知,以样本均值代替,自由度减一。

协方差就是定义了两个维度之间的相关性,即这个样本的两个维度之间有没有关系。

协方差为0,证明这两个维度之间没有关系;协方差为正,两个维度正相关;协方差为负,两个维度负相关。

(3)协方差矩阵:

对n个维度,任意两个维度都计算一个协方差,组成矩阵。

直观地,对于一个含有x,y,z三个维度的样本,协方差矩阵如下:

可以看出,对角线表示了样本在各个维度上的方差,其他元素表示不同维度两两之间的相关性。

例:

假设原始数据为5个样本,每个样本有2个特征x和y。矩阵是:

第一步,样本矩阵中心化(计算每个维度的均值,所有样本都减去均值)

维度x的均值为2,维度y的均值为1。

各维度去均值后,矩阵是:

这时,两个维度上的均值都为0。

第二步,计算协方差矩阵

协方差矩阵:

第三步,计算协方差矩阵的特征值和特征向量

特征值2.5对应的特征向量是eigenVectors的第1列:

特征值0.5对应的特征向量是eigenVectors的第2列:

第四步,将特征值按照从大到小的顺序排列,选择其中最大的k个,然后将其对应的k个特征向量分别作为列向量组成特征向量矩阵

这里特征值只有2个,我们选取最大的那个2.5,对应的特征向量是:

第五步,将样本点投影到选取的特征向量上。

假设样本数为m,特征数为n,减去均值后的样本矩阵为DataAdjust(m×n),协方差矩阵为C(n×n),选取的k个特征向量组成的矩阵为TopEigenVectors(n×k),那么投影后的低维数据LowDimData为:

这里是

这样就将原始样本的n维(这个例子n=2)特征变成了k维(这个例子k=1),这k维就是原始特征在k维上的投影。

第六步,查看重构之后的数据,用于调试(假设K取值为n,重构回去的数据reconMat应该与原始数据Data重合)

程序清单 PCA算法

from numpy import *
import matplotlib
import matplotlib.pyplot as plt

def loadDataSet(fileName, delim='\t'):
    fr = open(fileName)
    stringArr = [line.strip().split(delim) for line in fr.readlines()]
    datArr = [list(map(float,line)) for line in stringArr]
    # python3 needs list()
    return mat(datArr)

def pca(dataMat, topNfeat=9999999):
    meanVals = mean(dataMat, axis=0)
    dataAdjust = dataMat - meanVals #remove mean
    covMat = cov(dataAdjust, rowvar=0)
    eigVals,eigVects = linalg.eig(mat(covMat))
    eigValInd = argsort(eigVals)            #sort, sort goes smallest to largest
    eigValInd = eigValInd[:-(topNfeat+1):-1]  #cut off unwanted dimensions
    topEigVects = eigVects[:,eigValInd]       #reorganize eig vects largest to smallest
    lowDimDataMat = dataAdjust * topEigVects#transform data into new dimensions
    reconMat = (lowDimDataMat * topEigVects.T) + meanVals
    return lowDimDataMat, reconMat

dataMat = loadDataSet('testSet.txt')
lowDimDataMat, reconMat = pca(dataMat, 1)

fig = plt.figure()
ax = fig.add_subplot(111)
ax.scatter(dataMat[:,0].flatten().A[0],  dataMat[:,1].flatten().A[0], marker='^', s=90)
ax.scatter(reconMat[:,0].flatten().A[0], reconMat[:,1].flatten().A[0], marker='o', s=50, c='red')
plt.show()

运行结果如图1:

图1 原始数据集(三角形)及第一主成分(圆形)

用到的数据集testSet.txt

参考文献:

[1] (美) Harrington Peter著. 机器学习实战[M]. 李锐, 李鹏, 曲亚东, 王斌, 译. 北京: 人民邮电出版社, 2013.