ML System 设计全景:推理、训练、数据与部署

最近在看斯坦福的 CS 329S:Machine Learning Systems Design,这门课专门讲 ML 系统的整体设计,涉及面比较广。记录一下课程里让我觉得值得关注的内容。

ML 系统分层示意:从上到下依次为 Interface、Data 与 ML algorithms、Infrastructure、Hardware
图 1:一个 ML 系统的分层视图——Interface、Data、ML algorithms、Infrastructure、Hardware,本课程会逐层展开

课程里出现了不少值得关注的关键词:DevOps、CI/CD、A/B test、Flink(流计算)、Microservices(微服务)与 REST APIs、Kubernetes、tinyML(一本基于 TensorFlow Lite 的新书)。整体感觉这门课在工业落地层面覆盖得比较全面。

推理、计算与学习方式

课程前几个 slides 系统梳理了不同的推理、计算和学习方式。

推理方式方面,并非非黑即白,多种方式可以混合使用:

批量预测与在线预测的对比表格:频率、适用场景、优化目标、输入空间、示例
图 2:Batch prediction 与 Online prediction 的对比——批量预测周期性运行、优化吞吐、输入有限(如 TripAdvisor 排序、Netflix 推荐);在线预测随请求到来、优化低延迟、输入可无限(如语音识别、Twitter feed)
在线预测为默认,常见查询预计算并缓存:以 DoorDash 和 Netflix 为例
图 3:在线预测为默认,但常见查询会被预计算并缓存——DoorDash 的餐厅推荐用批量预测、店内菜品推荐用在线预测;Netflix 的标题推荐用批量预测、行内排序用在线预测

计算方式方面:

Cloud computingEdge computing
Computations在云端(服务器)完成在边缘设备(浏览器、手机、平板、笔记本、智能手表、可穿戴设备、汽车等)上完成
Requirements网络连接:数据传输的可用性与速度硬件:内存、算力、做计算所需的能量
Examples对 Alexa / Siri / Google Assistant 的大部分查询;稀有语种对的 Google 翻译(如英语-意第绪语)Alexa / Siri / Google Assistant 的唤醒词;常见语种对的 Google 翻译(如英语-西班牙语);输入法预测;指纹、人脸解锁
以硬件约束为纵轴、模型推理延迟为横轴划分的四象限图
图 4:硬件约束(纵轴)与模型推理延迟(横轴)构成的四象限——随着硬件越来越强,应用整体从「云端 + 高延迟」向「边缘 + 低延迟」迁移

学习方式方面:

Offline learningOnline learning
Iteration cycle周期性(数月)持续(数分钟)——注意 ≠ 连续(continuous)
Batch sizebatch(数千 → 数百万样本);GPT-3 125M 参数:batch size 0.5M;GPT-3 175B 参数:batch size 3.2Mmicrobatch(数百样本)
Data usage每个样本被看到多次(epochs)每个样本至多被看到一次
Evaluation主要离线评估离线评估作 sanity check;主要依赖在线评估(A/B testing)
Examples大多数应用TikTok 推荐系统、Twitter 话题趋势

这里有一点值得单独说:在有多个优化目标的时候,课程建议把它们拆成多个模型,每个模型专注于一个指标,这样训练和调参都会更容易。

拆分多目标为多个模型的三点理由:更易训练、更易调整系统、更易维护
图 5:把多优化目标拆成多个模型的好处——更易训练(单目标优化简单于多目标)、更易调整系统(如 α% 优化质量 + β% 优化互动)、更易维护(不同目标的维护节奏不同,如反垃圾系统比质量排序系统更新更频繁)

数据存储与特征管理

这部分讲了两种主要的数据存储方式。

基于行的存储,类似于 numpy 的组织方式,适合频繁 INSERT 的场景:

OLTP(在线事务处理)幻灯片:处理大量小事务、ACID 要求、INSERT/UPDATE/DELETE 操作,附按行插入的 SQL 示例
图 6:OLTP(OnLine Transaction Processing)——处理大量小事务(点餐、打车、转账),要求满足 ACID(原子性、一致性、隔离性、持久性),操作以 INSERT/UPDATE/DELETE 为主,按行组织(INSERT INTO RideTable …)

