PCA,LDA基礎+sklearn 簡單實踐
- 1.PCA+sklearn.decomposition.PCA
- 1.PCA理論基礎
- 2.sklearn.decomposition.PCA簡單實踐
- 2.LDA+sklearn.discriminant_analysis.LinearDiscriminantAnalysis
- 2.1 LDA理論基礎
- 2.2 sklearn LDA簡單實踐
1.PCA+sklearn.decomposition.PCA
1.PCA理論基礎
PCA:(principal component analysis)無監督線性降維算法,通過投影減少數據的特征數。投影方向是數據投影后方差最大的方向(重構誤差最小的方向/坐標軸相關度)
投影方差最大理論:在信號處理中認為信號具有較大的方差,噪聲有較小的方差,信噪比就是信號與噪聲的方差比,越大越好。
最小平方理論:點到線的距離平方和越小越好(具體推導)。
兩種理論都能推出同一個算法:協方差矩陣求均值。
step1:原特征向量去中心化:x=x^?x ̄x=\hat{x}-\overline{x}x=x^?x,去中心化,使得投影后的樣本均值為0;
step2: 投影后求方差,uuu投影方向的單位向量:uTx?uTx=>uTx?xTu=>∑iuTxi?xiTu=uT∑uu^Tx*u^Tx=>u^Tx*x^Tu=>\sum_i u^Tx_i*x_i^Tu=u^T\sum uuTx?uTx=>uTx?xTu=>∑i?uTxi??xiT?u=uT∑u(單個樣本方差=>all sample方差);
step3:帶約束問題拉格朗日乘子法:uT∑u+λ(1?uTu)u^T\sum u+\lambda(1-u^Tu)uT∑u+λ(1?uTu);
step4:求最大,對上式求導為0 : ∑u=λu\sum u = \lambda u∑u=λu;
由上式子可得最大投影方向為協方差矩陣的最大特征值對的特征向量,依次類推,可以得到第二大投影方向,第k大投影方向。
取特征值topk大的k個特征向量,組成一個kn的投影矩陣M,Mx可以得到k*1維的向量,作為原來向量的低維度的等價表示形式。
2.sklearn.decomposition.PCA簡單實踐
如果數據的各個維度的特征不一致,需要先做Z-sore Normalization(減均值除方差)。具體原因可參考博文:https://www.jianshu.com/p/c21c0e2c403a
sklearn.decomposition.PCA(n_components=None, copy=True, whiten=False)
PCA對象的初始化參數 | |
---|---|
n_components | nums/ string,default=None,所有成分被保留。 n_components > 1降維后的維度;0< n_components<1將自動選取特征個數n,使得滿足所要求的方差百分比。 |
copy | 是否在運行算法時,將原始訓練數據復制一份 |
whiten | 是否對降維后的數據的每個特征進行歸一化 |
PCA對象方法 | |
---|---|
fit(x) | 用x訓練PCA 對象pca.fit(x) |
transform(x) | 訓練好PCA對象后用pca.transform(x)進行降維 |
fit_transform(x) | 用x來訓練PCA模型,同時返回降維后的數據x_reduced= pca.fit_transform(x) |
inverse_transform() | 將降維后的數據轉換成原始數據 x = pca.inverse_transform(x_reduced) |
PCA對象的屬性 | |
---|---|
pca.components_ | k個特征向量 |
pca.n_components_ | 特征向量的數量 k |
pca.explained_variance_ | 往各個特征向量方向投影后的方差 |
pca.explained_variance_ratio_ | 各個特征值占總特征值的比例 ? |
鳶尾花降維算法demo:鳶尾花數據特征是4維的,共三類樣本。
import matplotlib.pyplot as plt
import sklearn.decomposition as dp
from sklearn.datasets.base import load_iris
from mpl_toolkits.mplot3d import Axes3D
plt.switch_backend('agg')# 鳶尾花數據一共有三個類別
n = 3 # 降到n維度
x,y=load_iris(return_X_y=True)
pca=dp.PCA(n_components=n)reduced_x=pca.fit_transform(x)# PCA對象的一些屬性
print(pca.explained_variance_ratio_,sum(pca.explained_variance_ratio_)) # 各個特征值占總特征值的比例?
print(pca.explained_variance_) # 各個特征向量方向投影后的方差
print(pca.n_components_) # 特征向量的數量 k
print(pca.components_) # k個特征向量red_x,red_y,red_z = [], [], []
blue_x,blue_y, blue_z = [], [], []
green_x,green_y, green_z = [], [], []# 將同一個類別的數據繪制成同一個元素
for i in range(len(reduced_x)): if y[i]==0:red_x.append(reduced_x[i][0])red_y.append(reduced_x[i][1])red_z.append(reduced_x[i][2])elif y[i]==1:blue_x.append(reduced_x[i][0])blue_y.append(reduced_x[i][1])blue_z.append(reduced_x[i][2])else:green_x.append(reduced_x[i][0])green_y.append(reduced_x[i][1])green_z.append(reduced_x[i][2])
figure = plt.figure()
ax1 = figure.add_subplot(1,2,1)
ax2 = figure.add_subplot(1,2,2,projection='3d')# 兩個主成分,二維圖像
ax1.scatter(red_x,red_y,c='r',marker='x')
ax1.scatter(blue_x,blue_y,c='b',marker='D')
ax1.scatter(green_x,green_y,c='g',marker='.')# 三個主成分,三維圖像,更高維度的不好顯示
ax2.scatter3D(red_x,red_y,red_z,c='r',marker='x')
ax2.scatter3D(blue_x,blue_y,blue_z, c='b',marker='D')
ax2.scatter3D(green_x,green_y,green_z, c='g',marker='.')
plt.savefig("./pca_iris_test.png")
plt.close()
輸出
[0.92461872 0.05306648 0.01710261] 0.9947878161267246
[4.22824171 0.24267075 0.0782095 ]
3
[[ 0.36138659 -0.08452251 0.85667061 0.3582892 ][ 0.65658877 0.73016143 -0.17337266 -0.07548102][-0.58202985 0.59791083 0.07623608 0.54583143]]```
2.LDA+sklearn.discriminant_analysis.LinearDiscriminantAnalysis
2.1 LDA理論基礎
LDA–Linear Discriminant Analysis,線性判別分析。有監督的降維過程,依據類別選擇降維方向。
降維方向選擇依據:Fisher準則,類內離散程度越小,類間離散程度越大.
FDR=(μ1?μ2)2σ12+σ22FDR=\frac{(\mu_1-\mu_2)^2}{\sigma_1^2+\sigma_2^2}FDR=σ12?+σ22?(μ1??μ2?)2?
式中都是投影后的統統計量,引入投影前特征向量x和投影方向u:
(μ1?μ2)2=uT(μ ̄1?μ ̄2)(μ ̄1?μ ̄2)Tu:=uTSbu(\mu_1-\mu_2)^2=u^T(\overline\mu_1-\overline\mu_2)(\overline\mu_1-\overline\mu_2)^Tu := u^TS_bu(μ1??μ2?)2=uT(μ?1??μ?2?)(μ?1??μ?2?)Tu:=uTSb?u
σi2=uTΣiu?>σ12+σ22:=uTSwu\sigma_i^2=u^T\Sigma_iu->\sigma_1^2+\sigma_2^2:= u^TS_wuσi2?=uTΣi?u?>σ12?+σ22?:=uTSw?u
則FDR可以寫維:
FDR=uTSbuuTSwuFDR=\frac{u^TS_bu}{u^TS_wu}FDR=uTSw?uuTSb?u?
其中:類內散度矩陣:sw=Σ1+Σ2s_w=\Sigma_1+\Sigma_2sw?=Σ1?+Σ2?
類間散度矩陣:sb=(μ ̄1?μ ̄2)(μ ̄1?μ ̄2)s_b = (\overline\mu_1-\overline\mu_2)(\overline\mu_1-\overline\mu_2)sb?=(μ?1??μ?2?)(μ?1??μ?2?)
上式子為廣義瑞麗熵,有解析解:最優解的條件:
Sbu=λSwuS_b u=\lambda S_w uSb?u=λSw?u
二分類問題u=sw?1(μ ̄1?μ ̄2)(μ ̄1?μ ̄2)u=s_w^{-1}(\overline\mu_1-\overline\mu_2)(\overline\mu_1-\overline\mu_2)u=sw?1?(μ?1??μ?2?)(μ?1??μ?2?)
詳細推導不詳,參考資料:https://www.cnblogs.com/pinard/p/6244265.html
LDA key point:
1)找降維后最容易分類的方向
2)只能降到min(sample nums, class num-1), 二分類就只能降到1維。
2.2 sklearn LDA簡單實踐
def demo_lda(x,y,n=3):lda = LinearDiscriminantAnalysis(n_components=n)lda.fit(x,y)reduced_x = lda.transform(x)index_list = []for i in range(n):index_list.append("com%d"%i)reduced_data = pd.DataFrame(reduced_x, columns = index_list)reduced_data["label"] = yreduced_data.to_csv("lda_%dcom_open.csv"%n)red_x,red_y = [], []blue_x,blue_y = [], []green_x,green_y = [], []# 將同一個類別的數據繪制成同一個元素for i in range(len(reduced_x)): if y[i]==0:red_x.append(reduced_x[i][0])red_y.append(reduced_x[i][1])elif y[i]==1:blue_x.append(reduced_x[i][0])blue_y.append(reduced_x[i][1])else:green_x.append(reduced_x[i][0])green_y.append(reduced_x[i][1])figure = plt.figure()ax1 = figure.add_subplot(1,2,1)# 兩個主成分,二維圖像ax1.scatter(red_x,red_y,c='r',marker='x')ax1.scatter(blue_x,blue_y,c='b',marker='D')ax1.scatter(green_x,green_y,c='g',marker='.')plt.savefig("./lda_iris_test.png")plt.close()if __name__ == "__main__":n = 2 # 降到n維度x,y=load_iris(return_X_y=True)demo_lda(x,y,n)
參考博文:
PCA:
https://blog.csdn.net/u012102306/article/details/52294726
https://www.cnblogs.com/youngsea/p/9334773.html
https://www.jb51.net/article/181205.htm
LDA:
https://zhuanlan.zhihu.com/p/161556242
sklearn 中的降維算法:https://www.cnblogs.com/LUOyaXIONG/gallery/image/259967.html