55

我做了很多遗传算法;他们工作(他们很快找到一个合理的解决方案)。但我现在发现了TDD。有没有办法以 TDD 方式编写遗传算法(严重依赖随机数)?

为了更笼统地提出这个问题,您如何测试非确定性方法/功能。这是我的想法:

  1. 使用特定的种子。如果我首先在代码中犯了错误,这将无济于事,但有助于在重构时发现错误。

  2. 使用已知的数字列表。与上面类似,但我可以手动跟踪代码(这将非常乏味)。

  3. 使用一个常数。至少我知道会发生什么。当 RandomFloat(0,1) 始终返回 1 时,最好确保骰子始终读取 6。

  4. 尝试将尽可能多的非确定性代码移出 GA。这似乎很愚蠢,因为这是其目的的核心。

链接到非常好的测试书籍也将不胜感激。

4

10 回答 10

14

在我看来,测试其一致逻辑的唯一方法是应用一致的输入,......或者将每次迭代视为一个单一的自动机,其状态在迭代之前和之后进行测试,将整个非确定性系统转换为基于确定性的可测试组件迭代值。

对于迭代中的变体/繁殖/属性继承,在每次迭代的边界上测试这些值,并根据成功迭代子测试的已知输入/输出测试所有迭代的全局输出......

因为该算法是迭代的,所以您可以在测试中使用归纳法来确保它适用于 1 次迭代、n+1 次迭代,以证明对于给定的输入范围/域和对可能值的约束,它将产生正确的结果(无论数据确定性如何)在输入。

编辑我发现这种用于测试非确定性系统的策略可能会提供一些见解。一旦 TDD/开发过程证明逻辑是合理的,它可能有助于实时结果的统计分析。

于 2009-06-24T15:33:01.947 回答
4

我会通过多次测试随机函数并分析返回值的分布是否符合统计预期(这涉及一些统计知识)来测试随机函数。

于 2009-06-24T15:48:03.413 回答
2

如果您在谈论 TDD,我会说肯定从选择一个常数开始并从那里扩展您的测试套件。我已经在一些高度数学问题上完成了 TDD,它有助于拥有一些你知道并从一开始就手工解决的恒定案例。

W/R/T 您的第四点,将不确定性代码移出 GA,我认为这可能是一种值得考虑的方法。如果您可以分解算法并分离非确定性关注点,那么它应该使测试确定性部分变得简单。只要您注意命名事物的方式,我认为您不会在这里牺牲太多。除非我误解了你,否则 GA 仍将委托给此代码,但它存在于其他地方。

至于非常好的(开发人员)测试书籍的链接,我最喜欢的是:

于 2009-06-24T17:07:55.770 回答
2

我对 GA 算法的非确定性函数进行单元测试的一种方法是将随机数的选择放在使用该随机数的逻辑函数的不同函数中。

例如,如果你有一个函数,它需要一个基因(某物的向量)并使用基因的两个随机点来处理它们(突变或其他),你可以将随机数的生成放在一个函数中,并且然后将它们与基因一起传递给另一个包含给定数字的逻辑的函数。

通过这种方式,您可以使用逻辑函数进行 TDD 并将某些基因和某些数字传递给它,确切地知道在给定数字的情况下逻辑应该对基因做什么,并能够在修改后的基因上编写断言。

另一种测试随机数生成的方法是将该生成外部化到另一个类,该类可以通过上下文访问或从配置值加载,并使用不同的类进行测试执行。该类将有两种实现,一种用于生成实际随机数的生产,另一种用于测试,它可以接受稍后将生成的数字。然后在测试中,您可以提供该类将提供给测试代码的某些数字。

于 2012-12-23T14:18:15.353 回答
1

您可以编写一个冗余神经网络来分析算法的结果,并根据预期结果对输出进行排名。:)

尽可能多地分解你的方法。然后,您还可以仅围绕随机部分进行单元测试以检查值的范围。甚至让测试运行几次,看看结果是否改变。

于 2009-06-24T15:32:45.613 回答
1

您的所有功能都应该是完全确定的。这意味着您正在测试的任何函数都不应该在函数本身内部生成随机数。您将希望将其作为参数传递。这样,当您的程序根据您的随机数做出决策时,您可以传入代表数字来测试该数字的预期输出。唯一不应该是确定性的是你的实际随机数生成器,你真的不需要太担心,因为你不应该自己写这个。只要它是一个已建立的库,您就应该能够假设它可以工作。

那是为了你的单元测试。对于您的集成测试,如果您正在这样做,您可能会考虑模拟您的随机数生成,将其替换为一种算法,该算法将为您需要生成的每个随机数从 0..n 返回已知数字。

于 2009-06-24T17:31:12.527 回答
1

我写了一个 C# TDD 遗传算法教学应用程序: http ://code.google.com/p/evo-lisa-clone/

让我们采用应用程序中最简单的随机结果方法:PointGenetics.Create,它在给定边界的情况下创建一个随机点。对于这种方法,我使用了 5 个测试,它们都不依赖于特定的种子:

http://code.google.com/p/evo-lisa-clone/source/browse/trunk/EvoLisaClone/EvoLisaCloneTest/PointGeneticsTest.cs

随机性测试很简单:对于一个大边界(许多可能性),两个连续生成的点不应该相等。其余测试检查其他约束。

于 2009-07-02T17:03:13.713 回答
1

好吧,最可测试的部分是适应度函数——你所有的逻辑都在这里。这在某些情况下可能非常复杂(您可能会根据输入参数运行各种模拟),因此您要确保所有这些东西都可以与大量单元测试一起使用,并且这项工作可以遵循任何方法。

关于测试 GA 参数(突变率、交叉策略等),如果你自己实现这些东西,你当然可以测试它(你可以再次围绕突变逻辑进行单元测试等),但你不会能够测试 GA 的“微调”。

换句话说,除了通过找到的解决方案的优点之外,您将无法测试 GA 是否真的执行。

于 2011-07-05T10:49:44.170 回答
0

算法为您提供相同输入的相同结果的测试可能会对您有所帮助,但有时您会进行更改以改变算法的结果选择行为。

我会尽最大努力进行测试,以确保算法为您提供正确的结果。如果该算法为您提供了一些静态种子和随机值的正确结果,则该算法可以工作,或者不会通过所做的更改进行破坏。

TDD 的另一个机会是评估算法的可能性。如果您可以自动检查结果有多好,您可以添加测试以表明更改并未降低结果的质量或增加您的计算时间不合理。

如果您想使用许多基础种子测试您的算法,您可能需要测试一套西装,该西装在每次保存后运行快速测试以确保您没有损坏任何东西,并且一套西装可以运行更长时间后期评价

于 2009-06-24T15:42:35.733 回答
0

我强烈建议考虑为您的单元测试用例使用模拟对象(http://en.wikipedia.org/wiki/Mock_object)。您可以使用它们来模拟进行随机猜测的对象,以使您获得预期的结果。

于 2010-03-12T00:10:37.653 回答