单元测试机器学习代码

时间:2010-02-10 18:14:57

标签: unit-testing machine-learning

我正在为计算机视觉论文编写一个相当复杂的机器学习程序。它工作得很好,但我需要继续尝试新的东西并添加新的功能。这是有问题的,因为我在扩展代码或尝试简化算法时有时会引入错误。

显然,正确的做法是添加单元测试,但目前尚不清楚如何执行此操作。我的程序的许多组件产生了一些主观的答案,我不能自动进行健全性检查。

例如,我有一些代码使用较低分辨率的曲线近似曲线,因此我可以在较低分辨率的曲线上进行计算密集型工作。我不小心在这段代码中引入了一个错误,只有当我整个程序的结果稍微差一点时才通过艰苦的搜索找到它。

但是,当我尝试为它编写单元测试时,我不知道该做什么。如果我制作一个具有明确正确的低分辨率版本的简单曲线,那么我并没有真正测试出错的一切。如果我做一个简单的曲线,然后稍微扰乱点,我的代码开始产生不同的答案,即使这段特殊的代码现在似乎真的很好。

6 个答案:

答案 0 :(得分:12)

“然后我并没有真正测试出错的一切。”

正确。

单元测试的工作来测试可能出错的所有

单元测试的工作是在给定特定输入和特定预期结果的情况下测试您所拥有的正确事物。这里的重要部分是具体的可见外部要求,具体测试用例满足。并非所有可能出错的事都以某种方式被阻止。

没有什么能测试可能出错的一切。你可以写一个证明,但是你很难为所有编写测试。

明智地选择您的测试用例。

此外,单元测试的工作是测试整个应用程序的每个小部分都是正确的 - 孤立地。

例如,您的“使用较低分辨率曲线近似曲线的代码”可能有几个小部件可以作为单独的单元进行测试。处于隔离状态。整合的整体也可以进行测试,以确保它的工作原理。

例如,您对“低分辨率曲线的计算密集型工作”可能有几个小部件可以作为单独的单元进行测试。孤立地。

单元测试的重点是创建稍后组装的小型正确单元。

答案 1 :(得分:11)

没有看到你的代码,很难说,但我怀疑你是在尝试在太高的水平上编写测试。您可能想要将您的方法分解为确定性的小组件并对其进行测试。然后通过提供从底层方法(可能位于不同对象)返回可预测值的模拟实现来测试使用这些方法的方法。然后,您可以编写涵盖各种方法领域的测试,确保您覆盖所有可能的结果。对于小方法,您可以通过提供表示输入域的值来实现。对于依赖于这些的方法,通过提供从依赖项返回结果范围的模拟实现。

答案 2 :(得分:9)

你可能不会感激讽刺,但基本上你所拥有的是遗留代码:一大堆没有任何单元测试的软件。当然你不知道从哪里开始。因此,您可能会发现阅读处理遗留代码很有帮助。

关于这一点的最终想法是Michael Feather的书,有效地使用遗留代码。在ObjectMentor网站上曾经有过一个有用的摘要,但是网站已经走了公司的道路。然而,WELC在评论和其他文章中留下了遗产。 Check them out (or just buy the book),虽然关键课程是S.Lott和tvanfosson在回复中所涵盖的内容。


2019更新:我已使用Wayback Machine网络存档中的版本修复了WELC摘要的链接(感谢@milia)。

此外 - 尽管知道主要包含其他网站链接的答案都是低质量的答案:) - 这里是a new (2019 new) Google tutorial on Testing and Debugging ML code的链接。我希望这会让那些偶然发现这个答案的未来的搜索者有所了解。

答案 3 :(得分:7)

您的单元测试需要使用某种模糊因子,要么接受近似值,要么使用某种概率检查。

例如,如果您有一些返回浮点结果的函数,则几乎不可能编写一个在所有平台上都能正常工作的测试。您的检查需要执行近似。

TEST_ALMOST_EQ(result, 4.0);

高于TEST_ALMOST_EQ可能会验证result介于3.9和4.1之间(例如)。

或者,如果您的机器学习算法是概率性的,那么您的测试需要通过取多次运行的平均值并期望它在一定范围内来适应它。

x = 0;
for (100 times) {
  x += result_probabilistic_test();
}

avg = x/100;
TEST_RANGE(avg, 10.0, 15.0);

当然,测试是非确定性的,因此您需要对它们进行调整,以便您可以很高的概率进行非片状测试。 (例如,增加试验次数,或增加误差范围)。

你也可以使用模拟(例如,你的概率算法的模拟随机数生成器),它们通常有助于确定性地测试特定的代码路径,但它们需要付出很多努力来维护。理想情况下,您将使用模糊测试和模拟的组合。

HTH。

答案 4 :(得分:1)

通常,对于统计测量,您可以使用epsilon构建答案。 I.E.你的点的均方差将是< 0.01或一些这样的。另一个选择是运行几次,如果它“经常”失败,那么你就有问题了。

答案 5 :(得分:0)

  1. 获取适当的测试数据集(可能是您通常使用的子集)
  2. 计算此数据集的某些指标(例如准确度)
  3. 记下获得的值(交叉验证)
  4. 这应该说明了为
  5. 设置阈值的内容

    当然,如果在对代码进行更改时,数据集上的性能会稍微增加,但如果它大幅减少,则表明出现了问题。