ML 设计案例


文档摘要

ML 设计案例 学 ML 系统设计最好的办法就是看完整案例。本文件走查七个完整设计:推荐系统、搜索排序、广告点击预测、欺诈检测、内容审核、对话式 AI,以及大规模图像搜索 每个案例都遵循一致的框架: 问题定义:我们在造什么、用户是谁、约束是什么? 数据:我们有什么数据、怎么收集、怎么标注? 特征:模型需要哪些特征? 模型:什么架构和训练方法? 服务:模型怎么部署和服务? 评估:怎么衡量成功? 迭代:随着时间推移,我们会做哪些改进? 推荐系统(如 YouTube、Netflix、Spotify) 问题定义 目标:给用户看他们会喜欢的内容,最大化参与度(观看时长、收听次数、点击)。 规模:10 亿+ 用户、1 亿+ 物品、每秒 1 万+ 次推荐。 延迟:整个推荐流水线 <200ms。

ML 设计案例

学 ML 系统设计最好的办法就是看完整案例。本文件走查七个完整设计:推荐系统、搜索排序、广告点击预测、欺诈检测、内容审核、对话式 AI,以及大规模图像搜索

  • 每个案例都遵循一致的框架:
    1. 问题定义:我们在造什么、用户是谁、约束是什么?
    2. 数据:我们有什么数据、怎么收集、怎么标注?
    3. 特征:模型需要哪些特征?
    4. 模型:什么架构和训练方法?
    5. 服务:模型怎么部署和服务?
    6. 评估:怎么衡量成功?
    7. 迭代:随着时间推移,我们会做哪些改进?

1. 推荐系统(如 YouTube、Netflix、Spotify)

问题定义

  • 目标:给用户看他们会喜欢的内容,最大化参与度(观看时长、收听次数、点击)。
  • 规模:10 亿+ 用户、1 亿+ 物品、每秒 1 万+ 次推荐。
  • 延迟:整个推荐流水线 <200ms。
  • 关键挑战:候选空间巨大(1 亿物品)。无法实时为所有用户对所有物品打分。

架构:两阶段流水线

推荐流水线:1 亿物品经候选生成收窄到 1000,经排序精排到 100,再经重排得到 20 个展示给用户的物品

1 亿物品 → 候选生成(快、粗) → 1000 个候选 → 排序(慢、精) → 100 个排好序的物品 → 重排(业务规则) → 20 个展示给用户的物品

候选生成

  • 目标:把 1 亿物品收窄到约 1000 个候选。必须快(<50ms)。
  • 双塔模型(two-tower model):把用户和物品编码到同一个嵌入空间。用户嵌入捕捉偏好,物品嵌入捕捉内容特征。打分 = 用户嵌入与物品嵌入的点积。
  • 训练:在 (user, positive_item, negative_items) 三元组上做对比学习。正样本 = 用户交互过的物品。负样本 = 随机物品 + 困难负样本(用户没交互过的热门物品)。
  • 服务:预先算好所有物品嵌入。请求时:算出用户嵌入,做 ANN 搜索(向量数据库中的 HNSW)找出 1000 个最近的物品嵌入。

排序

  • 目标:精确地为 1000 个候选打分。可以花约 100ms。
  • 模型:一个深度神经网络(MLP 或 transformer),输入丰富的特征:用户特征(人口统计、历史、上下文)、物品特征(内容、热度、新鲜度)、以及交叉特征(用户-物品交互历史、上下文相关性)。
  • 输出:预测的参与概率(点击、看完 50%+、点赞、分享)。多目标可以组合:\text{score} = w_1 \cdot P(\text{click}) + w_2 \cdot P(\text{watch}) + w_3 \cdot P(\text{like})

重排

  • 应用业务规则:多样性(不要连放同一个创作者的 5 个视频)、新鲜度(加权新内容)、安全(过滤被标记的内容)、以及个性化探索(展示一些排名较低、用户可能会发现的物品)。

