一、降維算法概述
1.降維算法概述
降維就是一種針對高維度特征進行的數據預處理方法,是應用非常廣泛的數據預處理方法。
降維算法指對高維度的數據保留下最重要的一些特征,去除噪聲和不重要的特征,從而實現提升數據處理速度的目的。在實際的生產和應用中,在一定的信息損失范圍內,降維可以節省大量的時間和成本。
機器學習領域中所謂的降維就是指采用某種映射方法,將原高維空間中的數據點映射到低維度的空間中。
2.降維算法的分類
主成分分析(Principal Component Analysis,PCA)法
試圖在保證數據信息丟失最少的原則下,對多個變量進行最佳綜合簡化,即對高維變量空間進行降維處理。
因子分析(Factor Analysis,FA)法
因子分析法是從假設出發。
因子分析法有幾個主要目的:一是進行結構的探索,在變量之間存在高度相關性的時候希望用較少的因子來概括其信息;二是把原始變量轉換為因子得分后,使用因子得分進行其他分析,從而簡化數據,如聚類分析、回歸分析等;三是通過每個因子得分計算出綜合得分,對分析對象進行綜合評價。
3.降維算法的應用場景
降維算法通常應用于數據壓縮與數據可視化中。
二、數據降維
數據降維(Dimensionality Reduction):
數據降維案例(經濟分析):
任務(真實事件):通過美國1929-1938年各年經濟數據,預測國民收入與支出
數據包括:雇主補貼、消費資料和生產資料、純公共支出、凈增庫存、股息、利息、外貿平衡等十七個指標

數據降維,是指在某些限定條件下,降低隨機變量個數,得到一組“不相關”主變量的過程。
作用:減少模型分析數據量,提升處理效率,降低計算難度,實現數據可視化。

數據量下降舉例:2D數據降維到1D數據

將二維數據投影到一條直線上面

數據量下降舉例:3D數據降維到2D數據

投影之后變成二維數據

數據可視化舉例:國家分布可視化(基于50項經濟指標)

縮減為兩項指標:復合指標F1和復合指標F2

這樣就可以進行可視化展示:


三、主成分分析(PCA)
數據降維的實現:主成分分析(PCA)
PCA(principal components analysis):數據降維技術中,應用最最多的方法
目標:尋找k(k<n)維新數據,使它們反映事物的主要特征
核心:在信息損失盡可能少的情況下,降低數據維度。
二維數據PCA


三維數據PCA


3D到2D:投影到u1、u2形成的平面
n維到k維:投影到u1、u2...uk形成的空間
如何保留主要信息:
投影后的不同特征數據盡可能分得開(即不相關)

如何實現?
使投影后數據的方差最大,因為方差越大數據也越分散。
計算過程
(1)、原始數據預處理(標準化:μ=0,σ=1),即將N維數據實現標準正態分布,即處理后均值為0,方差為1。
(2)、計算協方差矩陣特征向量、及數據在各特征向量投影后的方差,方差越大,相關性越小,將方差小的舍棄掉。
(3)、根據需求(任務指定或方差比例)確定降維維度k
(4)、選取k維特征向量,計算數據在其形成空間的投影
三、實戰-PCA(iris數據降維后分類)
數據集

