网易首页 > 网易号 > 正文 申请入驻

手把手教你Pandas+Sklearn特征工程(附完整代码)

0
分享至

Feature engineering 是机器学习 pipeline 里最关键的一环。算法再好,如果输入数据噪声大、不一致或者缺乏有意义的特征,模型表现都不会很好

这篇文章用 Pandas 和 Scikit-learn,把一条完整的 feature engineering pipeline 做个完整的介绍


什么是 Feature Engineering

把原始数据转换成有意义的输入变量(特征),让机器学习模型表现更好——这就是 feature engineering。


Step 1 — 探索性数据分析(EDA)

动手做特征之前,先把数据看明白。

import pandas as pd
import numpy as np

np.random.seed(42)

df = pd.DataFrame({
'Age': [25, 30, np.nan, 40, 35, 120, 28],
'Salary': [50000, 60000, 55000, 80000, np.nan, 1000000, 62000],
'Gender': ['Male', 'Female', 'Female', np.nan, 'Male', 'Male', 'Female'],
'City': ['NY', 'LA', 'NY', 'SF', np.nan, 'LA', 'SF'],
'Experience': [1, 3, 2, 10, 7, 25, 4],
'Date': pd.date_range(start='2024-01-01', periods=7),
'Target': [0, 1, 0, 1, 0, 1, 0]
})

print(df)
print(df.head())
print(df.info())
print(df.describe())

检查缺失值

print(df.isnull().sum())

查看分布

import matplotlib.pyplot as plt
df.hist(figsize=(12, 10))
plt.show()

Step 2 — 缺失值填补

缺失值会拉低模型准确率。

均值 / 中位数填补

from sklearn.impute import SimpleImputer
imputer = SimpleImputer(strategy='median')
df['Age'] = imputer.fit_transform(df[['Age']])

众数填补

cat_imputer = SimpleImputer(strategy='most_frequent')
df['City'] = cat_imputer.fit_transform(df[['City']])

KNN 填补

from sklearn.impute import KNNImputer
knn_imputer = KNNImputer(n_neighbors=5)
numeric_cols = df.select_dtypes(include=['int64', 'float64'])
df[numeric_cols.columns] = knn_imputer.fit_transform(numeric_cols)

Step 3 — 类别编码

模型只认数字,不认文本。

Label Encoding

from sklearn.preprocessing import LabelEncoder
encoder = LabelEncoder()
df['Gender'] = encoder.fit_transform(df['Gender'])

One-Hot Encoding

df = pd.get_dummies(df, columns=['City'], drop_first=True)

使用 Scikit-learn OneHotEncoder

from sklearn.preprocessing import OneHotEncoder
ohe = OneHotEncoder(handle_unknown='ignore')

Step 4 — 异常值检测与处理

异常值会扭曲模型的学习过程。

用 IQR 检测异常值

Q1 = df['Salary'].quantile(0.25)
Q3 = df['Salary'].quantile(0.75)
IQR = Q3 - Q1
lower = Q1 - 1.5 * IQR
upper = Q3 + 1.5 * IQR
outliers = df[(df['Salary'] < lower) | (df['Salary'] > upper)]
print(outliers)

移除异常值

df = df[(df['Salary'] >= lower) & (df['Salary'] <= upper)]

Winsorization

from scipy.stats.mstats import winsorize
df['Salary'] = winsorize(df['Salary'], limits=[0.05, 0.05])

Step 5 — 特征缩放与归一化

不同量纲的特征会影响模型表现。

StandardScaler

from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
df[['Age', 'Salary']] = scaler.fit_transform(df[['Age', 'Salary']])

MinMaxScaler

from sklearn.preprocessing import MinMaxScaler
minmax = MinMaxScaler()
df[['Age', 'Salary']] = minmax.fit_transform(df[['Age', 'Salary']])

RobustScaler

数据里有异常值时使用。

from sklearn.preprocessing import RobustScaler
robust = RobustScaler()
df[['Age', 'Salary']] = robust.fit_transform(df[['Age', 'Salary']])

Step 6 — 特征构造与变换

构造出有意义的特征,往往是准确率拉升最明显的一步。

日期特征抽取

