首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >AI数据工程不是"洗洗数据":从采集到特征仓库的工程化流水线,附可运行代码

AI数据工程不是"洗洗数据":从采集到特征仓库的工程化流水线,附可运行代码

原创
作者头像
用户12339161
发布于 2026-10-17 15:22:39
发布于 2026-10-17 15:22:39
1410
举报

AI数据工程的核心不是写几个pandas脚本,而是把采集→校验→清洗→特征→版本→服务做成可复现、可回溯、可监控的流水线。模型效果的上限由数据决定,而数据工程决定了这个上限能否稳定兑现。下面按生产级流水线拆解,每环给可运行代码。

一、数据契约:先定义Schema,再谈采集

没有契约的数据入湖就是灾难。用Pydantic定义数据契约,在入口处强制校验,脏数据不进管道。

代码语言:javascript
复制
# contracts.py
from pydantic import BaseModel, Field, field_validator
from datetime import datetime

class RawEvent(BaseModel):
    user_id: str = Field(min_length=1)
    item_id: str = Field(min_length=1)
    event_type: str
    ts: datetime
    features: dict = Field(default_factory=dict)

    @field_validator("event_type")
    @classmethod
    def valid_type(cls, v):
        assert v in {"click","view","buy","fav"}, f"非法事件类型:{v}"
        return v

    @field_validator("ts")
    @classmethod
    def not_future(cls, v):
        assert v <= datetime.utcnow(), "时间戳不能是未来"
        return v

契约的价值在于:校验失败的数据直接进死信队列(DLQ),而不是悄悄污染训练集。生产上建议用Great Expectations或Pandera做批量校验,Pydantic负责流式入口。

二、采集与入湖:幂等写入是底线

代码语言:javascript
复制
# ingest.py
import json, hashlib
from contracts import RawEvent

def ingest(line: str, sink):
    try:
        evt = RawEvent(**json.loads(line))
    except Exception as e:
        sink.dlq(line, str(e)); return
    # 幂等键:用户+物品+事件+时间戳哈希,重复消费不重复写
    key = hashlib.sha1(f"{evt.user_id}{evt.item_id}{evt.event_type}{evt.ts}".encode()).hexdigest()
    sink.upsert(key, evt.model_dump())

工程约束:幂等键必须包含时间戳,否则用户同一秒重复点击会被误去重;upsert而非insert,保证至少一次语义下不产生重复样本。

三、清洗与去重:规则化 + 语义化双通道

代码语言:javascript
复制
# clean.py
import pandas as pd

def clean(df: pd.DataFrame) -> pd.DataFrame:
    df = df.drop_duplicates(subset=["user_id","item_id","event_type","ts"])
    # 规则:异常时长、缺失关键字段
    df = df[df["features"].apply(lambda x: x.get("dwell_ms",0) < 3600_000)]
    df = df.dropna(subset=["user_id","item_id"])
    # 语义去重:文本特征做minhash近似去重(伪代码示意)
    # from datasketch import MinHashLSH
    return df.reset_index(drop=True)

专业点:规则清洗负责硬约束(空值、越界、格式),语义去重负责软重复(同一内容的改写、近重复样本)。训练集里的近重复样本会直接导致模型过拟合和评测虚高。

四、特征工程:离线特征必须与在线特征同源

这是AI数据工程最容易翻车的地方——离线用pandas算,在线用Java重写,两边口径不一致,线上线下效果对不上。正确做法是特征定义只写一次,离线批算和在线点查共用同一份逻辑。

代码语言:javascript
复制
# features.py
from feast import Entity, FeatureView, Field, FileSource
from feast.types import Float32, Int64
from datetime import timedelta

user = Entity(name="user_id", join_keys=["user_id"])
src = FileSource(path="data/features.parquet", timestamp_field="event_ts")

user_fv = FeatureView(
    name="user_behavior",
    entities=[user],
    ttl=timedelta(days=7),
    schema=[
        Field(name="click_cnt_7d", dtype=Int64),
        Field(name="buy_rate_30d", dtype=Float32),
        Field(name="avg_dwell_ms", dtype=Float32),
    ],
    source=src,
    online=True,   # 关键:同一份定义同时产出离线和在线特征
)

用Feast这类特征仓库,materialize把离线特征推到在线存储(Redis),训练时用get_historical_features做point-in-time join,严格防止特征穿越——只用标签发生时刻之前可用的特征,否则离线AUC虚高、上线暴跌。

五、数据版本与血缘:每次训练可回溯

代码语言:javascript
复制
# versioning.py
import dvc.api

def train_dataset(path="data/train.parquet"):
    # DVC跟踪数据版本,git commit关联数据hash
    with dvc.api.open(path, repo=".", rev="v1.2.0") as f:
        return load(f)

def log_lineage(dataset_hash, feature_view_ver, model_ver):
    lineage = {"dataset": dataset_hash, "feature_view": feature_view_ver, "model": model_ver}
    # 写入元数据库,任何一次模型故障都能反查是哪版数据、哪版特征
    db.lineage.insert_one(lineage)

工程约束:数据、特征定义、模型三者版本必须绑定。线上模型出问题,第一件事是反查训练数据版本,没有血缘就只能盲猜。

六、监控:数据漂移比模型崩溃更隐蔽

代码语言:javascript
复制
# monitor.py
from scipy.stats import ks_2samp

def drift_check(ref, cur, cols, thr=0.05):
    alerts = []
    for c in cols:
        stat, p = ks_2samp(ref[c].dropna(), cur[c].dropna())
        if p < thr:
            alerts.append({"col": c, "ks": round(stat,3), "p": round(p,4)})
    return alerts  # 空列表表示无显著漂移

KS检验盯特征分布漂移,PSI盯分箱稳定性,再叠加标签延迟监控(购买标签往往T+1甚至T+7才回传)。漂移告警要联动重训练流水线,而不是只发钉钉。

总结:AI数据工程的专业度体现在契约先行、幂等入湖、特征同源、版本血缘、漂移监控五件事上。代码量不大,但每一环的工程约束决定了数据能不能被信任。能给别人讲清楚"为什么离线AUC高上线却崩",你就抓住了数据工程的命门。觉得有用点赞收藏,需要完整工程目录留言。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 一、数据契约:先定义Schema,再谈采集
  • 二、采集与入湖:幂等写入是底线
  • 三、清洗与去重:规则化 + 语义化双通道
  • 四、特征工程:离线特征必须与在线特征同源
  • 五、数据版本与血缘:每次训练可回溯
  • 六、监控:数据漂移比模型崩溃更隐蔽
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档