3. 数据需求分析与采集策略:到底需要哪些数据?从哪来?怎么拿?

好,咱们进入第三章。前面我们把业务需求理清了,模型目标也定好了。接下来这一步,说白了就是“找米下锅”——数据从哪来?

我个人习惯,在动手写任何一行采集代码之前,先花至少半天时间把数据需求清单列清楚。你想想看,模型做得再漂亮,数据源搞错了,或者数据量不够,那全是白搭。我在项目中遇到过好几次,业务方拍胸脯说“数据都有”,结果一查,关键字段的覆盖率不到 30%。嗯,那叫一个酸爽。

3.1 数据需求清单:先问自己三个问题

别急着去翻数据库。先拿张纸,把下面三个问题写下来:

  1. 模型需要哪些特征? 用户画像?交易行为?设备信息?
  2. 标签(目标变量)是什么? 这个数据有没有历史记录?
  3. 数据的时间跨度多长? 训练集需要过去 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 本章知识结构图

下面这张图,把数据需求分析到采集策略的完整链路串起来了。你可以把它当作一个检查清单:

数据需求分析与采集策略总览 ① 数据需求清单 需要哪些特征? 标签(目标变量)是什么? 时间跨度多长? ② 数据来源 内部 DB(首选) 第三方 API(次选) 日志文件(备选) ③ 采集技术方案 ETL 批处理(离线) 实时流处理(在线) ④ 数据隐私与合规(GDPR)

这张图从左到右、从上到下,就是咱们做数据采集的完整流程。每一步都有对应的技术选型和注意事项。你照着这个框架走,基本不会漏掉关键环节。