df['Date'] = pd.to_datetime(df['Date'])
df['Year'] = df['Date'].dt.year
df['Month'] = df['Date'].dt.month
df['Day'] = df['Date'].dt.day

多项式特征

from sklearn.preprocessing import PolynomialFeatures
poly = PolynomialFeatures(degree=2)
poly_features = poly.fit_transform(df[['Age', 'Experience']])

数值变量分箱

df['Age_Group'] = pd.cut(
df['Age'],
bins=[0, 18, 35, 60, 100],
labels=['Teen', 'Young', 'Adult', 'Senior']
)

Step 7 — 特征选择

挑出真正重要的特征,可以减少过拟合,也能让模型跑得更快。

基于相关系数的选择

import seaborn as sns
corr = df.corr(numeric_only=True)
sns.heatmap(corr, annot=True)

SelectKBest

from sklearn.feature_selection import SelectKBest, f_classif
X = df.drop('Target', axis=1)
y = df['Target']
selector = SelectKBest(score_func=f_classif, k=5)
X_new = selector.fit_transform(X, y)

递归特征消除(RFE)

from sklearn.feature_selection import RFE
from sklearn.linear_model import LogisticRegression
model = LogisticRegression()
rfe = RFE(model, n_features_to_select=5)
X_rfe = rfe.fit_transform(X, y)

Pipeline 把预处理自动化,也能降低数据泄露的风险。

完整 Pipeline 示例

from sklearn.pipeline import Pipeline
from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.impute import SimpleImputer
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split

X = df.drop('Target', axis=1)
y = df['Target']

numeric_features = ['Age', 'Salary', 'Experience']
categorical_features = ['Gender', 'City']

numeric_transformer = Pipeline(steps=[
('imputer', SimpleImputer(strategy='median')),
('scaler', StandardScaler())
])

categorical_transformer = Pipeline(steps=[
('imputer', SimpleImputer(strategy='most_frequent')),
('onehot', OneHotEncoder(handle_unknown='ignore'))
])

preprocessor = ColumnTransformer(
transformers=[
('num', numeric_transformer, numeric_features),
('cat', categorical_transformer, categorical_features)
]
)

model_pipeline = Pipeline(steps=[
('preprocessor', preprocessor),
('classifier', LogisticRegression(max_iter=1000))
])

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

model_pipeline.fit(X_train, y_train)

print("Model trained successfully")

总结

Feature engineering 是机器学习项目能否成立的基石。干净、变换过、有意义的特征,往往胜过用劣质数据训练的复杂算法。

上面把这些步骤都做扎实,模型的准确率和稳健性都会上一个台阶。

在真实的机器学习项目里,feature engineering 往往比挑哪个模型更决定胜负。特征做得好,预测自然好。

https://avoid.overfit.cn/post/188a618a76db427191da88bb4a7aba5c

by Dhivakar

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
不断挑拨离间!小玥儿忍无可忍,一个动作揭开了与马筱梅的关系

不断挑拨离间!小玥儿忍无可忍,一个动作揭开了与马筱梅的关系

可乐谈情感
2026-05-13 00:17:36
溥仪的贴身侍卫,不仅睡过皇后婉容,还无恶不作,后来被毙于刑场

溥仪的贴身侍卫,不仅睡过皇后婉容,还无恶不作,后来被毙于刑场

宅家伍菇凉
2026-05-07 16:58:56
周迅王骁关系曝光,陈坤领证传闻真相大白

周迅王骁关系曝光,陈坤领证传闻真相大白

汉字笔迹心理分析
2026-05-12 19:21:53
老人不死,子孙遭罪?如果家有八九十岁双亲还在,要牢记这两条准则

老人不死,子孙遭罪?如果家有八九十岁双亲还在,要牢记这两条准则

心理观察局
2026-05-05 09:24:14
奔驰撞人2死6伤后续:女司机正脸曝光,职业反差太大路人曝猛料

奔驰撞人2死6伤后续:女司机正脸曝光,职业反差太大路人曝猛料

大鱼简科
2026-05-11 16:56:45
4月汽车销量前十只剩一款燃油车了

4月汽车销量前十只剩一款燃油车了

金融界
2026-05-12 18:21:50
俄媒曝出惊天内幕:莫斯科故意“养着”泽连斯基,只为一件事

