人工智能之核心基础 机器学习 第十五章 数据预处理

人工智能之核心基础 机器学习

第十五章 数据预处理


文章目录

  • [人工智能之核心基础 机器学习](#人工智能之核心基础 机器学习)
    • [15.1 数据探索性分析(EDA)](#15.1 数据探索性分析(EDA))
    • [15.2 缺失值处理](#15.2 缺失值处理)
      • [📌 原则:**先分析原因,再决定策略**](#📌 原则:先分析原因,再决定策略)
      • [✅ 常用方法:](#✅ 常用方法:)
        • [1. 删除法](#1. 删除法)
        • [2. 填充法](#2. 填充法)
    • [15.3 异常值处理](#15.3 异常值处理)
      • [🔍 识别方法](#🔍 识别方法)
      • [🛠️ 处理方法](#🛠️ 处理方法)
    • [15.4 特征编码](#15.4 特征编码)
      • [📌 分类特征处理](#📌 分类特征处理)
      • [🔢 数值特征离散化](#🔢 数值特征离散化)
    • [15.5 特征缩放](#15.5 特征缩放)
      • [📏 两种主流方法](#📏 两种主流方法)
      • [❓ 哪些算法需要缩放?](#❓ 哪些算法需要缩放?)
    • [15.6 特征选择](#15.6 特征选择)
      • [🔍 三大方法对比](#🔍 三大方法对比)
    • [15.7 半监督/自监督专属数据处理](#15.7 半监督/自监督专属数据处理)
      • [🧩 无标签数据清洗要点](#🧩 无标签数据清洗要点)
      • [🎨 自监督数据增强技巧(关键!)](#🎨 自监督数据增强技巧(关键!))
      • [🔗 少量标签与无标签数据的一致性处理](#🔗 少量标签与无标签数据的一致性处理)
    • [15.8 特征工程实战:全流程预处理(含半监督场景)](#15.8 特征工程实战:全流程预处理(含半监督场景))
      • [场景:电商用户行为预测(少量标签 + 大量无标签)](#场景:电商用户行为预测(少量标签 + 大量无标签))
    • [🎯 本章终极总结:数据预处理 Checklist](#🎯 本章终极总结:数据预处理 Checklist)
  • 资料关注

15.1 数据探索性分析(EDA)

🎯 目标:理解你的数据长什么样

步骤1:识别数据类型
类型 特点 示例
数值型 连续/离散数字 年龄、价格、点击次数
类别型 有限个取值 性别(男/女)、城市
有序型 类别但有顺序 评分(1~5星)、教育程度
文本型 自由文本 评论、商品描述
时间型 日期/时间 注册时间、交易时间
步骤2:基础统计描述
python 复制代码
import pandas as pd
df = pd.read_csv('data.csv')
print(df.info())        # 数据类型、非空数
print(df.describe())    # 数值特征统计(均值、std、min、max等)
print(df['category'].value_counts())  # 类别分布
步骤3:缺失值 & 异常值初筛
python 复制代码
# 缺失值比例
print(df.isnull().mean() * 100)

# 异常值:用箱线图快速查看
import matplotlib.pyplot as plt
df.boxplot(column=['income', 'age'])
plt.show()
步骤4:特征分布分析
python 复制代码
# 数值特征:直方图看是否偏斜
df['income'].hist(bins=30)
plt.title("收入分布")
plt.show()

# 类别特征:条形图
df['city'].value_counts().plot(kind='bar')
plt.show()

💡 关键

  • 收入通常右偏 → 需要对数变换
  • 某城市样本极少 → 可能需合并为"其他"

15.2 缺失值处理

📌 原则:先分析原因,再决定策略

缺失类型 特征 处理建议
完全随机缺失(MCAR) 与任何变量无关 可删除或填充
随机缺失(MAR) 与其它变量有关 推荐模型填充
非随机缺失(MNAR) 与自身值有关(如高收入不愿填) 谨慎处理,可能需新增"是否缺失"标志

✅ 常用方法:

1. 删除法
  • 行删除df.dropna() → 仅当缺失比例<5%
  • 列删除df.drop(columns=['col']) → 当某列>50%缺失
2. 填充法
python 复制代码
from sklearn.impute import SimpleImputer, KNNImputer

# 均值/中位数/众数填充
num_imputer = SimpleImputer(strategy='median')      # 数值用中位数(抗异常值)
cat_imputer = SimpleImputer(strategy='most_frequent')  # 类别用众数

# 插值填充(时间序列)
df['price'].interpolate(method='linear', inplace=True)

# KNN模型填充(利用相似样本)
knn_imputer = KNNImputer(n_neighbors=5)
X_filled = knn_imputer.fit_transform(X)

⚠️ 注意 :填充必须在训练集拟合,再应用于测试集,避免数据泄露!


15.3 异常值处理

🔍 识别方法

方法 公式/规则 适用场景
Z-score ∣ z ∣ > 3 |z| > 3 ∣z∣>3 数据近似正态分布
IQR Q 1 − 1.5 × I Q R Q1 - 1.5 \times IQR Q1−1.5×IQR 或 Q 3 + 1.5 × I Q R Q3 + 1.5 \times IQR Q3+1.5×IQR 任意分布,推荐!
箱线图 可视化IQR结果 快速检查
python 复制代码
# IQR方法
Q1 = df['income'].quantile(0.25)
Q3 = df['income'].quantile(0.75)
IQR = Q3 - Q1
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR

# 标记异常值
df['is_outlier'] = (df['income'] < lower_bound) | (df['income'] > upper_bound)

🛠️ 处理方法

方法 代码示例 适用场景
删除 df = df[~df['is_outlier']] 异常值极少(<1%)
修正 df['income'] = np.clip(df['income'], lower_bound, upper_bound) 传感器噪声
隔离 新增二值特征 is_income_high 业务上异常值有意义(如高净值客户)

💡 重要原则
不要盲目删除异常值!先问业务:这是错误数据,还是真实但稀有的情况?


15.4 特征编码

📌 分类特征处理

编码方式 适用场景 优缺点
标签编码(Label Encoding) 树模型(决策树、XGBoost) 简单,但引入虚假序关系
独热编码(One-Hot) 线性模型、神经网络 无序关系,但维度爆炸
目标编码(Target Encoding) 高基数类别(如城市ID) 利用标签信息,但需防过拟合
python 复制代码
from sklearn.preprocessing import LabelEncoder, OneHotEncoder
from category_encoders import TargetEncoder

# 标签编码(用于树模型)
le = LabelEncoder()
df['city_encoded'] = le.fit_transform(df['city'])

# 独热编码(用于线性模型)
ohe = OneHotEncoder(sparse_output=False)
city_ohe = ohe.fit_transform(df[['city']])

# 目标编码(需有标签y)
te = TargetEncoder()
df['city_target'] = te.fit_transform(df[['city']], y)

🔢 数值特征离散化

python 复制代码
# 等宽分箱
df['age_bin'] = pd.cut(df['age'], bins=5, labels=False)

# 等频分箱(每箱样本数相同)
df['income_qbin'] = pd.qcut(df['income'], q=4, labels=False)

何时离散化

  • 树模型:通常不需要
  • 线性模型:可捕捉非线性关系

15.5 特征缩放

📏 两种主流方法

方法 公式 适用算法
标准化(Z-score) x ′ = x − μ σ x' = \frac{x - \mu}{\sigma} x′=σx−μ SVM、逻辑回归、PCA、K-Means、神经网络
归一化(Min-Max) x ′ = x − x min ⁡ x max ⁡ − x min ⁡ x' = \frac{x - x_{\min}}{x_{\max} - x_{\min}} x′=xmax−xminx−xmin 神经网络(尤其图像像素0~1)
python 复制代码
from sklearn.preprocessing import StandardScaler, MinMaxScaler

# 标准化(推荐默认)
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)

# 归一化
minmax = MinMaxScaler()
X_minmax = minmax.fit_transform(X)

❓ 哪些算法需要缩放?

需要缩放 不需要缩放
SVM、逻辑回归、PCA、K-Means、KNN、神经网络 决策树、随机森林、XGBoost

💡 口诀
"基于距离或梯度的算法要缩放,基于规则的不用"


15.6 特征选择

🔍 三大方法对比

方法 原理 优点 缺点
过滤式 单变量统计(方差、相关系数) 快、简单 忽略特征交互
包裹式 用模型性能评价子集(如RFE) 考虑交互,效果好 计算慢
嵌入式 模型训练中自动选(如Lasso) 效率与效果平衡 依赖特定模型
python 复制代码
from sklearn.feature_selection import VarianceThreshold, SelectKBest, f_classif, RFE
from sklearn.linear_model import LogisticRegression

# 过滤式:低方差特征删除
vt = VarianceThreshold(threshold=0.1)
X_vt = vt.fit_transform(X)

# 过滤式:基于统计检验
skb = SelectKBest(score_func=f_classif, k=10)
X_skb = skb.fit_transform(X, y)

# 包裹式:递归特征消除
estimator = LogisticRegression()
rfe = RFE(estimator, n_features_to_select=10)
X_rfe = rfe.fit_transform(X, y)

# 嵌入式:L1正则化(Lasso)
lasso = LogisticRegression(penalty='l1', solver='liblinear')
lasso.fit(X_scaled, y)
selected = lasso.coef_ != 0

实践建议

先用过滤式 快速降维,再用嵌入式精细筛选。


15.7 半监督/自监督专属数据处理

🧩 无标签数据清洗要点

  • 一致性检查 :确保无标签数据与标签数据同分布

    python 复制代码
    # 用PCA/t-SNE可视化两者是否重叠
    all_X = np.vstack([X_labeled, X_unlabeled])
    labels = ['labeled']*len(X_labeled) + ['unlabeled']*len(X_unlabeled)
    # ... 画图检查
  • 去重 :无标签数据常含大量重复(如爬虫数据)

    python 复制代码
    df_unlabeled.drop_duplicates(inplace=True)

🎨 自监督数据增强技巧(关键!)

模态 增强方法
图像 随机裁剪、颜色抖动、旋转、高斯模糊
文本 随机掩码、同义词替换、句子打乱
表格 随机掩码特征、加高斯噪声
python 复制代码
# 图像增强示例(用于对比学习)
from torchvision import transforms

augment = transforms.Compose([
    transforms.RandomResizedCrop(224, scale=(0.2, 1.0)),
    transforms.RandomHorizontalFlip(),
    transforms.ColorJitter(0.4, 0.4, 0.4, 0.1),
    transforms.ToTensor(),
    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])

🔗 少量标签与无标签数据的一致性处理

  • 统一预处理管道

    python 复制代码
    # 错误做法:分别处理
    X_labeled_scaled = scaler.fit_transform(X_labeled)
    X_unlabeled_scaled = scaler.fit_transform(X_unlabeled)  # ❌ 数据泄露!
    
    # 正确做法:仅用标签数据拟合
    scaler = StandardScaler().fit(X_labeled)
    X_labeled_scaled = scaler.transform(X_labeled)
    X_unlabeled_scaled = scaler.transform(X_unlabeled)      # ✅

15.8 特征工程实战:全流程预处理(含半监督场景)

场景:电商用户行为预测(少量标签 + 大量无标签)

python 复制代码
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler, LabelEncoder
from sklearn.impute import SimpleImputer
from sklearn.feature_selection import SelectKBest, f_classif
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score

# ========================
# 1. 加载数据
# ========================
# 模拟数据:user_id, age, income, city, clicks, purchase (0/1)
np.random.seed(42)
n_labeled = 200    # 少量标签
n_unlabeled = 2000 # 大量无标签

# 生成有标签数据
df_labeled = pd.DataFrame({
    'age': np.random.randint(18, 70, n_labeled),
    'income': np.random.exponential(50000, n_labeled),
    'city': np.random.choice(['北京', '上海', '广州', '深圳', '其他'], n_labeled),
    'clicks': np.random.poisson(10, n_labeled),
    'purchase': np.random.binomial(1, 0.3, n_labeled)
})

# 生成无标签数据(同分布)
df_unlabeled = pd.DataFrame({
    'age': np.random.randint(18, 70, n_unlabeled),
    'income': np.random.exponential(50000, n_unlabeled),
    'city': np.random.choice(['北京', '上海', '广州', '深圳', '其他'], n_unlabeled),
    'clicks': np.random.poisson(10, n_unlabeled),
    'purchase': -1  # 无标签标记为-1
})

# 合并(保留标识)
df_all = pd.concat([df_labeled, df_unlabeled], ignore_index=True)
df_all['is_labeled'] = df_all['purchase'] != -1

# ========================
# 2. EDA
# ========================
print("缺失值比例:\n", df_all.isnull().mean())
print("\n收入分布偏度:", df_all['income'].skew())  # 通常>1,右偏

# ========================
# 3. 缺失值处理(本例无缺失,模拟一个)
# ========================
# 假设income有10%缺失
df_all.loc[np.random.choice(df_all.index, size=int(0.1*len(df_all)), replace=False), 'income'] = np.nan

num_imputer = SimpleImputer(strategy='median')
df_all['income'] = num_imputer.fit_transform(df_all[['income']])

# ========================
# 4. 异常值处理
# ========================
Q1 = df_all['income'].quantile(0.25)
Q3 = df_all['income'].quantile(0.75)
IQR = Q3 - Q1
upper_bound = Q3 + 1.5 * IQR
df_all['income'] = np.clip(df_all['income'], None, upper_bound)  # 修正上限

# ========================
# 5. 特征编码
# ========================
# 城市:目标编码(因有少量标签)
from category_encoders import TargetEncoder
te = TargetEncoder()
# 仅用有标签数据拟合
labeled_mask = df_all['is_labeled']
df_all['city_te'] = te.fit_transform(
    df_all.loc[labeled_mask, ['city']], 
    df_all.loc[labeled_mask, 'purchase']
)
# 应用到全部数据
df_all['city_te'] = te.transform(df_all[['city']])['city']

# ========================
# 6. 特征缩放
# ========================
features = ['age', 'income', 'clicks', 'city_te']
scaler = StandardScaler()
# 仅用有标签数据拟合(避免数据泄露)
scaler.fit(df_all.loc[labeled_mask, features])
df_all[features] = scaler.transform(df_all[features])

# ========================
# 7. 特征选择(仅用有标签数据)
# ========================
X_labeled = df_all.loc[labeled_mask, features]
y_labeled = df_all.loc[labeled_mask, 'purchase']

selector = SelectKBest(score_func=f_classif, k=3)
X_selected = selector.fit_transform(X_labeled, y_labeled)
selected_features = np.array(features)[selector.get_support()]

print("选中的特征:", selected_features)

# ========================
# 8. 半监督训练:伪标签法
# ========================
# 步骤1: 用少量标签训练初始模型
rf = RandomForestClassifier(n_estimators=100, random_state=42)
rf.fit(X_labeled[selected_features], y_labeled)

# 步骤2: 预测无标签数据,取高置信度
X_unlabeled = df_all.loc[~labeled_mask, selected_features]
proba = rf.predict_proba(X_unlabeled)
pseudo_labels = rf.predict(X_unlabeled)
high_conf = proba.max(axis=1) > 0.8

# 步骤3: 构建增强训练集
X_train = pd.concat([
    X_labeled[selected_features],
    X_unlabeled[high_conf]
])
y_train = pd.concat([
    y_labeled,
    pd.Series(pseudo_labels[high_conf], index=X_unlabeled[high_conf].index)
])

# 步骤4: 重新训练
rf_final = RandomForestClassifier(n_estimators=100, random_state=42)
rf_final.fit(X_train, y_train)

# ========================
# 9. 评估(假设我们有隐藏测试集)
# ========================
# 模拟测试集
X_test = pd.DataFrame({
    'age': np.random.randint(18, 70, 500),
    'income': np.random.exponential(50000, 500),
    'clicks': np.random.poisson(10, 500)
})
# 目标编码需用原te
X_test['city_te'] = te.transform(pd.DataFrame({'city': np.random.choice(['北京','上海','其他'], 500)}))['city']
X_test_scaled = scaler.transform(X_test[features])
X_test_final = pd.DataFrame(X_test_scaled, columns=features)[selected_features]

y_test = np.random.binomial(1, 0.3, 500)  # 简化

acc = accuracy_score(y_test, rf_final.predict(X_test_final))
print(f"\n半监督模型准确率: {acc:.2%}")

📊 典型收益

  • 仅用200个标签:准确率 ~70%
  • 加入伪标签后:准确率 ~78%
  • 若有2000全标签:准确率 ~82% → 用10%标注达到95%性能!

🎯 本章终极总结:数据预处理 Checklist

步骤 关键问题 工具
EDA 数据长什么样?缺失/异常多吗? pandas, matplotlib
缺失值 缺失机制是什么?如何填充? SimpleImputer, KNNImputer
异常值 是噪声还是真实值?如何处理? IQR, np.clip
编码 类别特征怎么转数字? OneHotEncoder, TargetEncoder
缩放 算法需要标准化吗? StandardScaler
特征选择 哪些特征真正有用? SelectKBest, L1正则
半监督/自监督 无标签数据干净吗?增强够吗? 数据增强、一致性检查

💡 黄金法则
"预处理管道必须在训练集上拟合,再应用于验证/测试/无标签数据" ------ 防止数据泄露!


📘 延伸建议

  • 自动化工具:Feature-engine, tsfresh(时序)
  • 高级技巧:对抗验证(检查训练/测试分布一致性)
  • 未来方向:自动化特征工程(AutoFeat, Tsfresh)

🌟 建议
80%的机器学习工作是数据预处理,20%才是建模。

把数据弄干净,模型自然就强!

资料关注

公众号:咚咚王

gitee:https://gitee.com/wy18585051844/ai_learning

《Python编程:从入门到实践》

《利用Python进行数据分析》

《算法导论中文第三版》

《概率论与数理统计(第四版) (盛骤) 》

《程序员的数学》

《线性代数应该这样学第3版》

《微积分和数学分析引论》

《(西瓜书)周志华-机器学习》

《TensorFlow机器学习实战指南》

《Sklearn与TensorFlow机器学习实用指南》

《模式识别(第四版)》

《深度学习 deep learning》伊恩·古德费洛著 花书

《Python深度学习第二版(中文版)【纯文本】 (登封大数据 (Francois Choliet)) (Z-Library)》

《深入浅出神经网络与深度学习+(迈克尔·尼尔森(Michael+Nielsen)》

《自然语言处理综论 第2版》

《Natural-Language-Processing-with-PyTorch》

《计算机视觉-算法与应用(中文版)》

《Learning OpenCV 4》

《AIGC:智能创作时代》杜雨+&+张孜铭

《AIGC原理与实践:零基础学大语言模型、扩散模型和多模态模型》

《从零构建大语言模型(中文版)》

《实战AI大模型》

《AI 3.0》

相关推荐
七夜zippoe2 小时前
Python算法优化实战:时间与空间复杂度的艺术平衡
开发语言·python·算法·贪心算法·动态规划·复杂度
EterNity_TiMe_2 小时前
用 openJiuwen 构建一个历史介绍 AI Agent:从需求到可运行实操
人工智能·开源·实战测评·openjiuwen
无忧智库2 小时前
智慧法院法律大模型辅助办案与文书生成系统建设方案:全面解析AI如何重塑司法生产力
人工智能
力学与人工智能2 小时前
2025中国力学大会AI+分享 | 国防科技大学刘杰研究员:AI赋能PDE全流程求解
人工智能·ai赋能·国防科技大学·力学大会·pde求解
AC赳赳老秦2 小时前
华为昇腾适配DeepSeek实战:FP8转BF16权重与FlashMLA加速配置详解
大数据·人工智能·机器学习·数据分析·kafka·etl工程师·deepseek
sg_knight2 小时前
Claude Code 与 ChatGPT、Copilot 有什么区别?
人工智能·chatgpt·llm·copilot·claude·ai大模型·claude-code
赤狐先生2 小时前
第一步--了解深度神经网络
人工智能·神经网络·dnn
weixin_433179332 小时前
Python -- 列表 list、字典 dictionary
开发语言·python
小北方城市网2 小时前
SpringBoot 集成消息队列实战(RabbitMQ/Kafka):异步通信与解耦,落地高可靠消息传递
java·spring boot·后端·python·kafka·rabbitmq·java-rabbitmq