【手撕机器学习 03】从“生数据”到“黄金特征”:机器学习项目中价值最高的一步

摘要:在机器学习领域,有一句名言:"Garbage in, garbage out." (垃圾进,垃圾出)。本文将带你深入机器学习项目中价值最高的部分------数据预处理与特征工程。你将学会如何清洗"生"数据,并从中提炼出能让模型"吃得更好、学得更快"的"黄金特征"。掌握这些,你对模型效果的掌控力将远超那些只关心算法的人。


前言:你不是算法工程师,你是"数据大厨"

在上一篇 【手撕机器学习 02】 中,我们已经掌握了NumPy和Pandas这两把锋利的"厨刀"。现在,是时候处理真正的"食材"了。

想象一下,再厉害的米其林大厨(机器学习算法),如果拿到的是一堆发霉、未经清洗的食材(原始数据),也做不出美味佳肴。

💡 在实际的机器学习项目中,超过70%的时间都花在了数据准备上。这一步的质量,直接决定了你模型性能的上限。算法和调参,只是在逼近这个上限而已。

本篇,我们将扮演一位"数据大厨",学习两项核心技艺:

  • 数据预处理 (Data Preprocessing):就像"洗菜、择菜、切菜"。它是数据准备的基础,目的是处理数据中的噪声和不一致性。
  • 特征工程 (Feature Engineering):就像"配菜、调味、腌制"。它是一门艺术,目的是从原始数据中创造出更能体现问题本质的、对模型更有用的新特征。

准备好,让我们开始处理我们的"食材"吧。


一、数据预处理:把"脏数据"变"干净"的三步清洗法

我们将使用Pandas来完成大部分预处理工作。

python 复制代码
import pandas as pd
import numpy as np
from sklearn.preprocessing import StandardScaler, MinMaxScaler, LabelEncoder

# 创建一个包含各种问题的模拟DataFrame
data = {
    'age': [25, 30, np.nan, 35, 40],
    'gender': ['Male', 'Female', 'Male', 'Female', 'Male'],
    'city': ['New York', 'Los Angeles', 'Chicago', 'New York', 'Chicago'],
    'income': [50000, 120000, 80000, 60000, 90000]
}
df = pd.DataFrame(data)
print("--- 原始数据 ---")
print(df)

第一步:处理缺失值

这是我们在上一篇中接触过的,也是最常见的任务。

python 复制代码
# 用年龄的平均值填充缺失的年龄
mean_age = df['age'].mean()
df['age'].fillna(mean_age, inplace=True) # inplace=True 表示直接在原始DataFrame上修改
print("\n--- 1. 处理缺失值后 ---")
print(df)

第二步:处理类别特征

机器学习算法只能理解数字。我们需要将像'Male', 'New York'这样的文本转换成数值。

方法一:独热编码 (One-Hot Encoding)

这是最常用的方法,它为每个类别创建一个新的二进制(0/1)列,避免了类别间不存在的大小关系。

python 复制代码
# 使用Pandas的get_dummies函数
df_onehot = pd.get_dummies(df, columns=['gender', 'city'])
print("\n--- 2. 独热编码后 ---")
print(df_onehot)

方法二:标签编码 (Label Encoding)

将每个类别映射到一个整数。

python 复制代码
# 标签编码只适用于有序类别,或某些树模型
# 这里我们仅作演示
label_encoder = LabelEncoder()
df_label = df.copy()
df_label['gender'] = label_encoder.fit_transform(df_label['gender'])
# df_label -> 'Male'会变成1, 'Female'会变成0

⚠️ 注意 :标签编码会引入0 < 1 < 2这样的人为大小关系。它只适用于本身就有序的类别(如"学士"<"硕士"<"博士"),或者一些对数值大小不敏感的树模型。通常情况下,优先使用独热编码。

第三步:特征缩放 (Feature Scaling)

如果不同特征的数值范围相差巨大(比如年龄是几十,收入是几万),很多算法(如线性回归、KNN、SVM)的表现会变差。我们需要将所有特征"拉"到同一个尺度上。

  • 标准化 (Standardization) :将数据缩放到均值为0,方差为1 。它保留了数据的原始分布形状,是最常用的缩放方法。
python 复制代码
scaler = StandardScaler()
# 我们对经过独热编码后的DataFrame进行操作
df_scaled = df_onehot.copy()
df_scaled[['age', 'income']] = scaler.fit_transform(df_scaled[['age', 'income']])
print("\n--- 3. 特征标准化后 ---")
print(df_scaled)
  • 归一化 (Normalization):将数据缩放到一个固定的区间,通常是****。适用于数据分布有明显边界的情况。

