PCA主成分分析算法,是一種線性降維,將高維座標系映射到低維座標系中。算法
如何選擇低維座標系呢?數組
經過協方差矩陣的特徵值和特徵向量,特徵向量表明座標系,特徵值表明映射到新座標的長度。spa
輸入:樣本集D={x1,x2,...,xm};code
低維空間維數korm
第一步:將樣本集中心化。每一列的特徵值減去當前列的均值
blog
第二步:求協方差矩陣的特徵值和特徵向量排序
協方差矩陣:矩陣×矩陣的轉置;索引
方法:np.dot(x, np.transpot(x))class
特徵值和特徵向量:協方差矩陣特徵分解。import
方法一:np.linalg.eig(),返回:特徵值,一維數組,沒有排序;特徵向量,二維數組,列表示特徵向量
方法二:np.linalg.svd(),返回:酉矩陣;奇異值,從大到小排序;酉矩陣
第三步:選取前k個特徵值,對應的特徵向量
新樣本集:對應的特徵向量×中心化數據
輸出:降維後樣本集。
方差貢獻率:特徵值與全部特徵值總和的比值
累計貢獻率:前k個特徵值和與全部特徵值總和的比值
通常根據累計貢獻率選取k值。
代碼以下:
1 import numpy as np 2 3 4 def feature_Normalize(x): 5 """ 6 歸一化數據 7 (每一個數據-當前列的均值)/當前列的標準差 8 :param x: 樣本集 9 :return: 歸一化後樣本集,均值,標準差 10 """ 11 m, n = x.shape 12 mean = np.zeros((1, n)) 13 std = np.zeros((1, n)) 14 # 計算各列均值 15 mean = np.mean(x, axis=0) 16 # 計算各列標準差 17 std = np.std(x, axis=0) 18 # 對每一個特徵值歸一化 19 for i in range(n): 20 x[:, i] = (x[:, i] - mean[i]) / std[i] 21 return x, mean, std 22 23 24 def cal_eigenvalue(nor_x): 25 """ 26 求樣本協方差矩陣的特徵值和特徵向量 27 :param nor_x: 歸一化後的樣本集 28 :return: 特徵值,特徵向量,排序索引號 29 """ 30 m, n = nor_x.shape 31 # 協方差矩陣 32 sigma = np.dot(np.transpose(nor_x), nor_x)/(m - 1) 33 # 求協方差矩陣的特徵值和特徵向量,eig_vec[:,i]是對應於eig_val[i]的特徵向量 34 eig_val, eig_vec = np.linalg.eig(sigma) 35 index = eig_val.argsort() 36 return eig_val, eig_vec, index 37 38 39 def pca(x, k): 40 """ 41 提取前k個主成分 42 :param x: 樣本集 43 :param k: 前k個特徵值 44 :return: 返回降維後樣本,累計貢獻度,主成分索引 45 """ 46 # 歸一化 47 nor_x, mean, std = feature_Normalize(x) 48 # 求特徵值和特徵向量 49 eig_val, eig_vec, index = cal_eigenvalue(nor_x) 50 eig_index = index[:-(k+1):-1] 51 # 累計貢獻度 52 sum_con = sum(eig_val[eig_index])/sum(eig_val) 53 # 前k個特徵值對應的特徵向量 54 k_eig_vec = eig_vec[:, eig_index] 55 lowDData = np.dot(nor_x, k_eig_vec) 56 return lowDData, sum_con, eig_index