以前[聊过一些](/system-design-interview.html)怎么从（机器学习）系统设计面试中得到足够的信号来评估面试者的能力。这次过了一年，再来总结一下这一年新的学习体会。和上次说的一样，工程的核心是妥协。一个精度又高，速度又快，成本又低的系统往往很难实现。现实中通过创新把这个真的拱出来情况极少，大多数情况都是在做取舍，做妥协。工程师的功夫体现在在哪里妥协，用什么去换什么。换言之，设计的目标是搞清楚哪些地方必须妥协，并且在正确的地方做出决策来实现适当的妥协。这个决策的结论不是特别重要，关键是要知道在这个地方决策，并且给出决策过程。这个设计的过程大致的说可以用一个问题来把主线串起来，就是：这个工程项目，你可以预见到哪些困难，这些困难可以如何解决？或者说，如果你可以告诉过去的自己，要在这些地方注意避坑，你会着重介绍哪些地方？

要想预见挑战，第一步其实需要知道这个工程的目标是什么。比如如果这是个离线系统，那latency就不是目标，自然也就不是一个挑战。相应的，throughput是个重要目标，取决于具体的资源，可能是个挑战。所以这个问题隐含的第一个考点是搞清楚工程的目标是什么。要定义目标，自然需要从指标，数据，计算等几个方面来讨论。这里面有很多坑，比如不同的问题适合不同的指标（accuracy还是precision），不同的场合也适合不同的指标（imbalanced multi-class需要多个指标综合来看）和不同的数据采样方法。这就能看出来面试者平时有没有给组里定义指标的经验，是被动接受老板给的指标，还是主动去思考和改进，能不能预见到指标里面的坑。同时如何利用指标来做决策也是个考点。比如我们搜索系统想要改进relevance，但relevance是个离线指标，AB testing的时候只有engagement这样的在线指标。那这两个指标矛盾的时候怎么决策？所以取舍，权衡，决策，在互相矛盾的信息中抓住本质，甚至在回答关键的"遇见困难"之前已经开始在提供信号了。

在进入更技术的讨论以后，我们可以得到更多的信号。最重要的一点其实不是真的看出来了多少未来的挑战，或者说答案本身，而是思维方式，或者说怎么得出答案的过程。其中有三个要点。第一是条理性，这样才可以尽可能地让挑战无重复无遗漏。比较好的方法可以是，既然要设计的是一个机器学习的系统，那我从评价，数据，特征，架构几个角度来分别考虑。首先提纲挈领把要点摆出来，后面就不容易遗漏。第二点是[做决策的意识](/new-employee-suggestions.html)，对各个妥协所在需要意识到这里有个决策要做，至于具体决策怎么做，只要能自圆其说，通过牺牲什么指标A来换取指标B，为什么这么做，讲清楚就好。第三个是思考的深度，最好可以预判面试官的预判，跟着自己的方案走几步，看看有没有什么可能的问题。一个综合的例子是，我们要在嵌入式设备上设计一个模型，那么提出了一个效果不错的架构。但粗粗验算一下发现这个运算量可能比芯片的能力有数量级上的差异，所以就要做下一步决策，是用一些修补的方法比如quantziation，distillation来缩小计算量，还是从头换一个架构，还是有什么别的招。这种过程通过不同的候选人横向比较，就可以看出很多东西，比如条理性（选择技术的标准和流程），技术的熟练度（是否知道quantization，知道它的边界在哪里），决策的意识（修补不行的时候还有从头改架构这个选项），思维的深度（能不能看出来这个计算量太大）等等。但这些都不绝对，比如有些人做事很乱，没有系统性地找到挑战的方法，但他为祖国健康工作了50年以后，看到项目前几个字就知道有什么坑，这样也不是不行。而只要意识到挑战在哪里，大多数情况找到正确的方法其实不难，所以这部分反而不是特别重要，只能提供有限的技术熟练度的信号。

但其实还有另一个方面的挑战在技术之外。我们以前讲[软件工程](/behavior-questions.html)的时候讲过，软件开发一个核心就是时间和空间上的扩展性。所以我们也要在这些方面观察面试者有没有软件工程的技能。从时间上来说，他/她能不能跟着走完模型的整个lifecycle，是觉得部署完了就没了，还是意识到后面还有维护和改进的过程？这里面有没有什么挑战？比如如果我加了一点训练数据，是不是要整个重新训练？类似于技术的考察，面试者是假设这个问题非常重要，直接开始想解决方法，还是先分析这个问题是否重要，在确认重要以后再着手解决？从空间上来说，这个模型架构是否适合多个组合作？对上下游是不是有复杂的依赖？需要技术攻关吗？不确定性在哪里？如果搞不定的话怎么办？甚至可以问一些偏行为的问题，比如这个项目时间很紧，但如果走捷径又会留下技术债。在这个具体的项目里，你怎么平衡长期的可维护性和短期的交付？关键妥协的决策点在哪里？等等等等。类似的，这些问题的关键在预见问题本身，尤其在如何预见到这些问题的观察。

所以我们通过这个看似简单的问题"你预计这个工程项目的难点在哪里？"，可以串起来一系列对面试者综合素质的深入考察。这个考察上限下限都很高，跟staff面试者可以聊抽象的妥协决策（比如上面提到的长期可维护性和短期交付之间的妥协），业界创新，依赖剥离；跟senior面试者可以聊架构设计，测试维护，跨组合作；跟[junior面试者](/coding-questions.html)可以聊具体的技术细节。总之，观察的核心是方法论和熟练度，关键是看面试者能不能提出正确的问题。虽然这个文章比较干，但希望可以对各位面试官和面试者关于如何进行（机器学习）系统设计面试有所启发。

<script async data-uid="49b08a3e73" src="https://yage-ai.kit.com/49b08a3e73/index.js"></script>
