技术交流QQ群:1027579432,欢迎你的加入!

一、进行数据降维的原因

  • 1.使得数据更加容易使用
  • 2.降低很多算法的计算开销
  • 3.去除数据中的噪声(例如使用自编码器AE可以给图片进行降噪处理)
  • 4.便于可视化

二、常见的降维技术

  • 在已标注和未标注的数据上都有降维技术。下面主要关注未标注数据上的降维技术,此技术也可以使用在已标注的数据上。
  • 1.主成分分析PCA:在PCA中,数据从原来的坐标系中转换到新的坐标系中,新的坐标系的选择是由数据本身决定的。第一个新的坐标轴选择的是原始数据中方差最大的方向;第二个新坐标轴的选择是与第一个坐标轴正交且具有最大方差的方向。此过程一直重复,重复次数为原始数据中特征的数量。
  • 2.因子分析FA:在因子分析中,假设在观察数据的生成中有一些观察不到的隐变量。假设观察数据是这些隐变量和某些噪声的线性组合。那个隐变量的数据可能比观察数据的数目少,也就是说通过找到隐变量,就可以实现数据的降维。
    -3.独立成分分析ICA:ICA假设数据是从N个数据源生成的。假设数据为多个数据源的混合观察结果,这些数据源之间在统计上是相互独立的,而PCA中只假设数据是不相关的,如果数据源的数量小于观察数据的数量,则可以实现降维的过程。

三、PCA的降维过程

  • 1.原始的数据集可视化如图所示:


    原始数据集可视化.png
  • 2.如果要求画出一条直线,这条直线能尽可能覆盖上图中的点,,那么最长的线可能是哪条?显然是下图的情况。在PCA中,我们对数据的坐标进行了旋转,该旋转的过程取决于数据的本身。第一条坐标轴旋转到覆盖数据的最大方差位置,即下图中的直线B。数据的最大方差给出了数据的最重要的信息。在选择了覆盖数据最大差异性的坐标轴后,开始旋转第二条坐标轴。假设该坐标轴与第一条坐标轴正交,它就是覆盖数据次大差异性的坐标轴。


    直线B.png

    三条直线可视化.jpg
  • 3.具体的过程:第一个主成分是从数据差异性最大(即方差最大)的方向提取出来;第二个主成分的方向则来自于数据差异性次大的方向,并且该方向与第一个主成分方向正交。通过数据集的协方差矩阵及特征值的分析,就可以得到这些主成分的值。一旦得到了协方差矩阵的特征向量,就可以保留最大的N个值。这些特征向量也给出了N个最重要特征的真实结构,可以通过将数据乘上这N个特征向量而将它转换到新的空间中。


    降维效果.png

四、PCA的代码实现

```
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    # @Date    : 2019-05-19 15:30:22
    # @Author  : cdl (1217096231@qq.com)
    # @Link    : https://github.com/cdlwhm1217096231/python3_spider
    # @Version : $Id$

    from numpy import *


    # 加载数据集
    def loadDataSet(fileName, delim='\t'):
        fr = open(fileName)
        stringArr = [line.strip().split(delim) for line in fr.readlines()]
        datArr = [list(map(float, line)) for line in stringArr]
        return mat(datArr)


    # PCA算法
    def pca(dataMat, topNfeature=9999999):
        meanVals = mean(dataMat, axis=0)  # 计算原始数据集的均值
        meanRemoved = dataMat - meanVals  # 减去原始数据集的均值
        covMat = cov(meanRemoved, rowvar=0)  # 计算协方差矩阵
        eigVals, eigVects = linalg.eig(mat(covMat))  # 求特征值和特征向量
        eigValInd = argsort(eigVals)  # 对特征值进行从小到大排序
        # 根据特征值排序结果的逆序,可以得到topNfeature个最大特征向量
        eigValInd = eigValInd[:-(topNfeature + 1):-1]
        redEigVects = eigVects[:, eigValInd]  # 上面的特征向量将构成后面对数据进行转换的矩阵
        lowDDataMat = meanRemoved * redEigVects  # 降维后的数据集
        reconMat = (lowDDataMat * redEigVects.T) + meanVals
        return lowDDataMat, reconMat


    def replaceNanWithMean():
        dataMat = loadDataSet(
            "E:\\Code\\local_code\\机器学习实战\\DataSet\\***.data", ' ')
        numfeatures = shape(dataMat)[1]
        for i in range(numfeatures):
            meanVal = mean(dataMat[nonzero(~isnan(dataMat[:, i].A))[0], i])
            dataMat[nonzero(isnan(dataMat[:, i].A))[0], i] = meanVal
        return dataMat

```