=====================================================================
github 源码同步:https://github.com/Thinkgamer/Machine-Learning-With-Python
对数据简化的原因
1:使得数据更易使用
2:降低很多算法的计算开销
3:去除噪声
4:使得结果易懂
降维方法
1:主成分分析法( PrincipalComponentAnalysis, P C A )
在 PCA中,数据从原来的坐标系转换到了新的坐标系,新坐标系的选择是由数据本身决定的。第一个新坐标轴选择的是原始数据中方差最大的方向,第二个新坐标轴的选择和第一个坐标轴正交且具有最大方差的方向。该过程一直重复,重复次数为原始数据中特征的数目。我们会发现,大部分方差都包含在最前面的几个新坐标轴中。因此,我们可以忽略余下的坐标轴,即对数据进行了降维处理
2:因子分析(Factor Analysis)
在因子分析中,我们假设在观察数据的生成 中 有一 些观察 不 到的隐 变量 ( latentvariable )。假设观察数据是这些隐变量和某些噪声的线性组合 。那么隐变量的数据可能比观察数据的数目少,也就是说通过找到隐变量就可以实现数据的降维。
3:独立成分分析(Independent Component Analysis, ICA)
ICA假设数据是从 N 个数据源生成的,这一点和因子分析有些类似。 假设数据为多个数据源的混合观察结果,这些数据源之间在统计上是相互独立的,而在 ? 0 人中只假设数据是不相关的。同因子分析一样,如果数据源的数目少于观察数据的数目,则可以实现降维过程。
PCA降维技术(应用最广泛)
覆盖整个数据集的三条直线,其中直线 8 最长,并给出了数据集中差异化最大的方向
在PCA中我们对数据进行了旋转,该旋转的过程取决与数据本身,如上图,在A,B,C三条直线中。B直线覆盖数据的范围最广,那么把第一条坐标轴旋转到B直线的位置,此时覆盖数据的方差最大,数据的最大放方差给出了数据的最重要的信息
选定第一条坐标轴之后,假如该坐标轴与第一条坐标轴垂直, 它就是覆盖数据次大差异性的坐标轴。这里更严谨的说法就是正交(orthogonal)当然 ,在二维平面下,垂直和正交是一回事,直线 C 就是第二条坐标轴。利用PCA我们将数据坐标轴旋转至数据角度上的那些最重要的方向。
我们已经实现了坐标轴的旋转,接下来开始讨论降维,坐标轴的旋转并没有减少数据的维度。
二维空间的 3 个类别。当在该数据集上应用PCA时,就可以去掉一维,从而使得该分类问题变得更容易处理
如上图,其中包含着 3 个不同的类别。要区分这 3 个 类 别 ,可以使用决策树。我们还记得决策树每次都是基于一个特征来做决策的。我 们会发现,在 x轴上可以找到一些值,这些值能够很好地将这 3 个类别分开。这 样 ,我们就可能得到一些规则,比 如 当 0 < 4 ) 时 ,数据属于类别 0 。如果使用 SVM这样稍微复杂一点的分类器,我们就会得到更好的分类面和分类规则,比如当(w0 * x + w1 * y + b) > 0 时 ,数据也属于类别 0 。 SVM可能比决策树得到更好的分类间隔,但是分类超平面却很难解释。
通过PCA进行降维处理,我们就可以同时获得 SVM和决策树的优点: 一 方 面 ,得到了和决策树一样简单的分类器,同时分类间隔和 SVM一样好,如上图,其中的数据来自于上面的图并经 过PCA转换之后绘制而成的,如果仅使用原始数据,那么这里的间隔会比决策树的间隔更大。 另 外 ,由于只需要考虑一维信息,因此数据就可以通过比 S V M 简单得多的很容易采用的规则进行区分 。
在上图中,我们只需要一维信息即可,因为另一维信息只是对分类缺乏贡献的噪声数据,在二位平面下,这一点看上去微不足道,但是如果在高维空间下则意义重大。
下面我们用代码实现PCA:
<span style="font-size:18px;"><span style="font-size:14px;">#-*-coding:utf8-*- ''' Created on 2016-5-15 @author: thinkgamer ''' 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) #dataMat对应数据集,N个特征 def pca(dataMat, topNfeat=9999999): meanVals = mean(dataMat, axis = 0) #求平均值 meanRemoved = dataMat - meanVals #去平均值 covMat = cov(meanRemoved,rowvar=0) #计算协防差矩阵 eigVals, eigVects = linalg.eig(mat(covMat)) eigValInd = argsort(eigVals) #从小到大对N个值排序 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 shape(lowDMat) #show 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' )</span> <span style="font-size:14px;">plt.show() </span></span>
print的结果为:
(1000,1)
画图:
实例:利用PCA降维技术对半导体制造数据降维
<span style="font-size:18px;"><span style="font-size:14px;">#将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 #加载数据 dataMat = replaceNanWithMean() #去除均值 meanVals = mean(dataMat, axis=0) meanRemoved = dataMat - meanVals #计算协方差 covMat = cov(meanRemoved, rowvar=0) #特征值分析 eigVals, eigVects = linalg.eig(mat(covMat)) print eigVals </span> </span>
输出结果为:
数据说明:
我们会发现其中很多值都是 0吗?实 际 上 ,其中有超过 2 0 % 的特征值都是 0 。这就意味着这些特征都是其他特征的副本,也就是 说 ,它们可以通过其他特征来表示,而本身并没有提供额外的信息。
接 下 来 ,我们了解一下部分数值的数量级。最 前 面 15 个 值的 数量 级 大 于 105 ,实际上那以后 的 值 都 变 得 非 常 小 。这 就相 当 于 告 诉 我 们 只 有 部 分 重 要 特 征 ,重要特征的数目也很快就会下 降 。
最 后 ,我们可能会注意到有一些小的负值,它们主要源自数值误差应该四舍五入成 0 。
表 13-1 给出了这些主成分所对应的方差百分比和累积方差百分比。浏 览 “ 累积方差百分比( % )” 这一列就会注意到 , 前六个主成分就覆盖了数据 96.8% 的方 差 , 而前 20 个主成分覆盖了 99.3%的方差。这就表明了,如果保留前 6 个而去除后 584 个 主 成 分 ,我们就可以实现大概 100 : 1 的压缩比。另 外 ,由于舍弃了噪声的主成分,将后面的主成分去除便使得数据更加干净。
于 是 ,我们可以知道在数据集的前面多个主成分中所包含的信息量。我们可以尝试不同的截断值来检验它们的性能。有些人使用能包含90%信息量的主成分数量, 而其他人使用前20个主成分。 我们无法精确知道所需要的主成分数目, 必须通过在实验中取不同的值来确定。有效的主成分数目则取决于数据集和具体应用。
上述分析能够得到所用到的主成分数目, 然后我们可以将该数目输人到PCA算法中, 最后得到约简后数据就可以在分类器中使用了。