实验目的

了解基本数据降维的基本原理,并掌握Python语言中实现数据降维算法的函数方法

实验原理

主成分分析(PCA)是一种无监督的学习方式,是一种常用的线性降维方法。如果遇到多因素分析,想要很多个自变量与因变量进行线性回归分析,一般都必须进行降维处理,而主成分分析是一种很好的解决方案。

实验步骤

一、PCA简介

PCA是将数据的n维特征映射到k维上(k<n),k维是全新的正交特征。这里的k维是重新构造出来的k维特征,而不是简单的从n维特征中找出k维。

PCA求解的一般流程为:

(1)将原始数据进行标准化;

(2)计算标准化数据集的协方差矩阵;

(3)计算协方差矩阵的特征值和特征向量;

(4)保留最重要的k个特征(k<n),可以选择一个阈值,让前k个特征值之和减去后面n-k个特征值之和大于这 个阈值,找到这个k值,计算主成分变量值;

(5)找到这k个特征值对应的特征向量;

(6)将m乘n的数据集乘以k个n维的特征向量(n乘k),得到最终降维的数据集;

其实PCA的本质就是对角化协方差矩阵,解释一下为什么将特征值按照从大到小排序后再选择。首先解释一下特征值和特征向量表示什么。在线性代数中,对一个n*n的对称矩阵进行分解,我们可以求出它的特征值和特征向量,就会产生n个n维的正交基,每个正交基会对应一个特征值。然后把矩阵投影到这n个正交基上,此时特征值的模就表示矩阵在该基的投影长度。特征值越大,表示矩阵在对应的特征向量上的方差越大,样本越离散,越容易区分,信息量也越多。因此,特征值最大的对应的特征向量方向上所包含的信息量就越多。如果某几个特征值很小,那么说明在该方向上的信息量非常少,我们就可以删除小特征值所对应方向的数据,只保留大特征值方向对应的数据,这样做以后数据量越小,但是有用的信息量都保留下来了。

二、PCA的python实现

注意:python2中print语句不加括号,python3中print语句打印内容要加括号!

点击下载数据:https://github.com/csuldw/MachineLearning/blob/master/PCA/data.txt

矩阵运算需要用到numpy包以及numpy包中的genfromtxt函数,这个函数是可以读取txt文件;还需要用到matplotlib进行画图.

首先,计算均值,要求输入数据为numpy的矩阵格式,行表示样本数,列表示特征 。计算方差,传入的是一个numpy的矩阵格式,行表示样本数,列表示特征 。标准化,传入的是一个numpy的矩阵格式,行表示样本数,列表示特征。

  1. # -*- coding: utf-8 -*-
      1. import numpy as np
  2. import pandas as pd
  3. import matplotlib.pyplot as plt
    1. #计算均值,要求输入数据为numpy的矩阵格式,行表示样本数,列表示特征
  4. def meanX(dataX):
  5. return np.mean(dataX,axis=0)#axis=0表示按照列来求均值,如果输入list,则axis=1
      1. #计算方差,传入的是一个numpy的矩阵格式,行表示样本数,列表示特征
  6. def variance(X):
  7. m, n = np.shape(X)
  8. mu = meanX(X)
  9. muAll = np.tile(mu, (m, 1))
  10. X1 = X - muAll
  11. variance = 1./m * np.diag(X1.T * X1)
  12. return variance

  13. #标准化,传入的是一个numpy的矩阵格式,行表示样本数,列表示特征

  14. def normalize(X):

  15. m, n = np.shape(X)

  16. mu = meanX(X)
  17. muAll = np.tile(mu, (m, 1))
  18. X1 = X - muAll
  19. X2 = np.tile(np.diag(X.T * X), (m, 1))
  20. XNorm = X1/X2
  21. return XNorm

  22. """

  23. 参数:

    • XMat:传入的是一个numpy的矩阵格式,行表示样本数,列表示特征
    • k:表示取前k个特征值对应的特征向量
  24. 返回值:
    • finalData:参数一指的是返回的低维矩阵,对应于输入参数二
    • reconData:参数二对应的是移动坐标轴后的矩阵
  25. """
  26. def pca(XMat, k):
  27. average = meanX(XMat)
  28. m, n = np.shape(XMat)
  29. data_adjust = []
  30. avgs = np.tile(average, (m, 1))
  31. data_adjust = XMat - avgs
  32. covX = np.cov(data_adjust.T) #计算协方差矩阵
  33. featValue, featVec= np.linalg.eig(covX) #求解协方差矩阵的特征值和特征向量
  34. index = np.argsort(-featValue) #按照featValue进行从大到小排序
  35. finalData = []
  36. if k > n:
  37. print ("k must lower than feature number")
  38. return
  39. else:
  40. #注意特征向量时列向量,而numpy的二维矩阵(数组)a[m][n]中,a[1]表示第1行值
  41. selectVec = np.matrix(featVec.T[index[:k]]) #所以这里需要进行转置
  42. finalData = data_adjust * selectVec.T
  43. reconData = (finalData * selectVec) + average
  44. return finalData, reconData
    1. def loaddata(datafile):
  45. return np.array(pd.read_csv(datafile,sep="\t",header=-1)).astype(np.float)
      1. def plotBestFit(data1, data2):
  46. dataArr1 = np.array(data1)
  47. dataArr2 = np.array(data2)
  48. m = np.shape(dataArr1)[0]
  49. axis_x1 = []
  50. axis_y1 = []
  51. axis_x2 = []
  52. axis_y2 = []
  53. for i in range(m):
  54. axis_x1.append(dataArr1[i,0])
  55. axis_y1.append(dataArr1[i,1])
  56. axis_x2.append(dataArr2[i,0])
  57. axis_y2.append(dataArr2[i,1])
  58. fig = plt.figure()
  59. ax = fig.add_subplot(111)
  60. ax.scatter(axis_x1, axis_y1, s=50, c='red', marker='s')
  61. ax.scatter(axis_x2, axis_y2, s=50, c='blue')
  62. plt.xlabel('x1'); plt.ylabel('x2');
  63. plt.savefig("outfile.png")
  64. plt.show()

接下来进行测试:

  1. #测试
  2. def test():
  3. X = [[2.5, 0.5, 2.2, 1.9, 3.1, 2.3, 2, 1, 1.5, 1.1],
  4. [2.4, 0.7, 2.9, 2.2, 3.0, 2.7, 1.6, 1.1, 1.6, 0.9]]
  5. XMat = np.matrix(X).T
  6. k = 2
  7. return pca(XMat, k)
    1. #根据数据集data.txt
  8. def main():
  9. datafile = "data.txt"
  10. XMat = loaddata(datafile)
  11. k = 2
  12. return pca(XMat, k)
  13. if __name__ == "__main__":
  14. finalData, reconMat = main()
  15. plotBestFit(finalData, reconMat)

得到结果:

results matching ""

    No results matching ""