特征縮放的重要性?

對于許多機器學習算法而言,通過標準化(或Z分數標準化)進行特征縮放可能是重要的預處理步驟。標準化涉及重新縮放特征,以使它們具有標準正態分布的屬性,平均值為零,標準差為1。

盡管許多算法(例如SVM,K近鄰算法和邏輯回歸)都需要對功能進行規范化,但直覺上我們可以將主成分分析(PCA)視為規范化非常重要的主要示例。在PCA中,我們對最大化方差的組件感興趣。如果一個組成部分(例如,人類身高)因其各自的尺度(米與公斤)而變化的幅度小于另一個組成部分(例如,體重),則PCA可能會確定最大方差的方向與“體重”軸更接近,如果這些特征不縮放。因為一米的高度變化比一公斤的重量變化重要得多,這顯然是不正確的。

為了說明這一點,執行PCA時將應用了StandardScaler的數據使用與未縮放的數據進行比較。結果可視化并記錄明顯的差異。可以看到未縮放集合中的第一個主成分。可以看出,特征13主導了方向,比其他特征高兩個數量級。當觀察數據的縮放版本的主成分時,這形成對比。在縮放版本中,所有功能的數量級大致相同。

使用的數據集是UCI上提供的Wine數據集。該數據集具有連續的特征,這些特征由于它們測量的不同屬性(即,酒精含量和蘋果酸)而在規模上不統一。

然后將轉換后的數據用于訓練樸素的貝葉斯分類器,并觀察到預測準確性方面的明顯差異,其中在PCA之前縮放的數據集大大優于未縮放的版本。

from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA
from sklearn.naive_bayes import GaussianNB
from sklearn import metrics
import matplotlib.pyplot as plt
from sklearn.datasets import load_wine
from sklearn.pipeline import make_pipeline
print(__doc__)

# 源代碼: Tyler Lanigan <tylerlanigan@gmail.com>
#        Sebastian Raschka <mail@sebastianraschka.com>

# 執照: BSD 3 clause

RANDOM_STATE = 42
FIG_SIZE = (107)


features, target = load_wine(return_X_y=True)

# 使用30%的測試大小進行訓練/測試拆分
X_train, X_test, y_train, y_test = train_test_split(features, target,
                                                    test_size=0.30,
                                                    random_state=RANDOM_STATE)

# 使用管道式GNB和PCA擬合數據并進行預測
unscaled_clf = make_pipeline(PCA(n_components=2), GaussianNB())
unscaled_clf.fit(X_train, y_train)
pred_test = unscaled_clf.predict(X_test)

# 使用管道縮放,GNB和PCA擬合數據并進行預測。
std_clf = make_pipeline(StandardScaler(), PCA(n_components=2), GaussianNB())
std_clf.fit(X_train, y_train)
pred_test_std = std_clf.predict(X_test)

# 在縮放和非縮放數據中顯示預測精度
print('\nPrediction accuracy for the normal test dataset with PCA')
print('{:.2%}\n'.format(metrics.accuracy_score(y_test, pred_test)))

print('\nPrediction accuracy for the standardized test dataset with PCA')
print('{:.2%}\n'.format(metrics.accuracy_score(y_test, pred_test_std)))

# 從管道中提取PCA
pca = unscaled_clf.named_steps['pca']
pca_std = std_clf.named_steps['pca']

# 展示第一主成分
print('\nPC 1 without scaling:\n', pca.components_[0])
print('\nPC 1 with scaling:\n', pca_std.components_[0])

# 可視化使用了縮放和未使用縮放時的PCA
X_train_transformed = pca.transform(X_train)
scaler = std_clf.named_steps['standardscaler']
X_train_std_transformed = pca_std.transform(scaler.transform(X_train))

# 使用PCA可視化標準化和未修改的數據集
fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=FIG_SIZE)


for l, c, m in zip(range(03), ('blue''red''green'), ('^''s''o')):
    ax1.scatter(X_train_transformed[y_train == l, 0],
                X_train_transformed[y_train == l, 1],
                color=c,
                label='class %s' % l,
                alpha=0.5,
                marker=m
                )

for l, c, m in zip(range(03), ('blue''red''green'), ('^''s''o')):
    ax2.scatter(X_train_std_transformed[y_train == l, 0],
                X_train_std_transformed[y_train == l, 1],
                color=c,
                label='class %s' % l,
                alpha=0.5,
                marker=m
                )

ax1.set_title('Training dataset after PCA')
ax2.set_title('Standardized training dataset after PCA')

for ax in (ax1, ax2):
    ax.set_xlabel('1st principal component')
    ax.set_ylabel('2nd principal component')
    ax.legend(loc='upper right')
    ax.grid()

plt.tight_layout()

plt.show()

輸出:

Prediction accuracy for the normal test dataset with PCA
81.48%


Prediction accuracy for the standardized test dataset with PCA
98.15%


PC 1 without scaling:
 [ 1.76e-03 -8.36e-04  1.55e-04 -5.31e-03  2.02e-02  1.02e-03  1.53e-03
 -1.12e-04  6.31e-04  2.33e-03  1.54e-04  7.43e-04  1.00e+00]

PC 1 with scaling:
 [ 0.13 -0.26 -0.01 -0.23  0.16  0.39  0.42 -0.28  0.33 -0.11  0.3   0.38
  0.28]

腳本的總運行時間:(0分鐘 0.231秒)