3. 数据需求分析与采集策略:到底需要哪些数据?从哪来?怎么拿?
好,咱们进入第三章。前面我们把业务需求理清了,模型目标也定好了。接下来这一步,说白了就是“找米下锅”——数据从哪来?
我个人习惯,在动手写任何一行采集代码之前,先花至少半天时间把数据需求清单列清楚。你想想看,模型做得再漂亮,数据源搞错了,或者数据量不够,那全是白搭。我在项目中遇到过好几次,业务方拍胸脯说“数据都有”,结果一查,关键字段的覆盖率不到 30%。嗯,那叫一个酸爽。
3.1 数据需求清单:先问自己三个问题
别急着去翻数据库。先拿张纸,把下面三个问题写下来:
- 模型需要哪些特征? 用户画像?交易行为?设备信息?
- 标签(目标变量)是什么? 这个数据有没有历史记录?
- 数据的时间跨度多长? 训练集需要过去 3 个月还是 3 年?
核心原则: 数据需求清单必须与第二章的模型目标一一对应。每个特征都要能回答“为什么需要它”。
举个例子。假设我们要做一个“用户流失预警”模型。那数据需求清单大概长这样:
| 数据类别 | 具体字段 | 用途 | 时间范围 |
|---|---|---|---|
| 用户基础信息 | 注册时间、年龄、性别、地域 | 构建用户画像基线 | 截至当前 |
| 行为日志 | 登录频次、页面停留时长、点击事件 | 提取活跃度特征 | 过去 90 天 |
| 交易数据 | 订单金额、支付方式、退款记录 | 计算消费能力与粘性 | 过去 180 天 |
| 客服交互 | 投诉次数、工单类型、解决时长 | 识别负面体验信号 | 过去 90 天 |
| 标签(目标) | 是否流失(1/0) | 模型训练与评估 | 未来 30 天 |
你看,每个字段都有明确的“用途”列。这就是数据需求分析的核心——拒绝模糊。
3.2 数据来源:内部 DB、第三方 API、日志文件
数据不会自己送上门。一般来说,来源就三种。我按优先级排个序:
3.2.1 内部数据库(首选)
这是最靠谱的来源。公司自己的 MySQL、PostgreSQL、Hive、ClickHouse 等等。数据质量可控,权限也好申请。
- 优点: 稳定、安全、延迟低。
- 坑: 字段定义可能跟业务文档对不上。我曾经遇到过“订单状态”字段,代码里写的是 0/1/2,文档里写的是“待支付/已支付/已取消”,结果 0 代表“已取消”。嗯,这种坑踩一次就够了。
3.2.2 第三方 API(次选)
比如天气数据、地图数据、社交平台数据。这些数据通常需要付费,而且有调用频率限制。
- 优点: 能补充内部没有的外部特征。
- 坑: API 可能随时变更字段,或者突然限流。我建议在代码里加个熔断机制,别让第三方 API 挂了导致整个 ETL 流程卡死。
3.2.3 日志文件(备选)
服务器 Nginx 日志、App 埋点日志。这些数据量巨大,但信息密度低。
- 优点: 最原始、最真实。
- 坑: 解析起来很痛苦。格式不统一,还有大量脏数据。我曾经处理过一份日志,里面混了二进制乱码,排查了半天才发现是某个老版本 SDK 的 bug。
我的建议: 优先从内部 DB 拿数据。如果内部 DB 没有,再考虑日志文件。第三方 API 作为最后补充,而且一定要做好降级方案。
3.3 数据采集技术方案:ETL 还是实时流?
数据来源确定了,接下来就是怎么把数据搬到你的数据仓库或者特征存储里。这里有两个主流方案:
3.3.1 传统 ETL(批处理)
适合历史数据、离线训练场景。每天凌晨跑一次,把昨天的数据拉过来。
- 工具: Apache Airflow、Informatica、Talend。
- 适用场景: 用户画像、月度报表、模型离线训练。
# 一个简单的 Airflow DAG 示例
from airflow import DAG
from airflow.operators.python import PythonOperator
from datetime import datetime, timedelta
def extract_from_db():
# 从 MySQL 拉取昨天的订单数据
pass
def transform_data():
# 清洗、去重、特征工程
pass
def load_to_warehouse():
# 写入 Hive 表
pass
default_args = {
'owner': 'data_team',
'retries': 1,
'retry_delay': timedelta(minutes=5),
}
with DAG(
'user_behavior_etl',
start_date=datetime(2024, 1, 1),
schedule_interval='0 2 * * *', # 每天凌晨 2 点
catchup=False
) as dag:
t1 = PythonOperator(task_id='extract', python_callable=extract_from_db)
t2 = PythonOperator(task_id='transform', python_callable=transform_data)
t3 = PythonOperator(task_id='load', python_callable=load_to_warehouse)
t1 >> t2 >> t3
3.3.2 实时流处理
适合需要秒级响应的场景,比如风控、实时推荐。
- 工具: Apache Kafka + Flink / Spark Streaming。
- 适用场景: 实时特征计算、在线推理。
注意: 实时流不是万能的。它运维成本高,数据回溯困难。我见过不少团队,一上来就搞实时流,结果数据对不上,排查问题要翻好几天的日志。我的建议是:能用批处理解决的,就别上实时流。等业务量真的上来了,再考虑迁移。
3.4 数据隐私与合规性:GDPR 不是闹着玩的
这部分我放在最后,但它的重要性排第一。尤其是你的业务涉及欧洲用户,或者公司有上市计划,数据合规就是红线。
3.4.1 核心原则
- 数据最小化: 只采集模型需要的字段。别为了“以后可能有用”就一股脑全存下来。
- 去标识化: 用户 ID、手机号、邮箱等个人身份信息(PII),在进入特征工程之前必须脱敏。
- 明确告知: 数据用途必须在用户协议里写清楚。模型训练算不算“合理使用”?这个得跟法务确认。
3.4.2 技术落地
我一般会在 ETL 流程里加一个“脱敏层”。数据从源库出来,先经过脱敏模块,再进入数据仓库。
# 脱敏示例:对手机号进行掩码处理
def mask_phone(phone: str) -> str:
if len(phone) == 11:
return phone[:3] + '****' + phone[7:]
return phone
# 对用户 ID 进行哈希处理
import hashlib
def hash_user_id(user_id: str) -> str:
return hashlib.sha256(user_id.encode()).hexdigest()[:16]
避坑指南: 我曾经在一个项目里,因为疏忽把用户的原始 IP 地址存到了特征表里。虽然只是内部使用,但审计的时候被查出来了。嗯,从那以后,我要求所有 PII 字段在入库前必须经过脱敏,而且脱敏逻辑要写进代码审查清单里。
3.5 本章知识结构图
下面这张图,把数据需求分析到采集策略的完整链路串起来了。你可以把它当作一个检查清单:
这张图从左到右、从上到下,就是咱们做数据采集的完整流程。每一步都有对应的技术选型和注意事项。你照着这个框架走,基本不会漏掉关键环节。