想象你是刚刚抵达案发现场的一位侦探。案件卷宗还没翻开,你只知道有人报了案,具体发生了什么、嫌疑人在哪里、证据链是否完整——全都茫无头绪。这时候,你不会急着冲进现场抓人,而是先环顾四周:问一句“这案子有多大?涉及多少人?什么类型的线索散落一地?”然后才蹲下身,逐一检查每一条线索,标出缺失的脚印,比对血迹的方向,画出人物关系网。 在机器学习竞赛里,数据探索(EDA)就是这位侦探的第一步现场勘查。在你训练哪怕一个模型之前,必须先读懂数据本身:它有几千行几列?哪些字段空空如也?目标变量长什么样?哪些特征彼此纠缠?这些看似琐碎的观察,最终会告诉你该往哪个方向做特征工程、该选什么模型、该用什么验证方案。蒙着眼睛建模,就像不勘查现场就抓人——大概率抓错。
这门“勘查术”是竞赛夺牌的起跑线。掌握 EDA 的完整套路,能让 AI 从业者从“拿到数据就训练”的蛮干,升级为“先看清数据再出手”的策略型选手,从而在真实项目与竞赛中大幅减少试错成本。
可视化演示
演示缺失值模式、目标变量分布与特征相关性矩阵,从EDA中提取有价值的建模洞察。
本节配有交互动效(进入视口后自动加载,约 3KB)。
缺失值:模式分析 完整样本 缺失样本 NA 识别缺失模式
数据概览检查
侦探到达案发现场,第一句话往往是:“这案子涉及多少人?现场有多大?”在数据世界里,对应的问题是:这个数据集有几行几列?每个字段是数字还是文本?数值的分布范围是多少?这些基础信息决定了你接下来要动用哪种“侦查工具”。
在 Jupyter 里,这通常体现为三个动作:df.shape 看形状,df.dtypes 看字段类型,df.describe() 看统计量。形状告诉你样本量和特征数,字段类型决定该用数值建模还是类别编码,统计量则给出均值、标准差、分位数——这些是后续一切判断的底稿。
均值是这里最朴素也最常用的统计量。它帮你快速感知一个数值特征的“中心”在哪,从而判断是否存在明显偏移。
回到侦探的视角:数据概览就像在现场拉起一道警戒线,先圈定案子的边界。你不需要立刻查明凶手,但必须知道这案子有多大、现场有哪些种类的物证——这是后续所有推断的坐标系。
- 求和符号的含义把从第 1 个样本到第 n 个样本的取值全部累加在一起。$\displaystyle \sum_{i=1}^{n} x_i$ 表示对 n 个数值求和。
- 乘以系数用总和除以样本量 n,相当于把总和平均摊回每个样本身上。$\displaystyle \frac{1}{n}$ 是“平均分配”的缩放因子。
- 得到均值最终得到的 \bar{x} 就是特征的中心位置。$\displaystyle \bar{x} = \frac{\text{总和}}{\text{样本数}}$
缺失值分析
现场勘查时,你常会发现“脚印断了一截”“监控录像少了一段”。这些残缺之处不是可以忽略的细节,而往往隐藏着案件的真相。数据的缺失值也一样:某个字段大量为空,可能是因为用户没填写,可能是因为系统采集失败,也可能是因为“特定人群才不填”——这正是很有价值的信号。
缺失值分析的起点是计算每一列的缺失率。缺失率过高的特征需要审慎对待:若超过 80%,通常会考虑直接删除;若在 5%~20% 之间,则需要进一步判断缺失模式是否能提供信息。
缺失值分析不是简单地“删掉空行”了事。如果缺失率在同一样本里同时扎堆出现,说明这些样本很可能来自同一类异常群组;如果缺失集中在某个特征上且与目标值相关,那缺失本身就可以当作一个强特征使用。侦探看到缺了一段脚印,会思考“为什么恰恰在这里断了”——这就是从缺失率走向缺失模式的思维升级。
- 统计空缺个数数一数第 j 个特征这一列中,有多少行是空值(null)。$\displaystyle \text{count}(x_j \text{ is null})$ 是空缺样本的计数。
- 除以总样本数用空缺数除以总行数 n,得到空缺的比例。$\displaystyle \frac{\text{count}(x_j \text{ is null})}{n}$ 是“空缺占比”。
- 转为百分比乘上 100% 把比例放大成更直观的百分数,便于横向比较各列的缺失严重程度。$\displaystyle \times 100\%$ 就是单位换算。
目标变量分析
侦探勘查现场时,最关心的问题是:“被害人是谁?他有什么特征?”在机器学习竞赛中,这个“被害人”就是目标变量——你要预测的那个 y。搞清楚 y 的分布形态,直接决定了该用什么模型、要不要做变换、用什么评价指标。
目标变量如果是连续值,先看它的直方图:是接近正态分布,还是严重右偏?如果是分类问题,看各类别数量悬殊程度。两者都会严重影响训练效果。最常见的处理是发现严重右偏时,对目标做对数变换。
偏度是衡量分布不对称程度的核心指标。它告诉你长尾到底甩在右边还是左边。
看完目标分布,侦探会感慨:“原来这位受害人身上有个显著特征。”这个洞察会指向后续操作:右偏则做对数变换,类别不平衡则考虑分层采样或加权损失。目标变量永远是案件的核心,围绕它的 EDA 怎么投入都不为过。
- 计算每个样本与均值的差值把每个 x_i 减去均值 \bar{x},得到“偏离中心多少”。$\displaystyle x_i - \bar{x}$ 是单样本的偏差。
- 对偏差求三次方再取平均三次方保留了偏差的符号,让正方向的极端值在分子上被放大。$\displaystyle \frac{1}{n}\sum_{i=1}^{n}(x_i-\bar{x})^3$ 是整个分布的“带符号离差”。
- 计算标准差并三次方分母是标准差的立方,相当于把偏差按分布的离散程度做了归一化。$\displaystyle \left(\sqrt{\frac{1}{n}\sum_{i=1}^{n}(x_i-\bar{x})^2}\right)^3$ 是归一化因子。
- 两者相除得偏度分子正负决定了偏斜方向,分母保证结果无量纲。$\displaystyle Skew(X) > 0$ 表示右偏。
特征分布分析
现场遗留的每一样物证——指纹、毛发、弹壳——都需要单独鉴别。特征分析就是对每个字段单独“验明正身”:数值特征是否集中在某个范围?类别特征有哪些取值?有没有偏离常规的异常值?
异常值往往是最容易误导模型的一类数据。一个极端值可能让线性模型的系数偏移十万八千里,也可能让均值统计失真。常用的异常值检测方法是 IQR(四分位距)法:把数据切出四段,定义上下界,超过界限的即为异常。
特征分布分析要配合可视化:直方图看数值分布的形状,条形图看类别的频数,箱线图直接标注异常值。侦探不会只看物证的清单,还要亲手掂量每样物证的分量——特征分析和可视化的关系正是如此,一通直方图扫下来,哪个特征有双峰、哪个有长尾、哪个有离群点,一目了然。
- 确定四分位数Q_1 是第 25% 分位数,Q_3 是第 75% 分位数,它们框住了中间一半数据。$\displaystyle Q_1$ 和 $Q_3$ 分别是数据排序后的位置值。
- 计算四分位距用 Q_3 减去 Q_1 得到 IQR,也就是中间 50% 数据占据的宽度。$\displaystyle IQR = Q_3 - Q_1$ 是这个核心区域的宽度。
- 推得上边界在 Q_3 的基础上加上 1.5 倍的 IQR,得到异常值的上警戒线。$\displaystyle \text{upper\_bound} = Q_3 + 1.5 \times IQR$ 是常规值允许到达的最远位置。
相关性分析
现场物证之间往往存在隐蔽的联系:某个嫌疑人的脚印同时出现在窗台和保险柜旁。特征之间的相关性,就是数据世界的“作案关联”。构建相关性矩阵,可以看到哪些特征彼此纠缠、哪些特征与目标变量关系密切,进而决定特征取舍与防共线策略。
最常用的相关性度量是皮尔逊相关系数,它衡量两个连续变量之间的线性关联强弱,取值在 -1 到 1 之间。
相关矩阵通常用热力图呈现:横纵轴都是特征,颜色深浅表示相关强度。侦探把关系网一画出来,往往能发现“原来这两个线索来自同一个人”——这种洞察在建模阶段就转化为:去掉冗余的共线特征,保留与目标高度相关的核心特征,甚至基于相关性做特征组合。
- 分别计算两组偏差x_i 减去其均值 \bar{x},y_i 减去其均值 \bar{y},得到各自的偏离量。$\displaystyle (x_i - \bar{x})(y_i - \bar{y})$ 是两者偏离方向的乘积。
- 乘积求和判断联动把每对偏离乘积累加。如果两者总是一起高一起低,乘积为正且数值大。$\displaystyle \sum_{i=1}^{n}(x_i - \bar{x})(y_i - \bar{y})$ 是协方差项。
- 除以各自的标准差分母部分用各自偏差平方和开根后相乘,相当于把不同量纲的特征对齐到同一尺度。$\displaystyle \sqrt{\sum (x_i - \bar{x})^2} \cdot \sqrt{\sum (y_i - \bar{y})^2}$ 是归一化因子。
- 得到标准化的相关系数结果 r 被严格约束在 [-1, 1] 区间内。$\displaystyle r > 0$ 为正相关,$r < 0$ 为负相关。
建模洞察复用
侦查的最后阶段,侦探需要把零散的线索整合成一套完整的案情理论,指出“凶手是谁、如何作案、下一步从哪突破”。EDA 同样如此:所有分布、缺失、相关性的观察,必须收敛为可执行的建模决策。
如果 EDA 发现目标严重右偏,就在特征工程阶段加入 log1p 变换;如果发现某些特征与目标相关性极高,就优先对其做分箱或交叉组合;如果发现数据存在严重类别不平衡,验证方案就必须采用分层采样。EDA 是为后续每一步建模提供决策依据的“情报总站”。
对数变换是处理长尾数据的典型操作,它能让大数值被压缩、小数值被拉开,减轻极端值的影响。
从 EDA 到建模,像侦探把案件报告递交给检察官:每一个结论都要有依据,每一条依据都来自现场勘查。EDA 的产物不是几张小图表,而是一份“建模作战地图”——它告诉你哪些特征值得深挖、哪些样本需要警惕、哪种模型先天占优。这份洞察,才是竞赛中从青铜走向王者的真正分水岭。
- 加上偏置 1y + 1 保证了 y=0 时变换结果也是 0,避免出现 \ln(0) 无定义的情况。$\displaystyle y + 1$ 是防止对零取对数。
- 取自然对数\ln 把指数级差异压缩成线性差异,长尾被“剪短”。$\displaystyle \ln(y+1)$ 是变换后的目标值。
- 建模后反变换预测完成后再用 \exp(预测值) - 1 还原到原始尺度,用于结果评估。$\displaystyle y = \exp(y') - 1$ 是反变换公式。
AI 应用场景
信贷风控模型上线前的数据体检
阶段:数据处理与探索阶段
解决的问题:信贷数据通常存在严重的缺失值和极端值:客户年收入有大量空白,部分样本负债收入比高达 9999%。传统做法是直接删残缺样本或让缺失值留白,结果导致模型在真实场景中泛化极差。通过 EDA 逐列统计缺失率、绘制目标违约率的分布直方图、构建特征相关矩阵,团队可以快速定位“哪类客户更容易缺失信息”,从而把这些线索转化为“缺失指示特征”,显著提升模型的区分度。
具体案例:某消费金融公司上线贷款违约预测模型前,数据分析师用 EDA 发现“月收入字段缺失”与违约率呈强相关——收入缺失反而意味着高风险群体。团队将此洞察编码为二值特征,AUC 提升了约 4 个百分点。同时 IQR 检测出 2000 余个极端值样本,经核查为异常申请,直接剔除后模型稳定性大幅改善。
Kaggle 房价预测竞赛的特征工程前哨
阶段:竞赛数据处理环节
解决的问题:Kaggle 的 House Prices 竞赛有近百个特征,大量特征缺失严重,且目标变量 SalePrice 明显右偏。新手直接喂给模型分数惨淡。通过系统 EDA:用偏度判断做 log1p 变换,用缺失率热力图找出“地下室质量”这类大量缺失但本身就能当“无地下室”标记的字段,再通过相关性矩阵锁定 GrLivArea 与 OverallQual 等核心特征,特征工程就有了明确优先级。
具体案例:参赛者在 EDA 阶段发现,SalePrice 经 log1p 变换后从右偏变为近似正态,随即对模型输出做逆变换评估,RMSE 显著下降;同时相关矩阵显示 TotalBsmtSF 与 1stFlrSF 高度共线,参赛者决定只保留其一,训练速度提升 20% 且精度未降。
电商用户流失预警项目的验证方案设计
阶段:模型验证阶段
解决的问题:用户流失数据集常出现类别严重不平衡——流失用户仅占 8%。如果直接随机划分训练集和验证集,验证集中流失样本可能寥寥无几,导致 P/R 波动剧烈。EDA 阶段通过检查目标变量的类别分布,团队决定采用分层采样,并在时间维度上验证“流失行为”的稳定性,最终选型梯度提升树而非朴素逻辑回归。
具体案例:某电商平台在用户流失预警项目中,EDA 发现活跃天数特征呈现双峰分布,且与流失标签明显联动。团队据此构造了“近 30 天活跃天数变化率”等特征,并设计了按周分层的时间序列验证方案,模型 AUC 提升 6%,上线后避免误杀大量高价值用户。
Python 演示
# -*- coding: utf-8 -*-"""数据探索EDA演示:概览、缺失、分布与相关性分析"""import numpy as npimport pandas as pd def load_demo_data(n=1000, seed=42): rng = np.random.default_rng(seed) df = pd.DataFrame({ 'age': rng.normal(40, 15, n).round(1), 'income': rng.lognormal(10, 0.8, n).round(0), 'score': (rng.normal(0, 1, n) * 5 + 60).round(1), 'category': rng.choice(['A', 'B', 'C', 'D'], n), 'target': (rng.normal(0, 1, n) - 0.3 * rng.normal(0, 1, n)).round(3) }) for col in ['income', 'category']: idx = rng.choice(df.index, size=int(n * 0.08), replace=False) df.loc[idx, col] = np.nan df.loc[rng.choice(df.index, size=5, replace=False), 'income'] = 9999 return df def inspect_overview(df): print('数据形状:', df.shape) print('字段类型:') print(df.dtypes.to_string()) print('基础统计量:') print(df.describe().round(2).to_string()) def analyze_missing(df): miss = df.isna().mean().mul(100).round(2) miss = miss[miss > 0] if miss.empty: print('无缺失值') return print('缺失率(%):') for col, rate in miss.items(): print(' %s: %.2f%%' % (col, rate)) def analyze_target(df, target='target'): print('目标变量统计:') print(df[target].describe().round(3).to_string()) print('偏度: %.3f' % df[target].skew()) def find_correlations(df, target='target'): num = df.select_dtypes(include=[np.number]).drop(columns=[target]) corr = num.corrwith(df[target]).abs().sort_values(ascending=False) print('与目标相关度Top3:') for col, r in corr.head(3).items(): print(' %s: %.3f' % (col, r)) cm = num.corr().abs() for i, c1 in enumerate(cm.columns): for c2 in cm.columns[i + 1:]: v = cm.loc[c1, c2] if v > 0.8: print('高共线性特征对: %s - %s = %.3f' % (c1, c2, v)) def main(): df = load_demo_data() inspect_overview(df) analyze_missing(df) analyze_target(df) find_correlations(df) if __name__ == '__main__': main()
rng.choice(df.index, size=int(n * 0.08), replace=False)随机挑出 8% 的行索引,为注入缺失值做准备,模拟真实数据的不完整状态。df.isna().mean().mul(100)逐列计算空值占比并转化为百分比,是缺失率统计的一行式写法。df[target].describe().round(3)一次性输出目标变量的均值、标准差、分位数和极值,快速嗅出分布异常。df[target].skew()直接计算目标变量的偏度,数值越大说明右尾越长,需要警惕对模型的干扰。num.corrwith(df[target]).abs().sort_values(ascending=False)计算各数值特征与目标的相关系数绝对值并按重要性降序,瞬间锁定最值得深挖的特征。cm.loc[c1, c2]从相关矩阵中顺手提取特征两两之间的相关系数,用于发现高共线对。
常见误区
误区EDA 不就是画几张直方图、热力图摆摆样子吗?反正画完图该训练还是训练,EDA 对分数没什么帮助。
正解EDA 的价值不在于“画没画图”,而在于“从图中读出了什么决策”。侦探不会因为拍了几张现场照就破案,关键是从照片里看出脚印方向、指纹位置。EDA 的正确产出是“建模决策清单”:是否做对数变换、哪些特征需要删掉、验证集要不要分层。如果画完图后两手空空,那确实是浪费时间的打卡;但若有决策结论,EDA 就是性价比最高的环节。
为何常见:很多初学者从教程里复制了一段“EDA 模板”,机械地跑一遍 describe 和 heatmap,却从未把结果和建模步骤连接起来,于是自然觉得 EDA 冗余没用。
误区这列有 10% 的缺失?直接把这 10% 的行删掉,或者干脆删掉整列,省事又干净。
正解缺失值不是垃圾,而是线索。侦探看到一段断了脚印的路面,不会直接把路面挖掉,而是会思考“脚印为什么在这里断”——缺失可能本身就是目标值的重要信号。在做信贷风控时,收入缺失的客户往往是高违约群体,把“缺失”当作一个取值保留下来,往往比删行更有效。要不要删、删多少,必须建立在缺失模式分析上,而不是肌肉记忆。
为何常见:删缺失值是门槛最低的处理方式,且在小规模样例上“看起来没出问题”,让人产生了安全的错觉;但真实数据中缺失往往与目标有隐蔽关联。
误区冰激凌销量和溺水人数相关系数高达 0.9,那肯定是吃冰激凌导致了溺水,模型里可以直接把冰激凌销量拿来做风控指标。
正解相关系数只描述“步调是否一致”,不证明“谁导致了谁”。夏天这两个变量同时升高,背后是“气温”这个第三方原因。EDA 里发现强相关特征时,要提醒自己相关≠因果。验证一个特征是否真的可用,要看它在时间平移、样本拆分后是否仍然稳定,而不是只看一纸相关矩阵。
为何常见:相关矩阵用颜色深浅制造了视觉冲击,很容易让人脑补出因果叙事;尤其当某个特征与目标相关性高达 0.9 时,克制“这就是关键原因”的冲动很难。
误区目标变量的直方图画完了,整体看着还挺正的,看来不需要做什么预处理。
正解全局分布平滑,不代表每个分组内分布也平滑。侦探看整体案卷会觉得“这邻居街坊都很正常”,但逐户走访才发现某一家人行迹可疑。EDA 必须按关键分组(如类别特征、时间窗口)拆开看分布的差异:A 类客户的目标均值也许是 5,B 类却是 50。这种“局部信号”往往才是建模最需要的金矿。
为何常见:直方图一眼就看完了,人本能地会满足于整体形状;而分组是一件麻烦事,没有明确指引时很少有人主动去做。
面试题
Q1. EDA 在机器学习竞赛流程中的主要目的是什么?
- A.压缩数据量节省存储空间
- B.理解数据分布以指导特征工程← 正确答案
- C.直接替代模型训练过程
- D.自动生成高维组合特征
答案:B。EDA 的核心使命是“看清数据、指导建模”,而不是替代训练或压缩存储。侦探勘查现场是为了找到破案线索,而特征工程正是建模路上的破案线索。A、C、D 都是对 EDA 角色的误解。
Q2. 某连续特征缺失率达到 85%,最合理的初步处理策略是?
- A.立即用均值填充缺失值
- B.当作核心特征重点建模
- C.评估后优先考虑删除← 正确答案
- D.复制其他列数据补上
答案:C。缺失率过高意味着该列几乎为空,难以提供稳定信息,通常会先评估再删除。均值填充对此类列意义不大,因为它无法还原真实分布;复制数据或当核心特征也缺乏依据。侦探不会对着一段完全消失的脚印死磕,而是先看看还有没有其他线索。
Q3. 目标变量严重右偏时,常见的处理手段是?
- A.直接删除大部分样本
- B.对所有特征做标准化
- C.对目标做对数变换← 正确答案
- D.把目标值四舍五入
答案:C。右偏意味着长尾在右侧、极端值拉高了均值,对数变换能压缩长尾、让分布更接近正态,利于线性模型和误差评估。删除样本、标准化、四舍五入都无法解决偏态问题。这就像用对数刻度画地震震级图,让 8 级和 2 级能放在同一张图上比较。
Q4. 皮尔逊相关系数主要衡量的是两个变量之间的什么关系?
- A.非线性依赖关系
- B.线性关联强度与方向← 正确答案
- C.因果作用大小
- D.互信息的信息量
答案:B。皮尔逊相关系数对线性关系敏感,反映两个变量协同偏离各自均值的程度,大小表示强弱、正负表示方向。它无法捕捉复杂的非线性依赖,更不能判断因果。用脚印步调判断两个嫌疑人是同向还是反向行动可以,但断定谁带坏了谁就超出它的能力了。
Q5. 使用 IQR 方法检测异常值时,上边界通常定义为?
- A.Q1 - 1.5 × IQR
- B.Q3 + 1.5 × IQR← 正确答案
- C.Q1 + 1.5 × IQR
- D.Q3 - 1.5 × IQR
答案:B。上边界等于 Q3 加上 1.5 倍四分位距,超出即视为异常。选项 A 是常用的下边界,C、D 的方向和取值位置均不正确。好比高速路的上限是“最高限速 = 正常车流速度 + 1.5 倍波动幅度”,超过这个速度就会被摄像头抓拍。
Q6. EDA 中分析类别特征时,合理的思路有哪些?
- A.检查各类别的频数分布
- B.统计类别数量决定编码方式
- C.将类别值按字母表转数字
- D.检查类别与目标变量的关系
答案:。频数分布能揭示稀有类别,类别数量决定用 one-hot 还是 target encoding,与目标的交叉分析能发现高风险分组。而把类别按字母表转数字是机械映射,没有业务或统计依据,属于伪编码。侦探看嫌疑人的职业,不会按姓名首字母排序,而是看职业与作案手法的关系。
Q7. 以下哪项不是 EDA 阶段的典型产出?
- A.特征工程优先级清单
- B.模型线上部署脚本← 正确答案
- C.缺失值处理策略
- D.验证方案设计建议
答案:B。EDA 产出的是决策依据,包括特征优先级、缺失策略、验证方案设计等,但不包括线上部署脚本。部署属于运维工程阶段,相当于侦探交出了案情报告,却不需要亲手去追捕犯人。A、C、D 都是 EDA 报告中的核心章节。
Q8. 时间序列数据中,目标变量随月份周期性波动,合理的验证方案设计依据是?
- A.随机打乱后随机划分
- B.仅按目标值大小排序
- C.按时间先后顺序划分训练与验证集← 正确答案
- D.删除时间字段后交叉验证
答案:C。时间序列数据必须保持时序完整性,用未来预测过去会造成数据泄漏。按时间顺序划分训练集和验证集,才能还原真实业务的在线预测场景。随机打乱和删除时间字段都会破坏时序结构。侦探查案必须按时间轴还原案发经过,而不是把线索洗成一团乱麻。
Q9. 关于缺失值的理解,以下哪些说法正确?
- A.缺失模式可能与目标变量相关
- B.缺失率高的特征应无条件删除
- C.缺失本身可以编码为额外特征
- D.不同列缺失率相加即为总缺失率
答案:。缺失模式可能携带被忽略的信号,编码成“缺失指示”特征往往有增益;缺失率高的列应评估后决定去留,而非无条件删除。D 选项将各列缺失率直接相加没有任何统计意义。现场缺了一段的脚印,恰恰可能是判断凶手逃跑方向的关键证据。
Q10. 如果 EDA 发现多个特征与目标相关系数都较低,合理的后续动作是?
- A.认为数据没有价值直接放弃
- B.尝试构造交叉特征与组合特征
- C.考虑非线性模型的建模能力
- D.用一个高相关特征复制多份加权
答案:。低线性相关不代表没有非线性关系,构造交叉特征或改用树模型常能挖掘出隐藏模式。复制高相关特征加权重没有增加信息量,反而加剧共线性。侦探发现单一脚印都对不上嫌疑人时,会考虑“会不会是同伙作案”——组合特征就是数据里的同伙。