粗算数据

  • 物品嵌入索引:1 亿物品 × 256 维 × float16 = 50 GB。HNSW 索引再加约 2 倍开销 → 约 100 GB。能塞进一台 128 GB 内存的机器,或分片到 4 台 × 32 GB 的机器上。

  • 用户嵌入计算:每个用户约 5ms(用户特征上的小 MLP)。在 1 万 QPS 下,需要约 50 个模型副本来扛负载。

  • ANN 搜索:用 HNSW 从 1 亿向量中找 top-1000 约 2ms。在 1 万 QPS 下,每个索引副本处理约 500 QPS → 需要 20 个副本。

  • 排序模型:1000 候选 × 每候选约 0.1ms = 每请求 100ms。在 1 万 QPS 下,每秒需要 1000 GPU 秒 → 光排序就约要 10 张 A10G GPU。

  • 基础设施总量:约 20 个嵌入索引副本 + 约 50 个用户嵌入服务器 + 约 10 张排序 GPU + 缓存 + 负载均衡器。成本:云价格下约 $50K-$100K/月。

冷启动

  • 新用户(无历史):用人口统计特征、设备/位置上下文和基于热度的推荐。交互 5-10 次后,切到个性化模型。

  • 新物品(无交互数据):用基于内容的特征(标题、描述、缩略图嵌入)。分配一个探索预算:把新物品展示给一部分用户,以快速收集交互数据。加权期过后仍无交互的物品会被降权。

  • 冷启动是一个系统问题:特征存储必须优雅地处理缺失特征(返回默认值,而非报错)。模型必须用带缺失特征的数据训练(训练时对用户历史特征做 dropout 来模拟新用户)。

评估

  • 离线:在留出集上的 NDCG(归一化折损累计增益)、recall@K、precision@K。
  • 在线:A/B 测试观看时长、DAU、留存。长期 A/B 测试(数周)以捕捉短测试发现不了的、对用户留存的长期影响。

2. 搜索排序(如 Google、Bing)

问题定义

  • 目标:给定一个用户查询,从数十亿文档的语料库中返回最相关的结果。
  • 延迟:总计 <500ms(100ms 召回 + 200ms 排序 + 100ms 渲染 + 开销)。

架构:查询理解 → 召回 → 排序

查询理解

  • 在召回之前,先处理原始查询以改善结果:

  • 拼写纠错:"reccomendation systm" → "recommendation system"。用编辑距离模型,或在搜索日志的(拼错,纠正)对上训练的序列到序列模型。

  • 查询扩展:加入相关词以提高召回。"Python ML" → "Python machine learning scikit-learn pytorch"。用同义词典、词嵌入,或用 LLM 生成扩展。

  • 意图分类:判断用户想要什么。"buy Nike shoes" 是交易型(transactional)(展示商品页)。"How does backpropagation work" 是信息型(informational)(展示文章)。"facebook.com" 是导航型(navigational)(直接跳到该网站)。不同意图应触发不同的召回策略和结果布局。

  • 实体识别:从查询中抽出实体。"best restaurants near Times Square" → 地点:"Times Square",实体类型:"restaurants"。路由到一个位置感知的搜索流水线。

召回

  • BM25(传统):基于倒排索引的词项匹配召回。快,对关键词查询有效。没有语义理解("dog food" 匹配不到 "canine nutrition")。

  • 稠密召回(dense retrieval):用双编码器(如 DPR 或 ColBERT)把查询和文档编码成嵌入。用 ANN 搜索召回。能捕捉语义相似("dog food" 能匹配 "canine nutrition")。比 BM25 慢,但对自然语言查询更好。

  • 混合召回(hybrid retrieval):结合 BM25 和稠密召回。BM25 找精确关键词匹配,稠密召回找语义匹配。合并并去重。两全其美。

