0
点赞
收藏
分享

微信扫一扫

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


降维技术

对数据进行简化的原因 : 

  1. 使得数据集更易使用
  2. 降低算法的计算开销
  3. 去除噪声
  4. 使得结果易懂

在已标注与未标注的数据上都有降维技术。我们将主要关注未标注数据集上的降维技术,该技术同时也可以用于已标注的数据。

PCA 。在PCA中,数据从原来的坐标系转换到了新的坐标系,新坐标系的选择是由数据本身决定的。第一个新坐标轴选择的是原始数据中方差最大的方向,第二个新坐标轴的选择和第一个坐标轴正交且具有最大方差的方向。该过程一直重复,重复次数为原始数据中特征的数目。我们会发现,大部分方差都包含在最前面的几个新坐标轴中。因此,我们可以忽略余下的坐标轴,即对数据进行了降维处理。

另外一种降维技术是因子分析(Factor Analysis)。在因子分析中,我们假设在观察数据的生成中有一些观察不到的隐变量(latent variable)。假设观察数据是这些隐变量和某些噪声的线性组合。那么隐变量的数据可能比观察数据的数目少,也就是说通过找到隐变量就可以实现数据的降维。因子分析已经应用于社会科学、金融和其他领域中了。

还有一种降维技术就是独立成分分析(Independent Component Analysis,ICA )。ICA假设数据是从N个数据源生成的,这一点和因子分析有些类似。假设数据为多个数据源的混合观察结果,这些数据源之间在统计上是相互独立的,而在PCA中只假设数据是不相关的。同因子分析一样,如果数据源的数目少于观察数据的数目,则可以实现降维过程。

 

PCA

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

移动坐标轴

考虑一下图13-1中的大量数据点。如果要求我们画出一条直线,这条线要尽可能覆盖这些点,那么最长的线可能是哪条?我做过多次尝试。在图13-1中,3条直线中B最长。在PCA中 ,我们对数据的坐标进行了旋转,该旋转的过程取决于数据的本身。第一条坐标轴旋转到覆盖数据的最大方差位置,即图中的直线B。数据的最大方差给出了数据的最重要的信息。

在选择了覆盖数据最大差异性的坐标轴之后,我们选择了第二条坐标轴。假如该坐标轴与第一条坐标轴垂直,它就是覆盖数据次大差异性的坐标轴。这里更严谨的说法就是正交(orthogonal)。当然,在二维平面下,垂直和正交是一回事。在图13-1中,直线C就是第二条坐标轴。利用PCA,我们将数据坐标轴旋转至数据角度上的那些最重要的方向。(这里提到的数据差异性其实指的就是一个特征的方差,正交是指特征之间无线性相关性)

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

我们实现了坐标轴的旋转,接下来讨论降维。坐标的旋转并没有减少数据的维度。图13-2 中, 我们都用PCA 进行降维处理,我们就同时获得SVM 和 决策树的优点: 一方面,得到了和决策树一样简单的分类器,同时分类间隔和SVM 一样好。图13-2 下面的图就是经PCA绘制的。如果仅使用原始数据,那么这里的间隔会比决策树的间隔更大。另外,由于只需要考虑一维信息,因此数据就可以通过比SVM简单得多的很容易采用的规则进行区分。

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

在图13-2中,我们只需要一维信息即可,因为另一维信息只是对分类缺乏贡献的噪声数据。前面我曾提到的第一个主成分就是从数据差异性最大(即方差最大)的方向提取出来的,第二个主成分则来自于数据差异性次大的方向,并且该方向与第一个主成分方向正交。通过数据集的协方差矩阵及其特征值分析,我们就可以求得这些主成分的值。 
一旦得到了协方差矩阵的特征向量,我们就可以保留最大的N个值。这些特征向量也给出了个最重要特征的真实结构。我们可以通过将数据乘上这N个特征向量而将它转换到新的空间

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

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

 

import numpy as np
import matplotlib.pyplot as plt

def loadDataSet(filename,delim='\t'):
with open(filename,'r') as fr :
stringArr = [line.strip().split(delim) for line in fr.readlines()]
datArr = [list(map(float,line)) for line in stringArr]
return np.matrix(datArr)
def pca(dataMat,topNfeat = 9999999) :

meanVals =np.mean(dataMat,axis=0) # 按列求平均值
meanRemoved = dataMat-meanVals
covMat = np.cov(meanRemoved,rowvar=0) # 协方差
# 求特征值
eigVals,eigVects = np.linalg.eig(np.matrix(covMat))
# 对特征值进行从小到大的排序
eigValInd = np.argsort(eigVals)
# 逆序得到topNfeat 个最大的特征向量
eigValInd = eigValInd[:-(topNfeat+1):-1]
redEigVects = eigVects[:,eigValInd]

lowDDataMat = meanRemoved*redEigVects
reconMat = (lowDDataMat*redEigVects.T) +meanVals
return lowDDataMat ,reconMat





dataMat = loadDataSet('testSet.txt')

lowDMat , reconMat = pca(dataMat,1)
print(np.shape(lowDMat))



fig = plt.figure()
ax = fig.add_subplot(111)
ax.scatter(dataMat[:,0].A.ravel(),dataMat[:,1].A.ravel(),marker='^',s=90)
ax.scatter(reconMat[:,0].A.ravel(),reconMat[:,1].A.ravel(),marker='o',s=50,c='red')

plt.show()

topNfeat = 1 时 


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

原始数据集(三角形)及第一主成分

topNfeat = 2 时

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

因为没有剔除任何特征,可以看到数据会和原始数据重合。

实例 : 利用PCA对半导体制造数据降维

本次数据包含很多的缺失值。这些缺失值是以NaN (Not a Number的缩写)标识的。对于这些缺失值,我们有一些处理办法(参考第5章)。在590个特征下,几乎所有样本都有NAN,因此去除不完整的样本不太现实。尽管我们可以将所有的NAN替换成0 ,但是由于并不知道这些值的意义,所以这样做是个下策。如果它们是开氏温度,那么将它们置成0这种处理策略就太差劲了。下面我们用平均值来代替缺失值,平均值根据那些非NAN得到。

 

# 将 NAN 替换成平均值的函数
def replaceNanwithMean():
dataMat = loadDataSet('secom.data',' ')
# 计算特征数目
numFeat = np.shape(dataMat)[1]
for i in range(numFeat) :
meanVal = np.mean(dataMat[np.nonzero(~np.isnan(dataMat[:,i].A))[0],i])
dataMat[np.nonzero(np.isnan(dataMat[:,i].A))[0],i] = meanVal
return dataMat

 

dataMat = replaceNanwithMean()

lowDMat , reconMat = pca(dataMat,40)
print(np.shape(lowDMat))
plt.figure(figsize=(8,10))
for i in range(5) :

lowDMat, reconMat = pca(dataMat, i*10)
plt.subplot(5,1,i+1)
plt.scatter(dataMat[:,0].A.ravel(),dataMat[:,1].A.ravel(),marker='^',s=90)
plt.scatter(reconMat[:,0].A.ravel(),reconMat[:,1].A.ravel(),marker='o',s=50,c='red')

plt.show()

下图展示的是 前10 , 20 ,30 ,40 ,50 主成分 和原始数据集.  

机器学习实战 -- 利用PCA来简化数据_方差_05

 

 

举报

相关推荐

0 条评论