機器學習之主成分分析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()
從三維降到二維效果顯示:

三維特徵
二維特徵

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