排序

  • 排序学习(learning to rank):一个模型为每个 (query, document) 对打分。三种方法:

    • 逐点(pointwise):独立地为每个文档预测相关性分数。简单,但忽略了相对顺序。
    • 成对(pairwise):预测两篇文档哪个更相关。LambdaMART(梯度提升树)是经典方法。
    • 列表(listwise):直接为一个列表级指标(NDCG)优化整个排好序的列表。更复杂,但效果最好。
  • 交叉编码器(cross-encoder):一个把 [query, document] 作为输入、输出相关性分数的 transformer。比双编码器(独立编码查询和文档)更准,因为它能捕捉细粒度交互。但对整个语料库太慢——只用于对召回得到的 top 100-1000 候选做重排。

特征

  • 查询特征:查询长度、语言、意图分类(导航型、信息型、交易型)。
  • 文档特征:PageRank、新鲜度、内容质量分、域名权威度。
  • 查询-文档特征:BM25 分、嵌入相似度、精确匹配数、历史日志中该 (query, document) 对的点击率。

3. 广告点击预测

问题定义

  • 目标:预测用户点击某条广告的概率。这决定了在实时拍卖中出多少价。
  • 规模:每秒 10 万+ 次拍卖,每次都要在 10ms 内给出预测。
  • 营收影响:点击预测准确率每提升 0.1%,都意味着数百万的额外营收。

架构

  • 特征工程 是广告系统的核心。特征包括:

    • 用户特征:人口统计、浏览历史、购买历史、设备、位置、时间段。
    • 广告特征:创意(图/文)、广告主、类别、历史 CTR、出价金额。
    • 上下文特征:页面内容、广告位、设备类型、连接速度。
    • 交叉特征:user_category × ad_category 交互、user_region × ad_campaign 交互。
  • 模型:历史上用逻辑回归(简单、快、可解释)。现代系统用深度学习:一个 DLRM(深度学习推荐模型),类别特征走嵌入表,密集特征走 MLP。

  • 校准(calibration):预测概率必须准确(如果模型说 P(click) = 0.05,那么这类曝光中实际真该有 5% 被点击)。校准至关重要,因为预测概率直接决定出价金额。

  • 探索-利用(exploration-exploitation):永远只展示预测最好的广告,长期是次优的(你永远不会发现某条新广告可能更好)。Thompson 采样或 \epsilon-greedy 探索确保一部分曝光流向不太确定的广告,以收集数据。

实时竞价

  • 当用户加载一个页面时,一场广告拍卖在 <100ms 内完成:
    1. 发布方向多个广告交易平台发送竞价请求(用户信息、页面上下文)。
    2. 每个广告主的竞价服务器为自己的广告预测 CTR。
    3. 出价 = CTR × value_per_click。出价高者赢得拍卖。
    4. 获胜广告被展示;若被点击,广告主付费。

4. 欺诈检测

问题定义

  • 目标:实时检测欺诈交易(信用卡欺诈、账户盗用、虚假评论)。
  • 延迟:<100ms(交易必须在支付处理之前被批准或标记)。
  • 关键挑战:极端的类别不平衡(0.1% 欺诈率)。假阳性挡住合法用户;假阴性损失钱。

架构

欺诈检测流水线:交易 → 实时特征流水线 → ML 模型 → 决策引擎 → 放行/复审/拦截,人工复审的结果回流成标签用于重训

特征

  • 交易特征:金额、币种、商户类别、时间段、是否跨境。
  • 用户特征:账户年龄、平均交易金额、最近交易数、设备指纹。
  • 速度特征(velocity features)(实时,来自流式流水线):过去 5 分钟的交易数、过去 1 小时的不同商户数、与上一笔交易的地理距离。
  • 图特征:这个商户是否连接到已知欺诈团伙?这个设备是否与被标记的账户共享?

