【机器学习|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
)

二、特征工程回忆

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

类别 核心动作 本篇覆盖 后续详述
特征提取 原始数据 → 数值特征 DictVectorizer、CountVectorizer、TfidfVectorizer Word2Vec、BERT嵌入、图像特征(SIFT/HOG/CNN)
特征预处理 数值变换/缩放/编码 MinMaxScaler、StandardScaler 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, b。a=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,1 或 a,b 均值为 0,标准差为 1
异常值 极度敏感 相对鲁棒
分布假设 无 正态时效果佳
稀疏保持 ✅ ❌(0 会变非零)
典型场景 KNN、K-Means、图像 线性回归、SVM、PCA、神经网络

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


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

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

相关推荐
IT_陈寒23 分钟前
SpringBoot自动配置差点让我加班到凌晨
前端·人工智能·后端
yumgpkpm36 分钟前
Acceldata ODP(Open Data Platform)3.3.6.4(RHEL9)保姆级完整安装手册
大数据·人工智能·hive·hadoop·kafka·hbase·cloudera
程序员cxuan39 分钟前
腾讯又来一王炸,开源版 WorkBuddy 太夯了!
人工智能·后端·程序员
邓工说电1 小时前
智慧断路器安全吗?数据加密、离线保护与合规认证全解读
大数据·数据库·人工智能·智能断路器·炜晔科技
阿里云大数据AI技术1 小时前
Lance 数据检索怎么选,当然阿里云 Milvus 向量湖
人工智能
出海客1 小时前
跨境电商多语言客服知识库怎么建:资料结构、检索边界与人工升级
大数据·人工智能
xsd202411181 小时前
从自主导航到视觉读表:一台工业巡检机器人的全栈技术链路拆解
人工智能
袁哥大话安全1 小时前
巡隐WEBSHELL扫描软件
人工智能·安全·web
论文复现现场1 小时前
8卡4090能跑70B吗?Llama-2显存预算、QLoRA与通信瓶颈
人工智能·深度学习·分布式训练·llama·显存·qlora·算家云
酷虎软件2 小时前
如何用AI创作AI歌曲AI音乐
人工智能