【机器学习|DAY02】数据划分与特征工程

文章目录

  • 数据划分与特征工程
    • 一、数据集划分
      • [1.1 为什么要先划分再处理?](#1.1 为什么要先划分再处理?)
      • [1.2 API - train_test_split](#1.2 API - train_test_split)
    • 二、特征工程回忆
    • [三、特征提取(Feature Extraction)](#三、特征提取(Feature Extraction))
      • [3.1 字典特征提取:DictVectorizer](#3.1 字典特征提取:DictVectorizer)
      • [3.2 文本特征提取:CountVectorizer](#3.2 文本特征提取:CountVectorizer)
      • [3.3 文本特征提取:TfidfVectorizer](#3.3 文本特征提取:TfidfVectorizer)
    • [四、特征预处理(Feature Preprocessing)](#四、特征预处理(Feature Preprocessing))
      • [4.1 归一化(Min-Max Scaling)](#4.1 归一化(Min-Max Scaling))
      • [4.2 标准化(Z-score Standardization)](#4.2 标准化(Z-score Standardization))
      • [4.3 归一化 vs 标准化](#4.3 归一化 vs 标准化)

数据划分与特征工程


一、数据集划分

数据划分不属于特征工程,它是特征工程的前置操作。

1.1 为什么要先划分再处理?

防止数据泄漏(Data Leakage)。标准化、归一化等操作需要从数据中"学参数"(均值、标准差、最大最小值等),如果测试集也混进去一起算,测试集的信息就污染了训练过程,评估结果虚高,后面对真正的新数据就会暴露问题。

顺序原则:

  • 不需要学参数的操作(去除 HTML 标签、全量去停用词)→ 可以在划分前对全量数据统一做。
  • 需要学参数的操作 (算均值/标准差、最大/最小值、类别编码映射)→ 必须先划分,只用训练集 fit,然后 transform 测试集。

1.2 API - train_test_split

所属模块: sklearn.model_selection(助记:"模型选择"模块)

python 复制代码
from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(
    X, y,                    # 特征矩阵、标签向量
    test_size=0.2,           # 测试集占比,常用 0.2 或 0.3
    train_size=None,         # 训练集占比,通常不填,由 test_size 推算
    random_state=42,         # 随机种子,固定后每次划分结果一致
    shuffle=True,            # 划分前是否打乱(默认 True)
    stratify=y               # 分层抽样:保持各类别比例不变
)
参数 类型 默认值 含义
test_size float/int None 测试集比例(0.0~1.0)或样本数
train_size float/int None 训练集比例或样本数,通常不填
random_state int None 随机种子,固定可复现结果
shuffle bool True 划分前是否打乱数据
stratify array-like None 按标签比例分层抽样,分类任务强烈建议设置 最终保证:训练集里 A:B = 测试集里 A:B = 原始数据集里 A:B

返回值: 四个数组,按顺序为 X_train, X_test, y_train, y_test

python 复制代码
# 完整示例:按 8:2 分层划分
X = df.drop('label', axis=1)
y = df['label']

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42, stratify=y
)

二、特征工程回忆

回忆概述篇的笔记,特征工程包含:特征提取、特征预处理、特征降维、特征选择、特征组合。这里先展开最常用的前两类-特征提取和特征预处理。

类别 核心动作 本篇覆盖 后续详述
特征提取 原始数据 → 数值特征 DictVectorizerCountVectorizerTfidfVectorizer Word2Vec、BERT嵌入、图像特征(SIFT/HOG/CNN)
特征预处理 数值变换/缩放/编码 MinMaxScalerStandardScaler One-Hot、Label、Target 编码、RobustScaler
特征降维 高维 → 低维 --- PCA、LDA、t-SNE
特征选择 筛选有用特征、丢弃冗余 --- 过滤法、包裹法、嵌入法、L1正则化
特征组合 交叉/乘积构造交互特征 --- 多项式特征、交叉特征

三、特征提取(Feature Extraction)

3.1 字典特征提取:DictVectorizer

  • 所属模块: sklearn.feature_extraction

  • 什么时候用: 数据是字典列表的形式,比如 [{'city': '北京', 'gender': '男'}, ...]

  • 本质: 对类别字段做 One-Hot 编码,每个类别取值变成独立的一列 0/1。

python 复制代码
from sklearn.feature_extraction import DictVectorizer

data = [
    {'city': '北京', 'gender': '男'},
    {'city': '上海', 'gender': '女'},
    {'city': '北京', 'gender': '女'}
]

dv = DictVectorizer(sparse=True)        # sparse=True:返回稀疏矩阵,节省内存
result = dv.fit_transform(data)
print("特征名:", dv.get_feature_names_out())
print("转换结果:\n", result)
    

输出:

text 复制代码
特征名: ['city=上海' 'city=北京' 'gender=女' 'gender=男']

转换结果:
 [[0. 1. 0. 1.]    ← 第1条:city=北京(1), gender=男(1)
 [1. 0. 1. 0.]     ← 第2条:city=上海(1), gender=女(1)
 [0. 1. 1. 0.]]    ← 第3条:city=北京(1), gender=女(1)

可以看到:3 条原始字典 → 4 列 One-Hot 特征矩阵。city 有 {北京,上海} 两种取值 → 2 列;gender 有 {男,女} 两种取值 → 2 列。

参数 含义
sparse 默认 True,返回稀疏矩阵;维度高且多数为 0 时大幅节省内存

核心方法:

方法 作用
fit(data) 扫描数据,学习所有类别取值
transform(data) 按已学特征名转为数值矩阵
fit_transform(data) 一步完成
get_feature_names_out() 获取转换后特征名列表
inverse_transform(X) 数值矩阵还原为字典列表

3.2 文本特征提取:CountVectorizer

  • 所属模块: sklearn.feature_extraction.text

  • 核心思想(词袋模型): 把每篇文档变成一个词频向量,只统计每个词出现了多少次,不管词序。就像一个袋子把词装进去,不看先后顺序。

python 复制代码
from sklearn.feature_extraction.text import CountVectorizer

cv = CountVectorizer(
    max_features=1000,       # 最多保留 1000 个高频词(控制维度)
    stop_words='english',    # 移除停用词(也可传自定义列表如 ['的','了'])
    ngram_range=(1, 2),      # 同时提取单个词和双词组合
    min_df=1,                # 至少在 1 篇文档中出现才保留
    max_df=0.8               # 出现在超过 80% 文档中的高频词忽略
)

corpus = ['I love machine learning', 'Machine learning is great']
X = cv.fit_transform(corpus)         # 返回稀疏矩阵
print("词表(按字母排序):", cv.get_feature_names_out())
print("词频矩阵(密集形式):\n", X.toarray())

输出:

text 复制代码
词表(按字母排序): ['great' 'learning great' 'love' 'love machine']
词频矩阵(密集形式):
 [[0 0 1 1]
 [1 1 0 0]]
常用参数 含义
max_features 按词频保留前 N 个词,控制维度的最常用方式
stop_words 'english' 或自定义列表,移除无区分度的高频词
ngram_range (1,1) 仅单词,(1,2) 加双词组合,捕捉局部语序
min_df / max_df 过滤太罕见/太常见的词

返回值: fit_transform() 返回稀疏矩阵(scipy.sparse.csr_matrix),形状 (文档数, 词表大小),可通过 .toarray() 转 NumPy 数组。

3.3 文本特征提取:TfidfVectorizer

  • 所属模块: sklearn.feature_extraction.text

  • 解决的问题: CountVectorizer 只看词频。TF-IDF 在词频基础上加入了"这个词在整个语料库中的区分能力"。也就是说TF-IDF的主要思想就是:如果某个词或短语在一篇文章中出现的概率高,并且在其他文章中很少出现,则认为此词或者短语具有很好的类别区分能力,适合用来做分类。

  • 公式:TF * IDF

    • TF(词频): 这个词在这篇文档中出现得多频繁?TF 高 = 本文档反复提到它。但不区分"主题词"和"通用词"。
      TF ( t , d ) = 词 t 在文档 d 中的次数 文档 d 的总词数 \text{TF}(t, d) = \frac{\text{词 } t \text{ 在文档 } d \text{ 中的次数}}{\text{文档 } d \text{ 的总词数}} TF(t,d)=文档 d 的总词数词 t 在文档 d 中的次数
    • IDF(逆文档频率): 这个词在整个语料库中有多少区分度?
      IDF ( t ) = log ⁡ ( 文档总数 包含词 t 的文档数 + 1 ) + 1 \text{IDF}(t) = \log\left(\frac{\text{文档总数}}{\text{包含词 } t \text{ 的文档数} + 1}\right) + 1 IDF(t)=log(包含词 t 的文档数+1文档总数)+1
      • 几乎所有文档都有(如"的")→ 分母大 → IDF 小
      • 仅少数文档有(如"神经网络")→ 分母小 → IDF 大

注意TF依据本文档,IDF依据语料库(文档集合)

python 复制代码
from sklearn.feature_extraction.text import TfidfVectorizer

# 和 CountVectorizer 同样的语料,对比效果
tfidf = TfidfVectorizer(
    max_features=1000,       # 最多保留 1000 个高频词(控制维度)
    stop_words='english',    # 移除停用词(也可传自定义列表如 ['的','了'])
    ngram_range=(1, 2),      # 同时提取单个词和双词组合
    min_df=1,                # 至少在 1 篇文档中出现才保留
    max_df=0.8               # 出现在超过 80% 文档中的高频词忽略
)

corpus = [
    'I love machine learning',           # 文档1
    'Machine learning is great'           # 文档2
]
X = tfidf.fit_transform(corpus)

print("词表:", tfidf.get_feature_names_out())
print("TF-IDF 矩阵:\n", X.toarray())

输出:

text 复制代码
词表: ['great' 'learning great' 'love' 'love machine']
TF-IDF 矩阵:
 [[0.         0.         0.70710678 0.70710678]
 [0.70710678 0.70710678 0.         0.        ]]

TfidfVectorizer 继承了 CountVectorizer 的全部参数,额外增加了:

独有参数 含义
use_idf 默认 True。设 False 退化回纯 TF
smooth_idf 默认 True,平滑处理防止除零
norm 'l2'(每行缩放为单位长度)、'l1'None
sublinear_tf True 时对 TF 取 1 + log(TF),抑制高频词

返回值: 稀疏矩阵,每个值不再是词频而是 TF-IDF 加权分数。


四、特征预处理(Feature Preprocessing)

对各特征做数值变换、缩放或编码,让不同量纲的特征"对齐",模型不被数值大小带偏。

4.1 归一化(Min-Max Scaling)

核心公式(缩放到 0, 1):

x ′ = x − x min x max − x min x' = \frac{x - x_{\text{min}}}{x_{\text{max}} - x_{\text{min}}} x′=xmax−xminx−xmin

推导分两步:

  1. 平移: x - x_min,最小值移到 0,范围变为 [0, x_max - x_min]
  2. 缩放: 除以范围长度,最大值恰好变 1

通用形式(扩展到 a, b):

x ′ = a + ( x − x min ) ( b − a ) x max − x min x' = a + \frac{(x - x_{\text{min}})(b - a)}{x_{\text{max}} - x_{\text{min}}} x′=a+xmax−xmin(x−xmin)(b−a)

其实就是:先算出 x 在 0,1 里的比例位置 → 再映射到 a, ba=0, b=1 就是第一个公式。需要非 0,1 区间时(如 tanh 激活函数适合 -1,1)用通用形式。

API: sklearn.preprocessing.MinMaxScaler

python 复制代码
from sklearn.preprocessing import MinMaxScaler

scaler = MinMaxScaler(feature_range=(0, 1))      # 默认 [0,1]

# 核心:fit 只在训练集!
scaler.fit(X_train)                              # 学 x_min、x_max
X_train_scaled = scaler.transform(X_train)       # 套用
X_test_scaled = scaler.transform(X_test)         # 测试集只能用训练集学的参数!

# 训练集一步到位:scaler.fit_transform(X_train)

局限: 对异常值极度敏感,一个极端值会拉大范围,把正常数据压缩到极小空间。

4.2 标准化(Z-score Standardization)

核心公式:

x ′ = x − μ σ x' = \frac{x - \mu}{\sigma} x′=σx−μ

μ 是均值,σ 是标准差。分两步理解:

  1. 减均值: 解决的是特征之间的不一致问题,让所有特征的均值都围绕0,消除不同特征在中心位置上的巨大差异。
  2. 除标准差: 解决的是特征内部的尺度不统一问题,让每个特征自身的波动幅度都标准化为1,保证单个特征内部离散程度一致。

API: sklearn.preprocessing.StandardScaler

python 复制代码
from sklearn.preprocessing import StandardScaler

scaler = StandardScaler(with_mean=True, with_std=True)   # 默认值

scaler.fit(X_train)
X_train_scaled = scaler.transform(X_train)
X_test_scaled = scaler.transform(X_test)
参数 含义
with_mean 默认 True,减均值。稀疏矩阵需设 False
with_std 默认 True,除标准差
copy 默认 True,复制后操作

fit / transform / fit_transform 的区别

sklearn 所有 Transformer 都遵循这个约定,极其重要。原因请见机器学习概述篇,同本篇第一个知识点。

方法 做了什么 用在哪个数据上
fit(X) 学参数(均值、标准差、最大值、词表......) 只训练集
transform(X) 套用已学的规则做转换 训练集、测试集、新数据
fit_transform(X) 先 fit 再 transform,一步 只训练集

4.3 归一化 vs 标准化

归一化 标准化
输出 固定区间 0,1a,b 均值为 0,标准差为 1
异常值 极度敏感 相对鲁棒
分布假设 正态时效果佳
稀疏保持 ❌(0 会变非零)
典型场景 KNN、K-Means、图像 线性回归、SVM、PCA、神经网络

选择原则: 有异常值 → StandardScalerRobustScaler;需稀疏 → MinMaxScaler;不确定 → 先试 StandardScaler


特征提取和特征预处理是特征工程中最先接触、最常用的两块。降维、选择、组合在后面学具体算法时按需补充。

以上为个人学习总结,旨在梳理个人理解。如有疏漏或不当之处,欢迎指正与交流。如果文章对你有帮助,别忘了点个赞、留个言~ 我们下篇再见!

相关推荐
Database_Cool_8 小时前
AI Agent 应用数据库选型:阿里云 PolarDB-X 高并发分布式数据底座
数据库·人工智能·阿里云
中微极客8 小时前
从Prompt到RAG:LLM工程实战全链路解析
人工智能·python·prompt
AI新角度9 小时前
MLOps 服务韧性:推理服务的限流、熔断与降级设计
人工智能
飞凌嵌入式9 小时前
Buildroot vs Ubuntu选型指南
人工智能·飞凌嵌入式
染指11109 小时前
61.RAG-RAG存在的问题
人工智能·llama·rag·llama_index·llamaindex
黄焖鸡能干四碗9 小时前
IT数据架构规划设计方案(PPT文件)
大数据·网络·数据库·人工智能·架构·区块链
黑夜路人9 小时前
可靠 Agent 设计:从一句 Prompt 到稳定交付
数据库·人工智能·prompt
ofoxcoding9 小时前
Seedance 2.0 与 Wan 2026 视频生成 API 成本效率深度对比分析
网络·人工智能·ai·音视频
wuyuanshun9 小时前
LangGraph原理逻辑-LangGraph接入MCP(三)
人工智能·ai