《sklearn机器学习——数据预处理》归一化

发布于:2025-09-11 ⋅ 阅读:(22) ⋅ 点赞:(0)

sklearn 数据预处理中的归一化(Normalization)

📌 注意:在 sklearn 中,“归一化”(Normalization)通常指 样本归一化(Sample-wise Normalization),即对每一行(每个样本) 进行缩放,使其范数为 1。
而对特征列进行缩放到 [0,1] 或 [-1,1] 的操作,在 sklearn 中称为 缩放(Scaling),如 MinMaxScaler


核心思想

归一化(Normalization) 是指将每个样本(每行) 缩放,使其满足某种范数约束(通常是 L1 或 L2 范数为 1)。

数学公式(L2 归一化):xnormalized=x∣∣x∣∣2x_{normalized} = \frac{x}{||x||₂}xnormalized=∣∣x2x

其中 ||x||₂ = sqrt(x₁² + x₂² + ... + xₙ²) 是 L2 范数。

常见范数类型:

范数类型 公式 说明
'l2' sqrt(sum(x_i²)) 默认,欧几里得范数,最常用
'l1' `sum( x_i
'max' `max( x_i

适用场景

  • 文本分类、聚类中 TF-IDF 向量的归一化
  • 使用余弦相似度或点积的算法(如 SVM with cosine kernel)
  • 神经网络中样本输入需要单位长度时
  • 避免样本因“长度”不同导致模型偏向“长”样本

常用函数与类

1. sklearn.preprocessing.Normalizer

对每个样本(行)独立进行归一化。

参数说明:

参数名 类型 默认值 说明
norm str 'l2' 范数类型,可选 'l1', 'l2'
copy bool True 是否复制数据。若为 False,尝试原地修改(对 numpy 数组有效)

⚠️ Normalizer无状态转换器 —— 它不从数据中学习任何参数,因此 .fit() 是空操作,可直接 .transform()

方法:

  • .fit(X[, y]) → 返回 self(无实际拟合操作)
  • .transform(X) → 对每个样本进行归一化
  • .fit_transform(X[, y]) → 等价于 .transform(X)
  • .get_feature_names_out(...) → 返回特征名(兼容管道)

返回值:

  • .transform(X) → 返回 numpy.ndarrayscipy.sparse matrix(保持输入类型),形状同输入,数据类型为 float64

简单示例代码

from sklearn.preprocessing import Normalizer
import numpy as np

# 创建示例数据(每行是一个样本)
X = np.array([[3.0, 4.0],
              [1.0, 1.0],
              [0.0, 5.0]], dtype=float)

print("原始数据:")
print(X)
print("原始 L2 范数:", np.linalg.norm(X, axis=1))

# 初始化 L2 归一化器
normalizer_l2 = Normalizer(norm='l2')

# 转换数据(无需 fit,直接 transform)
X_normalized_l2 = normalizer_l2.transform(X)

print("\nL2 归一化后:")
print(X_normalized_l2)
print("L2 归一化后范数:", np.linalg.norm(X_normalized_l2, axis=1))  # 应全为 1.0

# 使用 L1 归一化
normalizer_l1 = Normalizer(norm='l1')
X_normalized_l1 = normalizer_l1.transform(X)

print("\nL1 归一化后:")
print(X_normalized_l1)
print("L1 归一化后 L1 范数:", np.abs(X_normalized_l1).sum(axis=1))  # 应全为 1.0

输出示例:

原始数据:
[[3. 4.]
 [1. 1.]
 [0. 5.]]
原始 L2 范数: [5.         1.41421356 5.        ]

L2 归一化后:
[[0.6        0.8       ]
 [0.70710678 0.70710678]
 [0.         1.        ]]
L2 归一化后范数: [1. 1. 1.]

L1 归一化后:
[[0.42857143 0.57142857]
 [0.5        0.5       ]
 [0.         1.        ]]
L1 归一化后 L1 范数: [1. 1. 1.]

2.使用 preprocessing.normalize 函数(函数式接口)

除了 Normalizer 类,sklearn 也提供函数式接口:

from sklearn.preprocessing import normalize

X_normalized = normalize(X, norm='l2', axis=1)  # axis=1 表示按行归一化(样本)
print(X_normalized)

✅ 功能与 Normalizer().transform(X) 完全一致,适合脚本快速使用。

❗ 但不适用于管道(Pipeline),因为没有 .fit() 方法。


在管道中使用示例

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)

# 构建管道:样本归一化 + SVM分类器
pipeline = Pipeline([
    ('normalizer', Normalizer(norm='l2')),  # 样本L2归一化
    ('classifier', SVC(kernel='linear'))
])

pipeline.fit(X_train, y_train)
score = pipeline.score(X_test, y_test)
print(f"测试集准确率:{score:.4f}")

与其他缩放器对比

方法 操作对象 是否有状态 是否改变分布 是否受异常值影响 适用场景
Normalizer 样本(行) ❌ 无状态 是(改变方向) 是(范数计算) 文本、余弦相似度
StandardScaler 特征(列) ✅ 有状态 保留形状 通用标准化
MinMaxScaler 特征(列) ✅ 有状态 改变形状 缩放到 [0,1]
RobustScaler 特征(列) ✅ 有状态 保留形状 ❌ 否 含异常值数据

注意事项

重要提醒:

  • Normalizer 是无状态的,训练集和测试集可独立归一化,无数据泄露风险。
  • 归一化是样本级操作,不适用于“特征需要相同尺度”的场景(此时应使用 StandardScaler 或 MinMaxScaler)。
  • 若某样本全为 0,归一化后仍为 0(避免除零错误,sklearn 自动处理)。
  • 对稀疏矩阵友好,归一化后仍保持稀疏性。

总结

在 sklearn 中,归一化(Normalization)特指对每个样本向量进行单位范数缩放,常用于文本处理、相似度计算等场景。核心工具是 Normalizer 类或 normalize() 函数,支持 L1/L2 范数。它与对特征列进行缩放的 StandardScaler、MinMaxScaler 有本质区别,使用时需根据任务目标选择正确的预处理方法。


网站公告

今日签到

点亮在社区的每一天
去签到