降維
降維方法總結
特徵抽取
a. 線性降維
主成分分析:PCA
線性判別器:LDA
因子分析:FA
b. 流行學習,非線性降維
KPCA
KPA
c. 奇異值分解
SVD
特徵篩選
a. 缺失值比率
b. 低方差濾波
c. 高相關濾波
e. 隨機森林
f. 反向特徵消除
g. 前向特徵選擇
Feature Extraction
PCA : Principal Component Analysis
數學知識
方差
協方差
協方差矩陣
原理
PCA是將 \(n\) 維特徵空間映射到 \(k\) 維空間上,並且這 \(k\) 維是全新的正交特徵,並且保留的信息最大!
原理是:將n維樣本點變換爲k維後,使得原始數據在投影子空間的各個維度的方差最大化,並且不同維度正交.
矩陣相乘的意義
向量在\((0,1),(0,1)\)基下的座標是\((3,2)\),已知另外一組基($1/\sqrt{2} $,\(1/\sqrt(2)\))和($-1/\sqrt{2} $,\(1/\sqrt{2}\))那麼\((3,2)\)在新座標是
一般的
兩個矩陣相乘的意義將右邊的矩陣中的每一列列向量變換到左邊矩陣中每一行行向量爲基所表示的空間中去。
一個矩陣可以表示一種線性變換 ,矩陣可以對座標系進行旋轉
協方差矩陣
-
方向:基的方向才能儘量保留最多的原始信息呢?方差最大
-
方差
\[Var(a) = \frac{1}{m}\sum_{i=1}^m(a_i-u)^2 \] -
協方差:
多維隨機變量\(X = [X_1, X_2,..,X_n]^T\),
\[\begin{bmatrix}cov(X_1,X_1), cov(X_1,X_2),...,cov(X_1,X_n)\\ cov(X_2,X_1),cov(X_2,X_2),..,cov(X_2,X_n)\\ \dots \\ cov(X_n,X_1),cov(X_n,X_2),...,cov(X_n,X_n) \\ \end{bmatrix} \]
兩個字段的協方差表示線性相關性。如果協方差爲0,表示兩個字段完全獨立,爲了讓協方差爲0,選擇第二個基時,與第一個基正交方向上選擇。
第一個基:方差最大。第二基:正交與第一個基,方差最大。
優化目標
推導方法一:
原始數據變換到這組基上後,各個字段之間協方差爲0,字段的方差儘可能大。
協方差矩陣
對角線是方差,其它原始是a和b的協方差。
目標是:非對角線上,全0.
實對稱矩陣:n*n的實對稱矩陣一定有n個單位正交的特徵向量。
E = (e_1,e_2,...,e_n)
實對稱矩陣對角化:
在根據特徵值的從大到小,將特徵向量從上往下排列,
計算步驟
-
數據:去除平均值(均值爲0)
-
協方差矩陣
-
特徵值,特徵向量(單位化)
-
降維
基*數據= 降維
基:按行排
數據:按列排
-
協方差對角化
# 導入包
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
# 導入數據
testSet = pd.read_table('iris.txt',header= None)
testSet.head()
testSet.shape
# 查看原始數據分佈
plt.scatter(testSet.iloc[:,0], testSet.iloc[:,1], market = '.',c = 'orange')
# 去均值化
dataSet = testSet
meanVals = dataSet.mean(0)
meanRemoved = dataSet - meanVals
# 協方差矩陣
covMat = np.mat(np.cov(meanRemoved, rowvar = 0))
#0:n 1:n-1
# 特徵值,特徵向量
eigVals, eigVects = np.linalg.eig(covMat)
eigValInd = np.argsort(eigVals)
N = 1
eigValInd = eigValInd[:-(N+1):-1] # 反向
redValInd = eigVects[:,eigValInd]
# 降維
lowDDataMat = np.mat(meanRemoved) * redEigVects
PCA 推導方法二
新的座標是\({w_1,w_2,..,w_k}\),滿足
原始數據在新座標上的投影 \(Z= W^TX\)
向量\(x_i\)在\(w\)上投影座標是 \((x_i,w) = x_i^Tw\)
因爲已經去均值了,所以投影后的方差爲
協方差矩陣
優化問題是
拉格朗日求解
因此方差對於的特徵值,特徵值最大的對於的特徵向量就是基.
Kernelized PCA
矩陣每一列是一個樣本
往高維空間映射,得到新的表達式
定理: 空間中任意向量,都可以用空間中所以的樣本線性表示,因此我們有
帶回化簡有
再在求特徵向量
Linear Discriminant Analysis
對於分類問題,使用 PCA 可能得不到好的結果,忽略class information, 是屬於非監督學習,而線性判別器是監督學習。
概念
儘可能保留類信息,\(x_1,x_2,...,x_n\),新的座標系\(w_1,w_2,...,w_k\),數據在新座標系的座標是:\(y = w^Tx\)
原理
- 兩分類問題
原始不同類的均值
類的中心距離要大
\(S_B\):類間距離
\(S_w\):類內離散度
\(S_i\): \(\sum_{x \in w_i}(x-u_i)(x-u_i)^T\)
\(\begin{aligned} \tilde{{s}}_{1}^{2}=\sum_{y \in \omega_{1}}(y-\tilde{\mu})^{2}=\sum_{x \in \omega_{1}}\left(w^{\top} x-w^{\top} \mu_{1}\right)^{2} &=\sum_{x \in \omega_{0} \atop \tau}\left(x-\mu_{1}\right)\left(x-\mu_{1}\right)^{T} w=w^{\top} S_{1} w \\ & \tilde{{s}}_{1}^{2}+\tilde{{s}}_{2}^{2}=w^{\top} S_{w} w \end{aligned}\)
目標函數:\(J(w)=\frac{\left|\widetilde{\mu}_{1}-\widetilde{\mu}_{2}\right|^{2}}{\widetilde{\mathbf{s}}_{1}^{2}+\widetilde{\mathbf{s}}_{2}^{2}} | \Longrightarrow J{(w)=\frac{w^{\top} S_{B} w}{w^{\top} S_{w} w}}\)
\(S_w^{-1}S_Bw = Jw\)
轉化爲 特徵值,特徵向量的問題了
- 多分類問題
Derivation
- within_class scatter
- between -class scatter
Limitation of LDA
-
\(S_B\)的rank是最大n-1,或者更少,這個決定了降到幾維空間。而 PCA沒有限制,新座標是正交的,而LDA不一定是正交的
-
\(S_w\)可能奇異矩陣,不存在逆矩陣
-
LDA可能表現的不是很好,找不到投影方向。\(u_1 = u_2\)當類中心重合時
計算流程
(1) 計算每個類別的均值\(u_i\), 全局樣本均值\(u\)
(2) 計算類內散度矩陣\(S_w\),類間散度矩陣\(S_B\)
(3)計算矩陣\(S_w^{-1}S_B\)的特徵值和特徵向量
(4) 取特徵值到的特徵向量
(5)計算投影矩陣
The difference of PCA and LDA
1. 原理(保留的信息)
PCA是保留數據儘可能多的信息,最大方差的方向
LDA是保留儘可能的類別信息
2. 監督學習和非監督學習
有標籤和無標籤數據
LDA還可以進行預測應用
3. 對稱問題
都是用於降維,LDA降維後最多生成分類標籤-1維子空間。LDA與原始空間N無關。PCA與原始空間的維度有關係.
實驗
-
PCA in Python VS. MYPCA
數據: sklearn.datasets裏面的iris
PCA的實現:
import numpy as np from sklearn.datasets import load_iris from sklearn. decomposition import PCA from sklearn.decomposition import KernelPCA from scipy.spatial.distance import pdist, squareform import matplotlib.pyplot as plt def mypca(data, n_dim): ''' :param data : (n_samples, n_features) :param n_dim: target dimensions :return (n_samples, n_dim) ''' data = data - np.mean(data, axis = 0, keepdims = True) cov = np.dot(data.T, data)/ (len(data[:,0] - 1) eig_values, eig_vector = np.linalg.eig(cov) indexs_ = np.argsort(-eig_values)[:n_dim] picked_eig_values = eig_values[indexs_] picked_eig_vector = eig_vector[:,indexs_] data_dim = np.dot(data, picked_eig_vector) return data_dim if __name__ == "__main__": data = load_iris() X = data.data Y = data.target data_2d1 = mypca(X,2) plt.subplot(121) plt.scatter(data_2d1[:, 0], data_2d1[:, 1], c = Y) plt.title('MyPCA') sklearn_pca = PCA(n_components = 2) data_2d2 = sklearn_pca.fit_transform(X) plt.subplot(122) plt.scatter(data_2d2[:,0], data_2d2[:, 1],c = Y) plt.title('Python PCA') plt.show()
- PCA in Python VS MyKernelPCA
import numpy as np from sklearn.datasets import load_iris from sklearn. decomposition import PCA from sklearn.decomposition import KernelPCA from scipy.spatial.distance import pdist, squareform import matplotlib.pyplot as plt # Kernel def sigmoid(x, coef = 0.25): x = np.dot(x, x.T) return np.tanh(coef*x+1) def linear(x): x = np.dot(x, x.T) return x def rbf(x, gamma = 15): sq_dists = pdist(x, 'sqeuclidean') mat_sq_dists = squareform(sq_dists) return np.exp(-gamma*mat_sq_dists) def mykernelpca(data, n_dim, kernel = 'rbf') ''' :param data: (n_samples, n_features) :param n_dims: target n_dims :param kernel: kernel functions :return: (n_samples, n_dims) ''' K = kernel(data) # 核矩陣歸一化 N = K.shape[0] one_n = np.ones((N, N)) / N K = K - one_n.dot(K) - K.dot(one_n) + one_n.dot(K).dot(one_n) # 特徵值 eig_values, eig_vector = np.linalg.eig(K) idx = eig_values.argsort()[::-1] eigval = eig_values[idx][:n_dims] eigvector = eig_vector[:, idx][:, :n_dims] print(eigval) # 特徵向量標準化處理 eigval = eigval**(1/2) vi = eigvector/eigval.reshape(-1,n_dims) data_n = np.dot(K, vi) return data_n if __name__ == "__main__": data = load_iris().data Y = load_iris().target data_1 = kpca(data, kernel=rbf) sklearn_kpca = KernelPCA(n_components=2, kernel="rbf", gamma=15) data_2 = sklearn_kpca.fit_transform(data) plt.figure(figsize=(8,4)) plt.subplot(121) plt.title("my_KPCA") plt.scatter(data_1[:, 0], data_1[:, 1], c = Y) plt.subplot(122) plt.title("sklearn_KPCA") plt.scatter(data_2[:, 0], data_2[:, 1], c = Y) plt.show()