数据集的标准化是scikit-learn中实现许多机器学习估计器的普遍要求;如果个别特征看起来或多或少不像标准正态分布数据:均值和单位方差为零的高斯分布,则它们的性能可能不好。
在实践中,我们通常会忽略分布的形状,而只是通过删除每个特征的平均值来实现特征数据中心化,然后除以非常数特征的标准差来缩放数据。
例如,学习算法的目标函数中使用的许多元素(例如支持向量机的RBF内核或线性模型的l1和l2正则化器)都假定所有特征都围绕零为中心并且具有相同阶数的方差。如果某个特征的方差比其他特征大几个数量级,则它可能会极大影响目标函数,并使估计器无法按预期从其他特征中正确学习。
sklearn 数据预处理中的数据标准化
核心思想
数据标准化(Standardization)是将特征数据转换为均值为 0、标准差为 1 的分布(即标准正态分布)。其数学公式为:z=(x−μ)/σz = (x - μ) / σz=(x−μ)/σ
其中:
x
是原始特征值μ
是该特征的均值σ
是该特征的标准差z
是标准化后的值
标准化适用于特征尺度差异较大或算法假设数据服从正态分布的情况(如 SVM、逻辑回归、PCA、神经网络等)。
常用函数与类
1. sklearn.preprocessing.StandardScaler
这是最常用的标准化工具类。
参数说明:
参数名 | 类型 | 默认值 | 说明 |
---|---|---|---|
copy | bool | True | 是否复制数据。若为 False ,则尝试在原数据上进行变换(不保证一定原地修改)。 |
with_mean | bool | True | 是否中心化(减去均值)。若为 False ,则不减均值。对稀疏矩阵必须设为 False 。 |
with_std | bool | True | 是否缩放(除以标准差)。若为 False ,则仅中心化。 |
属性(拟合后可用):
属性名 | 说明 |
---|---|
mean_ | 每个特征的均值(形状为 (n_features,) ) |
scale_ | 每个特征的标准差(形状为 (n_features,) ) |
var_ | 每个特征的方差(形状为 (n_features,) ) |
n_samples_seen_ | 拟合时看到的样本数 |
方法:
.fit(X[, y])
:计算均值和标准差。.transform(X)
:使用拟合的参数对数据进行标准化。.fit_transform(X[, y])
:先拟合再转换。.inverse_transform(X)
:将标准化后的数据还原为原始尺度。.get_feature_names_out(input_features=None)
:获取输出特征名(适用于管道)。
返回值:
.fit()
:返回self
(用于链式调用).transform(X)
:返回numpy.ndarray
或scipy.sparse matrix
,形状与输入相同,类型为float64
简单示例代码
from sklearn.preprocessing import StandardScaler
import numpy as np# 创建示例数据
X = np.array([[1, 2],[3, 4],[5, 6],[7, 8]], dtype=float)print("原始数据:")
print(X)# 初始化标准化器
scaler = StandardScaler()# 拟合并转换数据
X_scaled = scaler.fit_transform(X)print("\n标准化后数据:")
print(X_scaled)print("\n各特征均值:", scaler.mean_)
print("各特征标准差:", scaler.scale_)# 逆变换还原数据
X_original = scaler.inverse_transform(X_scaled)
print("\n逆变换还原数据:")
print(X_original)
输出示例:
原始数据:
[[1. 2.][3. 4.][5. 6.][7. 8.]]标准化后数据:
[[-1.34164079 -1.34164079][-0.4472136 -0.4472136 ][ 0.4472136 0.4472136 ][ 1.34164079 1.34164079]]各特征均值: [4. 5.]
各特征标准差: [2.23606798 2.23606798]逆变换还原数据:
[[1. 2.][3. 4.][5. 6.][7. 8.]]
管道中使用示例:
from sklearn.pipeline import Pipeline
from sklearn.svm import SVC
from sklearn.model_selection import train_test_split
from sklearn.datasets import make_classification# 生成示例数据
X, y = make_classification(n_samples=100, n_features=4, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)# 构建管道:先标准化,再分类
pipeline = Pipeline([('scaler', StandardScaler()),('classifier', SVC())
])pipeline.fit(X_train, y_train)
score = pipeline.score(X_test, y_test)
print(f"测试集准确率:{score:.4f}")
sklearn 数据预处理中的均值去除(Mean Removal / Centering)
核心思想
均值去除(Mean Removal),也称为数据中心化(Centering),是指对每个特征维度减去其样本均值,使得处理后的数据在该维度上的均值为 0。
数学公式:xcentered=x−mean(x)x_{centered} = x - mean(x)xcentered=x−mean(x)
- 不改变数据的方差或分布形状
- 仅将数据“平移”至以 0 为中心
- 是数据标准化(Standardization)的第一步(标准化 = 均值去除 + 方差缩放)
✅ 适用场景:
- 某些算法要求输入数据均值为 0(如 PCA、SVM、神经网络)
- 避免特征因均值偏移导致模型学习偏差
- 作为预处理步骤,常与缩放结合使用
常用函数与类
1. sklearn.preprocessing.StandardScaler
(最常用)
虽然名为“标准化器”,但通过设置 with_std=False
,可仅执行均值去除。
参数说明:
参数名 | 类型 | 默认值 | 说明 |
---|---|---|---|
copy | bool | True | 是否复制数据。若为 False ,尝试原地修改(不保证)。 |
with_mean | bool | True | 是否进行均值去除(中心化)。必须为 True 才能去均值。 |
with_std | bool | True | 是否进行标准差缩放。设为 False 时仅做中心化。 |
⚠️ 对稀疏矩阵(如
scipy.sparse
),with_mean=True
会报错,因为会导致稠密输出。
属性(拟合后可用):
属性名 | 说明 |
---|---|
mean_ | 每个特征的均值(形状 (n_features,) ) |
scale_ | 若 with_std=True ,为标准差;否则为 None |
n_samples_seen_ | 拟合时看到的样本数 |
方法:
.fit(X[, y])
:计算每个特征的均值。.transform(X)
:对数据执行中心化(减去均值)。.fit_transform(X[, y])
:先拟合再转换。.inverse_transform(X)
:还原数据(加上均值)。.get_feature_names_out(...)
:获取输出特征名(兼容管道)。
返回值:
.fit()
→ 返回self
.transform(X)
→ 返回numpy.ndarray
或scipy.sparse matrix
(若输入为稀疏且with_mean=False
),类型为float64
,形状同输入
简单示例代码
from sklearn.preprocessing import StandardScaler
import numpy as np# 创建示例数据
X = np.array([[1, 10],[2, 20],[3, 30],[4, 40]], dtype=float)print("原始数据:")
print(X)
print("原始均值:", np.mean(X, axis=0))# 初始化仅做均值去除的缩放器
scaler = StandardScaler(with_std=False) # 关闭标准差缩放# 拟合并转换
X_centered = scaler.fit_transform(X)print("\n中心化后数据:")
print(X_centered)
print("中心化后均值:", np.mean(X_centered, axis=0)) # 应为 [0., 0.]print("\n学习到的均值:", scaler.mean_)# 逆变换还原原始数据
X_original = scaler.inverse_transform(X_centered)
print("\n逆变换还原数据:")
print(X_original)
输出示例:
原始数据:
[[ 1. 10.][ 2. 20.][ 3. 30.][ 4. 40.]]
原始均值: [ 2.5 25. ]中心化后数据:
[[-1.5 -15. ][-0.5 -5. ][ 0.5 5. ][ 1.5 15. ]]
中心化后均值: [0. 0.]学习到的均值: [ 2.5 25. ]逆变换还原数据:
[[ 1. 10.][ 2. 20.][ 3. 30.][ 4. 40.]]
sklearn 数据预处理中的方差缩放(Scaling to Unit Variance)
核心思想
方差缩放(Variance Scaling) 是指将每个特征维度的数据除以其标准差(或等效统计量),使得缩放后的特征方差为 1(即单位方差)。
数学公式:xscaled=x/σx_{scaled} = x / σxscaled=x/σ
其中:
x
是原始特征值σ
是该特征的标准差(std(x)
)x_scaled
是方差缩放后的值
✅ 注意:方差缩放通常不单独使用,而是与均值去除(中心化) 结合构成完整的标准化(Standardization):
z = (x - μ) / σ
为什么需要方差缩放?
- 某些算法(如 SVM、KNN、PCA、神经网络)对特征尺度敏感
- 若某特征方差远大于其他特征,会主导目标函数或距离计算
- 保证所有特征在“相同量级”上,提升模型收敛速度和性能
常用函数与类
1. sklearn.preprocessing.StandardScaler
(最常用)
通过设置 with_mean=False
,可仅执行方差缩放(不中心化)。
参数说明:
参数名 | 类型 | 默认值 | 说明 |
---|---|---|---|
copy | bool | True | 是否复制数据。若为 False ,尝试原地修改(不保证)。 |
with_mean | bool | True | 是否中心化。设为 False 可仅做方差缩放。 |
with_std | bool | True | 是否进行方差缩放。必须为 True 才生效。 |
⚠️ 对稀疏矩阵,
with_mean=True
会导致报错(因为中心化会破坏稀疏性),但with_mean=False
是安全的。
属性(拟合后可用):
属性名 | 说明 |
---|---|
scale_ | 每个特征的标准差(形状 (n_features,) ) |
mean_ | 若 with_mean=True ,为均值;否则为 None |
var_ | 每个特征的方差(scale_ ** 2 ) |
n_samples_seen_ | 拟合时看到的样本数 |
方法:
.fit(X[, y])
:计算每个特征的标准差(和均值,若启用)。.transform(X)
:对数据执行缩放(和中心化,若启用)。.fit_transform(X[, y])
:先拟合再转换。.inverse_transform(X)
:还原数据(乘以标准差,加上均值)。.get_feature_names_out(...)
:获取输出特征名(兼容管道)。
返回值:
.fit()
→ 返回self
.transform(X)
→ 返回numpy.ndarray
或scipy.sparse matrix
(若输入稀疏且with_mean=False
),类型为float64
,形状同输入
简单示例代码
from sklearn.preprocessing import StandardScaler
import numpy as np# 创建示例数据(注意:不同列方差差异大)
X = np.array([[1, 100],[2, 200],[3, 300],[4, 400]], dtype=float)print("原始数据:")
print(X)
print("原始标准差:", np.std(X, axis=0))# 初始化仅做方差缩放的缩放器(不中心化)
scaler = StandardScaler(with_mean=False, with_std=True)# 拟合并转换
X_scaled = scaler.fit_transform(X)print("\n方差缩放后数据:")
print(X_scaled)
print("缩放后标准差:", np.std(X_scaled, axis=0)) # 应为 [1., 1.]print("\n学习到的标准差(scale_):", scaler.scale_)# 逆变换还原原始数据
X_original = scaler.inverse_transform(X_scaled)
print("\n逆变换还原数据:")
print(X_original)
输出示例:
原始数据:
[[ 1. 100.][ 2. 200.][ 3. 300.][ 4. 400.]]
原始标准差: [1.11803399 111.80339887]方差缩放后数据:
[[0.89442719 0.89442719][1.78885438 1.78885438][2.68328157 2.68328157][3.57770876 3.57770876]]
缩放后标准差: [1. 1.]学习到的标准差(scale_): [ 1.11803399 111.80339887]逆变换还原数据:
[[ 1. 100.][ 2. 200.][ 3. 300.][ 4. 400.]]
仅方差缩放 vs 完整标准化 对比示例
import numpy as np
from sklearn.preprocessing import StandardScalerX = np.array([[1, 100],[2, 200],[3, 300],[4, 400]], dtype=float)# 仅方差缩放
scaler_var_only = StandardScaler(with_mean=False)
X_var_scaled = scaler_var_only.fit_transform(X)# 完整标准化(去均值 + 方差缩放)
scaler_full = StandardScaler()
X_standardized = scaler_full.fit_transform(X)print("仅方差缩放:\n", X_var_scaled)
print("完整标准化:\n", X_standardized)
输出:
仅方差缩放:[[0.89442719 0.89442719][1.78885438 1.78885438][2.68328157 2.68328157][3.57770876 3.57770876]]完整标准化:[[-1.34164079 -1.34164079][-0.4472136 -0.4472136 ][ 0.4472136 0.4472136 ][ 1.34164079 1.34164079]]
在管道中使用示例:
from sklearn.pipeline import Pipeline
from sklearn.svm import SVC
from sklearn.model_selection import train_test_split
from sklearn.datasets import make_classification# 生成数据(故意制造方差差异)
np.random.seed(42)
X, y = make_classification(n_samples=100, n_features=4, random_state=42)
# 放大第二列方差
X[:, 1] *= 100X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)# 管道:仅方差缩放 + SVM
pipeline = Pipeline([('var_scaler', StandardScaler(with_mean=False)), # 仅缩放方差('svm', SVC())
])pipeline.fit(X_train, y_train)
score = pipeline.score(X_test, y_test)
print(f"测试集准确率(仅方差缩放):{score:.4f}")# 对比:完整标准化
pipeline_full = Pipeline([('scaler', StandardScaler()), # 完整标准化('svm', SVC())
])
pipeline_full.fit(X_train, y_train)
score_full = pipeline_full.score(X_test, y_test)
print(f"测试集准确率(完整标准化):{score_full:.4f}")
与其他缩放器对比
缩放器 | 是否去均值 | 是否单位方差 | 是否受异常值影响 | 适用场景 |
---|---|---|---|---|
StandardScaler(with_mean=False) | ❌ | ✅ | 是 | 仅需统一方差,保留原始均值 |
StandardScaler() (默认) | ✅ | ✅ | 是 | 最常用标准化 |
MinMaxScaler | ❌ (映射到[0,1]) | ❌ | 是 | 需固定范围,如图像像素 |
RobustScaler | ✅ (中位数) | ✅ (IQR) | 否 | 含异常值的数据 |
注意事项
重要提醒:
- 方差缩放应在训练集上拟合,然后应用于测试集/新数据。
- 若特征标准差为 0(常数特征),StandardScaler 会将其缩放为 0(可后续删除或填充)。
- 对稀疏数据,使用
with_mean=False
是安全的;若需中心化,考虑 RobustScaler 或手动处理。 - 单独使用方差缩放较少见,通常建议与均值去除结合使用(完整标准化)。
总结
方差缩放是确保所有特征具有相同“能量级别”的关键步骤。在 sklearn 中,通过 StandardScaler(with_mean=False) 可实现纯方差缩放。虽然实践中更常用完整标准化(with_mean=True),但在某些特定场景(如保留原始偏移量、处理稀疏数据)下,仅缩放方差仍具有实用价值。