基于列的存储,类似于 pandas,适合频繁 SELECT 的场景:

OLAP(在线分析处理)幻灯片:从大量数据聚合信息、复杂查询、以 SELECT 为主,附按列查询的 SQL 示例
图 7:OLAP(OnLine Analytical Processing)——从海量数据中聚合信息(如某地上月平均车费),能处理大数据量上的复杂查询、容忍较慢响应,操作以 SELECT 为主,按列组织(SELECT AVG(Price) FROM RideTable …)

两种存储之间可以通过 ELT 进行转换:

ETL(Extract、Transform、Load)示意:数据从 OLTP 经抽取-转换-加载流向 OLAP
图 8:ETL(Extract、Transform、Load)——数据从 OLTP 经「抽取 → 转换 → 加载」流向 OLAP,其中 Transform 是最核心的部分(清洗、校验、转置、派生、连接多源、去重、拆分、聚合等)

此外,课程还提到可以将静态数据与动态数据结合起来做推理:

Static dataStreaming data
CSV、PARQUET 等Kafka、Kinesis 等
有界(bounded):知道一个作业何时结束无界(unbounded):永不结束
静态特征:年龄、性别、职业、城市、收入;账号创建时间;评分动态特征:最近 10 分钟的位置;近期活动
可批处理(如 SQL、MapReduce)随事件到达逐条处理(如 Apache Flink、Samza)
同一模型的两条数据管线:推理用流式数据经流处理,训练用静态数据经批处理,最终汇入同一 ML 模型
图 9:一个模型、两条管线——推理时流式数据经流处理生成特征,训练时静态数据经批处理生成特征,二者最终都喂给同一个 ML 模型

第三个 slides 后面还有一些迁移学习相关的内容,暂时跳过了。

采样与类别不平衡处理

第四个 slides 主要讲采样和类别不平衡,讲者看起来是做传统 ML 理论的。解决类别不平衡主要有三种方式:重采样(Resampling)、权重平衡(Weight Balancing)、集成学习(Ensembles)。

重采样分两种:下采样与过采样。

下采样与过采样对比及示意图:下采样移除多数类样本(可能过拟合),过采样复制少数类样本(可能丢失信息)
图 10:下采样(Undersampling)与过采样(Oversampling)——下采样从多数类移除样本、可能导致过拟合;过采样向少数类添加样本、可能造成信息损失