模型

  • 梯度提升树(XGBoost、LightGBM)是表格型欺诈检测的标准。它们能处理混合特征类型、可解释(特征重要性),且训练快。

  • 处理不平衡:欠采样多数类、过采样少数类(SMOTE),或在损失函数里用类别权重。Focal loss(第 8 章)会降低简单负样本的权重。

  • 代价矩阵:一个假阳性(拦截合法交易)有它的代价(用户挫败、流失订单)。一个假阴性(漏掉欺诈)有不同的代价(经济损失)。决策阈值应当最小化总期望代价,而不是最大化准确率。

人在回路(Human-in-the-Loop)

  • 不确定的预测(模型置信度在 0.3 到 0.7 之间)送给人工复审。复审员的判定会成为重训的标签。这形成一个反馈回路:模型随着看到更多带标签的欺诈案例而不断改进。

5. 内容审核

问题定义

  • 目标:自动检测并移除平台上的有害内容(仇恨言论、暴力、虚假信息、CSAM)。
  • 规模:每天数十亿条帖子(文本、图片、视频)。
  • 挑战:依赖上下文(反讽、讽刺、文化细微差别)。必须在言论自由和安全之间取得平衡。

架构

  • 多模态分类:为文本、图片和视频分别设模型,再用一个融合层把它们的信号合并。

  • 文本审核:微调过的语言模型把文本分类到各类(骚扰、仇恨言论、虚假信息、垃圾)。多语言模型能处理 100+ 种语言。

  • 图片审核:视觉模型检测:露骨内容(裸露、暴力)、图片中的文字(OCR + 文本分类器)、以及已知有害内容(与已知 CSAM 数据库做哈希匹配)。

  • 视频审核:按固定间隔采样帧,对每帧跑图像分类器,再结合音频转写(ASR → 文本分类器)。

  • 策略即代码(policy-as-code):审核策略被定义成结构化规则,把模型输出映射到动作:

if text_model.hate_speech_score > 0.9: action = "remove" # 移除 elif text_model.hate_speech_score > 0.7: action = "human_review" # 人工复审 else: action = "allow" # 放行
  • 策略经常变(新法规、演变的规范)。把策略和模型分开,能确保改策略时不必重训模型。

主动式 vs 反应式审核

  • 主动式(proactive,发布前):在内容上线前跑分类器。高置信度违规被自动拦截。这能防止有害内容被任何人看到,但会增加发布延迟,且有假阳性风险(拦截合法内容)。

  • 反应式(reactive,发布后):内容立即上线。用户可以举报违规。举报触发分类器 + 人工复审。对发布者延迟低,但有害内容在被发现前是可见的。

  • 多数平台两者并用:对高严重性类别主动式(CSAM:零容忍,发布前拦截),对需要细致判断的类别反应式(虚假信息:需要人工判断,举报后复审)。

哈希匹配

  • 对于已知的有害内容(CSAM、恐怖主义宣传),用感知哈希(perceptual hashing):算出一个对小幅修改(裁剪、缩放、压缩)稳健的图像/视频哈希。与已知有害内容数据库(NCMEC 的哈希库、GIFCT 共享哈希库)对比。命中 → 立即移除,无需分类器。

  • PhotoDNA(微软)是 CSAM 检测的标准感知哈希。在许多司法管辖区它是法律义务,不只是技术选择。

粗算数据

  • 规模:每天 10 亿帖 = 约 1.2 万帖/秒。每帖需要:文本分类(约 5ms)、图片分类(约 20ms)、哈希匹配(约 1ms)。在 1.2 万 QPS 下:需要约 60 个文本分类器、约 240 个图片分类器、约 12 个哈希匹配器(外加冗余)。

  • 人工复审:如果 2% 的帖子被标记送审 = 每天 2000 万帖。每个复审员每天 100 帖,需要 20 万复审员(这就是为什么自动化准确率如此重要:假阳性每降 0.1%,每天就省 100 万次复审)。

  • 延迟预算:主动式审核必须在发布流水线内完成(约 500ms)。文本(5ms)+ 图片(20ms)+ 哈希(1ms)+ 开销 = 远在预算内。视频是例外:即便对一段 10 分钟视频每秒采样 1 帧,也要 600 次分类器调用 → 异步处理。