1、基于iris_data.csv數據,建立KNN模型實現數據分類(n_neighbors=3)
2、對數據進行標準化處理,選取一個維度可視化處理后的效果
3、進行與原數據等維度PCA,查看各主成分的方差比例
4、保留合適的主成分,可視化降維后的數據
5、基于降維后數據建立KNN模型,與原數據表現進行對比
1、加載數據
#加載數據 import torch import pandas as pd import numpy as np from sklearn.metrics import accuracy_score # from matplotlib import pyplot as plt import matplotlib matplotlib.use('TkAgg') import matplotlib.pyplot as plt data = pd.read_csv('./data/iris_data.csv') print(data)
結果:
sepal length sepal width ... target label 0 5.1 3.5 ... Iris-setosa 0 1 4.9 3.0 ... Iris-setosa 0 2 4.7 3.2 ... Iris-setosa 0 3 4.6 3.1 ... Iris-setosa 0 4 5.0 3.6 ... Iris-setosa 0 .. ... ... ... ... ... 145 6.7 3.0 ... Iris-virginica 2 146 6.3 2.5 ... Iris-virginica 2 147 6.5 3.0 ... Iris-virginica 2 148 6.2 3.4 ... Iris-virginica 2 149 5.9 3.0 ... Iris-virginica 2
2、定義X和y
#定義X,y X = data.drop(['target','label'],axis=1) # 去掉最后兩列 y = data.loc[:,'label'] print(X.shape,y.shape)#打印X,y的維度
結果:(150, 4) (150,)
3、建立KNN模型實現數據分類(n_neighbors=3)
選用最近的3個點來預測新的點屬于哪一類
#建立KNN模型 from sklearn.neighbors import KNeighborsClassifier KNN = KNeighborsClassifier(n_neighbors=3) KNN.fit(X,y) # 訓練 # 預測 y_predict = KNN.predict(X) # 計算準確率 accuracy = accuracy_score(y,y_predict) print(accuracy)
結果:0.96
第一步已經完成,接下來進入第二步:對數據進行標準化處理,選取一個維度可視化處理后的效果
4、對數據進行標準化處理
# 對數據進行標準化處理 from sklearn.preprocessing import StandardScaler X_norm = StandardScaler().fit_transform(X) print(X_norm)
結果:
[[-9.00681170e-01 1.03205722e+00 -1.34127240e+00 -1.31297673e+00] [-1.14301691e+00 -1.24957601e-01 -1.34127240e+00 -1.31297673e+00] [-1.38535265e+00 3.37848329e-01 -1.39813811e+00 -1.31297673e+00] ...... [ 1.03800476e+00 -1.24957601e-01 8.19624347e-01 1.44795564e+00] [ 5.53333275e-01 -1.28197243e+00 7.05892939e-01 9.22063763e-01] [ 7.95669016e-01 -1.24957601e-01 8.19624347e-01 1.05353673e+00] [ 4.32165405e-01 8.00654259e-01 9.33355755e-01 1.44795564e+00] [ 6.86617933e-02 -1.24957601e-01 7.62758643e-01 7.90590793e-01]]
5、選取一個維度(sepal length)計算均值和方差
# 計算均值和方差 x1_mean = X.loc[:,"sepal length"].mean() x1_sigma = X.loc[:,"sepal length"].std() x1_norm_mean = X_norm[:,0].mean() x1_norm_sigma = X_norm[:,0].std() print(x1_mean,x1_sigma,x1_norm_mean,x1_norm_sigma)
結果:
5.843333333333334 0.8280661279778629 -4.736951571734001e-16 1.0
x1_norm_mean的值為-4.736951571734001e-16,相當于0了。
6、選取一個維度,可視化處理后的效果
# 選取一個維度,可視化處理后的效果 fig1 = plt.figure(figsize=(20, 5)) # 原來的數據分布 plt.subplot(121) plt.hist(X.loc[:,"sepal length"],bins=100) # 標準化處理之后的數據 plt.subplot(122) plt.hist(X_norm[:,0],bins=100) plt.show()
結果:

發現原來的sepal length這個維度的均值在6左右,標準化處理之后變為了0左右。
到這里第二步已經完成,現在來看第三步:進行與原數據等維度PCA,查看各主成分的方差比例
7、進行與原數據等維度PCA
# 進行與原數據等維度PCA,查看各主成分的方差比例 print(X.shape) # (150,4) 即原數據的維度為4 from sklearn.decomposition import PCA pca = PCA(n_components=4) # 同等維度處理 # 等維度PCA后的數據x_pca x_pca = pca.fit_transform(X_norm) # 參數為標準化處理之后的數據X_norm print(x_pca)
結果:
[[-2.26454173e+00 5.05703903e-01 1.21943348e-01 -2.30733235e-02] [-2.08642550e+00 -6.55404729e-01 2.27250832e-01 -1.03208244e-01] [-2.36795045e+00 -3.18477311e-01 -5.14796236e-02 -2.78252250e-02] [-2.30419716e+00 -5.75367713e-01 -9.88604444e-02 6.63114622e-02] ...... [ 1.55849189e+00 -9.05313601e-01 2.53819099e-02 -2.21322184e-01] [ 1.52084506e+00 2.66794575e-01 -1.79277203e-01 -1.18903043e-01] [ 1.37639119e+00 1.01636193e+00 -9.31405052e-01 -2.41461953e-02] [ 9.59298576e-01 -2.22839447e-02 -5.28794187e-01 1.63675806e-01]]
8、查看各主成分的方差比例
# 計算每個主成分的方差比例 var_ratio = pca.explained_variance_ratio_ print(var_ratio) # [0.72770452 0.23030523 0.03683832 0.00515193]
9、可視化各主成分的方差比例
# 可視化方差比例 fig2 = plt.figure(figsize=(20,5)) plt.bar([1, 2, 3, 4],var_ratio) plt.xticks([1, 2, 3, 4],['PC1', 'PC2', 'PC3', 'PC4']) plt.ylabel("variance ratio of each principle components") plt.show()
結果:

發現前面兩個主成分的方差比例比較大, 后面兩個比較小。
至此,第三步已經完成,現在來看第四步:保留合適的主成分,可視化降維后的數據
10、保留合適的主成分,只需要保留前面兩個成分
pca = PCA(n_components=2) # 只需要保留前面兩個成分 即開始降維 X_pca = pca.fit_transform(X_norm) # 降維后的數據 print(X_pca) # 4維數據變為2維數據 print(X_pca.shape) # (150,2)
結果:
[[-2.26454173e+00 5.05703903e-01] [-2.08642550e+00 -6.55404729e-01] [-2.36795045e+00 -3.18477311e-01] [-2.30419716e+00 -5.75367713e-01] [-2.38877749e+00 6.74767397e-01] ..... [ 2.04330844e+00 8.64684880e-01] [ 2.00169097e+00 1.04855005e+00] [ 1.87052207e+00 3.82821838e-01] [ 1.55849189e+00 -9.05313601e-01] [ 1.52084506e+00 2.66794575e-01] [ 1.37639119e+00 1.01636193e+00] [ 9.59298576e-01 -2.22839447e-02]] (150,2)
11、可視化降維后的數據
# 可視化展示pca結果 fig3 = plt.figure(figsize=(20, 10)) setosa = plt.scatter(X_pca[:, 0][y == 0], X_pca[:,1][y == 0]) versicolour = plt.scatter(X_pca[:, 0][y == 1], X_pca[:,1][y == 1]) virginica = plt.scatter(X_pca[:, 0][y == 2], X_pca[:,1][y == 2]) plt.legend((setosa, versicolour, virginica), ('setosa', 'versicolour', 'virginica')) plt.show()
結果:

