python大戰機器學習——資料降維
注:因為公式敲起來太麻煩,因此本文中的公式沒有呈現出來,想要知道具體的計算公式,請參考原書中內容
降維就是指採用某種對映方法,將原高維空間中的資料點對映到低維度的空間中
1、主成分分析(PCA)
將n維樣本X通過投影矩陣W,轉換為K維矩陣Z
輸入:樣本集D,低維空間d
輸出:投影矩陣W
演算法步驟:
1)對所有樣本進行中心化操作
2)計算樣本的協方差矩陣
3)對協方差矩陣做特徵值分解
4)取最大的d個特徵值對應的特徵向量,構造投影矩陣W
注:通常低維空間維數d的選取有兩種方法:1)通過交叉驗證法選取較好的d 2)從演算法原理的角度設定一個閾值,比如t=0.95,然後選取似的下式成立的最小的d值:
Σ(i->d)λi/Σ(i->n)λi>=t,其中λi從大到小排列
PCA降維的準則有以下兩個:
最近重構性:重構後的點距離原來的點的誤差之和最小
最大可分性:樣本點在低維空間的投影儘可能分開
實驗程式碼:
1 import numpy as np 2 import matplotlib.pyplot as plt 3 from sklearn import datasets,decomposition,manifold 4 5 def load_data(): 6 iris=datasets.load_iris() 7View Codereturn iris.data,iris.target 8 9 def test_PCA(*data): 10 X,Y=data 11 pca=decomposition.PCA(n_components=None) 12 pca.fit(X) 13 print("explained variance ratio:%s"%str(pca.explained_variance_ratio_)) 14 15 def plot_PCA(*data): 16 X,Y=data 17 pca=decomposition.PCA(n_components=2)18 pca.fit(X) 19 X_r=pca.transform(X) 20 # print(X_r) 21 22 fig=plt.figure() 23 ax=fig.add_subplot(1,1,1) 24 colors=((1,0,0),(0,1,0),(0,0,1),(0.5,0.5,0),(0,0.5,0.5),(0.5,0,0.5),(0.4,0.6,0),(0.6,0.4,0),(0,0.6,0.4),(0.5,0.3,0.2),) 25 for label,color in zip(np.unique(Y),colors): 26 position=Y==label 27 # print(position) 28 ax.scatter(X_r[position,0],X_r[position,1],label="target=%d"%label,color=color) 29 ax.set_xlabel("X[0]") 30 ax.set_ylabel("Y[0]") 31 ax.legend(loc="best") 32 ax.set_title("PCA") 33 plt.show() 34 35 X,Y=load_data() 36 test_PCA(X,Y) 37 plot_PCA(X,Y)
實驗結果:
可以看出四個特徵值的比例分別佔比0.92464621,0.05301557,0.01718514,0.00518309,因此可將原始特徵4維降低到2維
IncrementalPCA超大規模資料降維
可以使用與超大規模資料,它可以將資料分批載入進記憶體,其介面和用法幾乎與PCA完全一致
2、SVD降維
SVD奇異值分解等價於PCA主成分分析,核心都是求解X*(X轉置)的特徵值以及對應的特徵向量
3、核化線性(KPCA)降維
是一種非線性對映的方法,核主成分分析是對PCA的一種推廣
實驗程式碼:
import numpy as np import matplotlib.pyplot as plt from sklearn import datasets,decomposition,manifold def load_data(): iris=datasets.load_iris() return iris.data,iris.target def test_KPCA(*data): X,Y=data kernels=['linear','poly','rbf','sigmoid'] for kernel in kernels: kpca=decomposition.KernelPCA(n_components=None,kernel=kernel) kpca.fit(X) print("kernel=%s-->lambdas:%s"%(kernel,kpca.lambdas_)) def plot_KPCA(*data): X,Y=data kernels = ['linear', 'poly', 'rbf', 'sigmoid'] fig=plt.figure() colors=((1,0,0),(0,1,0),(0,0,1),(0.5,0.5,0),(0,0.5,0.5),(0.5,0,0.5),(0.4,0.6,0),(0.6,0.4,0),(0,0.6,0.4),(0.5,0.3,0.2),) for i,kernel in enumerate(kernels): kpca=decomposition.KernelPCA(n_components=2,kernel=kernel) kpca.fit(X) X_r=kpca.transform(X) ax=fig.add_subplot(2,2,i+1) for label,color in zip(np.unique(Y),colors): position=Y==label ax.scatter(X_r[position,0],X_r[position,1],label="target=%d"%label,color=color) ax.set_xlabel("X[0]") ax.set_ylabel("X[1]") ax.legend(loc="best") ax.set_title("kernel=%s"%kernel) plt.suptitle("KPCA") plt.show() X,Y=load_data() test_KPCA(X,Y) plot_KPCA(X,Y)View Code
實驗結果:
不同的核函式,其降維後的資料分佈是不同的
並且採用同樣的多項式核函式,如果引數不同,其降維後的資料分佈是不同的。因此再具體應用中,可以通過選用不同的核函式以及設定多種不同的引數來對比哪種情況下可以獲得最好的效果。
4、流形學習降維
是一種借鑑了拓撲流形概念的降維方法
5、多維縮放(MDS)降維
MDS要求原始空間中樣本之間的距離在低維空間中得到保持
輸入:距離矩陣D,低維空間維數n'
輸出:樣本集在低維空間中的矩陣Z
演算法步驟:
1)依據公式計算di,.^2,dj,.^2,d.,.^2
2)依據公式計算降維後空間的內積矩陣B
3)對矩陣B進行特徵值分解
4)依據求得的對角矩陣和特徵向量矩陣,依據公式計算Z
實驗程式碼:
import numpy as np import matplotlib.pyplot as plt from sklearn import datasets,decomposition,manifold def load_data(): iris=datasets.load_iris() return iris.data,iris.target def test_MDS(*data): X,Y=data for n in [4,3,2,1]: mds=manifold.MDS(n_components=n) mds.fit(X) print("stress(n_components=%d):%s"%(n,str(mds.stress_))) def plot_MDS(*data): X,Y=data mds=manifold.MDS(n_components=2) X_r=mds.fit_transform(X) # print(X_r) fig=plt.figure() ax=fig.add_subplot(1,1,1) colors=((1,0,0),(0,1,0),(0,0,1),(0.5,0.5,0),(0,0.5,0.5),(0.5,0,0.5),(0.4,0.6,0),(0.6,0.4,0),(0,0.6,0.4),(0.5,0.3,0.2),) for label,color in zip(np.unique(Y),colors): position=Y==label ax.scatter(X_r[position,0],X_r[position,1],label="target=%d"%label,color=color) ax.set_xlabel("X[0]") ax.set_ylabel("Y[0]") ax.legend(loc="best") ax.set_title("MDS") plt.show() X,Y=load_data() test_MDS(X,Y) plot_MDS(X,Y)View Code
實驗結果:
stress表示原始資料降維後的距離誤差之和
6、等度量對映(Isomap)降維
輸入:樣本集D,近鄰引數k,低維空間維數n’
輸出:樣本集在低維空間中的矩陣Z
演算法步驟:
1)對每個樣本點x,計算它的k近鄰;同時將x與它的k近鄰的距離設定為歐氏距離,與其他點的距離設定為無窮大
2)呼叫最短路徑演算法計算任意兩個樣本點之間的距離,獲得距離矩陣D
3)呼叫多維縮放MDS演算法,獲得樣本集在低維空間中的矩陣Z
注:新樣本難以將其對映到低維空間中,因此需要訓練一個迴歸學習器來對新樣本的低維空間進行預測
建立近鄰圖時,要控制好距離的閾值,防止短路和斷路
實驗程式碼:
1 import numpy as np 2 import matplotlib.pyplot as plt 3 from sklearn import datasets,decomposition,manifold 4 5 def load_data(): 6 iris=datasets.load_iris() 7 return iris.data,iris.target 8 9 def test_Isomap(*data): 10 X,Y=data 11 for n in [4,3,2,1]: 12 isomap=manifold.Isomap(n_components=n) 13 isomap.fit(X) 14 print("reconstruction_error(n_components=%d):%s"%(n,isomap.reconstruction_error())) 15 16 def plot_Isomap_k(*data): 17 X,Y=data 18 Ks=[1,5,25,Y.size-1] 19 fig=plt.figure() 20 # colors=((1,0,0),(0,1,0),(0,0,1),(0.5,0.5,0),(0,0.5,0.5),(0.5,0,0.5),(0.4,0.6,0),(0.6,0.4,0),(0,0.6,0.4),(0.5,0.3,0.2),) 21 for i,k in enumerate(Ks): 22 isomap=manifold.Isomap(n_components=2,n_neighbors=k) 23 X_r=isomap.fit_transform(X) 24 ax=fig.add_subplot(2,2,i+1) 25 colors = ((1, 0, 0), (0, 1, 0), (0, 0, 1), (0.5, 0.5, 0), (0, 0.5, 0.5), (0.5, 0, 0.5), (0.4, 0.6, 0), (0.6, 0.4, 0), 26 (0, 0.6, 0.4), (0.5, 0.3, 0.2),) 27 for label,color in zip(np.unique(Y),colors): 28 position=Y==label 29 ax.scatter(X_r[position,0],X_r[position,1],label="target=%d"%label,color=color) 30 ax.set_xlabel("X[0]") 31 ax.set_ylabel("Y[0]") 32 ax.legend(loc="best") 33 ax.set_title("k=%d"%k) 34 plt.suptitle("Isomap") 35 plt.show() 36 37 X,Y=load_data() 38 test_Isomap(X,Y) 39 plot_Isomap_k(X,Y)View Code
實驗結果:
可以看出k=1時,近鄰範圍過小,此時發生斷路現象
7、區域性線性嵌入(LLE)
其目標是保持鄰域內樣本之間的線性關係
輸入:樣本集D,近鄰引數k,低維空間維數n'
輸出:樣本集在低維空間中的矩陣Z
演算法步驟:
1)對於樣本集中的每個點x,確定其k近鄰,獲得其近鄰下標集合Q,然後依據公式計算Wi,j
2)根據Wi,j構建矩陣W
3)依據公式計算M
4)對M進行特徵值分解,取其最小的n'個特徵值對應的特徵向量,即得到樣本集在低維空間中的矩陣Z
實驗程式碼:
1 import numpy as np 2 import matplotlib.pyplot as plt 3 from sklearn import datasets,decomposition,manifold 4 5 def load_data(): 6 iris=datasets.load_iris() 7 return iris.data,iris.target 8 9 def test_LocallyLinearEmbedding(*data): 10 X,Y=data 11 for n in [4,3,2,1]: 12 lle=manifold.LocallyLinearEmbedding(n_components=n) 13 lle.fit(X) 14 print("reconstruction_error_(n_components=%d):%s"%(n,lle.reconstruction_error_)) 15 16 def plot_LocallyLinearEmbedding_k(*data): 17 X,Y=data 18 Ks=[1,5,25,Y.size-1] 19 fig=plt.figure() 20 # colors=((1,0,0),(0,1,0),(0,0,1),(0.5,0.5,0),(0,0.5,0.5),(0.5,0,0.5),(0.4,0.6,0),(0.6,0.4,0),(0,0.6,0.4),(0.5,0.3,0.2),) 21 for i,k in enumerate(Ks): 22 lle=manifold.LocallyLinearEmbedding(n_components=2,n_neighbors=k) 23 X_r=lle.fit_transform(X) 24 ax=fig.add_subplot(2,2,i+1) 25 colors = ((1, 0, 0), (0, 1, 0), (0, 0, 1), (0.5, 0.5, 0), (0, 0.5, 0.5), (0.5, 0, 0.5), (0.4, 0.6, 0), (0.6, 0.4, 0), 26 (0, 0.6, 0.4), (0.5, 0.3, 0.2),) 27 for label,color in zip(np.unique(Y),colors): 28 position=Y==label 29 ax.scatter(X_r[position,0],X_r[position,1],label="target=%d"%label,color=color) 30 ax.set_xlabel("X[0]") 31 ax.set_ylabel("Y[0]") 32 ax.legend(loc="best") 33 ax.set_title("k=%d"%k) 34 plt.suptitle("LocallyLinearEmbedding") 35 plt.show() 36 37 X,Y=load_data() 38 test_LocallyLinearEmbedding(X,Y) 39 plot_LocallyLinearEmbedding_k(X,Y)View Code
實驗結果:
8、總結:
對原始資料採取降維的原因通常有兩個:緩解“維度災難”或者對資料進行視覺化。
降維的好壞沒有一個直接的標準(包括上面提到的重構誤差也只能作為一箇中性的指標)。通常通過對資料進行降維,然後用降維後的資料進行學習,再根據學習的效果選擇一個恰當的降維方式和一個合適的降維模型引數。