俄媒曝出惊天内幕:莫斯科故意“养着”泽连斯基,只为一件事

无情有思ss
2026-05-13 03:04:19
在名为“统治东方”的地方,让东方人去庆贺?海参崴阅兵未免过了

在名为“统治东方”的地方,让东方人去庆贺?海参崴阅兵未免过了

历史摆渡
2026-05-10 18:55:03
意甲加冕,国米不只赢了一个赛季!橡树加大投资,未来可期!

意甲加冕,国米不只赢了一个赛季!橡树加大投资,未来可期!

肥强侃球
2026-05-12 23:12:44
访华团落地不到7天,巴外长便公开质问中国:嘴上尊重,骨头很硬

访华团落地不到7天,巴外长便公开质问中国:嘴上尊重,骨头很硬

素衣读史
2026-05-11 21:54:32
004数据解读——沙特联:利雅得胜利vs利雅得新月

004数据解读——沙特联:利雅得胜利vs利雅得新月

懂球帝
2026-05-12 15:42:19
难兄难弟,维拉和热刺是本赛季英超仅有的2支还没获得点球的球队

难兄难弟,维拉和热刺是本赛季英超仅有的2支还没获得点球的球队

懂球帝
2026-05-13 03:46:11
散步再次被关注!医生发现:走得越多,高血压患者血管或越干净?

散步再次被关注!医生发现:走得越多,高血压患者血管或越干净?

健康科普365
2026-05-12 20:30:06
辣眼睛!徐州女子出轨求原谅被拒,不断扇自己耳光,现场照片流出

辣眼睛!徐州女子出轨求原谅被拒,不断扇自己耳光,现场照片流出

火山詩话
2026-05-12 06:31:04
卡西利亚斯点燃皇马球迷情绪:“我不想要穆里尼奥”

卡西利亚斯点燃皇马球迷情绪:“我不想要穆里尼奥”

绿茵情报局
2026-05-13 00:48:17
从今日起,中国不再需要日本道歉!这觉醒,来自3500万亡魂的重量

从今日起,中国不再需要日本道歉!这觉醒,来自3500万亡魂的重量

呼呼历史论
2026-05-13 00:53:16
老佛爷:现在不是聊穆帅的时候;有人想让我离开皇马但我不会走

老佛爷:现在不是聊穆帅的时候;有人想让我离开皇马但我不会走

懂球帝
2026-05-13 02:02:28
卫健委已将左氧氟沙星列为重点监控药!医生:服用千万注意7点

卫健委已将左氧氟沙星列为重点监控药!医生:服用千万注意7点

健康科普365
2026-05-10 18:45:06
中足联连开2张罚单:申花、上港外援均遭追加禁赛3场

中足联连开2张罚单:申花、上港外援均遭追加禁赛3场

中超伪球迷
2026-05-12 23:22:57
奶奶刚死3天,瞎子上门讨饭,临走时说:明天你们家要多一口棺材

奶奶刚死3天,瞎子上门讨饭,临走时说:明天你们家要多一口棺材

千秋文化
2026-04-27 20:12:24
2026-05-13 04:08:49
我不叫阿哏
我不叫阿哏
分享有趣、有用的故事!
456文章数 6747关注度
往期回顾 全部

科技要闻

宇树发布载人变形机甲,定价390万元起

头条要闻

特朗普称将同中方讨论对台军售和黎智英案 外交部回应

头条要闻

特朗普称将同中方讨论对台军售和黎智英案 外交部回应

体育要闻

骑士终于玩明白了?

娱乐要闻

白鹿风波升级!掉粉20万评论区沦陷

财经要闻

利润再腰斩 京东干外卖后就没过过好日子

汽车要闻

吉利银河“TT”申报图曝光 电动尾翼+激光雷达

态度原创

健康
本地
家居
旅游
公开课

干细胞能让人“返老还童”吗

本地新闻

用苏绣的方式,打开江西婺源

家居要闻

极简主义下的居住场域与空间

旅游要闻

故宫挤满游客,人人撑伞前行:宁愿热到出汗,也要奔赴紫禁城!

公开课

李玫瑾:为什么性格比能力更重要?

无障碍浏览 进入关怀版