PS:该系列数据都可以在图灵社区(点击此链接)中随书下载中下载(如下)
对数据进行简化的原因:
主成分分析(Principal Component Analysis,PCA): 在PCA中,数据从原来的坐标系转换到了新的坐标系,新坐标系的选择是由数据本身决定的。第一个新坐标轴选择的是原始数据中方差最大的方向,第二个新坐标轴的选择和第一个坐标轴正交且具有最大方差的方向。该过程一直重复,重复次数为原始数据中特征的数目。我们会发现,大部分方差都包含在最前面的几个新坐标轴中。因此,我们可以忽略余下的坐标轴,即对数据进行了降维处理。
因子分析(Factor Analysis): 在因子分析中,我们假设在观察数据的生成中有一些观察不到的隐变量(latent variable)。假设观察数据是这些隐变量和某些噪声的线性组合。那么隐变量的数据可能比观察数据的数目少,也就是说通过找到隐变量就可以实现数据的降维。
独立成分分析(Independent Component Analysis,ICA): ICA假设数据是从N个数据源生成的,这一点和因子分析有些类似。假设数据为多个数据源的混合观察结果,这些数据源之间在统计上是相互独立的,而在PCA中只假设数据是不相关的。同因子分析一样,如果数据源的数目少于观察数据的数目,则可以实现降维过程。
主成分分析
优点:降低数据的复杂性,识别最重要的多个特征。
缺点:不一定需要,且可能损失有用信息。
适用数据类型:数值型数据。
第一个主成分就是数据差异性最大(即方差最大)的方向提取出来的,第二个主成分则来自于数据差异性次大的方向,并且该方向与第一个主成分方向正交。通过数据集的协方差矩阵及其特征值分析,我们就可以求得这些主成分的值。
一旦得到了协方差矩阵的特征向量,我们就可以保留最大的N个值。这些特征向量也给出了N个最重要特征的真实结构。我们可以通过将数据乘上这N个特征向量而将它转换到新的空间。
将数据转换成前N个主成分的伪代码大致如下:
去除平均值
计算协方差矩阵
计算协方差矩阵的特征值和特征向量
将特征值从大到小排序
保留最上面的N个特征向量
将数据转换到上述N个特征向量构建的新空间中
建立pca.py文件,编写如下代码用于计算PCA,并在python命令行进行测试:
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
def loadDataSet(fileName, delim='\t'):
with open(fileName, 'r') as fileObject:
stringArr = [line.strip().split(delim) for line in fileObject.readlines()]
datArr = [list(map(float, line)) for line in stringArr]
return np.mat(datArr)
def pca(dataMat, topNfeat=9999999):
#计算特征值和特征向量
meanVals = np.mean(dataMat, axis=0)
meanRomoved = dataMat - meanVals
covMat = np.cov(meanRomoved, rowvar=0)
eigVals, eigVects = np.linalg.eig(np.mat(covMat))
#找出topNfeat个最大的特征向量
#并利用这N个特征向量将原始数据转换到新空间
eigValInd = np.argsort(eigVals)
eigValInd = eigValInd[:-(topNfeat + 1) : -1]
redEigVects = eigVects[:, eigValInd]
lowDDataMat = meanRomoved * redEigVects
reconMat = (lowDDataMat * redEigVects.T) + meanVals
return lowDDataMat, reconMat
def plotPCA(fileName, topNfeat):
dataMat = loadDataSet(fileName)
lowDMat, reconMat = pca(dataMat, topNfeat)
print("shape of lowDMat: ", np.shape(lowDMat))
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()
可以看到上述结果对testSet.txt文件中的数据集进行了降维操作。
secom.data文件中记录了半导体制造数据,它拥有590个特征。现在利用pca对这些特征进行降维处理。
该数据包含很多缺失值。这些缺失值是NaN,这里用平均值代替,平均值根据那些非NaN得到。
def replaceNanWithMean():
datMat = loadDataSet('secom.data', ' ')
numFeat = np.shape(datMat)[1]
for i in range(numFeat):
#计算非NaN值的平均值,并将所有NaN替换为该平均值
meanVal = np.mean(datMat[np.nonzero(~np.isnan(datMat[:, i].A))[0], i])
datMat[np.nonzero(np.isnan(datMat[:, i].A))[0], i] = meanVal
return datMat
考虑在该数据集上应用PCA。首先确定所需特征和可以去除特征的数目。PCA会给出数据中所包含的信息量。数据(data)和信息(information)之前是有巨大的差别的。数据指的是接受的原始材料,其中可能包含噪声和不相关信息。信息是指数据中的相关部分。
我们可以发现其中超过20%的特征值都是0,这意味着这些特征都是其他特征的副本,也就是说,它们可以通过其他特征来表示,而本身并没有提供额外的信息。又可以观察到很多值得数量级非常小,只有部分重要特征,重要特征的数目也很快就会下降。最后。我们可能会注意到有一些小的负值,它们主要源自数值误差应该四舍五入成0。
下图给出总方差的百分比,发现,在开始几个主成分之后,方差就会迅速下降。
可以看出大部分方差都包含在前面的几个主成分中,舍弃后面的主成分并不会损失太多的信息。如果保留前6个主成分,则数据集可以从590个特征约简成6个特征,大概实现了100:1的压缩。
下表给出了这些主成分所对应的方差百分比和累积方差百分比。浏览“累积方差百分比(%)”这一列就会注意到,前六个主成分就覆盖了数据96.8%的方差,而前20个主成分覆盖了99.3%的方差。这就表明了如果保留前6个而去除后584个主成分,我们就可以实现大概100:1的压缩比。另外,由于舍弃了噪声的主成分,将后面的主成分去除便使得数据更加干净。
降维技术使得数据变得更易使用,并且它们往往能够去除数据中的噪声,使得其他机器学习任务更加精确。降维往往作为预处理步骤,在数据应用到其他算法之前清洗数据。有很多技术可以用于数据降维,在这些技术中,独立成分分析、因子分析和主成分分析比较流行,其中又以主成分分析应用最广泛。
PCA可以从数据中识别其主要特征,它是通过沿着数据最大方差方向旋转坐标轴来实现的。选择方差最大的方向作为第一条坐标轴,后续坐标轴则与前面的坐标轴正交。协方差矩阵上的特征值分析可以用一系列的正交坐标轴来获取。