python standardscaler_教你用python一步步解决“维度灾难”
現代科技時代產生和收集的數據越來越多。然而在機器學習中,太多的數據可不是件好事。某種意義上來說,特征或維度越多,越會降低模型的準確性,因為需要對更多的數據進行泛化——這就是所謂的“維度災難”。
降維是一種降低模型復雜性和避免過度擬合的方法。特征選擇和特征抽取是兩種主要的降維方式。特征選擇是從原有特征集中選出一部分子集,而特征抽取是從原有特征集收集一部分信息來構建新的特征子空間。
本文將會帶你學習特征抽取。在實際應用中,特征抽取不僅可以擴大儲存空間,提高學習算法的計算效率,通過避免維度災難,還可以提升預測性能——尤其是在使用非正則化的模型時。
具體來說,我們將會討論使用主成分分析算法(PCA)將數據集壓縮至一個更低維的特征子空間,同時保留大部分相關信息。我們將會學到:
· PCA的概念及背后的數學知識
· 如何使用Python一步一步執行PCA
· 如何使用Python庫來執行PCAscikit-learn機器學習
現在開始吧!
本教程改編自Next Tec的Python機器學習系列的第二部分,該系列會帶領小白成功學會用Python進行機器學習和深度學習算法。本教程包含瀏覽器嵌入式沙箱環境,預先安裝好了所有必要的軟件和庫,還有使用公共數據集的一些項目。
1. 主成分分析法導論
主成分分析法是一種非監督式的線性變換方法,被廣泛應用于諸多領域,主要是用于特征抽取和降維。其他熱門應用還有探索性數據分析、排除股票交易市場嘈雜信號、以及生物信息學中對基因組數據和基因表達水平的分析。
PCA基于特征之間的聯系識別出數據中的模型。簡言之,PCA旨在找出高維數據中最大方差的方向,并將其投影到一個新的維數相同或更低的的子空間中。
在新特征軸互相正交的條件下,新子空間的正交軸(主成分)可以視為為最大方差方向,如下圖所示:
在上圖中,x1和x2是原始特征軸,PC1和PC2是主成分。
如果使用PCA進行降維,構造一個d×k維變換矩陣W,可以將一個樣本中的向量x映射到新的k維特征子空間(k比d小)。
由于將原先d維的數據映射到新的k維子空間(通常k遠小于d),第一個主成分會有最大的可能方差,并且如果其他的主成分都互不相關的話,他們也會有最大方差——即使輸入特征互相關聯,產生的主成分也會相互正交(不相關)。
注意:數據縮放對PCA方向有很大的影響,如果特征是在不同的規模下測量的,同時又想賦予這些特征相同的重要性,需要在PCA之前對這些特征進行標準化。
在詳細學習用于降維的PCA算法之前,用簡單的幾步將其概括一下:
1. 對d維數據集進行標準化。
2. 構建協方差矩陣。
3. 將協方差矩陣分解為特征向量和特征值。
4. 對特征值進行降序排序,對相應的向量進行排序。
5. 選取與k個最大特征值對應的k個特征向量,其中k為新特征子空間的維數(k ≤ d)。
6. 根據那k個特征向量構建投影矩陣W。
7. 通過投影矩陣W將d維輸入數據集X變換為新的k維數據子空間。
現在使用Python來一步步執行PCA作為練習。然后,看看如何使用scikit-learn機器學習來更好地執行PCA。
2. 逐步抽取主成分
我們將使用UCI機器學習存儲庫中的Wine數據集作為示例。該數據集包含178個葡萄酒樣品,用了13個特征描述它們的化學性質。
本節將學習PCA四步曲的第一步,然后再學習剩下的三步。可以使用Next Tech沙箱來學習本教程中的代碼,它預先安裝了所有必要的庫,或者也可以在本地環境中運行代碼片段。
一旦沙箱加載完畢,我們將從直接從存儲庫加載Wine數據集開始。
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()接下來,用70:30的分割將Wine數據處理為單獨的訓練和測試集,并將其標準化為單位方差。
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)完成必要的預處理后,現在進入第二步:構建協方差矩陣。對稱的d×d維協方差矩陣(d是數據集的維度),包含了不同特征間的成對協方差。例如,特征x_j和x_j在總體水平上的協方差可由下式計算:
這里μ_j和μ_k分別是特征j和特征k的樣本均值。
注意:如果對數據集進行了標準化,樣本均值則為0。如果兩個特征間是正值協方差,意味著二者同增減;若是負值協方差,意味著二者變化方向相反。例如,三個特征的協方差矩陣可以寫成(注意:Σ表示希臘大寫字母sigma,而不是表示和):
協方差矩陣的特征向量表示主分量(最大方差方向),對應的特征值定義其大小。從Wine數據集13×13維協方差矩陣中,可以得到13個特征向量和特征值。
第三步,從協方差矩陣中獲取特征值。特征向量v滿足以下條件:
λ是一個標量:特征值。由于手動計算特征向量和特征值有些復雜繁瑣,我們將使用NumPy的linalg.eig函數得到Wine協方差矩陣的特征對。
import numpy as np cov_mat = np.cov(X_train_std.T)eigen_vals, eigen_vecs = np.linalg.eig(cov_mat)使用numpy.cov函數計算標準化數據集的協方差矩陣。使用linalg.eig函數進行特征分解,得到一個包含13個特征值及對應的特征向量的向量(特征值),它們都作為列存儲在一個13×13維的矩陣(特征向量)中。
3. 總方差和可釋方差
由于想通過壓縮數據集得到一個新的特征子空間來降低數據集的維數,我們只選擇包含大部分信息(方差)的特征向量(主成分)的子集。
在收集這k個具有最大信息量的特征向量之前,先計算特征值的特征方差貢獻率。特征值λ_j的特征方差貢獻率就是特征值λ_j與特征值的總和之比。
使用NumPy cumsum函數計算出方差貢獻的總和,接下將用matplotlib’s step函數來描述:
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()結果表明,第一個主成分約占方差的40%。此外,我們可以看到前兩個主成分合起來占了數據集中近60%的方差。
4. 特征變換
在成功地將協方差矩陣分解為特征對之后,現在繼續PCA的最后三個步驟,將Wine數據集變換到新的主成分軸上。
先通過按特征值的遞減排序對特征對進行分類:
# 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)接下來,收集兩個最大特征值對應的兩個特征向量,來得到這個數據集中大約60%的方差。注意,為了便于說明,我們只選擇了兩個特征向量,因為我們將在本小節后面通過二維散點圖來繪制數據。在實際應用中,主成分的數量由計算效率和分類器性能共同確定:
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]]通過執行前面的代碼,根據上面的兩個特征向量創建了一個13x2維的投影矩陣W。
利用投影矩陣,可以將一個樣本x(一個1 x 13維的行向量)轉換到PCA子空間(主成分1和主成分2)中,得到一個包含兩個新特征的二維樣本向量x′:
X_train_std[0].dot(w)同樣,可以通過計算矩陣點積將124 x 13維訓練數據集變換成兩個主成分:
X_train_pca = X_train_std.dot(w)最后,將轉換后的Wine訓練集在一個二維散點圖中進行可視化,存儲為一個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()從圖中可以看出,數據沿著x軸上(第一個主分量)分布的更多,這與之前創建的特征方差貢獻率圖形是一致的。然而,我們可以直觀地看到,線性分類器應該可以很好地進行分類。
盡管在之前的散點圖中為了解釋說明,編碼了類標簽,但是記住,PCA是一種不使用類標簽信息的無監督技術。
5. PCA與scikit-learn機器學習
前一小節幫助我們了解了PCA的內部工作原理,現在將討論如何使用在scikit-learn中實現的PCA 類模型。PCA class模型是scikit-learn的另一個轉換器類,在使用相同的模型參數轉換訓練數據和測試數據集之前,我們首先使用訓練數據來擬合模型。
在Wine訓練數據集上使用PCA類模型,通過邏輯回歸對變換后的樣本進行分類:
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)現在用一個常規的plot_decision_regions函數對決策區域進行可視化:
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()執行完前面的代碼,現在應該看到訓練數據的決策區域減少到兩個主成分軸。
為了完整性,在轉換后的測試數據集中繪制邏輯回歸的決策區域,看看它是否能夠很好地分類:
# 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()通過執行前面的代碼為測試集繪制決策區域之后,我們可以看到邏輯回歸在這個二維特征子空間中表現得非常好,并且在對測試數據集進行分類時只犯了很少的錯誤。
如果對特征方差貢獻率感興趣的話,可以簡單地用n_components參數集對PCA 類進行初始化,所以所有主要成分的保存和特征方差貢獻率的計算都可以通過explained_variance_ratio屬性來實現:
pca = PCA(n_components=None)X_train_pca = pca.fit_transform(X_train_std)pca.explained_variance_ratio_注意:當對PCA類進行初始化時,即設置n_components=None,它將以分類的順序返回所有的主成分,而不是執行降維操作。
留言 點贊 關注
我們一起分享AI學習與發展的干貨
歡迎關注全平臺AI垂類自媒體 “讀芯術”
總結
以上是生活随笔為你收集整理的python standardscaler_教你用python一步步解决“维度灾难”的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python变量类型怎么决定的_Pyth
- 下一篇: 爱奇艺学生卡半价vip怎么购买?