欢迎光临
我们一直在努力

深度学习篇--- transform(转换器)

1. 核心比喻:厨房烹饪流水线

想象你是一个厨师,要做一道菜(比如炒菜)。原始食材(数据)不能直接下锅,需要预处理:

生蔬菜(原始数据) → 清洗(StandardScaler) → 切块(OneHotEncoder) → 调味(添加特征) → 成品(可用于炒菜的食材)

在机器学习中,这个预处理流程就是 transform!


2. 最简单的 transform 例子:标准化

场景:把考试成绩从“0-100分”变成“平均0,标准差1”的标准分

import numpy as np
from sklearn.preprocessing import StandardScaler

# 原始成绩(4个学生,2门课)
# 中文和数学成绩,每门课满分不同
raw_scores = np.array([
[85, 150], # 学生1:语文85,数学150
[60, 120], # 学生2:语文60,数学120
[95, 180], # 学生3:语文95,数学180
[70, 135] # 学生4:语文70,数学135
])

print("原始成绩:")
print(raw_scores)
print(f"语文平均分: {raw_scores[:, 0].mean():.1f}, 数学平均分: {raw_scores[:, 1].mean():.1f}")

输出:

原始成绩:
[[ 85 150]
[ 60 120]
[ 95 180]
[ 70 135]]
语文平均分: 77.5, 数学平均分: 146.2

问题:两门课分数范围不一样,比较不公平!

解决方案:标准化(StandardScaler)

# 创建转换器(就像请一个专门的标准化工序师傅)
scaler = StandardScaler()

# 步骤1:先学习(fit)- 师傅看数据,记住平均值和标准差
scaler.fit(raw_scores) # 师傅说:"我知道了,语文平均77.5,标准差…"

# 步骤2:再转换(transform)- 师傅开始工作
standard_scores = scaler.transform(raw_scores)

print("\\n标准化后的成绩:")
print(standard_scores)
print(f"\\n现在:每门课平均分 = {standard_scores.mean():.3f}")
print(f"每门课标准差 = {standard_scores.std():.3f}")

输出:

标准化后的成绩:
[[ 0.47243196 0.22601794]
[-1.08761082 -1.14981194]
[ 1.08761082 1.50758041]
[-0.47243196 -0.58378641]]

现在:每门课平均分 = 0.000
每门课标准差 = 1.000


3. transform 的两步结构:先学再做

