# 精读《设计机器学习系统》-ch02: 机器学习系统设计导论

# 业务和机器学习目标

对于大多数的算法/开发工程师，大部分关注机器学习模型的指标: 准确率, [F1 score](https://blog.csdn.net/matrix_space/article/details/50384518), 推理时耗等等，并且热衷于使用大量的资源(数据，计算量，开发时间)来获得微小的提升。 

然而对于大部分的公司，并不关心以上的机器学习指标，诺贝尔奖获得者 Milton Friedman 指出，大部分公司的关心的是“[能否提升股东们的收益](https://www.nytimes.com/1970/09/13/archives/a-friedman-doctrine-the-social-responsibility-of-business-is-to.html)”。 任何业务的终极目标都是这个，提升用户满意度，增加用户市场，提升点击率等等目标，都直接或者间接和它相关。

对于一个在商业组织成功的机器学习模型，如果想要成功，就必须把模型指标和业务收益紧密结合。比方说，你想要说服leader将推荐系统的离线模型打分改为在线模型打分，那么就要提出“在线预测能够更好的给用户推荐当前感兴趣的内容”的理由，并且进行实验，验证实验组的推荐准确率提升了X%, 根据以往数据，准确率提升X%会为公司带来多少的收益为基本点。

很多情况下想要说明机器学习模型指标提升带来多少商业收益并不是一件简单的事情，这也是为什么点击率预测和风控是机器学习比较流行的领域。它们的模型效果可以很直接地与商业指标挂钩，带来真金白银的收益。对于那些难以解释具体商业收益的模型，我们可以通过A/B实验或者[swtichbacks](https://zhuanlan.zhihu.com/p/584693742)来观察模型对商业目标的影响。

很多公司/组织吹嘘自己拥有“AI智能”，实际上只是用来吸引投资者/客户的幌子。并且很多人希望机器学习能够一夜之间给业务带来魔法般的效果，实际上魔法般的效果是可以的，一夜之间是不可能的。

# 机器学习系统指标
衡量机器学习系统的指标和《DDIA》中衡量数据密集型系统的质量很相似，毕竟 ML System 某种意义上来讲也是一种 Data-Intensive Application。 ML System 在某些方面又有它的特殊性。

## 可靠性(Reliability)

可靠性意味着系统在面对某些(硬件, 软件, 人为)错误时，仍能够在特定性能下表现出正确性。

然而，对于机器学习系统，“正确性”的定义是很困难的。传统的系统，错误通常指的是服务崩溃或者运行时错误。机器学习系统的错误不容易监控，会在不被察觉的情况下失败。举个例子，虽然模型预测的过程是正常的，但是模型打分却和正确值大相径庭。

因此对于线上的机器学习系统，通常会有两部分监控，一部分监控服务本身，如P99，Kubernetes事件，全链路错误码，拨测等等。还有一部分监控，对线上数据质量和模型预测相关参数、结果进行监控。

## 可拓展性(Scalability)

可拓展性是为了应对随着业务变化带来对机器学习系统的能力变化。

机器学习系统的可拓展性，体现在多个方面

1. 模型本身复杂度提升，对于同一个问题，可能使用1GB RAM的XGBoost模型，也可能过段时间会使用 16GB 显存的深度学习模型。 
2. 机器学习系统负载的提升，包括服务的QPS, 吞吐量等指标的提升。
3. 模型数量的提升，对于一个创业公司，可能在生产环境就可能有成千上万的模型服务。如何使用很低的人力成本维护，管理并监控这些模型，也是可拓展性的重要部分。

需要注意的是，可拓展性不只是需要应对峰值，在业务低谷期，也需要向下拓展，降低成本。

## 可维护性(Maintainability)
会有形形色色的角色参与到 ML system 的生命周期中，包括算法工程师，DevOps工程师，SME等等。重要的是，能够让不同决策很便利的使用工具，而不是由一组贡献者将他们的工具强加给其他组(PS: 这说的不就是EPC吗)。


## 适应性(Adaptability)

为了适应不断变化的数据分布和业务需求，系统应该有一定的能力，既能发现性能的改进点，又能在不中断服务的情况下更新。

这一点和可维护性紧密相关。

关于模型更新这里请教了下组里的算法同学，并非所有的机器学习模型都可以进行在线学习，对于训练时需要全量数据同时训练的算法，比如XGBoost，就不可以进行在线学习；对于大多数的深度学习算法，在tf和pytorch中保存了optimizer(其中有图的梯度和权重), 可不断根据新的数据优化梯度和权重，进行在线学习。

# 迭代过程

模型上线是一个反复迭代的过程，并且不同步骤之间存在跳跃关系，如下图。

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1669301736034/fAuI4f-a0.png align="left")

# 构建ML问题
> The formulation of a problem is often far more essential than its solution -- Albert Einstein

假如你在一家银行做ML的tech lead, 你的老板说竞争对手利用 ML 加快了客户支持服务的效率，让你也调研下。

客户支持效率慢是个问题，但不是一个 **ML 问题**。一个 ML 问题需要输入，输出和目标函数来指导学习过程。作为一个经验丰富的开发人员，我们的目标就是将实际业务问题转换为ML问题，并予以解决。

## ML任务类型
ML 任务主要可以分为两个类型, **分类(classification)** 和 **回归(regression)**


![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1669301767842/E2Yeu_4Jn.png align="left")
### 分类 VS 回归

分类和回归问题可以轻易地互相转化。二者只是对于模型的最后输出的处理结果不同。

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1669301685728/H8yHXBBhO.png align="left")

### 二分类 VS 多分类

二分类是多分类的一种特例。

多分类问题，具有 **高基数(high cardinality)** 的特性。对于高基数ML问题，在解决时会有以下挑战:

1. 数据收集。如果有1000个分类，那么最少需要100000种分类。对于某些稀有的分类，很难收集到足够多的数据。
2. 单个模型难以解决问题。因此通常使用 **层次分类( hierarchical classification)**。 首先使用分类器，将每个实例分类到大类中，对于每个大类，再使用特有的分类器，进行区分。

### 多分类 VS 多标签分类

在多分类问题中，一个样例只能属于一种类型，在多标签分类问题中，一个样例可以属于多种类型。

解决多分类的ML问题的方法主要有两种:

1. 使用单个模型的输出决定一个样例是否属于多个类
2. 将问题转化为 N 个二分类问题。

解决多分类 ML 问题，主要的困难在于：
1. 数据的标注，同样的一篇文章，有人会认为是属于互联网类别，有人会认为既属于互联网类别，也属于金融类别。
2. 很难从模型推理结果确认类别。比方说模型输出为`[0.45, 0.2, 0.02, 0.33]`, 那么阈值为多少才能确认是否属于该类别呢？

## 目标函数

通常将目标函数视为损失函数，但其实二者存在细微的差异。

### 解耦目标

一般来说，当有多个目标时，首先将它们解耦是个好主意，因为它使模型的开发和维护更容易。

在最近做的广告需求中，就是对`pctr`和`pcvr`设置了不同的权重，来决定对最终`ecpm`的影响。
```
epcm = price×pctr^p1×pcvr^p2 + xxxx 
```

# 想法 VS 数据
有两个派别, **mind-over-data** 和 **data-over-mind** ， 总是在争论数据和想法(算法)哪个更加重要。作者倾向于数据更重要的观点：

> 如果你想使用数据科学（ML是其中的一门学科）来改善你的产品或流程，你需要从建立你的数据开始，在质量和数量方面。没有数据，就没有数据科学。


![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1669301666445/AivZ6m3hh.png align="left")

在日常的实践中，我个人感受也是这样的，往往线上效果的提升取决于特征的实时性和可靠性。在数据不靠谱的情况下，高大上的深度模型比起朴素的树模型，很容易“失之毫厘，差之千里”(garbage in, garbage out)。很多人在强调实时模型的重要性，但结合业务来看，如果能把实时特征做好，就能给业务带来很大的提升。

没错，我也是数据派:)
