【问题标题】:How to automatically tune parameters of an algorithm?如何自动调整算法的参数?
【发布时间】:2009-10-12 09:02:18
【问题描述】:

设置如下:

我有一个可以成功或失败的算法。 我希望它以尽可能高的概率成功。 成功的概率取决于一些参数(和一些外部环境):

struct Parameters {
  float param1;
  float param2;
  float param3;
  float param4;
  // ...
};

bool RunAlgorithm (const Parameters& parameters) {
  // ...
  // P(return true) is a function of parameters.
}

如何(自动)以最少的调用次数找到最佳参数 RunAlgorithm ? 我会特别高兴有一个 readl 库。

如果您需要有关我的特定案例的更多信息:

  • 成功概率是参数的平滑函数,具有单一全局最优值。
  • 大约有 10 个参数,其中大部分是独立可调的(但有些是相互依赖的)
  • 我会在一夜之间运行调整,我可以处理大约 1000 次运行算法调用。

澄清:

最佳参数必须在一夜之间自动找到,并在白天使用。 外部环境每天都在变化,因此不可能一劳永逸地计算它们。

更多说明:

RunAlgorithm 其实就是玩游戏的算法。它与固定的对手进行一整场比赛(围棋或国际象棋)。我可以在一夜之间玩 1000 场比赛。每晚都是另一个对手。

我想看看不同的对手是否需要不同的参数。

RunAlgorithm 是平滑的,因为稍微改变参数只会改变一点算法。

可以通过具有相同参数的大量样本来估计成功概率。 但是在不改变参数的情况下运行这么多游戏成本太高了。

我可以尝试独立优化每个参数(这将导致每个参数运行 100 次),但我想存在一些依赖关系。

整个问题在于如何明智地使用稀缺数据。

玩的游戏非常随机,这没问题。

【问题讨论】:

  • 请指定您使用的语言。
  • 语言无关紧要。我可以将 RunAlgorithm 作为单独的可执行文件,并通过配置文件或命令行获取参数。
  • 也许你想多描述一下算法。
  • 算法是和一个固定的对手玩游戏,输赢。参数控制搜索、评估和算法的不同方面。
  • 当然这在参数上通常是不平滑的,如果你的玩家是确定性的,那么这个函数对于某些参数将是 0,对于其他参数是 1。即使它们不是确定性的并使用 RNG,该函数也很难平滑,这将是分段常数。请清楚您要达到的目标。具有离散估值(例如,基于 3 次运行)的遗传算法应该可以在恕我直言。

标签: algorithm parameters performance


【解决方案1】:

也许你正在寻找genetic algorithms

【讨论】:

  • 这正是遗传算法的用途。
  • 这不是一个真正的答案。遗传算法就是这样一种通用工具。你不得不说,如何应用它们。
  • GA 的问题是我的算法返回真或假,而不是适应度。
  • 感谢您的反对。如果您不提供有关您的问题的更多信息(如何计算成功,它取决于什么),您将很难得到准确的答案。有没有办法,你可以从参数集中得出“适应度”?
  • 如果我认为答案无用/误导性,我想我有权投反对票。没有直接的适应度,因为这不是 GA 问题。您可以通过运行 RunAlgorithm 1000 次来评估它并计算成功百分比。但这是慢下来的方式。整个问题在于如何充分利用稀缺数据。
【解决方案2】:

为什么不让程序自己打架呢?取一些向量 v(参数),让它与 v + (0.1,0,0,0,..,0) 对抗,比如 15 次。然后,取胜者并修改另一个参数,依此类推。运气好的话,你会得到一个强大的玩家,能够击败大多数人。

以前的答案(问题被编辑后大部分都无关紧要)

有了这些假设和那种程度的概括,你将一事无成(除了不可能的结果)。

基本问题:您能否更改算法,使其返回成功的概率,而不是单个实验的结果?然后,使用适当的optimization 技术(没有人会告诉你在这样的一般假设下)。在 Haskell 中,您甚至可以更改代码,以便在简单情况下找到概率(probability monad,而不是给出单个结果。正如其他人提到的,您可以使用遗传算法使用概率作为适应度函数。如果您有公式,使用computer algebra system 求最大值。

成功概率是参数的平滑函数,具有单一全局最优值。

平滑还是连续?如果平滑,您可以使用微积分 (Lagrange multipliers?)。您甚至可以只对代码进行少量更改(假设您的编程语言足够通用),使用 automatic differentiation 自动计算导数。

我会在一夜之间运行调整,我可以处理大约 1000 次运行算法调用。

那么复杂?这将允许您从许多浮点数中检查两个可能的值 (210=1024)。您甚至无法确定数量级,甚至无法确定数量级。

大约有 10 个参数,其中大部分是独立可调的(但有些是相互依赖的)

如果您知道什么是独立的,请修复一些参数并更改与它们无关的参数,例如分治法。显然,用 5 个参数调优两种算法要好得多。

除非您提供更多详细信息,否则我会否决这个问题。这对于学术问题来说噪音太大,而对于现实世界的问题来说却没有足够的数据。

【讨论】:

    【解决方案3】:

    你遇到的主要问题是,如果有十个参数,1000 次运行几乎没有,因为对于每次运行,你所拥有的只是一个真/假结果,而不是与参数关联的 P(成功)。

    这个想法一方面可以充分利用您的 1000 次运行,另一方面也说明了您的问题的难处理性。让我们假设这十个参数确实是独立的。为每个参数选择两个值(例如“高”值和“低”值)。有 1024 种方法可以选择这些值的唯一组合;为每个组合运行您的方法并存储结果。完成后,您将为每个参数的每个值运行 512 次测试;在独立性假设下,可能可以为您提供每个值的成功条件概率的体面估计。对该数据的分析应该为您提供有关如何设置参数的一些信息,并可能建议您为未来的夜晚改进“高”和“低”值。我的想法是在这里挖掘 ANOVA 作为一种可能有用的统计工具。

    非常模糊的建议...但是,正如已经指出的那样,这是一个相当模糊的问题。

    【讨论】:

      【解决方案4】:

      专门为玩游戏的代理调整参数,你可能对CLOP感兴趣

      http://remi.coulom.free.fr/CLOP/

      【讨论】:

        【解决方案5】:

        不确定我是否理解正确...

        如果你可以为你的算法选择参数,是否意味着你可以选择一次?

        那么,你可以简单地:

        • 让开发人员只运行一次所有/多个案例,找到最佳案例,然后将参数替换为最佳值
        • 在运行时,对于您的真实用户,算法已经使用最佳参数进行了参数化

        或者,如果每次运行的最佳值发生变化...... 您在寻找 遗传算法 类型的方法吗?

        【讨论】:

          【解决方案6】:

          这个问题的答案取决于:

          1. 参数范围。您的参数可以有小范围或大范围的值吗?
          2. 游戏分级。它必须是布尔值,还是可以是平滑函数?

          对于这个问题来说,一种似乎很自然的方法是Hill Climbing

          一种可能的实施方式是从几个点开始,然后计算它们的“等级”。然后为下一个点找出一个有利的方向,并尝试“上升”。

          正如您提出的那样,我在这个问题中看到的主要问题是参数值的范围很大,并且运行结果是布尔值(而不是数字等级)。这将需要多次运行才能确定一组选择的参数是否确实好,另一方面,还有大量的参数值需要检查。仅检查所有方向将导致(太?)大量运行。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2012-11-18
            • 2012-01-05
            • 2011-02-15
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-12-05
            相关资源
            最近更新 更多