升级工作流

  • 自动移除 → 申诉人工复审 → 专家复审(法律、文化专家)→ 模糊案例交策略团队。每一级处理的案例更少,但判断更细。

  • 反馈给模型:人工复审的判定是重训的最高质量标签。模型与复审员意见不一致的案例会优先用于主动学习——它们代表了模型处理得最差的那些情况。

6. 对话式 AI(基于 RAG 的聊天机器人)

问题定义

  • 目标:一个能基于公司产品文档回答用户问题的聊天机器人。
  • 要求:准确(不胡编)、引用来源、处理追问、且不离开产品领域。

RAG 架构:嵌入查询,在向量库里搜相关片段,重排,连同原始查询喂给 LLM,生成有依据的回答

架构:检索增强生成(RAG)

用户查询 → 查询嵌入 → 向量搜索(文档库) → Top-K 个片段 ↓ 用户查询 + 检索到的片段 → LLM → 回答(带引用)

组件

  • 文档摄入:把文档切块并嵌入。切块策略(chunking strategy) 影响很大:

    • 固定大小切块(fixed-size chunking):每 N 个 token 切一刀(如 500),带 M 个 token 重叠(如 50)。简单、块大小可预测,但可能在句子或段落中间切断,丢失上下文。

    • 语义切块(semantic chunking):在段落或小节边界切。每块是一个连贯的信息单元。大小可变(有的块 100 token,有的 800),需要检索系统能处理可变长度。

    • 递归切块(recursive chunking):先尝试在段落边界切。段落太长就在句子边界切。句子太长就按固定大小切。在连贯性和大小一致性之间取得最好平衡。

    • 嵌入(embedding):用文本编码器(如 E5、BGE、Cohere embed)嵌入每个块,存进向量数据库。

  • 检索:嵌入用户查询,在向量库里搜最相似的 k 个块(通常 k = 5-10)。可选地用交叉编码器重排以提高精度。

  • 生成:把检索到的块作为上下文构造提示词:

System: You are a helpful assistant. Answer based ONLY on the provided context. If the answer is not in the context, say "I don't know." Context: [chunk 1] [chunk 2] ... User: {question}
  • 护栏(guardrails):防止 LLM 回答产品领域外的问题、生成有害内容,或与检索到的上下文矛盾。实现为:输入过滤(拒绝跑题查询)、输出过滤(把回答和检索到的上下文核对)、以及宪法式提示(constitutional prompting,指示模型拒绝某些请求)。

  • 对话记忆(conversation memory):保留最近 n 轮对话,放进提示词,让模型理解追问("那价格呢?" → 需要之前关于哪个产品的上下文)。

查询改写

  • 用户常常问含糊的追问:"那价格呢?"(什么的价格?)。查询改写(query rewriting) 用对话历史产出一个独立的查询:

    • 输入:对话历史 + "那价格呢?"
    • 改写后:"产品 X 的企业版价格是多少?"
  • 这个改写后的查询才是被嵌入并拿去向量库搜索的对象。不改写的话,检索会无上下文地搜"价格",返回无关的块。

  • 查询改写可以用一次小 LLM 调用(约 50ms)或一个微调过的序列到序列模型(约 5ms)完成。

粗算数据

  • 文档语料库:1 万页,平均每页 2000 token = 2000 万 token。每块 500 token、50 重叠 = 约 4.4 万块。
  • 嵌入索引:4.4 万块 × 768 维 × float16 = 约 65 MB。轻松塞进内存。即便 1000 万块也只有约 15 GB。
  • 延迟拆解:查询嵌入(5ms)+ 向量搜索(2ms)+ 交叉编码器重排(top-50 用 20ms)+ LLM 生成(500-2000ms)= 总计约 600-2100ms。LLM 占大头。用流式输出来降低感知延迟。
  • 成本:按 $3/百万 token(Claude/GPT-4 API),每天 1000 次查询、每次约 2K token = 约 $6/天。大规模下(每天 100 万次查询),自托管一个 7B 模型用 2 张 A10G(约 $50/天),成本降到 1/100。

