机器学习——数据降维
文章目錄
- 數(shù)據(jù)降維
- 1 維度災(zāi)難與降維
- 2 主成分分析
- 2.1 PCA原理
- 2.2 PCA算法
- 2.3 PCA算法實(shí)驗(yàn)
- 3 SVD降維
- 4 核主成分分析降維
- 總結(jié)
數(shù)據(jù)降維
數(shù)據(jù)降維又稱維數(shù)約簡(jiǎn),就是降低數(shù)據(jù)的維度。其方法有很多種,從不同角度入手可以有不同的分類,主要分類方法有:根據(jù)數(shù)據(jù)的特性可以劃分為線性降維和非線性降維,根據(jù)是否考慮和利用數(shù)據(jù)的監(jiān)督信息可以劃分為無監(jiān)督降維、有監(jiān)督降維和半監(jiān)督降維,根據(jù)保持?jǐn)?shù)據(jù)的結(jié)構(gòu)可以分為全局保持降維、局部保持降維和全局與局部保持一致降維等。需要根據(jù)特定的問題選擇合適的數(shù)據(jù)降維方法。
數(shù)據(jù)降維一方面可以解決“維數(shù)災(zāi)難”,緩解信息豐富、知識(shí)貧乏的現(xiàn)狀,降低復(fù)雜度,另一方面可以更好地認(rèn)識(shí)和理解數(shù)據(jù)。
1 維度災(zāi)難與降維
維度災(zāi)難用來描述當(dāng)空間維度增加時(shí),分析和組織高維空間,因體積指數(shù)增加而遇到各種問題場(chǎng)景。例如在高維情況下,數(shù)據(jù)樣本稀疏的問題。例如k近鄰算法中,任意樣本附近任意小的距離內(nèi)總能找到一個(gè)訓(xùn)練樣本,即訓(xùn)練樣本的采樣密度足夠大才能保證分類性能,當(dāng)特征維度很大時(shí),滿足密采樣的樣本數(shù)量會(huì)呈現(xiàn)指數(shù)級(jí)增大,大到幾乎無法達(dá)到。所以在高維度情況下,涉及距離、內(nèi)積的計(jì)算變得困難。
緩解維度災(zāi)難的一個(gè)重要途徑就是降維。一般來說,想獲得低維子空間,最簡(jiǎn)單的方法就是對(duì)原始高維度空間進(jìn)行線性變換:給定d維空間中的樣本X=(x1,x2,···,xm)變換之后得到的d’<=d維空間中的樣本Z=W^TX。
變換矩陣W可視為d’個(gè)d維基向量,新空間中的屬性是原空間屬性的線性組合,基于線性變換來進(jìn)行降維的方法都成線性維方法,主要區(qū)別于對(duì)低維子空間的性質(zhì)有所不同,相當(dāng)于對(duì)W施加了不同的約束。
2 主成分分析
主成分分析是一種最常用的無監(jiān)督降維方法,通過降維技術(shù)吧多個(gè)變量化為少數(shù)幾個(gè)主成分的統(tǒng)計(jì)分析方法。這些主成分能夠反映原始變量的絕大部分信息,它們通常表示為原始變量的某種線性組合。
2.1 PCA原理
為了便于維度變換有如下假設(shè):
- 假設(shè)樣本數(shù)據(jù)是n維的。
- 假設(shè)原始坐標(biāo)系為由標(biāo)準(zhǔn)正交基向量{i1,i2,···,in}張成的空間。
- 假設(shè)經(jīng)過線性變換后的新坐標(biāo)系為由標(biāo)準(zhǔn)正交基向量{j1,j2,···,jn}張成的空間。
根據(jù)定義有:
記ws=(js·i1,js·i2,···,js·in),其各個(gè)分量就是基向量js在原始坐標(biāo)系中的投影。
根據(jù)定義,有:
令坐標(biāo)變換矩陣W為:W=(w1,w2,···,wn),則有:
這樣W的第s列就是js在原始坐標(biāo)系中的投影。
假設(shè)樣本點(diǎn)xi在原始坐標(biāo)系中的表示為:
令其中:
假設(shè)樣本點(diǎn)xi在新坐標(biāo)系中的表示為:
令其中:
于是可以推導(dǎo)出:
丟棄其中的部分坐標(biāo),將維度降低到d<n,則樣本點(diǎn)xi在低維坐標(biāo)系中的坐標(biāo):
那么,現(xiàn)在出現(xiàn)一個(gè)問題,即丟棄哪些坐標(biāo)?思想是:基于降低之后的坐標(biāo)重構(gòu)樣本時(shí),盡量要與原始樣本接近。
2.2 PCA算法
算法的輸入為樣本集D與低維空間維數(shù)d,輸出為所求的投影矩陣W。
算法的步驟表現(xiàn)在:
- 對(duì)所有樣本進(jìn)行中心化操作:
- 計(jì)算樣本的協(xié)方差矩陣XX^T。
- 對(duì)協(xié)方差矩陣作特征值分解。
- 取最大的d個(gè)特征值對(duì)應(yīng)的特征向量構(gòu)造投影矩陣W。
通常低維空間維數(shù)d的選取有兩種方法:
- 通過交叉驗(yàn)證法選取較好的d。
- 從算法原理角度設(shè)置一個(gè)閾值,例如t=95%,然后選取使得下式成立的最小的d的值:
PCA降維有兩個(gè)準(zhǔn)則:
- 最近重構(gòu)性:樣本集中所有點(diǎn),重構(gòu)后的點(diǎn)距離原來點(diǎn)的誤差之和最小。
- 最大可分性:樣本點(diǎn)在低維空間的投影盡可能分開。
2.3 PCA算法實(shí)驗(yàn)
加載PCA算法包,并加載PCA算法設(shè)置降維后的主成分?jǐn)?shù)目為2。
from sklearn.decomposition import PCApca=PCA(n_components=2) reduced_x=pca.fit_transform(x)樣本的數(shù)據(jù)結(jié)構(gòu)如下圖所示:
數(shù)據(jù)集包含150個(gè)數(shù)據(jù)集,分為三類,每類50個(gè)數(shù)據(jù),每個(gè)數(shù)據(jù)包含4個(gè)特征。可以通過花萼長(zhǎng)度,花萼寬度,花瓣長(zhǎng)度,花瓣寬度4個(gè)特征預(yù)測(cè)鳶尾花卉屬于(Setosa,Versicolour,Virginica)三個(gè)種類中的哪一類。
數(shù)據(jù)的結(jié)構(gòu)化表示為:
import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D from sklearn import datasets from sklearn.decomposition import PCA import pandas as pd import seaborndata = datasets.load_iris() X =data['data'] y =data['target'] a = pd.DataFrame(X, columns=data.feature_names)#seaborn.boxplot(data= a) plt.plot(a) plt.legend(data.feature_names) plt.show()首先選取三個(gè)特征查看數(shù)據(jù)的分布情況:
import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D from sklearn import datasetsdata = datasets.load_iris() X =data['data'] y =data['target'] ax = Axes3D(plt.figure()) for c, i, target_name in zip('rgb', [0, 1, 2], data.target_names):ax.scatter(X[y==i, 0], X[y==i, 2], c=c, label=target_name)ax.set_xlabel(data.feature_names[0]) ax.set_xlabel(data.feature_names[1]) ax.set_xlabel(data.feature_names[2]) ax.set_title('Iris') plt.legend() plt.show()可以發(fā)現(xiàn)紅色數(shù)據(jù)點(diǎn),也就是Setosa距離其他數(shù)據(jù)較遠(yuǎn)。
然后選擇兩個(gè)特征子集查看數(shù)據(jù)分布情況。
import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D from sklearn import datasetsdata = datasets.load_iris() X =data['data'] y =data['target'] ax = Axes3D(plt.figure()) for c, i, target_name in zip('rgb', [0, 1, 2], data.target_names):ax.scatter(X[y==i, 0], X[y==i, 1], c=c, label=target_name)ax.set_xlabel(data.feature_names[0]) ax.set_xlabel(data.feature_names[1]) ax.set_title('Iris') plt.legend() plt.show()可以發(fā)現(xiàn)紅色的Setosa仍然是線性可分的。
利用PCA將數(shù)據(jù)降到二維:
import matplotlib.pyplot as plt from sklearn.decomposition import PCA from sklearn.datasets import load_irisdata=load_iris() y=data.target x=data.data pca=PCA(n_components=2) reduced_x=pca.fit_transform(x)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])plt.scatter(red_x,red_y,c='r',marker='x') plt.scatter(blue_x,blue_y,c='b',marker='D') plt.scatter(green_x,green_y,c='g',marker='.') plt.show()最終得到的主成分降維效果如下圖所示:
可以看到用sklearn庫(kù)實(shí)現(xiàn)降維后,將原本的四維數(shù)據(jù)變成二維,以實(shí)現(xiàn)在平面中畫出樣本點(diǎn)的分布。
3 SVD降維
奇異值分解(SVD):設(shè)X為n*N階矩陣,且rank(X)=r,則n階正交矩陣V和N階正交矩陣U,使得:
其中,
根據(jù)正交矩陣的性質(zhì),有:
若令M為:
則可以推導(dǎo)出:
那么,λi(i=1,2,···,r)就是XX^ T的特征值,其對(duì)應(yīng)的特征向量組成正交矩陣V。因此SVD奇異值分解等價(jià)于PCA主成分分析,核心都是求解XX^ T的特征值以及對(duì)應(yīng)的特征向量。
下面的實(shí)驗(yàn)利用SVD對(duì)給定的數(shù)據(jù)進(jìn)行降維處理。
用戶數(shù)據(jù)的SVD奇異值分解:
def _svd(self):self.U, self.S, self.VT = np.linalg.svd(self.data)return self.U, self.S, self.VT前k個(gè)奇異值的平方和占比要大于等于percentage,求出滿足此條件的最小的k值。
def _calc_k(self, percentge):self.k = 0total = sum(np.square(self.S))svss = 0 for i in range(np.shape(self.S)[0]):svss += np.square(self.S[i])if (svss/total) >= percentge:self.k = i+1breakreturn self.k構(gòu)建由奇異值組成的對(duì)角矩陣。
def _buildSD(self, k):self.SD = np.eye(self.k) * self.S[:self.k] e = np.eye(self.k)for i in range(self.k):e[i,i] = self.S[i] return self.SDSVD降維。
def DimReduce(self, percentage):self._svd()self._calc_k(percentage)print('\n按照奇異值開方和占比閾值percentage=%d, 求得降維的k=%d'%(percentage, self.k))self._buildSD(self.k)k,U,SD,VT = self.k,self.U, self.SD, self.VTa = U[:len(U), :k]b = np.dot(SD, VT[:k, :len(VT)])newData = np.dot(a,b)return newData訓(xùn)練數(shù)據(jù)集,用戶對(duì)商品的評(píng)分矩陣,行為多個(gè)用戶對(duì)單個(gè)商品的評(píng)分,列為用戶對(duì)每個(gè)商品的評(píng)分。
def CSVD_manual():data = np.array([[5, 5, 0, 5],[5, 0, 3, 4],[3, 4, 0, 3],[0, 0, 5, 3],[5, 4, 4, 5],[5, 4, 5, 5]])percentage = 0.9svdor = CSVD(data)ret = svdor.DimReduce(percentage)print('====================================================')print('原始用戶數(shù)據(jù)矩陣:\n', data)print('降維后的數(shù)據(jù)矩陣:\n', ret)print('====================================================')最后運(yùn)行得到的結(jié)果如下圖所示:
4 核主成分分析降維
PCA方法假設(shè)從高維空間到低維空間的函數(shù)映射是線性的,但是在很多現(xiàn)實(shí)任務(wù)中,可能需要非線性的映射才能找到合適的降維空間來降維。
非線性降維的一種常用方法是基于核技巧對(duì)線性降維方法進(jìn)行核化。
考慮一個(gè)線性不可分的數(shù)據(jù)集,如果我們用一個(gè)映射 ,將其映射到三維空間,比如可取:
可以看到,映射到高維空間后數(shù)據(jù)變得線性可分。這意味著,非線性映射使得我們能夠處理非線性的數(shù)據(jù)。
假設(shè)要將高維特征空間中的數(shù)據(jù)投影到低維空間中,投影矩陣W根據(jù)PCA求解的結(jié)果需要求解方程:
通常并不清楚Φ的解析表達(dá)式,于是引入核函數(shù):
定義核矩陣:
定義:
可以推導(dǎo)出:
最終通過矩陣的化簡(jiǎn)可以得到KA=λA。同樣該問題也是一個(gè)特征值分解問題,取K的最大的d個(gè)特征對(duì)應(yīng)的特征向量組成W即可。
對(duì)于新樣本x,其投影后的坐標(biāo)為:
可以看到,為了獲取投影后的坐標(biāo),KPCA需要對(duì)所有樣本求和,因此它的計(jì)算開銷更大。
下面實(shí)現(xiàn)對(duì)非線性映射的降維。
def rbf_kernel_pca(X,gama,n_components):sq_dists = pdist (X, 'sqeuclidean') mat_sq_dists=squareform(sq_dists) K=exp(-gama * mat_sq_dists) 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) eigvals,eigvecs = eigh(K)X_pc = np.column_stack((eigvecs[:,-i] for i in range(1,n_components+1))) return X_pc首先計(jì)算樣本對(duì)歐幾里得距離,并生成核矩陣k(x,y)=exp(-gama * ||x-y||^ 2),x和y表示樣本,構(gòu)建一個(gè)NXN的核矩陣,矩陣值是樣本間的歐氏距離值。然后,聚集核矩陣K’=K-LK-KL + LKL,其中L是一個(gè)nXn的矩陣(和核矩陣K的維數(shù)相同,所有的值都是1/n。
聚集核矩陣的必要性是:樣本經(jīng)過標(biāo)準(zhǔn)化處理后,當(dāng)在生成協(xié)方差矩陣并以非線性特征的組合替代點(diǎn)積時(shí),所有特征的均值為0;但用低維點(diǎn)積計(jì)算時(shí)并沒有精確計(jì)算新的高維特征空間,也無法確定新特征空間的中心在零點(diǎn)。
隨后對(duì)聚集后的核矩陣求取特征值和特征向量 ,選擇前k個(gè)特征值所對(duì)應(yīng)的特征向量,和PCA不同,KPCA得到的K個(gè)特征,不是主成分軸,而是高維映射到低維后的低維特征數(shù)量核化過程是低維映射到高維,PCA是降維,經(jīng)過核化后的維度已經(jīng)不是原來的特征空間。核化是低維映射到高維,但并不是在高維空間計(jì)算(非線性特征組合)而是在低維空間計(jì)算(點(diǎn)積),做到這點(diǎn)關(guān)鍵是核函數(shù),核函數(shù)通過兩個(gè)向量點(diǎn)積來度量向量間相似度,能在低維空間內(nèi)近似計(jì)算出高維空間的非線性特征空間。
X,y=make_moons(n_samples=100,random_state=123) plt.scatter(X[y==0,0],X[y==0,1],color='red',marker='^',alpha=0.5) plt.scatter(X[y==1,0],X[y==1,1],color='blue',marker='o',alpha=0.5) plt.show()分離半月形數(shù)據(jù),生成二維線性不可分?jǐn)?shù)據(jù)。
sk_pca = PCA(n_components=2) X_spca=sk_pca.fit_transform(X) fig,ax = plt.subplots(nrows=1,ncols=2,figsize=(7,3)) ax[0].scatter(X_spca[y==0,0],X_spca[y==0,1],color='red',marker='^',alpha=0.5) ax[0].scatter(X_spca[y==1,0],X_spca[y==1,1],color='blue',marker='o',alpha=0.5) ax[1].scatter(X_spca[y==0,0],np.zeros((50,1))+0.02,color='red',marker='^',alpha=0.5) ax[1].scatter(X_spca[y==1,0],np.zeros((50,1))-0.02,color='blue',marker='^',alpha=0.5) ax[0].set_xlabel('PC1') ax[0].set_ylabel('PC2') ax[1].set_ylim([-1,1]) ax[1].set_yticks([]) ax[1].set_xlabel('PC1') plt.show()
顯然,這兩個(gè)半月形不是線性可分的,而我們的目標(biāo)是通過核 PCA 將這兩個(gè)半月形數(shù)據(jù)展開,使得數(shù)據(jù)集成為適用于某一線性分類器的輸入數(shù)據(jù)。 PCA降維,映射到主成分,但仍不能很好地進(jìn)行線性分類。
利用基于RBF核的KPCA來實(shí)現(xiàn)線性可分。可以看到,兩個(gè)類別(圓形和三角形)此時(shí)是線性可分的,這使得轉(zhuǎn)換后的數(shù)據(jù)適合作為線性分類器的訓(xùn)練數(shù)據(jù)集。
X,y=make_circles(n_samples=1000,random_state=123,noise=0.1,factor=0.2) plt.scatter(X[y==0,0],X[y==0,1],color='red',marker='^',alpha=0.5) plt.scatter(X[y==1,0],X[y==1,1],color='blue',marker='o',alpha=0.5) plt.show()分離同心圓,生成同心圓數(shù)據(jù)。再進(jìn)行標(biāo)準(zhǔn)的PCA映射,最后得到KPCA的降維效果圖。
sk_pca = PCA(n_components=2) X_spca=sk_pca.fit_transform(X) fig,ax = plt.subplots(nrows=1,ncols=2,figsize=(7,3)) ax[0].scatter(X_spca[y==0,0],X_spca[y==0,1],color='red',marker='^',alpha=0.5) ax[0].scatter(X_spca[y==1,0],X_spca[y==1,1],color='blue',marker='o',alpha=0.5) ax[1].scatter(X_spca[y==0,0],np.zeros((500,1))+0.02,color='red',marker='^',alpha=0.5) ax[1].scatter(X_spca[y==1,0],np.zeros((500,1))-0.02,color='blue',marker='^',alpha=0.5) ax[0].set_xlabel('PC1') ax[0].set_ylabel('PC2') ax[1].set_ylim([-1,1]) ax[1].set_yticks([]) ax[1].set_xlabel('PC1') plt.show()X_kpca=rbf_kernel_pca(X, gama=15, n_components=2) fig,ax = plt.subplots(nrows=1,ncols=2,figsize=(7,3)) ax[0].scatter(X_kpca[y==0,0],X_kpca[y==0,1],color='red',marker='^',alpha=0.5) ax[0].scatter(X_kpca[y==1,0],X_kpca[y==1,1],color='blue',marker='o',alpha=0.5) ax[1].scatter(X_kpca[y==0,0],np.zeros((500,1))+0.02,color='red',marker='^',alpha=0.5) ax[1].scatter(X_kpca[y==1,0],np.zeros((500,1))-0.02,color='blue',marker='^',alpha=0.5) ax[0].set_xlabel('PC1') ax[0].set_ylabel('PC2') ax[1].set_ylim([-1,1]) ax[1].set_yticks([]) ax[1].set_xlabel('PC1') ax[0].xaxis.set_major_formatter(FormatStrFormatter('%0.1f')) ax[1].xaxis.set_major_formatter(FormatStrFormatter('%0.1f')) plt.show()
通過實(shí)驗(yàn)可以發(fā)現(xiàn),仔細(xì)觀察PCA其實(shí)只對(duì)原始數(shù)據(jù)進(jìn)行了旋轉(zhuǎn)操作,這是由于其尋找的是數(shù)據(jù)的“主要分布方向”。從圖中看出,在重構(gòu)后的數(shù)據(jù)清晰的分為兩類,且在主成分方向上分割明顯,便于使用線性分類方法進(jìn)行處理。KPCA可以將原始數(shù)據(jù)投影至線性可分情況,打破了數(shù)據(jù)的原有結(jié)構(gòu)。但是KPCA不能將數(shù)據(jù)投影至完全線性可分的程度,這說明KPCA只是個(gè)無監(jiān)督的降維算法,它不管樣本的類別屬性,只是降維而已。
總結(jié)
主成分分析是一種降維方法。在PCA中,數(shù)據(jù)從原來的坐標(biāo)系轉(zhuǎn)換到了新的坐標(biāo)系,新坐標(biāo)系由數(shù)據(jù)本身決定。在新坐標(biāo)系中,第一個(gè)坐標(biāo)軸選擇的是原始數(shù)據(jù)中方差最大的方向,第二個(gè)坐標(biāo)軸選擇的是和第一個(gè)坐標(biāo)軸正交且具有最大方差的方向。該過程一直重復(fù),重復(fù)次數(shù)為原始數(shù)據(jù)中特征的數(shù)目。我們會(huì)發(fā)現(xiàn),大部分方差都包含在最前面的幾個(gè)新坐標(biāo)軸中。因此,我們可以忽略余下的坐標(biāo)軸,即對(duì)數(shù)據(jù)進(jìn)行了降維處理。其優(yōu)點(diǎn)是降低數(shù)據(jù)的復(fù)雜性,識(shí)別最重要的特征,但其缺點(diǎn)在于不一定需要,且可能損失有用信息。
奇異值分解,是一種矩陣因式分解。通過計(jì)算奇異值個(gè)數(shù)和奇異向量,生成一個(gè)可以代替原矩陣的近似矩陣,將數(shù)據(jù)集的奇異值表征按重要性排列,舍棄不重要的特征向量。可用來達(dá)到降維的目的,從而找出數(shù)據(jù)中的主成分。其優(yōu)點(diǎn)在于并行化,缺點(diǎn)是計(jì)算量大,分解后的矩陣解釋性較弱。我們說到PCA降維時(shí),需要找到樣本協(xié)方差矩陣X^ TX最大的d個(gè)特征向量,然后用著最大的d個(gè)特征向量組成的矩陣來做低維投影降維。可以看出,在這個(gè)過程中需要先求出協(xié)方差矩陣X^ TX,當(dāng)樣本數(shù)多、樣本特征數(shù)也多的時(shí)候,比如10000*10000的矩陣,這個(gè)計(jì)算量是很大的。注意到SVD也可以求出協(xié)方差矩陣X^ TX最大的d個(gè)特征向量組成的矩陣,但是SVD有個(gè)好處,就是可以不求出協(xié)方差矩陣X^TX,也能通過某些算法求出右奇異矩陣V。也就是說,PCA算法可以不用做特征分解,而是用SVD來進(jìn)行完成。
核主成分分析降維,為了更好地處理非線性數(shù)據(jù),引入非線性映射函數(shù),將原空間中的數(shù)據(jù)映射到高維空間,注意,這個(gè)是隱性的,利用核函數(shù)進(jìn)行處理,無需知道映射函數(shù)的具體形式,它讓降維變得更有意義
總結(jié)
以上是生活随笔為你收集整理的机器学习——数据降维的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 机器学习——聚类算法
- 下一篇: (FCN)-Fully Convolut