下采样可以使用 Tomek Links 方法(参考:https://www.kaggle.com/rafjaa/resampling-strategies-for-imbalanced-datasets):

Tomek Links 下采样示意:找出异类的近邻样本对,移除其中的多数类样本,使决策边界更清晰
图 11:Tomek Links 下采样——找出彼此靠近的异类样本对,移除每对中的多数类样本(优点:决策边界更清晰;缺点:模型鲁棒性下降)

过采样可以使用 SMOTE:

SMOTE 过采样示意:在少数类样本与其同类最近邻之间做凸(近似线性)组合,合成新样本
图 12:SMOTE 过采样——把少数类的新样本合成为「已有点与其同类最近邻」之间的凸(近似线性)组合,从而在少数类区域生成合成实例

权重平衡方面,比较经典的是 Focal Loss:

pt={pif y=11potherwise,p_{\mathrm{t}} = \begin{cases} p & \text{if } y = 1 \\ 1 - p & \text{otherwise,} \end{cases}
CE(pt)=log(pt)\mathrm{CE}(p_{\mathrm{t}}) = -\log(p_{\mathrm{t}})
FL(pt)=(1pt)γlog(pt)\mathrm{FL}(p_{\mathrm{t}}) = -(1 - p_{\mathrm{t}})^{\gamma} \log(p_{\mathrm{t}})

集成方法是训练多个分类器,再把所有结果做 ensemble:

Bagging 集成示意:有放回采样得到多个数据集,各训练一个分类器,再聚合所有分类器的预测
图 13:Bagging——有放回(with replacement)地采样出多个不同数据集(Bootstrapping),各自训练一个分类器,再聚合(Aggregating)所有分类器的预测得到集成分类器
Boosting 集成示意:迭代训练弱分类器,对被误分类的样本加权,再在重加权数据上重复训练
图 14:Boosting——训练一个弱分类器,给它误分类的样本更高权重,再在重加权后的数据上重复这一过程,迭代聚合为集成分类器

数据增强方面,2019 年有一篇综述可以参考:https://journalofbigdata.springeropen.com/articles/10.1186/s40537-019-0197-0

slides4 后面的内容主要是特征工程、数据泄露和模型选择,仍然偏传统 ML 风格。slides5 全是 PyTorch,没什么特别的。

并行训练与系统测试

slides6 讲了并行,包括数据并行和模型并行,但不够细节。另外 slides6 和 slides7 的前半部分都花了不少篇幅讲 ML 系统的测试,尤其是数据测试:

ML 系统各类测试对应到系统分层:数据测试对应 Data、模型评估对应 ML algorithms、管线测试与系统基准测试覆盖更大范围
图 15:不同测试在 ML 系统分层上的作用范围——数据测试(Data testing)对准 Data 层、模型评估(Model evaluation)对准 ML algorithms 层、管线测试(Pipeline testing)覆盖 Data 与 Infrastructure、系统基准测试(System benchmarking)覆盖整体
四类测试的定义:数据测试、管线测试、系统基准测试、模型评估,并标注在系统分层图上
图 16:四类测试的定义——数据测试(确保新数据满足假设)、管线测试(确保管线搭建正确)、系统基准测试(在明确任务/指标/规则上报告系统整体表现,用于对比)、模型评估(评估 ML 模型本身好坏)

实验管理工具

slides7 后半部分重点介绍了两个工具。

第一个是 Weights & Biases(wandb),提供丰富的可视化功能,有点像 NNI。

第二个是 DVC,用起来有点像 git,用 git 的方式来管理训练数据:

DVC 工作流示意:代码用 git push/pull 推送到 Git 服务器,数据用 dvc push/pull 推送到 S3/Azure/GCS,本地以小体积的 .dvc 文件指向大模型文件
图 17:DVC 工作流——代码通过 git push/pull 同步到 Git 服务器(GitHub/GitLab 等),数据通过 dvc push/pull 同步到远端存储(S3/Azure/GCS/SSH);本地仅保留 1KB 的 model.pkl.dvc 指针,链接到 500MB 的实际模型文件

DVC 除了管理数据,还可以用来管理实验,类似于 NNI,方便对比不同实验结果;最后它还支持 CI/CD 流程。

模型部署

slides8 主要讲部署,前面涉及模型压缩和 TensorRT 等内容,后面介绍了两种部署方式。

方式一:直接部署在云平台,可以用 GCP(类似于阿里云):

云端部署模型流程图:训练→压缩→导出模型后,上传模型走「Create predictor→Hosted model」或「Create function→Endpoint」,或建应用走「Create app→Sync app→Hosted app」
图 18:在云上部署模型的流程——训练、压缩、导出模型后,可上传模型并 Create predictor 得到 Hosted model(GCP AI Platform / AWS SageMaker)、或 Create function 暴露 Endpoint(GCP Cloud Functions / AWS Lambda),也可 Create app 同步 git repo 得到 Hosted app(GCP App Engine / AWS EC2)

方式二:基于 Docker 容器部署,同样可以放在 GCP,此外还有基于虚拟机和 Kubernetes 的方式。目前用 Docker 容器和用虚拟机的差别其实不太大:

折线图:Stack Overflow 上 containers 与 virtual-machine 两个标签的月度提问占比随年份变化,2015 年后 containers 持续走高
图 19:Stack Overflow 上 containers(容器)与 virtual-machine(虚拟机)两个标签的月度提问占比变化——2015 年后容器相关提问持续上升,反映容器化的普及趋势

tinyML 之后的 slides 基本都是比较空泛的 ML 工业实践,感觉看下去意义不大,以后有空再看。