python standardscaler_教你用python一步步解决“维度灾难”
現(xiàn)代科技時(shí)代產(chǎn)生和收集的數(shù)據(jù)越來(lái)越多。然而在機(jī)器學(xué)習(xí)中,太多的數(shù)據(jù)可不是件好事。某種意義上來(lái)說(shuō),特征或維度越多,越會(huì)降低模型的準(zhǔn)確性,因?yàn)樾枰獙?duì)更多的數(shù)據(jù)進(jìn)行泛化——這就是所謂的“維度災(zāi)難”。
降維是一種降低模型復(fù)雜性和避免過(guò)度擬合的方法。特征選擇和特征抽取是兩種主要的降維方式。特征選擇是從原有特征集中選出一部分子集,而特征抽取是從原有特征集收集一部分信息來(lái)構(gòu)建新的特征子空間。
本文將會(huì)帶你學(xué)習(xí)特征抽取。在實(shí)際應(yīng)用中,特征抽取不僅可以擴(kuò)大儲(chǔ)存空間,提高學(xué)習(xí)算法的計(jì)算效率,通過(guò)避免維度災(zāi)難,還可以提升預(yù)測(cè)性能——尤其是在使用非正則化的模型時(shí)。
具體來(lái)說(shuō),我們將會(huì)討論使用主成分分析算法(PCA)將數(shù)據(jù)集壓縮至一個(gè)更低維的特征子空間,同時(shí)保留大部分相關(guān)信息。我們將會(huì)學(xué)到:
· PCA的概念及背后的數(shù)學(xué)知識(shí)
· 如何使用Python一步一步執(zhí)行PCA
· 如何使用Python庫(kù)來(lái)執(zhí)行PCAscikit-learn機(jī)器學(xué)習(xí)
現(xiàn)在開(kāi)始吧!
本教程改編自Next Tec的Python機(jī)器學(xué)習(xí)系列的第二部分,該系列會(huì)帶領(lǐng)小白成功學(xué)會(huì)用Python進(jìn)行機(jī)器學(xué)習(xí)和深度學(xué)習(xí)算法。本教程包含瀏覽器嵌入式沙箱環(huán)境,預(yù)先安裝好了所有必要的軟件和庫(kù),還有使用公共數(shù)據(jù)集的一些項(xiàng)目。
1. 主成分分析法導(dǎo)論
主成分分析法是一種非監(jiān)督式的線性變換方法,被廣泛應(yīng)用于諸多領(lǐng)域,主要是用于特征抽取和降維。其他熱門(mén)應(yīng)用還有探索性數(shù)據(jù)分析、排除股票交易市場(chǎng)嘈雜信號(hào)、以及生物信息學(xué)中對(duì)基因組數(shù)據(jù)和基因表達(dá)水平的分析。
PCA基于特征之間的聯(lián)系識(shí)別出數(shù)據(jù)中的模型。簡(jiǎn)言之,PCA旨在找出高維數(shù)據(jù)中最大方差的方向,并將其投影到一個(gè)新的維數(shù)相同或更低的的子空間中。
在新特征軸互相正交的條件下,新子空間的正交軸(主成分)可以視為為最大方差方向,如下圖所示:
在上圖中,x1和x2是原始特征軸,PC1和PC2是主成分。
如果使用PCA進(jìn)行降維,構(gòu)造一個(gè)d×k維變換矩陣W,可以將一個(gè)樣本中的向量x映射到新的k維特征子空間(k比d小)。
由于將原先d維的數(shù)據(jù)映射到新的k維子空間(通常k遠(yuǎn)小于d),第一個(gè)主成分會(huì)有最大的可能方差,并且如果其他的主成分都互不相關(guān)的話,他們也會(huì)有最大方差——即使輸入特征互相關(guān)聯(lián),產(chǎn)生的主成分也會(huì)相互正交(不相關(guān))。
注意:數(shù)據(jù)縮放對(duì)PCA方向有很大的影響,如果特征是在不同的規(guī)模下測(cè)量的,同時(shí)又想賦予這些特征相同的重要性,需要在PCA之前對(duì)這些特征進(jìn)行標(biāo)準(zhǔn)化。
在詳細(xì)學(xué)習(xí)用于降維的PCA算法之前,用簡(jiǎn)單的幾步將其概括一下:
1. 對(duì)d維數(shù)據(jù)集進(jìn)行標(biāo)準(zhǔn)化。
2. 構(gòu)建協(xié)方差矩陣。
3. 將協(xié)方差矩陣分解為特征向量和特征值。
4. 對(duì)特征值進(jìn)行降序排序,對(duì)相應(yīng)的向量進(jìn)行排序。
5. 選取與k個(gè)最大特征值對(duì)應(yīng)的k個(gè)特征向量,其中k為新特征子空間的維數(shù)(k ≤ d)。
6. 根據(jù)那k個(gè)特征向量構(gòu)建投影矩陣W。
7. 通過(guò)投影矩陣W將d維輸入數(shù)據(jù)集X變換為新的k維數(shù)據(jù)子空間。
現(xiàn)在使用Python來(lái)一步步執(zhí)行PCA作為練習(xí)。然后,看看如何使用scikit-learn機(jī)器學(xué)習(xí)來(lái)更好地執(zhí)行PCA。
2. 逐步抽取主成分
我們將使用UCI機(jī)器學(xué)習(xí)存儲(chǔ)庫(kù)中的Wine數(shù)據(jù)集作為示例。該數(shù)據(jù)集包含178個(gè)葡萄酒樣品,用了13個(gè)特征描述它們的化學(xué)性質(zhì)。
本節(jié)將學(xué)習(xí)PCA四步曲的第一步,然后再學(xué)習(xí)剩下的三步。可以使用Next Tech沙箱來(lái)學(xué)習(xí)本教程中的代碼,它預(yù)先安裝了所有必要的庫(kù),或者也可以在本地環(huán)境中運(yùn)行代碼片段。
一旦沙箱加載完畢,我們將從直接從存儲(chǔ)庫(kù)加載Wine數(shù)據(jù)集開(kāi)始。
import pandas as pd df_wine = pd.read_csv('https://archive.ics.uci.edu/ml/' 'machine-learning-databases/wine/wine.data', header=None)df_wine.head()接下來(lái),用70:30的分割將Wine數(shù)據(jù)處理為單獨(dú)的訓(xùn)練和測(cè)試集,并將其標(biāo)準(zhǔn)化為單位方差。
from sklearn.model_selection import train_test_splitfrom sklearn.preprocessing import StandardScaler # split into training and testing setsX, y = df_wine.iloc[:, 1:].values, df_wine.iloc[:, 0].valuesX_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.3, stratify=y, random_state=0)# standardize the featuressc = StandardScaler()X_train_std = sc.fit_transform(X_train)X_test_std = sc.transform(X_test)完成必要的預(yù)處理后,現(xiàn)在進(jìn)入第二步:構(gòu)建協(xié)方差矩陣。對(duì)稱(chēng)的d×d維協(xié)方差矩陣(d是數(shù)據(jù)集的維度),包含了不同特征間的成對(duì)協(xié)方差。例如,特征x_j和x_j在總體水平上的協(xié)方差可由下式計(jì)算:
這里μ_j和μ_k分別是特征j和特征k的樣本均值。
注意:如果對(duì)數(shù)據(jù)集進(jìn)行了標(biāo)準(zhǔn)化,樣本均值則為0。如果兩個(gè)特征間是正值協(xié)方差,意味著二者同增減;若是負(fù)值協(xié)方差,意味著二者變化方向相反。例如,三個(gè)特征的協(xié)方差矩陣可以寫(xiě)成(注意:Σ表示希臘大寫(xiě)字母sigma,而不是表示和):
協(xié)方差矩陣的特征向量表示主分量(最大方差方向),對(duì)應(yīng)的特征值定義其大小。從Wine數(shù)據(jù)集13×13維協(xié)方差矩陣中,可以得到13個(gè)特征向量和特征值。
第三步,從協(xié)方差矩陣中獲取特征值。特征向量v滿(mǎn)足以下條件:
λ是一個(gè)標(biāo)量:特征值。由于手動(dòng)計(jì)算特征向量和特征值有些復(fù)雜繁瑣,我們將使用NumPy的linalg.eig函數(shù)得到Wine協(xié)方差矩陣的特征對(duì)。
import numpy as np cov_mat = np.cov(X_train_std.T)eigen_vals, eigen_vecs = np.linalg.eig(cov_mat)使用numpy.cov函數(shù)計(jì)算標(biāo)準(zhǔn)化數(shù)據(jù)集的協(xié)方差矩陣。使用linalg.eig函數(shù)進(jìn)行特征分解,得到一個(gè)包含13個(gè)特征值及對(duì)應(yīng)的特征向量的向量(特征值),它們都作為列存儲(chǔ)在一個(gè)13×13維的矩陣(特征向量)中。
3. 總方差和可釋方差
由于想通過(guò)壓縮數(shù)據(jù)集得到一個(gè)新的特征子空間來(lái)降低數(shù)據(jù)集的維數(shù),我們只選擇包含大部分信息(方差)的特征向量(主成分)的子集。
在收集這k個(gè)具有最大信息量的特征向量之前,先計(jì)算特征值的特征方差貢獻(xiàn)率。特征值λ_j的特征方差貢獻(xiàn)率就是特征值λ_j與特征值的總和之比。
使用NumPy cumsum函數(shù)計(jì)算出方差貢獻(xiàn)的總和,接下將用matplotlib’s step函數(shù)來(lái)描述:
import matplotlib.pyplot as plt# calculate cumulative sum of explained variancestot = sum(eigen_vals)var_exp = [(i / tot) for i in sorted(eigen_vals, reverse=True)]cum_var_exp = np.cumsum(var_exp) # plot explained variancesplt.bar(range(1,14), var_exp, alpha=0.5, align='center', label='individual explained variance')plt.step(range(1,14), cum_var_exp, where='mid', label='cumulative explained variance')plt.ylabel('Explained variance ratio')plt.xlabel('Principal component index')plt.legend(loc='best')plt.show()結(jié)果表明,第一個(gè)主成分約占方差的40%。此外,我們可以看到前兩個(gè)主成分合起來(lái)占了數(shù)據(jù)集中近60%的方差。
4. 特征變換
在成功地將協(xié)方差矩陣分解為特征對(duì)之后,現(xiàn)在繼續(xù)PCA的最后三個(gè)步驟,將Wine數(shù)據(jù)集變換到新的主成分軸上。
先通過(guò)按特征值的遞減排序?qū)μ卣鲗?duì)進(jìn)行分類(lèi):
# Make a list of (eigenvalue, eigenvector) tupleseigen_pairs = [(np.abs(eigen_vals[i]), eigen_vecs[:, i]) for i in range(len(eigen_vals))] # Sort the (eigenvalue, eigenvector) tuples from high to loweigen_pairs.sort(key=lambda k: k[0], reverse=True)接下來(lái),收集兩個(gè)最大特征值對(duì)應(yīng)的兩個(gè)特征向量,來(lái)得到這個(gè)數(shù)據(jù)集中大約60%的方差。注意,為了便于說(shuō)明,我們只選擇了兩個(gè)特征向量,因?yàn)槲覀儗⒃诒拘」?jié)后面通過(guò)二維散點(diǎn)圖來(lái)繪制數(shù)據(jù)。在實(shí)際應(yīng)用中,主成分的數(shù)量由計(jì)算效率和分類(lèi)器性能共同確定:
w = np.hstack((eigen_pairs[0][1][:, np.newaxis], eigen_pairs[1][1][:, np.newaxis]))print('Matrix W:', w) [Out:]Matrix W: [[-0.13724218 0.50303478] [ 0.24724326 0.16487119] [-0.02545159 0.24456476] [ 0.20694508 -0.11352904] [-0.15436582 0.28974518] [-0.39376952 0.05080104] [-0.41735106 -0.02287338] [ 0.30572896 0.09048885] [-0.30668347 0.00835233] [ 0.07554066 0.54977581] [-0.32613263 -0.20716433] [-0.36861022 -0.24902536] [-0.29669651 0.38022942]]通過(guò)執(zhí)行前面的代碼,根據(jù)上面的兩個(gè)特征向量創(chuàng)建了一個(gè)13x2維的投影矩陣W。
利用投影矩陣,可以將一個(gè)樣本x(一個(gè)1 x 13維的行向量)轉(zhuǎn)換到PCA子空間(主成分1和主成分2)中,得到一個(gè)包含兩個(gè)新特征的二維樣本向量x′:
X_train_std[0].dot(w)同樣,可以通過(guò)計(jì)算矩陣點(diǎn)積將124 x 13維訓(xùn)練數(shù)據(jù)集變換成兩個(gè)主成分:
X_train_pca = X_train_std.dot(w)最后,將轉(zhuǎn)換后的Wine訓(xùn)練集在一個(gè)二維散點(diǎn)圖中進(jìn)行可視化,存儲(chǔ)為一個(gè)124 x 2維矩陣:
colors = ['r', 'b', 'g']markers = ['s', 'x', 'o']for l, c, m in zip(np.unique(y_train), colors, markers): plt.scatter(X_train_pca[y_train==l, 0], X_train_pca[y_train==l, 1], c=c, label=l, marker=m)plt.xlabel('PC 1')plt.ylabel('PC 2')plt.legend(loc='lower left')plt.show()從圖中可以看出,數(shù)據(jù)沿著x軸上(第一個(gè)主分量)分布的更多,這與之前創(chuàng)建的特征方差貢獻(xiàn)率圖形是一致的。然而,我們可以直觀地看到,線性分類(lèi)器應(yīng)該可以很好地進(jìn)行分類(lèi)。
盡管在之前的散點(diǎn)圖中為了解釋說(shuō)明,編碼了類(lèi)標(biāo)簽,但是記住,PCA是一種不使用類(lèi)標(biāo)簽信息的無(wú)監(jiān)督技術(shù)。
5. PCA與scikit-learn機(jī)器學(xué)習(xí)
前一小節(jié)幫助我們了解了PCA的內(nèi)部工作原理,現(xiàn)在將討論如何使用在scikit-learn中實(shí)現(xiàn)的PCA 類(lèi)模型。PCA class模型是scikit-learn的另一個(gè)轉(zhuǎn)換器類(lèi),在使用相同的模型參數(shù)轉(zhuǎn)換訓(xùn)練數(shù)據(jù)和測(cè)試數(shù)據(jù)集之前,我們首先使用訓(xùn)練數(shù)據(jù)來(lái)擬合模型。
在Wine訓(xùn)練數(shù)據(jù)集上使用PCA類(lèi)模型,通過(guò)邏輯回歸對(duì)變換后的樣本進(jìn)行分類(lèi):
from sklearn.linear_model import LogisticRegressionfrom sklearn.decomposition import PCA # intialize pca and logistic regression modelpca = PCA(n_components=2)lr = LogisticRegression(multi_class='auto', solver='liblinear') # fit and transform dataX_train_pca = pca.fit_transform(X_train_std)X_test_pca = pca.transform(X_test_std)lr.fit(X_train_pca, y_train)現(xiàn)在用一個(gè)常規(guī)的plot_decision_regions函數(shù)對(duì)決策區(qū)域進(jìn)行可視化:
from matplotlib.colors import ListedColormap def plot_decision_regions(X, y, classifier, resolution=0.02): # setup marker generator and color map markers = ('s', 'x', 'o', '^', 'v') colors = ('red', 'blue', 'lightgreen', 'gray', 'cyan') cmap = ListedColormap(colors[:len(np.unique(y))]) # plot the decision surface x1_min, x1_max = X[:, 0].min() - 1, X[:, 0].max() + 1 x2_min, x2_max = X[:, 1].min() - 1, X[:, 1].max() + 1 xx1, xx2 = np.meshgrid(np.arange(x1_min, x1_max, resolution), np.arange(x2_min, x2_max, resolution)) Z = classifier.predict(np.array([xx1.ravel(), xx2.ravel()]).T) Z = Z.reshape(xx1.shape) plt.contourf(xx1, xx2, Z, alpha=0.4, cmap=cmap) plt.xlim(xx1.min(), xx1.max()) plt.ylim(xx2.min(), xx2.max()) # plot class samples for idx, cl in enumerate(np.unique(y)): plt.scatter(x=X[y == cl, 0], y=X[y == cl, 1], alpha=0.6, c=[cmap(idx)], edgecolor='black', marker=markers[idx], label=cl)# plot decision regions for training setplot_decision_regions(X_train_pca, y_train, classifier=lr)plt.xlabel('PC 1')plt.ylabel('PC 2')plt.legend(loc='lower left')plt.show()執(zhí)行完前面的代碼,現(xiàn)在應(yīng)該看到訓(xùn)練數(shù)據(jù)的決策區(qū)域減少到兩個(gè)主成分軸。
為了完整性,在轉(zhuǎn)換后的測(cè)試數(shù)據(jù)集中繪制邏輯回歸的決策區(qū)域,看看它是否能夠很好地分類(lèi):
# plot decision regions for test setplot_decision_regions(X_test_pca, y_test, classifier=lr)plt.xlabel('PC1')plt.ylabel('PC2')plt.legend(loc='lower left')plt.show()通過(guò)執(zhí)行前面的代碼為測(cè)試集繪制決策區(qū)域之后,我們可以看到邏輯回歸在這個(gè)二維特征子空間中表現(xiàn)得非常好,并且在對(duì)測(cè)試數(shù)據(jù)集進(jìn)行分類(lèi)時(shí)只犯了很少的錯(cuò)誤。
如果對(duì)特征方差貢獻(xiàn)率感興趣的話,可以簡(jiǎn)單地用n_components參數(shù)集對(duì)PCA 類(lèi)進(jìn)行初始化,所以所有主要成分的保存和特征方差貢獻(xiàn)率的計(jì)算都可以通過(guò)explained_variance_ratio屬性來(lái)實(shí)現(xiàn):
pca = PCA(n_components=None)X_train_pca = pca.fit_transform(X_train_std)pca.explained_variance_ratio_注意:當(dāng)對(duì)PCA類(lèi)進(jìn)行初始化時(shí),即設(shè)置n_components=None,它將以分類(lèi)的順序返回所有的主成分,而不是執(zhí)行降維操作。
留言 點(diǎn)贊 關(guān)注
我們一起分享AI學(xué)習(xí)與發(fā)展的干貨
歡迎關(guān)注全平臺(tái)AI垂類(lèi)自媒體 “讀芯術(shù)”
總結(jié)
以上是生活随笔為你收集整理的python standardscaler_教你用python一步步解决“维度灾难”的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: python变量类型怎么决定的_Pyth
- 下一篇: 用python排序算法_Python -