关键理解:

  • fit:只看数据,学习规则(不改变数据)

  • transform:应用规则,转换数据

  • fit_transform:两步合并,一步完成


  • 4. 常用 transform 示例大全

    示例1:MinMaxScaler – 缩放到固定范围

    from sklearn.preprocessing import MinMaxScaler

    # 把成绩缩放到 0-1 范围(常用于神经网络)
    scores = np.array([85, 60, 95, 70]).reshape(-1, 1) # 需要二维

    scaler = MinMaxScaler()
    scaled = scaler.fit_transform(scores)

    print("原始成绩:", scores.flatten())
    print("缩放后(0-1):", scaled.flatten())
    print(f"转换规则: 最小值={scaler.data_min_[0]}, 最大值={scaler.data_max_[0]}")

    输出:

    原始成绩: [85 60 95 70]
    缩放后(0-1): [0.71428571 0. 1. 0.28571429]
    转换规则: 最小值=60.0, 最大值=95.0

    示例2:OneHotEncoder – 文字变数字

    from sklearn.preprocessing import OneHotEncoder

    # 学生的年级:初一、初二、初三
    grades = np.array([['初一'], ['初三'], ['初二'], ['初一'], ['初三']])

    encoder = OneHotEncoder(sparse_output=False)
    encoded = encoder.fit_transform(grades)

    print("原始年级:")
    print(grades.flatten())
    print("\\n独热编码后(每个年级一列,1表示是,0表示不是):")
    print(encoded)
    print(f"\\n编码器记住的类别: {encoder.categories_}")

    输出:

    text

    原始年级:
    ['初一' '初三' '初二' '初一' '初三']

    独热编码后(每个年级一列,1表示是,0表示不是):
    [[1. 0. 0.]
    [0. 0. 1.]
    [0. 1. 0.]
    [1. 0. 0.]
    [0. 0. 1.]]

    编码器记住的类别: [array(['初一', '初二', '初三'], dtype=object)]

    示例3:SimpleImputer – 填充缺失值

    from sklearn.impute import SimpleImputer

    # 有缺失的成绩表(NaN表示缺考)
    scores_with_missing = np.array([
    [85, 90],
    [np.nan, 75], # 语文缺考
    [92, np.nan], # 数学缺考
    [70, 85]
    ])

    print("原始数据(有缺失):")
    print(scores_with_missing)

    imputer = SimpleImputer(strategy='mean') # 用平均值填充
    filled = imputer.fit_transform(scores_with_missing)

    print("\\n填充后(用平均值填充NaN):")
    print(filled)
    print(f"\\n填充的值: 语文={imputer.statistics_[0]:.1f}, 数学={imputer.statistics_[1]:.1f}")

    输出:

    原始数据(有缺失):
    [[85. 90.]
    [nan 75.]
    [92. nan]
    [70. 85.]]

    填充后(用平均值填充NaN):
    [[85. 90. ]
    [82.33 75. ]
    [92. 83.33]
    [70. 85. ]]

    填充的值: 语文=82.33, 数学=83.33


    5. 完整的 transform 流水线(Pipeline)

    from sklearn.pipeline import Pipeline
    from sklearn.preprocessing import StandardScaler, OneHotEncoder
    from sklearn.compose import ColumnTransformer

    # 模拟学生数据
    student_data = np.array([
    # 语文分, 数学分, 年级
    [85, 150, '初一'],
    [60, 120, '初三'],
    [95, 180, '初二'],
    [70, 135, '初一']
    ])

    # 拆分成特征
    X_numeric = student_data[:, :2].astype(float) # 前两列是数值
    X_categorical = student_data[:, 2].reshape(-1, 1) # 第三列是文字

    print("原始数据:")
    print(student_data)

    # 创建转换管道
    numeric_transformer = Pipeline(steps=[
    ('scaler', StandardScaler()) # 数值标准化
    ])

    categorical_transformer = Pipeline(steps=[
    ('onehot', OneHotEncoder()) # 文字编码
    ])

    # 组合转换器
    preprocessor = ColumnTransformer(
    transformers=[
    ('num', numeric_transformer, [0, 1]), # 列0-1用数值转换
    ('cat', categorical_transformer, [2]) # 列2用分类转换
    ]
    )

    # 一步完成:学习规则 + 转换
    transformed = preprocessor.fit_transform(student_data)

    print("\\n转换后的数据:")
    print(transformed)
    print(f"\\n形状: {transformed.shape}")
    print("说明: 前2列是标准化成绩,后3列是年级的独热编码")


    6. transform 在 PyTorch 中的样子

    import torch
    import torch.nn as nn

    # PyTorch 也有 transform,通常通过 nn.Module 实现
    class SimpleNormalizer(nn.Module):
    """自定义标准化转换器"""
    def __init__(self):
    super().__init__()
    self.mean = None
    self.std = None

    def fit(self, X):
    """学习规则"""
    self.mean = X.mean(dim=0)
    self.std = X.std(dim=0)
    return self

    def transform(self, X):
    """应用转换"""
    return (X – self.mean) / self.std

    def forward(self, X):
    """PyTorch风格"""
    return self.transform(X)

    # 使用示例
    X_tensor = torch.tensor([[85.0, 150.0],
    [60.0, 120.0],
    [95.0, 180.0],
    [70.0, 135.0]])

    normalizer = SimpleNormalizer()
    normalizer.fit(X_tensor)
    X_normalized = normalizer.transform(X_tensor)

    print("PyTorch转换结果:")
    print(X_normalized)
    print(f"平均值: {X_normalized.mean(dim=0)}")
    print(f"标准差: {X_normalized.std(dim=0)}")


    7. 什么时候用 transform?

    ✅ 必须用 transform 的情况:

  • 不同尺度特征:身高(米) vs 体重(公斤)

  • 文字特征:性别、城市、颜色

  • 缺失值:有缺考、缺勤记录

  • 异常值:特别高或特别低的分数

  • 非线性关系:需要多项式特征

  • ❌ 不需要 transform 的情况:

  • 所有特征已经是 0-1 范围

  • 树模型(随机森林、决策树)通常不需要标准化

  • 只有一两个简单特征


  • 8. 常见错误和正确用法

    ❌ 错误用法:

    # 错误1:用训练集规则转换测试集
    scaler = StandardScaler()
    X_train_scaled = scaler.fit_transform(X_train)
    X_test_scaled = scaler.fit_transform(X_test) # 错误!应该用transform,不是fit_transform

    # 错误2:在拆分数据前转换
    X_scaled = scaler.fit_transform(all_data) # 泄露了测试集信息!

    ✅ 正确用法:

    # 正确流程
    scaler = StandardScaler()

    # 只在训练集上学习规则
    X_train_scaled = scaler.fit_transform(X_train)

    # 用同样的规则转换测试集
    X_test_scaled = scaler.transform(X_test) # 注意:只有transform!


    📌 一句话总结:

    transform = 厨房预处理 fit = 师傅看菜谱学习怎么做 transform = 师傅动手处理食材 fit_transform = 师傅边学边做(但只用于训练数据)

    记住:测试集只用 transform,不用 fit,否则就是"作弊"!

    赞(0)
    未经允许不得转载:171主机测评 » 深度学习篇--- transform(转换器)
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址