评估

  • 检索质量:Recall@K(top-K 块里是否包含答案?)、MRR(平均倒数排名,Mean Reciprocal Rank)。
  • 生成质量:事实准确性(回答是否与检索到的上下文一致?)、有据性(回答是否引用了正确的块?)、答案相关性。
  • 端到端:用户满意度(赞/踩)、升级到人工客服的比率。

7. 大规模图像搜索

问题定义

  • 目标:给定一张图,从 10 亿+ 张图的语料库中找出视觉上相似的图。
  • 应用:以图搜图、商品搜索(照片 → 匹配的商品)、重复内容检测。
  • 延迟:<500ms,含网络往返。

架构

查询图像 → 嵌入模型(ViT/CLIP) → 512 维向量 → ANN 搜索 → Top-K 结果

嵌入抽取

  • 模型:一个预训练的视觉编码器(ViT、CLIP 的图像编码器、DINOv2)。必要时在特定领域(时尚、电商、医学影像)上微调。

  • 训练:对比学习(第 10 章)。正样本对 = 同一图像的不同视图(或图像 + 匹配文本)。负样本对 = 随机图像。模型学会为相似图像产出相似嵌入,为不同图像产出不同嵌入。

索引

  • 离线:把全部 10 亿张图嵌入并建一个 ANN 索引。对 HNSW(第 03 节),建索引要几小时,索引存在内存里(10 亿 × 512 维 × float16 + 图开销 ≈ 128 GB)。

  • 分片:把索引切分到多台机器上。每台持有一个分片。查询时并行搜索所有分片,合并 top-K 结果。

  • 增量更新:新图像(上传、新品)必须加进索引。HNSW 支持无需重建的增量插入。向量数据库(Milvus、Pinecone)原生支持这一点。

服务

  • 嵌入服务:一台跑 ViT 模型的 GPU 服务器。延迟:每图约 20ms。多个查询合并成 batch 以提高吞吐。

  • 搜索服务:ANN 索引服务器。在 10 亿向量上做 top-100 搜索延迟约 10ms(用 HNSW)。

  • 缓存:对热门查询缓存结果。对于重复内容检测,缓存最近上传图像的嵌入,让新上传先和缓存比对,再去搜全量索引。

评估

  • Precision@K:top-K 结果是否真的相似?
  • Recall@K:语料库中所有真正相似的图里,有多少进了 top-K?
  • 平均精度均值(Mean Average Precision,mAP):精确率-召回率曲线下面积。
  • 人工评估:对于主观的相似性,由人工评审判断检索到的图像是否相关。

面试框架

  • 遇到一道系统设计题时,按这个框架走:
  1. 澄清需求(2-3 分钟):问清楚规模、延迟、一致性要求和边界情况。"多少用户?可接受的延迟是多少?故障时怎么办?"

  2. 高层设计(5-7 分钟):画出主要组件及其交互。从"快乐路径"(happy path)开始。用第 01-03 节里的那些模式。

  3. 深入(15-20 分钟):挑一个最有意思/最有挑战的组件做详细设计。这是你展现深度的地方。对 ML 系统来说,深入往往在:模型架构、特征流水线,或服务架构。

  4. 评估与监控(3-5 分钟):怎么衡量成功?什么会出错?怎么检测和应对问题?

  5. 迭代(2-3 分钟):给你更多时间/资源,你会改进什么?这能体现你懂权衡、会排优先级。

  • 面试官看重什么:结构化思考(不急着抛方案)、权衡意识(每个选择都有代价)、实战经验(你真的搭过系统),以及沟通(你能把设计讲清楚吗?)。

发布者: 作者: HenryNdubuaku 转发
评论区 (0)
U