机器学习笔记(二)——广泛应用于数据降维的PCA算法实战

   最近在学习的过程当中,经常遇到PCA降维,于是就学习了PCA降维的原理,并用网上下载的iris.txt数据集进行PCA降维的实践。为了方便以后翻阅,特此记录下来。本文首先将介绍PCA降维的原理,然后进入实战,编写程序对iris.数据集进行降维。

一、为什么要进行数据降维?

    在数据处理中,经常会遇到特征维度比样本数量多得多的情况,如果直接放机器学习算法中,效果不一定好。一是因为冗余的特征会带来一些噪音,影响计算的结果;二是因为无关的特征会加大计算量,耗费时间和资源。因此,降维往往作为预处理步骤,在数据应用到其他算法之前清洗数据。降维技术使得数据变得更易使用,并且它们往往能够去除数据中的噪声,使得其他机器学习任务更加精确。准确来说,降维致力于解决三大问题:

(1)降维可以缓解维数灾难问题。  

     现实应用中属性维数经常成千上万,由于许多学习方法都涉及距离计算,而高维空间会给距离计算带来很大的麻烦,例如当维数很高时甚至连计算内积都不再容易。通常,在高维情形下出现的数据样本稀疏、距离计算困难等问题,是所有机器学习方法共同面临的严重障碍,被称为“维数灾难”。缓解维数灾难的一个重要途径就是降维,亦称为“维数约简”,即通过某种数学变换将原始高维属性空间转变为一个低维“子空间”,在这个子空间中样本密度大幅提高,距离计算也变得更为容易。

(2)降维可以在压缩数据的同时让信息损失最小化。

    我们希望在尽可能减少信息损失的情况下降低数据的维度通常来说,我们期望得到的结果,是把原始数据的特征空间(nd维样本)投影到一个小一点的子空间里nk维样本,其中k<<d去,并尽可能表达的很好(就是说损失信息最少)。

(3)由于人类思维的限制,理解几百个维度的数据结构很困难,若将数据维数降至二维或三维,则可以通过可视化技术来直观地展示数据分布。

二、PCA降维的概念

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

三、PCA算法的步骤

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

去除平均值

计算协方差矩阵

计算协方差矩阵的特征值和特征向量

将特征值从大到小排序

保留最前面的N特征值所对应的特征向量

将原始数据转换到上述N特征向量构建的新空间中

具体的算法流程如下所示:


四、PCA代码实现

    本文基于iris数据集来进行PCA降维演示,Iris数据集是常用的分类实验数据集,由Fisher, 1936收集整理。Iris也称鸢尾花卉数据集,是一类多重变量分析的数据集。数据集包含150个数据集,分为3类,每类50个数据。其中每行数据包含每个样本的四个特征和样本的类别信息,可通过花萼长度,花萼宽度,花瓣长度,花瓣宽度4个属性预测鸢尾花卉属于(SetosaVersicolourVirginica)三个种类中的哪一类。所以Iris数据集是一个1505列的二维表。 

我们把样本数据存储在一个irisdata.txt的文件当中,局部样本数据如下图所示:

   为了方便,本文的例子是想把二维的空间降成一维的空间,因此截取了花瓣长度和花瓣宽度这两列数据作为样本集(150*2),部分样本集如下所示:


 为了更加直观的表示样本数据集,我们利用matplotlib这个第三方绘图库,采用散点图的形式将数据展示出来,散点图分布如下所示:

 

    接下编写PCA算法的代码,我们在irisdata.txt文件所在的目录下,新建了一个pca.py的文件,并在里面写入以下代码,如下所示:

import numpy
import matplotlib
import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif']=['simHei']
#这句话用来设置 matplotlib.pyplot模块绘制的图中正常显示中文字体


###################################
####PCA降维技术应用于iris数据集#####
####     time:2018.3.8       ####
#################################


def loaddataset(filename):
    """
    这是一个加载iris数据集的函数
    输入: filename是iris数据集的相对存储路径
    输出: dataset是数据集合
    """
    with open(filename) as fr:
        rowArr = [line.strip().split(',')[2:]   for line in fr.readlines()[1:]]
        dataset =[]
        for i in range(len(rowArr )):
            dataArr = []
            for j in range(2):
                dataArr.append( float(rowArr[i][j] ))
            dataset.append(dataArr )
        return numpy.array(dataset)



def pcaProcessingData( dataset, figureNumber ):
    """
    此函数的作用是对输入的数据进行PCA降维处理
    输入: dataset是输入的待处理的数据集
           figureNumber用以指定降维后的数据维度  
    输出: 
    """
    meanValue = numpy.mean( dataset,axis=0 )  #mean()函数对数组进行求均值运算,其中axis=0表示对各列求均值,返回1* n数组
    centered_dataset = dataset -  meanValue   #将样本数据进行中心化,即对每个维度减去这个维度的数据均值
    covariance_matrix = numpy.cov( centered_dataset,rowvar=0 )
            #cov()函数实现的是求出两个变量的协方差矩阵,得到一个2*2的数组,其中rowvar=0表示将每一列看作一个变量
    eigenvalue,eigenvector = numpy.linalg.eig( covariance_matrix )
            #eig()函数求解矩阵的特征值和特征向量,该函数将返回一个元组,其中第一个元素为特征值,
            # 第二个元素为特征向量(且每一列为一个特征向量)
    eigenvalue_sorted_index = numpy.argsort( -eigenvalue )
            #将特征值数组元素从大到小进行排序,并返回排序后元素的索引
    projection_matrix = eigenvector[:,eigenvalue_sorted_index[:figureNumber]]
            #取排序后的前figureNumber个特征值所对应的特征向量组成投影矩阵
    newDataSet = numpy.dot(centered_dataset,projection_matrix)    #得到原样本向量在新坐标系中的坐标向量,即降维后的数据集
    reconstructedData = numpy.dot ( newDataSet, projection_matrix.T ) + meanValue  #将降维后的数据进行重构
    return  newDataSet, reconstructedData


def data_visualization( dataset, recondataset ):
    """
    这是一个将数据集进行可视化的函数,以散点图的形式将数据展示出来
    输入: dataset是输入的数据集
    输出: 散点图
    """
    x_coordinates_Arr1 =  dataset[:,0]
    y_coordinates_Arr1 = dataset[:,1]
    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.scatter(x_coordinates_Arr1, y_coordinates_Arr1, c='red',alpha=1,marker='^',label = u'降维前')
    x_coordinates_Arr2 = recondataset[:, 0]
    y_coordinates_Arr2 = recondataset[:, 1]
    ax.scatter(x_coordinates_Arr2, y_coordinates_Arr2, c='green', alpha=1,marker='+',label =u'降维后')
    plt.grid(True)
    plt.legend(loc=4)
    plt.show()


if __name__ == '__main__':
    dataset = loaddataset('irisdata.txt')
    print(dataset)
    newDataSet, reconstructedData = pcaProcessingData(dataset, 1)
    print('降维后的数据集:')
    print(newDataSet)
    data_visualization( dataset,reconstructedData )

运行上述代码,得到结果如下所示:

降维后的数据集(局部):


   得到原始数据集(红色三角形点表示)及第一主成分(绿色叉号表示),如下:

 

参考资料:

[1]  周志华  《机器学习》

[2]  Peter Harrington 《机器学习实战》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值