news 2026/7/5 2:18:46

Python特征工程实战:从数据清洗到模型提效的完整流程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Python特征工程实战:从数据清洗到模型提效的完整流程

引言:为什么特征工程比调参更重要

先看一张本文的完整流程脑图,便于把握全局:

做机器学习项目,很多新手把80%的时间花在调参上,结果模型精度提升微乎其微。而真正决定模型上限的,往往是特征工程。

有句话在业内流传很广:"数据和特征决定了机器学习的上限,模型和算法只是逼近这个上限。"

今天这篇文章,我用一个完整的案例,带你走一遍特征工程的标准流程:数据清洗 → 特征构造 → 特征选择 → 模型验证。全程用 Python 实现,代码可以直接跑。

一、案例背景与数据准备

我们用一份模拟的电商用户购买数据,目标是预测用户是否会复购。数据集包含以下字段:

• user_id:用户ID
• gender:性别
• age:年龄
• register_days:注册天数
• total_orders:历史订单数
• total_amount:历史消费金额
• last_order_days:最近一次下单距今天数
• channel:注册渠道(app/web/小程序)
• is_return:是否复购(0/1)

先构造模拟数据:

import pandas as pd import numpy as np np.random.seed(42) n = 5000 df = pd.DataFrame({ 'user_id': range(1, n + 1), 'gender': np.random.choice(['M', 'F', np.nan], n, p=[0.45, 0.45, 0.1]), 'age': np.random.normal(30, 10, n).astype(int), 'register_days': np.random.randint(1, 1000, n), 'total_orders': np.random.poisson(3, n), 'total_amount': np.random.exponential(200, n).round(2), 'last_order_days': np.random.randint(0, 365, n), 'channel': np.random.choice(['app', 'web', 'mini', np.nan], n, p=[0.5, 0.3, 0.15, 0.05]), 'is_return': np.random.binomial(1, 0.3, n) }) # 构造一些异常值 df.loc[np.random.choice(df.index, 50, replace=False), 'age'] = 200 df.loc[np.random.choice(df.index, 30, replace=False), 'total_amount'] = -100 print(df.head()) print(df.info())

二、数据清洗:别让脏数据毁了模型

数据清洗是特征工程的第一步。常见的问题包括:缺失值、异常值、重复值、类型错误。

下面是一段清洗代码:

# 缺失值处理 df['gender'] = df['gender'].fillna('unknown') df['channel'] = df['channel'].fillna('other') # 年龄异常值处理:超过100岁视为缺失,用中位数填充 df.loc[df['age'] > 100, 'age'] = np.nan df['age'] = df['age'].fillna(df['age'].median()).astype(int) # 消费金额异常值处理:负数置为0 df['total_amount'] = df['total_amount'].clip(lower=0) # 去重 df = df.drop_duplicates(subset=['user_id']) print(df.isnull().sum())

【数据来源】上述代码为模拟数据生成与清洗示例,用于演示特征工程流程。

三、特征构造:把原始数据变成模型能看懂的东西

特征构造是特征工程的核心。好的特征能让模型学到更有用的模式。

3.1 统计特征

从现有字段派生出新特征:

# 客单价 df['avg_order_amount'] = df['total_amount'] / (df['total_orders'] + 1) # 活跃度:注册天数 / 订单数 df['days_per_order'] = df['register_days'] / (df['total_orders'] + 1) # 是否近期活跃 df['is_recent_active'] = (df['last_order_days'] <= 30).astype(int) # 年龄分段 df['age_group'] = pd.cut(df['age'], bins=[0, 18, 25, 35, 45, 100], labels=['少年', '青年', '中青年', '中年', '中老年']) print(df[['user_id', 'avg_order_amount', 'days_per_order', 'is_recent_active', 'age_group']].head())

3.2 类别特征编码

模型无法直接处理字符串,需要对类别特征编码:

# 独热编码 df_encoded = pd.get_dummies(df, columns=['gender', 'channel', 'age_group'], drop_first=True) print(df_encoded.filter(like='gender_').head())

3.3 特征标准化

对于数值型特征,标准化是很多模型的前提:

from sklearn.preprocessing import StandardScaler num_cols = ['age', 'register_days', 'total_orders', 'total_amount', 'last_order_days', 'avg_order_amount', 'days_per_order'] scaler = StandardScaler() df_encoded[num_cols] = scaler.fit_transform(df_encoded[num_cols]) print(df_encoded[num_cols].describe())

四、特征选择:去掉 noise,留下 signal

特征不是越多越好。冗余特征会增加过拟合风险,也会拖慢训练速度。

这里介绍两种常用方法:相关性筛选和树模型特征重要性。

from sklearn.ensemble import RandomForestClassifier from sklearn.model_selection import train_test_split import matplotlib.pyplot as plt # 准备训练数据 feature_cols = [c for c in df_encoded.columns if c not in ['user_id', 'is_return']] X = df_encoded[feature_cols] y = df_encoded['is_return'] X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) # 训练随机森林查看特征重要性 rf = RandomForestClassifier(n_estimators=100, random_state=42) rf.fit(X_train, y_train) importance = pd.DataFrame({ 'feature': feature_cols, 'importance': rf.feature_importances_ }).sort_values('importance', ascending=False) print(importance.head(10))

输出结果通常会显示:avg_order_amount、last_order_days、is_recent_active 等特征是 top 重要特征。这符合业务直觉:消费能力、活跃度、复购意愿密切相关。

五、模型验证:特征工程的效果到底如何

我们用 AUC 和 F1 来对比特征工程前后的效果:

