精确诊断问题的重要性
在软件开发领域,测试(testing)和调试(debugging)是两个容易被混淆的概念。但其实两者有很大的不同,测试的重点在于发现问题;而调试的重点在于解决问题(在计算机领域,bug就是问题的别称,所以调试的英文是debug。直白的理解就是de-bug,把bug去掉,即解决问题)。因此,测试通常发生在调试之前,即通过测试发现了问题,接下来就要调试,解决问题了。
通常,人们在发现了问题之后,就会倾向于立即着手解决问题。但是这种方法往往并不能正确解决问题,即使能够解决问题,效率也非常低。那该怎么做呢?
雷·达里奥(Ray Dalio)在《原则》一书中详细阐述了自己“实现梦想的5大步骤”,即:
一、设立目标;
二、识别问题并对问题零容忍;
三、精确地诊断问题;
四、制定计划,清晰地列出解决问题所需执行的任务;
五、执行计划中的任务。
从这5个步骤中我们可以看出,达里奥在步骤二“识别问题”和步骤四、五“解决问题”之间还有一个步骤三——“精确地诊断问题”。没错,我们需要在开始解决问题之前精确地诊断问题。有人可能会觉得这不都一样吗,有什么区别?区别在于:先对发现的问题进行仔细的诊断,能够缩小问题根源的范围,极大地提高解决问题的效率,同时提升解决问题的准确率。
这样的解释可能过于空洞,举个实际的例子来帮助说明一下。
自动飞行器问题
吴恩达(Andrew Ng)教授在斯坦福大学《机器学习》公开课的第11课中讲了应用机器学习的建议。他举了自己的团队在做自动飞行器的例子。制造自动飞行器通常有三个步骤:
1.建立一个飞行模拟器;
2.选择一个判断飞行器飞行效果的标准J(θ)(即成本函数,cost function);
3.选取某个算法,通过训练获得最接近步骤2中所选择标准的参数θ。
吴恩达教授的团队完成了上述三个步骤,却发现:自动飞行器的飞行效果没有手动驾驶的飞行效果好。好,现在已经发现了问题,我们的目标是要让自动飞行器的飞行效果跟人类收到驾驶的效果一样好,甚至更好。如果是你面对这个问题,你会怎么办呢?(请先自己思考30秒)
吴教授是这样解决思路是这样的,如果上述三个步骤都正确的话,那么自动飞行器的飞行效果应该很好。现在既然没有达到预期的效果,那么上述三个步骤中至少有一个没有做对。
接下来就需要诊断到底是那个步骤出了问题。具体的诊断过程为:
1.如果经过三个步骤后得到的参数θ在模拟器中飞行效果良好,但是在现实中飞行效果很糟,那么说明问题出在模拟器上;
2.将人类手动驾驶得到的参数记为θ*。如果J(θ*)的效果比J(θ)好,说明问题出在步骤3选取的算法上;
3.如果J(θ)的效果比J(θ*),那么问题则出在步骤2上,没有选择正确的优化标准。
通过以上3个步骤的诊断,我们就能极大地缩小问题根源的范围,接下来才是真正的解决问题的过程:
1.如果是模拟器有问题,那么就换个更好的模拟器;
2.如果是优化算法有问题,那么就换个其他的优化算法试试;
3.如果是选取的优化标准有问题,那就换个其他的优化标准。
这就是正确的解决问题的流程,不知道你是不是也是这样想的呢?
最后,需要注意的是,针对我们发现的问题进行修改后也不一定马上就能解决问题。但是这并不是说诊断问题就没有必要了。恰恰相反,通过精确地诊断问题,起码我们极大地缩小了问题的范围,节省了解决问题所需的时间,而且极大地提升了正确解决问题的概率。这就是精确诊断问题的重要性。