[机器学习] PCA主成分析

PCA主成份分析

一.PCA原理

主成分分析Principal Component Analysis,主要用途:数据的降维。可以理解为提取数据中更有价值的信息

  • 核心的思想:寻找一个新的坐标基,将原有的数据投影到新的坐标基中

1.1基本概念

  • 样本均值
    ( x^-=frac{1}{n}sum^N_{i=1}x_i )

  • 样本方差
    ( s^2=frac{1}{n-1}sum^n_{i=1}(x_i-x^-)^2 )

  • 协方差
    ( Cov(X,Y)=frac{1}{n-1}sum^n_{i=1}(x_i-x^-)(y_i-y^-) )

  • 协方差矩阵

    假设有m个数据集,其中只有2个变量(特征),可以将数据表示为

[ X= left[ egin{matrix} a_1 & a_2 & cdots & a_m \ b_1 & b_2 & cdots & b_m \ end{matrix} ight] ]

可以得到

[frac{1}{m}XX^T= left[ egin{matrix} frac{1}{m}sum^m_{i=1}a_i^2 & frac{1}{m}sum^m_{i=1}a_ib_i \ frac{1}{m}sum^m_{i=1}a_ib_i & frac{1}{m}sum^m_{i=1}b_i^2 \ end{matrix} ight] = left[ egin{matrix} Cov(a,a) & Cov(a,b) \ Cov(b,a) & Cov(b,b) \ end{matrix} ight] ]

​ 一般表示形式( 有d个特征值,协方差矩阵就是d*d

[C=frac{1}{m}XX^T ]

​ 另外,在numpy.cov中采用的是

[C=frac{1}{m-1}XX^T ]

​ 因为最终我们需要计算的是协方差矩阵的特征向量,所以在上面的式子中m或者m-1不影响结果。

注意:上面的数据集中的X在进行协方差计算前需要进行去中心化处理,数据的均值为0

1.2计算步骤

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

二.实例代码

2.1 实例1:简单数据

import numpy as np

data = np.mat([[-1,-1,0,2,0], [-2,0,0,1,1]]).T

# 计算协方差
## 方法1
cov_mat = np.cov(data, rowvar=0)
## 方法2
#mean_vec = np.mean(data, axis=0)
#print(mean_vec)
#cov_mat = (data - mean_vec).T.dot((data - mean_vec)) / (data.shape[0]-1)
#print('协方差矩阵 
%s' %cov_mat)

# 计算特征值和特征向量
eig_als, eig_vecs = np.linalg.eig(cov_mat)
print('特征向量 
%s' %eig_vecs)
print('
特征值 
%s' %eig_vals)

# 投影到新的空间
new_vects = eig_vecs[:, 0]
new_data = data * new_vects
data:
matrix([[-1, -2],
        [-1,  0],
        [ 0,  0],
        [ 2,  1],
        [ 0,  1]])

cov_mat:
array([[1.5, 1. ],
       [1. , 1.5]])
       
特征向量 
[[ 0.70710678 -0.70710678]
 [ 0.70710678  0.70710678]]
特征值 
[2.5 0.5]

PCA降维后:
matrix([[-2.12132034],
        [-0.70710678],
        [ 0.        ],
        [ 2.12132034],
        [ 0.70710678]])

2.2 实例2:莺尾花数据集

import numpy as np
import pandas as pd
from matplotlib import pyplot as plt

def plotData(dataX, dataY, stringX, stringY):
	plt.figure(figsize=(6, 4))
	for lab, col in zip(('Iris-setosa', 'Iris-versicolor', 'Iris-virginica'),
	                        ('blue', 'red', 'green')):
	     plt.scatter(dataX[dataY==lab, 0].tolist(),
	                dataX[dataY==lab, 1].tolist(),
	                label=lab, c=col)
	plt.xlabel(stringX)
	plt.ylabel(stringY)
	plt.legend(loc='best')
	plt.tight_layout()
	plt.show()

# dataMat: 输入数据,每一行是一个样本
# topNfeat: 最终的维数
def pca(dataMat, topNfeat=9999999):
    # 计算平均值,去中心化
    meanVals = np.mean(dataMat, axis=0)
    ## 方法1
    meanRemoved = dataMat - meanVals 
    ## 方法2
    # from sklearn.preprocessing import StandardScaler
    # meanRemoved = StandardScaler().fit_transform(dataMat)

    # 计算协方差
    covMat = np.cov(meanRemoved, rowvar=0)
    # 计算特征值和特征向量
    eigVals,eigVects = np.linalg.eig(np.mat(covMat))

    # 特征值排序
    eigValInd = np.argsort(eigVals)            
    eigValInd = eigValInd[:-(topNfeat+1):-1]  
    redEigVects = eigVects[:,eigValInd]  

    # 映射出新的数据
    lowDDataMat = meanRemoved * redEigVects  
    reconMat = (lowDDataMat * redEigVects.T) + meanVals
    return lowDDataMat, reconMat


# 读取数据集
df = pd.read_csv('iris.data')

X = df.iloc[:,0:4].values
y = df.iloc[:,4].values

print(X.shape)

newX, recoMat = pca(X, 2)

plotData(X, y, 'sepal_len', 'sepal_wid')
plotData(newX, y, 'Principal Component 1', 'Principal Component 2')
  • 原始数据

  • PCA处理后

原文地址:https://www.cnblogs.com/zou107/p/12757619.html