正文
指数级调试难度
在标准软件工程中,当你编写一个问题的解决方案,在大多数情况下,某些东西不能按预期工作时,有两个维度,可能会出现问题:算法或实现。 例如,一个简单的递归算法:
def recursion(input):
if input is endCase:
return transform(input)
else:
return recursion(transform(input))
当代码不能按预期工作时,我们可以枚举失败的情况。 在此示例中,网格可能如下所示:
沿着水平轴,我们有几个可能在算法设计中犯了错误的例子。沿着垂直轴,我们有几个例子说明在算法的实现中可能出现问题的地方。沿着任何一个维度,我们可能有问题的组合(即多个实现错误),但是我们唯一有一个有效的解决方案是如果算法和实现都是正确的。
调试过程成为关于错误的信号(编译器错误消息,程序输出等)与你的直觉(问题可能在哪里)的组合问题。这些信号和启发式帮助使您将可能的错误的搜索空间减小。
在机器学习流水线的情况下,有两个额外的维度:实际的模型和数据。为了说明这些维度,最简单的例子是使用随机梯度下降的训练logistic回归。这里算法正确性包括梯度下降更新方程的正确性。实现正确性包括特征和参数更新的正确计算。数据中的错误通常涉及噪声标签,在预处理中产生的错误,没有正确的监控信号或甚至没有足够的数据。模型中的错误可能涉及建模能力的实际限制。例如,当您的真正决策边界是非线性时,可能使用了线性分类器。
我们的调试过程从2D网格到4D超立方体(为了清楚起见,上面四个维度中有三个)。 第四个数据维可以可视化为这些立方体的序列(注意,只有一个立方体具有正确的解)。
“指数级”更难的原因是如果有n种可能的方式出错,有n x n种方式可能会在2D出错和n x n x n x n方式在4D情况下出错。 必须根据可用的信号建立一个寻找出错地方的直觉。 幸运的是,对于机器学习算法,你还有更多的信号来找出哪里出错了。 例如,特别有用的信号是训练和测试集上的损失函数图,算法的实际输出,开发数据集和算法中间计算的汇总统计。