You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

机器学习数据预处理的正确流程是什么?附二分类场景验证请求

二分类问题机器学习数据预处理分步指南/速查表

你的整体流程框架遵循了数据泄露防控的核心原则,是可行的,但部分步骤顺序需要调整,同时补充一些关键细节。以下是优化后的完整流程及疑问解答:


一、优化后的完整预处理流程

步骤1. 加载数据

import pandas as pd    

df = pd.read_csv("data.csv")

步骤2. 划分训练集与测试集

核心规则:必须先划分,再做任何预处理,彻底杜绝数据泄露

from sklearn.model_selection import train_test_split

# 若数据存在类别不平衡,用stratify保证训练/测试集的类别比例一致
train_df, test_df = train_test_split(
    df, 
    test_size=0.33, 
    random_state=42, 
    stratify=df['target']
)

步骤3. 仅针对训练集做探索性数据分析(EDA)

import matplotlib.pyplot as plt
import seaborn as sns

# 基础统计与结构分析
train_df.info()
train_df.describe()

# 分布与相关性可视化
sns.displot(train_df)
sns.boxplot(data=train_df)
corr_matrix = train_df.corr()
# 查看特征与目标变量的相关性排序
corr_matrix["target"].sort_values(ascending=False)
sns.scatterplot(x="Column X", y="target", data=train_df)

步骤4. 训练集异常值处理

必须在缺失值填充、数据缩放前完成,避免异常值干扰统计量(如均值、方差)

# 基于四分位数法识别异常值范围
q1 = train_df.quantile(0.25)
q3 = train_df.quantile(0.75)
iqr = q3 - q1
lower_bound = q1 - 1.5 * iqr
upper_bound = q3 + 1.5 * iqr

# 处理异常值:根据业务场景选择删除、截断或替换
train_df = train_df[~((train_df < lower_bound) | (train_df > upper_bound)).any(axis=1)]

步骤5. 训练集缺失值处理

# 查看缺失值统计
train_df.isnull().sum()
# 定位含缺失值的行
train_df[train_df["Column"].isnull()]

# 针对性处理缺失值
# 数值型特征:用中位数(不受异常值影响)填充
train_df["numerical_col"] = train_df["numerical_col"].fillna(train_df["numerical_col"].median())
# 分类特征:用众数填充或新增"缺失"类别
train_df["categorical_col"] = train_df["categorical_col"].fillna(train_df["categorical_col"].mode()[0])

步骤6. 训练集特征工程(含分类数据处理)

将分类数据编码整合到特征工程中,先完成编码再做其他特征操作:

import numpy as np
from sklearn.preprocessing import OneHotEncoder

# 1. 分离特征与目标变量
X_train = train_df.drop("target", axis=1)
y_train = np.where(train_df["target"] == "yes", 1, 0)

# 2. 分类特征编码
onehot = OneHotEncoder(handle_unknown="ignore", sparse_output=False)
categorical_cols = X_train.select_dtypes(include=["object", "category"]).columns
encoded_cols = onehot.fit_transform(X_train[categorical_cols])
# 合并编码后的特征
X_train = pd.concat([
    X_train.drop(categorical_cols, axis=1),
    pd.DataFrame(encoded_cols, columns=onehot.get_feature_names_out(categorical_cols))
], axis=1)

# 3. 删除高相关特征
corr_matrix = X_train.corr()
high_corr_pairs = [(i,j) for i in corr_matrix.columns for j in corr_matrix.columns if i<j and abs(corr_matrix[i][j])>0.8]
for pair in high_corr_pairs:
    X_train = X_train.drop(pair[1], axis=1)

# 4. 偏态特征转换
skew_threshold = 0.5
skewed_cols = X_train.skew()[abs(X_train.skew()) > skew_threshold].index
for col in skewed_cols:
    # 对数变换(避免负数值,加1)
    X_train[f"log_{col}"] = np.log(X_train[col] + 1)
    X_train.drop(col, axis=1, inplace=True)

步骤7. 数据缩放