二、特征工程:从数据中"榨取"信息的两招提炼术

特征工程更依赖于你对业务的理解,是真正体现"人工"智能的地方。

第一招:特征创造 (Feature Creation)

从现有特征中组合出新的、更有意义的特征。

python 复制代码
# 假设我们有一个电商数据集
sales_df = pd.DataFrame({'price': [100, 50, 200], 'quantity': [2, 5, 1]})

# 创造一个新特征 'total_price'
sales_df['total_price'] = sales_df['price'] * sales_df['quantity']
print("\n--- 特征创造 ---")
print(sales_df)```

#### **第二招:特征提取 (Feature Extraction)**
从复杂数据中提取出关键信息。
```python
# 假设我们有时间戳数据
time_df = pd.DataFrame({'timestamp': ['2023-10-27 10:00:00']})
time_df['timestamp'] = pd.to_datetime(time_df['timestamp'])

# 从时间戳中提取出小时和星期几
time_df['hour'] = time_df['timestamp'].dt.hour
time_df['day_of_week'] = time_df['timestamp'].dt.dayofweek # Monday=0
print("\n--- 特征提取 ---")
print(time_df)

三、最后一步:划分训练集与测试集

这是模型训练前的"分班"仪式,也是保证我们能客观评价模型的关键。

💡 为什么要划分?

我们必须用模型从未见过的数据来评估它,就像用一张全新的"期末考试卷"来检验学生是否真的学会了,而不是"死记硬背"了练习册。

  • 训练集 (Training Set):用于训练模型,就像给学生的"练习册"。
  • 测试集 (Test Set):用于最终评估模型性能,就像"期末考试卷"。
python 复制代码
from sklearn.model_selection import train_test_split

# 假设df_scaled是我们的最终特征矩阵
# 我们想预测收入,所以'income'是目标y
X = df_scaled.drop('income', axis=1) # 特征 (除了目标以外的所有列)
y = df_scaled['income']             # 目标

# random_state保证每次划分的结果都一样,便于复现
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.3, random_state=42
)

print("\n--- 划分数据集 ---")
print(f"训练集特征形状: {X_train.shape}")
print(f"测试集特征形状: {X_test.shape}")

总结:准备好你的"黄金"食粮

在本篇中,我们扮演了一位"数据大厨",学习了机器学习项目中最关键的准备工作:

  1. 数据预处理 :掌握了处理缺失值类别特征 (独热编码vs标签编码)和进行特征缩放的三步清洗法。
  2. 特征工程 :学习了特征创造特征提取的两招提炼术。
  3. 数据集划分 :理解了为何必须划分训练集测试集,并学会了如何操作。

现在,我们的"食材"已经处理干净、调味完毕,变成了能让模型大快朵颐的"黄金特征"。从下一篇开始,我们将正式开火,把这些食粮喂给我们亲手实现的第一个机器学习模型!

如果觉得这篇文章让你对数据预处理有了质的飞跃,请一定记得 👍 点赞、⭐ 收藏、💬 评论,你的支持是"大厨"更新的全部动力!
预告:【手撕机器学习 04】手撕线性回归:从"蒙眼下山"彻底理解梯度下降

相关推荐
NAGNIP6 小时前
一文搞懂深度学习中的通用逼近定理!
人工智能·算法·面试
冬奇Lab8 小时前
一天一个开源项目(第36篇):EverMemOS - 跨 LLM 与平台的长时记忆 OS,让 Agent 会记忆更会推理
人工智能·开源·资讯
冬奇Lab8 小时前
OpenClaw 源码深度解析(一):Gateway——为什么需要一个"中枢"
人工智能·开源·源码阅读
AngelPP11 小时前
OpenClaw 架构深度解析:如何把 AI 助手搬到你的个人设备上
人工智能
宅小年11 小时前
Claude Code 换成了Kimi K2.5后,我再也回不去了
人工智能·ai编程·claude
九狼12 小时前
Flutter URL Scheme 跨平台跳转
人工智能·flutter·github
ZFSS12 小时前
Kimi Chat Completion API 申请及使用
前端·人工智能
天翼云开发者社区13 小时前
春节复工福利就位!天翼云息壤2500万Tokens免费送,全品类大模型一键畅玩!
人工智能·算力服务·息壤
知识浅谈13 小时前
教你如何用 Gemini 将课本图片一键转为精美 PPT
人工智能
Ray Liang14 小时前
被低估的量化版模型,小身材也能干大事
人工智能·ai·ai助手·mindx