主成分分析代码实现

主成分分析(PCA)是一种线性降维技术。在PCA中数据从原来坐转换到了新的坐标系,新坐标的选择是由数据本身决定的。(高维原空间 XXT 的前d’个大小的特征值(从大到小的排序)对应的特征向量决定了新坐标)。第一个坐标轴的选择是原始数据方差最大,第二新坐标轴的选择和第一个坐标轴正交且具有最大方差的方向。

  • PCA可以同时获得像决策树一样简单的分类,同时分类间隔SVM一样好。
  • 通过数据集协方差矩阵以及其特征值和对应的特征向量,保留最大的N个值构成属性转化空间矩阵W,将 WT] 乘以原空间样本得到降维空间属性。

实现过程:Python中Numpy有寻找特征向量和特征值模块linalg,有eig()方法
伪代码:

  • 去除平均值
  • 计算协方差矩阵
  • 计算协方差矩阵的特征值和特征向量
  • 将特征值从大到小排列
  • 保留最上面的N个特征向量
  • 将数据转换到上述N个特征向量构建的新空间中
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):
    meanVale=mean(dataMat,axis=0)#axis=0 col
    meanRemoved=dataMat-meanVale#remove mean
    covMat = cov(meanRemoved, rowvar=0)
    eigVals,eigVects = linalg.eig(mat(covMat))
    eigValInd = argsort(eigVals)            #sort, sort goes smallest to largest
    eigValInd = eigValInd[:-(topNfeat+1):-1]  #cut off unwanted dimensions
    redEigVects = eigVects[:,eigValInd]       #reorganize eig vects largest to smallest
    lowDDataMat = meanRemoved * redEigVects#transform data into new dimensions
    reconMat = (lowDDataMat * redEigVects.T) + meanVals
    return lowDDataMat, reconMat
  • map()用法: map()是 Python 内置的高阶函数,它接收一个函数 f 和一个 list,并通过把函数 f 依次作用在 list 的每个元素上,得到一个新的 list 并返回。
    • 例如,对于list [1, 2, 3, 4, 5, 6, 7, 8, 9],如果希望把list的每个元素都作平方,就可以用map()函数:因此,我们只需要传入函数f(x)=x*x,就可以利用map()函数完成这个计算
    • def f(x):
      return x*x
      print map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9])
      结果 [1, 4, 9, 10, 25, 36, 49, 64, 81]

      由于list包含的元素可以是任何类型,因此,map() 不仅仅可以处理只包含数值的 list,事实上它可以处理包含任意类型的 list,只要传入的函数f可以处理这种数据类型。
将每一行数据转换为float型
datArr=[map(float,line)for line in stringArr]
原始数据被重构后用于调试
reconMat = (lowDDataMat * redEigVects.T) + meanVals

示例:利用PCA对半导体制造数据降维
观察数据集,缺失值是以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]) #values that are not NaN (a number)
        datMat[nonzero(isnan(datMat[:,i].A))[0],i] = meanVal  #set NaN values to mean
    return datMat

npnzero()用法
nonzeros(a)返回数组a中值不为零的元素的下标,它的返回值是一个长度为a.ndim(数组a的轴数)的元组,元组的每个元素都是一个整数数组,其值为非零元素的下标在对应轴上的值。
例如对于一维布尔数组b1,nonzero(b1)所得到的是一个长度为1的元组,它表示b1[0]和b1[2]的值不为0(False)。
对于二维数组b2,nonzero(b2)所得到的是一个长度为2的元组。它的第0个元素是数组a中值不为0的元素的第0轴的下标,第
个元素则是第1轴的下标,因此从下面的结果可知b2[0,0]、b[0,2]和b2[1,0]的值不为0:

>>> b1 = np.array([True, False, True, False])
>>> np.nonzero(b1)
    (array([0, 2]),)
>>> b2 = np.array([[True, False, True], [True, False, False]])
>>> np.nonzero(b2)
    (array([0, 0, 1]), array([0, 2, 0]))

未完待续….

你可能感兴趣的:(机器学习)