机器学习实战-利用PCA来简化数据

来源:互联网 发布:吉他软件电脑版 编辑:程序博客网 时间:2024/06/05 16:32

在体育比赛中,人们面对的原本是百万像素的数据,但是只有球的三维位置才最重要,这就成为降维(dimensionlity reduction)。通常而言,我们在应用其他机器学习算法之前,必须先识别出其相关特征。
第一种降维称作主方法分析(Principal Component Analysis,PCA)。
第一个坐标值选择的是原始数据中方差最大的方向,第二个新坐标轴的选择和第一个坐标轴正交且具有最大方差的方向。
另一种降维技术是因子分析(Factor Analysis)。在因子分析中,我们假设在观察数据的生成一些观察不到的隐变量(latent variable)。假设观察数据是这些隐变量和某些噪声的线性组合。那么隐变量的数据可能比观察数据的数目少,也就是说通过隐变量可以实现数据的降维。
还有一种方法就是独立成分分析(Independent Component Analysis,ICA)。ICA假设数据是从N个数据源生成的,这一点和因子分析有些类似。假设数据为多个数据源的混合观察结果,这些数据源之间在统计上是互相独立的,而在PCA中之假设数据是不相关的。
在上述3种降维技术中,PCA的应用目前最为广泛,因此本章主要关注PCA。在下一节中,我们将会对PCA进行介绍,然后再通过一段Python代码来运行PCA。

主成分分析
优点:降低数据的复杂性,识别最重要的多个特征
缺点:不一定需要,且可能损失有用信息
适用数据类型:数据型数据

将数据转化成前N个主成分的伪代码大致如下:

去除平均值计算协方差矩阵计算协方差矩阵的特征值和特征向量将特征值从打到小排序保留最上面的N个特征向量将数据转换到上述N个特征向量构建的新空间中

下面开始构建PCA算法

from numpy import *def loadDataSet(fileName, delim='\t'):    fr = open(fileName)    stringArr = [line.strip().split(delim) for line in fr.readlines()]    datArr = [map(float,line) for line in stringArr]    return mat(datArr)def pca(dataMat, topNfeat=9999999):#数据集,返回特征数    meanVals = mean(dataMat, axis=0)    meanRemoved = dataMat - meanVals #去平均值    covMat = cov(meanRemoved, rowvar=0) #协方差    eigVals,eigVects = linalg.eig(mat(covMat))#特征值,特征矩阵    eigValInd = argsort(eigVals)            #从小到大排序    eigValInd = eigValInd[:-(topNfeat+1):-1]  #逆序,从大到小    redEigVects = eigVects[:,eigValInd]           lowDDataMat = meanRemoved * redEigVects#将数据转化到新的维度空间    reconMat = (lowDDataMat * redEigVects.T) + meanVals    return lowDDataMat, reconMat

我们在testSet.txt文件中加入一个由1000个数据点组成的数据集,开始进行PCA操作:

In [17]: import pca    ...: dataMat = pca.loadDataSet('testSet.txt')    ...: lowDMat, reconMat = pca.pca(dataMat, 1)    ...: shape(lowDMat)    ...: Out[17]: (1000L, 1L)

lowDMat,包含了降维之后的矩阵。我们可以通过如下命令将降维后的数据和原始数据一起绘制出来:

import matplotlibimport matplotlib.pyplot as pltfig = 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()    ...:

原始数据集(三角形点)及第一主成分(圆形点)
使用如下命令代替PCA调用,也会看到类似结果:

lowDMat, reconMat = pca.pca(dataMat, 2)

下面我们先处理一些异常值,用平均值代替NaN:

def replaceNanWithMean():     datMat = loadDataSet('secom.data', ' ')    numFeat = shape(datMat)[1]    for i in range(numFeat):        meanVal = mean(datMat[nonzero(~isnan(datMat[:,i].A))[0],i])         datMat[nonzero(isnan(datMat[:,i].A))[0],i] = meanVal  #将所有nan置为平均值    return datMat

PCA会给出数据中所包含的信息量。数据(data)和信息(information)之间具有巨大的差别。数据指的是接受的原始材料,其中包含噪声和不相关的信息。信息指数据中的相关部分。下面开始操作,首先将所有的NaN值替换为平均值:

In [36]: import pca    ...: dataMat = pca.replaceNanWithMean()    ...: 

接下来从pca()函数中借用一些代码来达到我们的目的,之所以借用是因为我们想了解中间结果而非最后输出结果,调用如下语句去除均值:

In [37]: meanVals = mean(dataMat, axis = 0)    ...: meanRemoved = dataMat - meanVals    ...:

然后计算协方差矩阵:

In [38]: covMat = cov(meanRemoved, rowvar=0)

最后对该矩阵进行特征值分析:

In [39]: eigVals,eigVects = linalg.eig(mat(covMat))    ...:     ...: eigVals    ...: Out[39]: array([ 53415197.85687517+0.j,  21746671.90465918+0.j,         8248376.61529074+0.j, ...,         0.00000000+0.j,               0.00000000+0.j,         0.00000000+0.j])

我们会发现超过20%的特征值都是0。这意味着这些特征都是其他特征的副本,也就是说,他们可以通过其他特征来表示,而本身并没有提供额外的信息。
接下来,我们了解一下部分数值的数量级。最前面15个值的数量级大于10的五次方,实际上那以后的值都变得非常小。这相当于告诉我们部分重要特征,重要特征的数目也很快就会下降。
最后,我们注意到一些负值,他们主要源于数值误差,应该四舍五入为0。

阅读全文
0 0
原创粉丝点击