《模型不玄学》第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 天分母算活跃率是多少?换成"观测天数"分母又是多少?体会一下分母选错有多离谱,也想明白为什么稀疏用户要单独路由。

小结

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

相关推荐
倒头就睡的小比特10 小时前
算法竞赛C++常用的STL
c++·算法
小羊没烦恼!10 小时前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
猎头南楼12 小时前
知识社区推荐系统实践:新用户冷启动与长短期兴趣建模的挑战 资深推荐算法工程师
人工智能·深度学习·算法·机器学习
旖旎夜光12 小时前
力控面试题 01.01: 判定字符是否唯一(位运算) —— 题解
c++·学习·算法·leetcode·力控
wzdark13 小时前
大规模并行计算中的负载均衡算法研究4
算法
Because_of_Her113 小时前
并查集-听课笔记
笔记·算法·并查集
码流子13 小时前
高速公路安全监测实践:碰撞监测预警+物联网底座,从感知到处置的闭环
大数据·人工智能·物联网·算法·架构
another heaven13 小时前
【算法/C++ MD5算法能否逆解码?原理、C++实现与同类哈希算法对比】
c++·算法·哈希算法
wzdark13 小时前
从算法设计模式看编程思维的抽象能力4
算法
2601_9622186114 小时前
万象生鲜系统称重自动多退少补算法解决生鲜非标品痛点
大数据·数据库·人工智能·python·算法