PCA實現教程

摘要: 手把手教你PCA降維技術!(有案例)數組

數據是機器學習模型的生命燃料。對於特定的問題,總有不少機器學習技術可供選擇,但若是沒有不少好的數據,問題將不能很好的解決。數據一般是大部分機器學習應用程序中性能提高背後的驅動因素。機器學習

有時,數據可能很複雜。在那麼多的數據中,知道哪些數據是真正重要的,具備必定的挑戰性。降維是一種能夠幫助咱們更好地瞭解數據的技術,它減小了數據集的特徵數量,所以只剩下最重要的部分特徵。性能

主成分分析(PCA)是一種用於降維的簡單而強大的技術。經過它,咱們能夠直接減小特徵變量的數量,從而減小重要特徵並節省計算量。從高層次來看,PCA有三個主要步驟:學習

(1)計算數據的協方差矩陣;this

(2)計算該協方差矩陣的特徵值和向量;code

(3)經過特徵值和向量來只選擇最重要的特徵向量,而後將數據轉換爲這些向量以下降維度。component

(1)計算協方差矩陣orm

PCA產生一個特徵子空間,使特徵向量的方差最大化。所以,爲了正確計算這些特徵向量的方差,必須對它們進行適當的平衡。爲實現此目的,咱們首先將數據歸一化爲零均值和單位方差,以便在計算中對每一個特徵進行加權。假設咱們的數據集爲X:blog

from sklearn.preprocessing import StandardScaler
   X = StandardScaler().fit_transform(X)

兩個變量的協方差衡量它們是如何「相關」的。若是兩個變量的協方差是正的,那麼當一個變量增長時,另外一個變量增長;在協方差爲負的狀況下,特徵變量的值將在相反方向上改變。協方差矩陣只是一個數組,其中每一個值基於矩陣中的x-y位置指定兩個特徵變量之間的協方差。公式是:排序

其中帶有上劃線的x是X的每一個特徵的均值向量,將轉置矩陣乘以原始矩陣時,咱們最終將每一個數據點的每一個特徵相乘!在numpy代碼中實現以下:

import numpy as np
# Compute the mean of the data
mean_vec = np.mean(X, axis=0)
# Compute the covariance matrix
cov_mat = (X - mean_vec).T.dot((X - mean_vec)) / (X.shape[0]-1)
# OR we can do this with one line of numpy:
cov_mat = np.cov(X.T)

(2)計算特徵值和向量

咱們的協方差矩陣的特徵向量(主成分)表示新特徵空間的向量方向,而特徵值表示這些向量的大小。因爲咱們正在研究協方差矩陣,所以特徵值量化了每一個向量的貢獻方差。

若是特徵向量具備相應的高幅度特徵值,則意味着咱們的數據在特徵空間中沿着該向量具備高方差。所以,該向量包含有關數據的大量信息,由於沿着該向量的任何移動都會致使大的「方差」。另外一方面,具備小特徵值的向量具備低方差,所以當沿着該向量移動時,咱們的數據不會有很大變化。因爲在沿着特定特徵向量移動時沒有任何變化,即改變該特徵向量的值不會對咱們的數據產生很大影響,那麼咱們能夠說這個特徵不是很重要,能夠忽略它。

這是PCA中特徵值和向量的所有本質,找到表示數據最重要的向量,並丟棄其他的向量。計算協方差矩陣的特徵向量和值是一個簡單的單線性的numpy。以後,咱們將根據它們的特徵值按降序對特徵向量進行排序。

# Compute the eigen values and vectors using numpy
eig_vals, eig_vecs = np.linalg.eig(cov_mat)
# Make a list of (eigenvalue, eigenvector) tuples
eig_pairs = [(np.abs(eig_vals[i]), eig_vecs[:,i]) for i in range(len(eig_vals))]
# Sort the (eigenvalue, eigenvector) tuples from high to low
eig_pairs.sort(key=lambda x: x[0], reverse=True)

(3)映射到新的向量上

此時,咱們有一個特徵向量列表,這些特徵向量基於它們的特徵值按照數據集的「重要性」進行排序。如今要作的是選擇最重要的特徵向量並丟棄其他的,能夠經過查看向量的可解釋方差百分比來巧妙地作到這一點。該百分比量化了總100%中每一個主成分可歸因於多少信息(方差)。

咱們舉一個例子來講明。假設一個最初有10個特徵向量的數據集。在計算協方差矩陣以後,特徵值是:

[12,10,8,7,5,1,0.1,0.03,0.005,0.0009]

該數組的總和= 43.1359,但前6個值表明:43 / 43.1359 =總數的99.68%!這意味着咱們的前6個特徵向量有效地保持了99.68%有關數據集的信息。所以,能夠丟棄最後4個特徵向量,由於它們只包含0.32%的信息,這就節省了40%的計算量。

所以,咱們能夠簡單地定義一個閾值,這個閾值能夠決定是保留仍是丟棄每一個特徵向量。在下面的代碼中,設定閾值97%來決定每一個特徵向量是否丟棄。

# Only keep a certain number of eigen vectors based on 
# the "explained variance percentage" which tells us how 
# much information (variance) can be attributed to each 
# of the principal components

exp_var_percentage = 0.97 # Threshold of 97% explained variance
tot = sum(eig_vals)
var_exp = [(i / tot)*100 for i in sorted(eig_vals, reverse=True)]
cum_var_exp = np.cumsum(var_exp)
num_vec_to_keep = 0
for index, percentage in enumerate(cum_var_exp):
  if percentage > exp_var_percentage:
    num_vec_to_keep = index + 1
    break

最後一步是將咱們的數據實際投射到決定保留的向量上。咱們經過構建投影矩陣來作到這一點:咱們將經過相乘將數據投影到新的向量上。爲了建立它,簡單地與決定保留的全部特徵向量進行鏈接,最後一步是簡單地在原始數據和投影矩陣之間取點積。

維度下降了!

# Compute the projection matrix based on the top eigen vectors
num_features = X.shape[1]
proj_mat = eig_pairs[0][1].reshape(num_features,1)
for eig_vec_idx in range(1, num_vec_to_keep):
  proj_mat = np.hstack((proj_mat, eig_pairs[eig_vec_idx][1].reshape(num_features,1)))
# Project the data 
pca_data = X.dot(proj_mat)

原文連接 

相關文章
相關標籤/搜索