仅对训练集执行fit操作,测试集仅做transform;二分类任务无需缩放目标列,回归任务仅在使用神经网络等对尺度敏感的模型时才需缩放目标列。

from sklearn.preprocessing import StandardScaler

scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)

步骤8. 不平衡数据处理(SMOTE)

必须在缩放之后执行,因为SMOTE基于欧氏距离计算,尺度不一致会导致采样偏差

from imblearn.over_sampling import SMOTE

sm = SMOTE(random_state=42)
X_train_balanced, y_train_balanced = sm.fit_resample(X_train_scaled, y_train)

步骤9. 主成分分析(PCA)- 降维

必须在缩放之后执行,否则尺度大的特征会主导方差计算,导致PCA结果偏差;仅在特征数量过多、模型训练困难时使用,注意PCA会丢失特征可解释性。

from sklearn.decomposition import PCA

# 可选:设置n_components为小数(如0.95)表示保留95%的方差
pca = PCA(n_components=50)
X_train_pca = pca.fit_transform(X_train_balanced)

步骤10. 建模、拟合、评估、预测

核心:测试集的预处理必须完全复用训练集的管道,不能重新fit,推荐用Pipeline封装所有步骤避免出错:

from sklearn.pipeline import Pipeline
from sklearn.linear_model import RidgeClassifier
from sklearn.metrics import (
    accuracy_score, recall_score, precision_score, f1_score, confusion_matrix
)

# 封装完整预处理+模型管道
pipe = Pipeline([
    ("onehot", OneHotEncoder(handle_unknown="ignore", sparse_output=False)),
    ("scaler", StandardScaler()),
    ("smote", SMOTE(random_state=42)),
    ("pca", PCA(n_components=50)),
    ("model", RidgeClassifier())
])

# 训练管道
pipe.fit(train_df.drop("target", axis=1), y_train)

# 测试集预测与评估
y_test = np.where(test_df["target"] == "yes", 1, 0)
y_pred = pipe.predict(test_df.drop("target", axis=1))

accuracy = accuracy_score(y_test, y_pred)
precision = precision_score(y_test, y_pred)
recall = recall_score(y_test, y_pred)
f1 = f1_score(y_test, y_pred)
print(f"模型评估结果:准确率={accuracy:.2f}, 精确率={precision:.2f}, 召回率={recall:.2f}, F1分数={f1:.2f}")
print("混淆矩阵:")
print(confusion_matrix(y_test, y_pred, labels=[1,0]))

步骤11. 保存模型与预处理管道

必须保存完整管道,而非单独模型,否则无法处理新数据

import joblib

# 保存完整管道
joblib.dump(pipe, "binary_classification_pipeline.joblib")

# 加载使用
loaded_pipe = joblib.load("binary_classification_pipeline.joblib")
new_pred = loaded_pipe.predict(new_data)

二、关键疑问解答

  • 仅针对训练集做EDA是否正确?
    完全正确。测试集必须模拟真实生产环境中的未知数据,任何基于测试集的分析都会导致数据泄露,使模型评估结果失真。

  • 异常值处理是否必须提前?
    是的。异常值会严重影响均值、方差等统计量,进而干扰缺失值填充、数据缩放的效果,因此必须在这些步骤之前处理。

  • 特征工程是否需要提前处理?
    是的。新创建的特征(如对数变换后的特征、编码后的分类特征)需要和原始特征一起参与后续的缩放、降维等操作,因此必须在这些步骤之前完成。

  • 回归任务中是否需要缩放目标列?
    大部分传统回归模型(如线性回归、决策树、随机森林)不需要。仅在使用对尺度敏感的模型(如神经网络、支持向量机回归)时,才需要缩放目标列。

  • 应用PCA前是否需要缩放数据?
    必须。PCA基于特征的方差排序,尺度大的特征会主导方差计算,导致PCA结果偏向这些特征,因此必须先缩放所有特征到同一尺度。


内容的提问来源于stack exchange,提问作者Yara1994

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 23:42:31