原來4維的話是無法可視化的,現在降為2維,從圖中可以看到,藍色是一種花,黃色是一種花,綠色是一種花,雖然黃色和綠色夾雜在一起,但是肉眼還是可以區分得開的。即通過PCA降維之后,這三種花實現了相關性最小。
至此第四步已經完成,現在來看第5步:基于降維后數據建立KNN模型,與原數據的表現(準確率)進行對比
12、基于降維后數據建立KNN模型
#建立KNN模型 from sklearn.neighbors import KNeighborsClassifier KNN = KNeighborsClassifier(n_neighbors=3) KNN.fit(X_pca,y) # 預測 y_predict = KNN.predict(X_pca) # 計算準確率 accuracy = accuracy_score(y,y_predict) print(accuracy)
結果:0.9466666666666667
原來是0.96,下降了一點,說明效果其實還挺不錯的。
完整代碼:
#加載數據 import torch import pandas as pd import numpy as np from sklearn.metrics import accuracy_score # from matplotlib import pyplot as plt import matplotlib matplotlib.use('TkAgg') import matplotlib.pyplot as plt data = pd.read_csv('./data/iris_data.csv') print(data) #定義X,y X = data.drop(['target','label'],axis=1) # 去掉最后兩列 y = data.loc[:,'label'] print(X.shape,y.shape)#打印X,y的維度 #建立KNN模型 from sklearn.neighbors import KNeighborsClassifier KNN = KNeighborsClassifier(n_neighbors=3) KNN.fit(X,y) # 訓練 y_predict = KNN.predict(X)# 預測 accuracy = accuracy_score(y,y_predict)# 計算準確率 print(accuracy) # 對數據進行標準化處理(均值為0,方差為1) from sklearn.preprocessing import StandardScaler X_norm = StandardScaler().fit_transform(X) print(X_norm) # 計算均值和方差 x1_mean = X.loc[:,"sepal length"].mean() x1_sigma = X.loc[:,"sepal length"].std() x1_norm_mean = X_norm[:,0].mean() x1_norm_sigma = X_norm[:,0].std() print(x1_mean,x1_sigma,x1_norm_mean,x1_norm_sigma) # 選取一個維度,可視化處理后的效果 fig1 = plt.figure(figsize=(20, 5)) # 原來的數據分布 plt.subplot(121) plt.hist(X.loc[:,"sepal length"],bins=100) # 標準化處理之后的數據 plt.subplot(122) plt.hist(X_norm[:,0],bins=100) plt.show() # 進行與原數據等維度PCA,查看各主成分的方差比例 print(X.shape) # (150,4) 即元數據的維度為4 from sklearn.decomposition import PCA pca = PCA(n_components=4) # 同等維度處理 # 等維度PCA后的數據x_pca x_pca = pca.fit_transform(X_norm) # 參數為標準化處理之后的數據X_norm print(x_pca) # 計算每個主成分的方差比例 var_ratio = pca.explained_variance_ratio_ print(var_ratio) # [0.72770452 0.23030523 0.03683832 0.00515193] # 可視化方差比例 fig2 = plt.figure(figsize=(20,5)) plt.bar([1, 2, 3, 4],var_ratio) plt.xticks([1, 2, 3, 4],['PC1', 'PC2', 'PC3', 'PC4']) plt.ylabel("variance ratio of each principle components") plt.show() pca = PCA(n_components=2) # 只需要保留前面兩個成分 即開始降維 X_pca = pca.fit_transform(X_norm) # 降維后的數據 print(X_pca) print(X_pca.shape) # 可視化展示pca結果 fig3 = plt.figure(figsize=(20, 10)) setosa = plt.scatter(X_pca[:, 0][y == 0], X_pca[:,1][y == 0]) versicolour = plt.scatter(X_pca[:, 0][y == 1], X_pca[:,1][y == 1]) virginica = plt.scatter(X_pca[:, 0][y == 2], X_pca[:,1][y == 2]) plt.legend((setosa, versicolour, virginica), ('setosa', 'versicolour', 'virginica')) plt.show() # 基于降維后數據建立KNN模型,與原數據表現進行對比 #建立KNN模型 from sklearn.neighbors import KNeighborsClassifier KNN = KNeighborsClassifier(n_neighbors=3) KNN.fit(X_pca,y) # 預測 y_predict = KNN.predict(X_pca) # 計算準確率 accuracy = accuracy_score(y,y_predict) print(accuracy)
總結:
1、通過計算數據對應的主成分(principle components),可在減少數據維度同時盡可能保留主要信息;
2、為確定合適的主成分維度,可先對數據進行與原數據相同維度的PCA處理,再根據根據各個成分的數據方差確認主成分維度,即比例大的保留下來;
浙公網安備 33010602011771號