降维技术使得数据变得更易使用,并且它们往往能够去除数据中的噪声,使得机器学习任务往往更加精确。
降维往往作为预处理步骤,在数据应用到其它算法之前清洗数据。有很多技术可以用于数据降维,在这些技术中,独立成分分析(Independent Component Analysis, ICA)、因子分析(Factor Analysis)、主成分分析(Principal Component Analysis, PCA)比较流行,其中又以主成分分析应用最广泛。
PCA可以从数据中识别其主要特征,它是通过沿着数据最大方差方向旋转坐标轴来实现的。选择方差最大的方向作为第一条坐标轴,后续坐标轴与前面的坐标轴正交。
协方差矩阵上的特征值分析可以用一系列的正交坐标轴来获取。
降维的优点
1 使得数据集更易使用
2 降低很多算法的计算开销
3 去除噪声
4 使得结果易懂
缺点
1 不一定需要,且有可能损失有用信息
注意:PCA技术适用于数值型数据,不适用与名义数据
假设有如下数据需要进行预处理,数据集合约1000行。
PCA算法的伪代码大致如下:
1 去除平均值
2 计算协方差矩阵
3 计算协方差矩阵的特征值和特征向量
4 将特征值从大到小排序
5 保留最上面的N个特征向量
6 将数据装换到上述N个特征向量构建新的特征空间中
本文通过PCA算法对数据降维处理,主要代码如下
1 from numpy import * 2 3 def loadDataSet(filename, delim = '\t'): 4 fr = open(filename) 5 stringArr = [line.strip().split(delim) for line in fr.readlines()] 6 datArr = [map(float, line) for line in stringArr] 7 return mat(datArr) 8 9 def pca(dataMat, topNfeat=9999999): 10 11 meanVals = mean(dataMat, axis=0) 12 meanRemoved = dataMat-meanVals 13 covMat = cov(meanRemoved, rowvar = 0) 14 eigVals, eigVects = linalg.eig(mat(covMat)) 15 eigValInd = argsort(eigVals) 16 eigValInd = eigValInd[:-(topNfeat+1):-1] 17 redEigVects = eigVects[:, eigValInd] 18 lowDDataMat = meanRemoved * redEigVects 19 reconMat = (lowDDataMat * redEigVects.T) + meanVals 20 21 return lowDDataMat, reconMat
以列为对象,画出原始数据的散点图
主成分分析后的叠加图像
画图Python代码
import pca reload(pca) dataMat = pca.loadDataSet('testSet.txt') lowDmat, reconMat = pca.pca(dataMat, 1) import matplotlib import matplotlib.pyplot as plt 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')
随机生成数据,观察降维效果
from numpy import * import matplotlib import matplotlib.pyplot as plt import pca n = 1000 #number of points to create xcord0 = []; ycord0 = [] xcord1 = []; ycord1 = [] xcord2 = []; ycord2 = [] markers =[] colors =[] fw = open('testSet3.txt','w') for i in range(n): groupNum = int(3*random.uniform()) [r0,r1] = random.standard_normal(2) if groupNum == 0: x = r0 + 16.0 y = 1.0*r1 + x xcord0.append(x) ycord0.append(y) elif groupNum == 1: x = r0 + 8.0 y = 1.0*r1 + x xcord1.append(x) ycord1.append(y) elif groupNum == 2: x = r0 + 0.0 y = 1.0*r1 + x xcord2.append(x) ycord2.append(y) fw.write("%f\t%f\t%d\n" % (x, y, groupNum)) fw.close() fig = plt.figure() ax = fig.add_subplot(211) ax.scatter(xcord0,ycord0, marker='^', s=90) ax.scatter(xcord1,ycord1, marker='o', s=50, c='red') ax.scatter(xcord2,ycord2, marker='v', s=50, c='yellow') ax = fig.add_subplot(212) myDat = pca.loadDataSet('testSet3.txt') lowDDat,reconDat = pca.pca(myDat[:,0:2],1) label0Mat = lowDDat[nonzero(myDat[:,2]==0)[0],:2][0] #get the items with label 0 label1Mat = lowDDat[nonzero(myDat[:,2]==1)[0],:2][0] #get the items with label 1 label2Mat = lowDDat[nonzero(myDat[:,2]==2)[0],:2][0] #get the items with label 2 #ax.scatter(label0Mat[:,0],label0Mat[:,1], marker='^', s=90) #ax.scatter(label1Mat[:,0],label1Mat[:,1], marker='o', s=50, c='red') #ax.scatter(label2Mat[:,0],label2Mat[:,1], marker='v', s=50, c='yellow') ax.scatter(label0Mat[:,0],zeros(shape(label0Mat)[0]), marker='^', s=90) ax.scatter(label1Mat[:,0],zeros(shape(label1Mat)[0]), marker='o', s=50, c='red') ax.scatter(label2Mat[:,0],zeros(shape(label2Mat)[0]), marker='v', s=50, c='yellow') plt.show()