赞
踩
第一种降维的方法称为主成分分析。在PCA中,数据从原来的坐标系转换到新的坐标系,新坐标系的选择是由数据本身决定的。第一个新坐标轴选择的是原始数据中方差最大的方向,第二个新坐标轴的选择和第一个坐标轴正交且具有最大方差的方向。该过程一直重复,重复次数为原始数据中特征的数目。我们会发现,大部分方差都包含在最前面的几个新坐标轴中。因此,我们可以忽略余下的坐标轴,即对数据进行了降维处理。
另外一种降维技术是因子分析。在因子分析中,我们假设在观察数据的生成中有一些观察不到的隐变量(latent variable)。假设观察数据是这些隐变量和某些噪声的线性组合。那么隐变量的数据可能比观察数据的数目少,也就是说通过找到隐变量就可以实现数据的降维。
还有一种降维技术就是独立成分分析。ICA假设数据是从N个数据源生成的,这一点和因子分析有些类似。假设数据为多个数据源的混合观察结果,这些数据源之间在统计上是相互独立的,而在PCA中只假设数据是不相关的。同因子分析一样,如果数据源的数目少于观察数据的数目,则可以实现降维。
主成分分析的优缺点:
优点:降低数据的复杂性,识别最重要的多个特征。
缺点:不一定需要,且可能损失有用信息。
适用数据类型:数值型数据。
考虑下图的数据点,我们画出一条直线,这条线尽可能覆盖这些点,即图中红线所示。在PCA中,我们对数据的坐标进行旋转,该旋转的过程取决于数据的本身。第一条坐标轴旋转到覆盖数据的最大方差位置,即图中的红线。接下来选择第二条坐标轴,这条坐标轴与第一条坐标轴正交,它就是覆盖数据次大差异的坐标轴,即图中的蓝线。利用PCA,我们将数据坐标轴旋转至数据角度上的那些最重要的方向。
考虑上图中的数据,其中包含着三个不同的类别。
如果采用决策树将其分类,我们会发现在x轴上可以找到一些值,这些值能够很好的将这三个类别分开,但是分类间隔不会很大。如图中绿色所示。
如果使用SVM分类器,我们就会得到更好的分类面和分类规则。SVM可能比决策树得到更好的分类间隔,但是分类超平面却很难解释。
通过PCA进行降维处理,如上图的蓝线所示。我们就可以同时获得SVM和决策树的优点:一方面,得到了和决策树一样简单的分类器,同时分类间隔和SVM一样好。
将数据转换成前N个主成分的伪代码如下:
去除平均值
计算协方差矩阵
计算协方差矩阵的特征值和特征向量
将特征值从大到小排序
保留最上面的N个特征向量
将数据转换到上述N个特征向量构建的新空间中
创建一个Pca.py文件并添加下列代码:
from numpy import * 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] #把每行字符串映射为浮点型数字 ## print 'datArr=',datArr return mat(datArr) #返回的是矩阵型数据集 ''' 功能:将数据降维 输入变量: dataMat:矩阵型原始数据 topNfeat:保留的特征个数 输出变量: lowDDataMat:降维之后的数据集 reconMat:重构原始数据集 ''' def pca(dataMat, topNfeat=9999999): meanVals = mean(dataMat, axis=0) meanRemoved = dataMat - meanVals #remove mean移除均值 ## print 'meanRemoved=',meanRemoved covMat = cov(meanRemoved, rowvar=0) eigVals,eigVects = linalg.eig(mat(covMat)) ## print 'eigVals=',eigVals eigValInd = argsort(eigVals) #sort, sort goes smallest to largest eigValInd = eigValInd[:-(topNfeat+1):-1] #cut off unwanted dimensions后面的-1代表的是将值倒序,原来特征值从小到大,现在从大到小 ## print 'eigValInd=',eigValInd redEigVects = eigVects[:,eigValInd] #reorganize eig vects largest to smallest lowDDataMat = meanRemoved * redEigVects#transform data into new dimensions将数据转换到新空间中 print(lowDDataMat) reconMat = (lowDDataMat * redEigVects.T) + meanVals #降维后的数据再次映射到原来空间中,用于与原始数据进行比较 return lowDDataMat, reconMat ''' 功能:绘图 ''' def fig(dataMat,reconMat): 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()
测试代码:
import Pca
from numpy import *
dataMat = Pca.loadDataSet('testSet.txt')
print('dataMat=',dataMat)
lowDMat, reconMat = Pca.pca(dataMat,1)
print(shape(lowDMat))
print('reconMat=',reconMat)
Pca.fig(dataMat,reconMat)
结果:
分析:
文件中的原始数据共有1000个样本,每个样本2个特征,保留1个特征,即降维到1维,其特征向量为方差最大的方向,就是如图红色直线的方向。
改变调用pca函数时的参数,改为 lowDMat, reconMat = Pca.pca(dataMat,2) ,即保量样本的2个特征,降维到2维那么得到的结果与原来的数据是重合的。这样没有剔除任何特征。如下图所示。
我们需要降维的数据集包含了590个特征。数据中包含很多缺失值,这些缺失值是以NaN(Not a Number的缩写)标识的。对于缺失值,我们使用特征的均值来填补缺失值。
在Pca.py中添加下列代码:
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]) # 利用该维度所有非NaN特征求取均值
#(找出第 i 列中是Nan的那些元素的位置(是为1,不是为0)再取反就找到了不是Nan的位置,
#然后再索引出来求均值。)
datMat[nonzero(isnan(datMat[:,i].A))[0],i] = meanVal # 将该维度中所有NaN特征全部用均值替换
return datMat
测试代码:
import Pca from numpy import * dataMat = Pca.replaceNanWithMean() meanVals = mean(dataMat,axis = 0) meanRemoved = dataMat - meanVals covMat = cov(meanRemoved,rowvar=False) eigVals,eigVects = linalg.eig(mat(covMat)) print(eigVals) # 对前20个特征值画图 Pca.plt.plot(eigVals[:20]) Pca.plt.show() #画占比 eigValsRate = [] for i in range(30): temRate = float(sum(eigVals[0:i]))/ sum(eigVals) eigValsRate.append(temRate) Pca.plt.plot(eigValsRate) Pca.plt.show()
结果:
前20个主成分占总方差的百分比:
前20个主成分累计方差百分比:
分析:
从结果中可以看到,其中有很多数据的特征值是0,意味着它们本身并没有提供额外的信息。
且大部分方差都包含在前面的几个主成分中,舍弃后面的主成分并不会损失太多的信息。如果保留前6个主成分,则数据集可以从590个特征约简成6个特征,大概实现了100:1的压缩。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。