特征缩放的重要性¶
对于许多机器学习算法而言,通过标准化(或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 = (10, 7)
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(0, 3), ('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(0, 3), ('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秒)