《模型不玄学》第5章 看懂你的数据:先认字段,再过门禁

第5章 看懂你的数据:先认字段,再过门禁

小白一句话

建模之前,得先搞清楚每一列在说什么,再把脏行踢出去。烂数据进去,模型再花哨也是烂结果。这章把示例数据的字段认一遍,再实跑一道质量门禁。

五列各自在说什么

示例数据(附件/00_公共/每日领取明细_示例.csv)每行一次领取,五列:

含义 合法取值 容易踩的坑
uid 用户编号 非空、非负 空的、负的要拦
claim_date 领取日期 YYYY-MM-DD,且在合理范围 格式错、超出范围的要拦
task_type 任务类型 非空(签到 / 看视频 / 分享好友 / 小游戏 / 填问卷) 空值要拦
num 当天该类任务领取次数 正整数(>0) ≤0 要拦
amount 当天该类任务奖励金额(元) 非负小数 <0 要拦

还有一个看不见但很关键的规矩:唯一键 = uid + claim_date + task_type。同一个用户、同一天、同一类任务,只能有一行。违反它,说明要么重复记录、要么统计错了。

顺带一句:样本里日期是显式写成一列的,方便你直接分析。真实大规模数据里,日期常由"按天分区的文件"隐含给出、表里未必有这一列------含义一样,只是来源不同。下面讲"缺失"时会回到这个差别。

数据质量门禁:三类脏数据必须拦

门禁是数据底座阶段(第3章第 1 站)的第一道关,干三件事:

  1. 字段合法性:uid 非空、日期能解析、task_type 非空、num 是正整数、amount 非负;
  2. 重复主键:同一个 (uid, claim_date, task_type) 只能出现一次;
  3. 范围校验:日期落在合理区间,不出现 2099 年这种离谱值。

手册配套的 附件/00_公共/check_quality.py 把这套门禁实现了一遍。直接跑原始样本:

bash 复制代码
python 附件/00_公共/check_quality.py

输出:

text 复制代码
[原始样本] 总行数=1643  脏行数=0  重复主键组数=0

样本本身是干净的,跑门禁只是为了确认"没有雷"。

再让它演示拦脏数据------人为往里塞三条:一条复制 U0036 某行(重复主键)、一条 amount 写成 -5(金额为负)、一条 uid 留空。重跑:

text 复制代码
[注入 3 条脏数据后] 总行数=1646  脏行数=3  重复主键组数=2
  第 1643 行 问题: ['重复主键']
  第 1644 行 问题: ['amount<0', '重复主键']
  第 1645 行 问题: ['uid为空']

三类问题全被抓住。如果不拦,后果很具体:

  • 重复主键:同一行为被算重。U0036 的总奖励、记录数、甚至活跃天数都会被凭空抬高,第3章那张特征表直接歪掉;
  • amount<0:奖励总额算出负值或偏差,模型还可能把"负奖励"当成一种奇怪信号去学;
  • uid 为空:用户数统计失真,而且这行没了分组键,要么整行丢掉、要么分组时报错。

门禁把它们清掉,后面的特征和标签才不会被带偏。

原理深挖:没出现的那天,不能补成"未活跃"

这是本章最关键、也最容易被忽略的一点。

我们的数据是事件表 :只有"发生了领取"才记一行。一个用户某天没出现,只代表"我们没观测到他领取",不代表"他领了 0 次"。这两件事差很远,但新手常混为一谈,顺手把缺失的日期补成 0。

为什么不能补:

  1. 日志可能不全。某些日期的数据文件可能缺失、迟到。那天"没记录"可能是数据没到,而不是用户真没动。把沉默当成"确认零活跃",是凭空造结论。
  2. 补零会污染特征和标签。你凭空塞进去的"0 活跃",会被当成负面信号喂给模型;拿它算"未来 7 天是否回来"的标签时,也可能误判。
  3. 分母会失真。一旦你把"没观测到的天"算进总天数,再去算"活跃率 = 活跃天数 / 总天数",分母就被你注水了,活跃率整体偏低,结论跟着错。

正确做法:把数据当事件流。算"活跃天数"就去数"出现过的不同日期";要算频率,分母是"被观测到的天数",不是"日历总天数"

拿样本举个具体的:数据覆盖 07-01~07-30 共 30 天。U0020 只活跃过 1 天。如果你图省事用 30 天做分母,算出"活跃率 = 1/30 ≈ 3%",看着特别凉。可 U0020 也许 07-15 才第一次露面(之前根本没他的数据),用 30 天分母就冤枉他了。分母该是"他被观测到的天数"才对------而这一步又引出下一个坑:U0020 只被观测到 1 天,那"活跃率 = 1/1 = 100%"又离谱了。

这串反直觉的结论,恰恰说明稀疏观测的用户不能随便喂模型。本项目后面用"冷启动分级"单独处理这类人(观测天数太少的,不进正式模型),就是为躲开这个坑。第3章特征表里的"近 7 天 / 近 14 天"之所以安全,是因为它们数的是"出现过的天数",没碰分母;可你一旦往后做比率类特征,分母怎么取就必须想清楚。

回到样本和真实数据的差别:样本日期是显式列,陷阱主要在"分母";真实大数据日期靠文件分区,陷阱还多个"某天文件压根没来"------那天的缺失不能当成"全员未活跃"。两句话是一回事:缺席 ≠ 零

动手:用样本过一遍门禁

  1. 打开 附件/00_公共/每日领取明细_示例.csv,肉眼确认五列都在、长相对应;
  2. python 附件/00_公共/check_quality.py,看到"脏行数=0"就说明样本干净;
  3. 自己改一行:把 U0036 的某行原样复制一遍粘到末尾,再跑一次,看它被标成"重复主键";
  4. 算一笔:U0020 用 30 天分母算活跃率是多少?换成"观测天数"分母又是多少?体会一下分母选错有多离谱,也想明白为什么稀疏用户要单独路由。

小结

这章认了字段、过了门禁,并记住一条贯穿全书的原理:数据是事件表,缺席不等于零活跃;算比率时分母要用观测天数,稀疏用户要单独处理。数据这关过了,下一章进特征与标签篇------从这张干净的事件表,造出模型和标签真正吃的特征。

相关推荐
国科安芯14 分钟前
低轨卫星姿轨控系统中抗辐射MCU的选型依据与工程实践
单片机·嵌入式硬件·算法·架构·系统安全·低轨卫星·抗辐射
高亦真19 分钟前
今天是学习嵌入式的第33天
linux·学习·算法
CoderYanger20 分钟前
A.每日一题:3345. 最小可整除数位乘积 I
java·数据结构·程序人生·算法·leetcode·面试·学习方法
带多刺的玫瑰22 分钟前
Leecode#16刷题之最接近的三数之和
数据结构·算法
Yfhonier28 分钟前
岛屿数量(DFS)
算法·深度优先
橘子汽水16829 分钟前
Leetcode15:三数之和
java·数据结构·算法
黄金龙PLUS32 分钟前
ASCON置换算法的优缺点
算法·网络安全·密码学·哈希算法·同态加密
邪修king37 分钟前
Re:Linux 系统篇(十六):进程篇(五):O (1) 调度算法深度解析 —— 优先级数组、位图优化与活跃 / 过期双队列
linux·运维·算法