机器学习之主成分分析PCA(Python实现)

理解PCA:what? why? how?

当我们拿到一个数据集的时候,往往数据集中每一个样本的描述是多维的,多维的特征空间不便于我们或者计算机对其进行分析和处理,所以我们希望用低维度的特征向量来表述样本的特征,此时我们需要对其进行降维

假设矩阵 X 在多维空间中有 n 个样本点:
样本投影

我们希望它们投影到一个方向 u 上,使得投影范围最大,这个方向称为主方向(主成分PCA),可以用方差度量一个随机变量离散程度,即可用方差度量样本点在一个方向上投影之后得离散程度

样本 X(150x4) 投影到 u(4x1) 方向上,即 Xu,得到一个一维的向量 Z(150x1)
Z向量
Z 求方差,而使得方差最大的那个 u 就是主方向,所以我们需要对z = Xu求方差,并且求方差的极值

一、求方差:

方差
对 X 进行中心化:
中心化
中心化后的方差为:
方差
线性代数表示方差 [ z12 + z22 + z32 + … + zn2 ] = zTz,而 z = Xu

二、拉格朗日乘子法求 zTz 极值(方差最大值)

u 是单位向量,约束条件为:uTu = 1, 即 uTu - 1 = 0
拉格朗日乘子法
由于 (XTAX)’ = 2•AX , 则L(u, λ) 对 u 求偏导得:
对 λ 求偏导
XT 是4x150矩阵,X 是150x4的矩阵,点乘得到4x4的协方差矩阵 XTX,对 XTX 求得特征值 λ 和特征向量 u
特征值和特征向量
而最大特征值 λ 所对应的 u 就是主方向

PCA就是样本投影之后方差最大的方向即主方向
次方向就是垂直于主方向的剩下的最大的 λ 所对应的 u
(特征向量 u 中的所有方向互相垂直)

前k个主方向的选取:

有时候降到一维(只选取一个主方向)并不是最优,所以我们可以选取 k 个主方向
对λ和u排序,计算 (λ1+λ2+λ3+λ4)x85% 得到一个值 w
如果发现前k个λ的和大于 w 就选取对应k个u作为前k个主向量
(85%只是一个可接受的能量比例)
反过来选取k个主方向,算出掌握多大能量和损失多大能量

python实现代码
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

# 对矩阵进行中心化
def centralization(mat):
    for j in range(mat.shape[1]):
        m = np.mean(mat[:, j:j+1])
        for i in range(mat.shape[0]):
            mat[i][j] -= m
    return mat

# 对特征值和对应的特征向量进行排序(选择排序算法)
def v_sort(egv, ftv):
    for i in range(egv.__len__()):
        for j in range(i+1, egv.__len__()):
            if egv[j]>egv[i]:
                tmp1 = egv[i]
                egv[i] = egv[j]
                egv[j] = tmp1
                tmp2 = ftv[i]
                ftv[i] = ftv[j]
                ftv[j] = tmp2
    return egv, ftv

# 降维
def PCA(mat, k, ctl=0):
    if ctl==1:
        # 对样本数据进行中心化
        mat = centralization(mat)
    # 求协方差矩阵
    cov_mat = np.dot(mat.T, mat)
    # 求解协方差矩阵的特征值和特征向量
    egv, ftv = np.linalg.eig(cov_mat)
    # 对特征值排序,同时对相应特征向量改变
    egv, ftv = v_sort(egv, ftv)
    # 取前 k 个主方向
    headv = ftv[:k]
    # 把多维特征投影到主方向上
    x = np.zeros((k, mat.shape[0]))
    for i in range(k):
        x[i] = np.dot(mat, headv[i])
    return x

if __name__=="__main__":
    # 从 Advertising.csv 读取数据
    data = pd.read_csv("../../Dataset/Advertising.csv").drop('Unnamed: 0', axis=1)
    # 将DataFrame型数据转化成矩阵
    mat = data.as_matrix(columns=None)[:, :-1]
    # PCA降维
    x = PCA(mat, 2, ctl=1)

    # 图形显示
    x1 = data['TV']
    x2 = data['radio']
    x3 = data['newspaper']
    y = data['sales']

    fig = plt.figure('三维特征')
    ax = Axes3D(fig)
    ax.scatter(x1, x2, x3)

    fig = plt.figure('二维特征')
    plt.plot(x[0], x[1], 'yo')
    plt.title('PCA')
    plt.show()
从三维降到二维效果显示:

三维特征
二维特征

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章