一、降维技术
降维就是指采用某种映射方法,将原高维空间中的数据点映射到低维度的空间中。在低维空间下,数据更容易进行处理,如果降到三维以下,还可以将数据通过图像显示出来,因为人处在一个三维的空间。目前流行的降维方法有:主成分分析(Principal Component Analysis,PCA)、因子分析(Factor Analysis)、独立成分分析(Independent Component Analysis,ICA),其中PCA最为广泛。
二、PCA
它的目标是通过某种线性投影,将高维的数据映射到低维的空间中表示,并期望在所投影的维度上数据的方差最大,以此使用较少的数据维度,同时保留住较多的原数据点的特性。在PCA中,数据从原来的坐标系转换到新的坐标系,新坐标系中第一个坐标轴选择的是原始数据中方差最大的方向,第二个坐标轴选择的是和第一个坐标轴正交且具有最大方差的方向。该过程一直重复,重复次数为原始数据中特征的数目。
那么问题出来了,为什么选择的坐标轴为方差最大的那个轴呢?
答案请看此文:http://blog.csdn.net/lming_08/article/details/21335313
通过此文分析得出:
一、数据的最大方差给出了数据的最重要的信息
二、方差就是特征值,最佳的投影直线是特征值最大时对应的特征向量,其次是第二大对应的特征向量,依次类推。
三、保留特征值大(方差最大)的,而方差较小的特征(如噪声)被丢弃。
三 、在Numpy中实现PCA
主要思路:
1、计算样本的平均值
即对原始变量进行中心化,因为协方差是离均差积和的平均,看公式
2、计算协方差矩阵
3、计算协方差矩阵的特征值和特征向量
4、将特征值从大到小排序
5、保留最大的特征值所对应的N个特征向量
6、将数据转换到上述N个特征向量构建的新空间中
源代码:
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 = [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()
dataMat = loadDataSet('testSet.txt')
print 'dataMat=',dataMat
lowDMat, reconMat = pca(dataMat,1)
##print shape(lowDMat)
print 'reconMat=',reconMat
fig(dataMat,reconMat)
运行结果:
dataMat= [[ 10.235186 11.321997]
[ 10.122339 11.810993]
[ 9.190236 8.904943]
[ 9.306371 9.847394]
[ 8.330131 8.340352]
[ 10.152785 10.123532]
[ 10.40854 10.821986]
[ 9.003615 10.039206]
[ 9.534872 10.096991]
[ 9.498181 10.825446]
[ 9.875271 9.233426]
[ 10.362276 9.376892]
[ 10.191204 11.250851]
[ 7.720499 6.4763 ]
[ 9.334379 8.471268]
[ 7.963186 6.731333]
[ 8.244973 9.013785]
[ 9.569196 10.568949]
[ 8.854793 9.076536]
[ 9.382171 7.240862]]
lowDDataMat= [[-2.03871919]
[-2.43596829]
[ 0.59387316]
[-0.31101859]
[ 1.46595626]
[-0.9152669 ]
[-1.65671815]
[-0.35894013]
[-0.63321292]
[-1.27985036]
[ 0.00942306]
[-0.32423664]
[-1.95570875]
[ 3.41431572]
[ 0.92778767]
[ 3.08125998]
[ 0.88954941]
[-1.07641315]
[ 0.57796936]
[ 2.02591845]]
reconMat= [[ 10.21503446 11.33125395]
[ 10.38085849 11.69223766]
[ 9.11610923 8.9389944 ]
[ 9.49383895 9.7612774 ]
[ 8.75207485 8.1465249 ]
[ 9.74607083 10.31036309]
[ 10.05557545 10.98412629]
[ 9.51384288 9.80482412]
[ 9.6283328 10.05405819]
[ 9.89825921 10.64166325]
[ 9.36007672 9.47008928]
[ 9.49935657 9.77328876]
[ 10.18038335 11.25582165]
[ 7.93876952 6.37603371]
[ 8.97672301 8.63556338]
[ 8.07779726 6.67868436]
[ 8.99268484 8.67031081]
[ 9.81333825 10.45679809]
[ 9.12274796 8.95344632]
[ 8.51832936 7.63768239]]
上面原始数据位20个样本,每个样本2个特征,保留1个特征,即降维到1维,其特征向量为方差最大的方向,就是如图红色直线的方向。