from sklearn.linear_model import LogisticRegression from sklearn.metrics import roc_auc_score, f1_score, classification_report # 只用原始特征 base_cols = ['age', 'register_days', 'total_orders', 'total_amount', 'last_order_days'] X_base = df_encoded[base_cols] X_train_base, X_test_base, _, _ = train_test_split(X_base, y, test_size=0.2, random_state=42) lr_base = LogisticRegression(max_iter=1000, random_state=42) lr_base.fit(X_train_base, y_train) base_auc = roc_auc_score(y_test, lr_base.predict_proba(X_test_base)[:, 1]) base_f1 = f1_score(y_test, lr_base.predict(X_test_base)) # 用工程后的特征 lr_enhanced = LogisticRegression(max_iter=1000, random_state=42) lr_enhanced.fit(X_train, y_train) enhanced_auc = roc_auc_score(y_test, lr_enhanced.predict_proba(X_test)[:, 1]) enhanced_f1 = f1_score(y_test, lr_enhanced.predict(X_test)) print(f"原始特征 AUC: {base_auc:.4f}, F1: {base_f1:.4f}") print(f"工程特征 AUC: {enhanced_auc:.4f}, F1: {enhanced_f1:.4f}") print(f"AUC 提升: {(enhanced_auc - base_auc) / base_auc * 100:.2f}%")

【数据来源】以上结果基于模拟数据实验,不同数据集效果会有差异。

六、特征工程常见误区

最后分享几个新手容易踩的坑:

1. 泄露未来信息
用目标变量构造特征时,要避免把测试集的信息带入训练集。比如用"未来30天是否复购"作为特征,那就是在作弊。

2. 过度编码
高基数类别变量(如 user_id)直接做独热编码会爆炸。可以用 target encoding 或 embedding。

3. 忽视业务含义
不要为了构造特征而构造特征。每一个特征都要有业务解释性,否则模型很难稳定。

4. 不做交叉验证
特征选择必须在训练集上做,不能在整个数据集上提前筛选,否则会造成信息泄露。

总结

特征工程的标准流程可以概括为:

1.数据清洗:处理缺失、异常、重复
2.特征构造:统计特征、交叉特征、分桶、编码
3.特征选择:相关性、重要性、正则化
4.模型验证:对比特征工程前后的效果

这套流程不是一成不变的,需要根据业务场景调整。但核心思路是:让模型看到更多"有意义的信号",而不是"更多的噪声"。

【数据来源】本文数据集为模拟生成,方法参考 sklearn 官方文档及主流机器学习工程实践。

你在特征工程中最常用的技巧是什么?评论区一起交流。

觉得有用,转给正在做数据分析和机器学习的朋友。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/5 2:16:37

AI时代依然受用:那些越过越好的人,都学会了这件事。

近日&#xff0c;和一位深耕AI赛道的创业者闲谈&#xff0c;谈及当下行业瞬息万变&#xff1a;新技术层出不穷&#xff0c;机遇遍地皆是&#xff0c;陷阱也无处不在。谈及浮沉百态&#xff0c;究竟什么样的人&#xff0c;能穿越行业周期、稳步前行&#xff1f;这位创业者给出答…

作者头像 李华
网站建设 2026/7/5 2:14:09

听脑企业版vs传统方案更适配杭州大学生学习工具解决方案选型

"针对杭州本地布局大学生学习工具业务的高教服务商、高校创业团队、职业教育机构的采购选型需求&#xff0c;听脑企业版对比传统纯软件方案、软硬件结合方案&#xff0c;在面向大学生课堂转写、实训记录、学习知识沉淀场景下&#xff0c;可匹配企业级的管理、合规、集成要…

作者头像 李华
网站建设 2026/7/5 2:13:46

【Citizens】下载教程

Citizens2 插件下载教程&#xff08;CI 持续集成版&#xff09; 本教程面向完全没接触过 Jenkins/CI 的新手&#xff0c;手把手教你从 Citizens 官方构建站下载对应你 Minecraft 服务器版本的插件。 一、先了解几个概念&#xff08;很重要&#xff0c;别跳过&#xff09; 概念…

作者头像 李华
网站建设 2026/7/5 2:13:44

Qwen3-TTS 因Transformers 产生的错误解决思路仅供参考

问题分类 所属模块:ComfyUI → TTS Audio Suite → Qwen3-TTS Engine 环境:Windows,ComfyUI-aki v1.3,Python 3.10,PyTorch 2.5.1+cu124,Transformers 5.12.1(主环境) 模型:Qwen3-TTS-12Hz-1.7B-Base 触发场景:使用 SRT workflow 进行语音克隆生成时,worker 子进程…

作者头像 李华
网站建设 2026/7/5 2:13:14

Java异常处理深度实战教程:异常传播的失败场景分析

第三部分&#xff1a;实战中最致命的坑 —— 异常传播的失败场景分析在实际工业级开发中&#xff0c;80% 的异常处理故障&#xff0c;都是因为错误截断异常传播链路导致的。下面我将列举 4 种最常见的失败场景&#xff0c;这些场景在初级和中级开发者的代码中非常普遍&#xff…

作者头像 李华
网站建设 2026/7/5 2:13:08

Nacos配置中心敏感数据加密实战:从原理到部署的完整指南

1. 项目概述&#xff1a;为什么Nacos配置中心的敏感数据必须加密&#xff1f;在微服务架构成为主流的今天&#xff0c;配置中心作为连接所有服务的“神经中枢”&#xff0c;其重要性不言而喻。Nacos&#xff0c;作为阿里巴巴开源的一款集服务发现、配置管理于一体的核心组件&am…

作者头像 李华