【问题标题】:Genetic algorithm for optimization in game playing agent heuristic evaluation function游戏代理启发式评价函数优化的遗传算法
【发布时间】:2017-12-18 04:35:58
【问题描述】:

这是对这个问题中给出的答案的回应: How to create a good evaluation function for a game?,尤其是@David(这是第一个答案)。

背景:我正在使用遗传算法来优化游戏代理中的超参数,该代理使用 minimax / alpha beta 剪枝(迭代加深)。特别是,我想使用遗传算法优化启发式(评估)函数参数。我使用的评价函数是:

f(w) = w * num_my_moves - (1-w) * num_opponent_moves

唯一要优化的参数是 [0,1] 中的 w。

我是这样编写遗传算法的:

  1. 创建一个由 100 个代理组成的随机群体
  2. 让他们随机玩 1000 场比赛并替换。
  3. 让父母成为表现最好的代理人,并混入一些表现较差的代理人,以实现遗传多样性。
  4. 随机繁殖一些父母来创造孩子。 * 育种过程:我们将孩子定义为父母体重的平均值。 即 childWeight = 0.5(father.w+ mother.w)
  5. 新种群由父母和新创建的孩子组成。
  6. 随机变异 1% 的人口如下:newWeight = agent.x + random.uniform(-0.01,0.01) 并考虑微不足道的边界情况(即适当地小于零和大于一)。
  7. 进化 10 次(即为新种群重复)

我的问题:请评估上面的粗体点。特别是,有没有人有更好的繁殖方式(而不是简单地平均父权重),有没有人有更好的变异方式,而不是仅仅添加 random.uniform(-0.01,0.01)?

【问题讨论】:

    标签: optimization artificial-intelligence genetic-algorithm depth-first-search game-theory


    【解决方案1】:

    看起来您实际上并未将遗传算法应用于您的代理,而只是直接在表型/权重上进行简单进化。我建议你尝试引入一个genetic representation 你的权重,然后进化这个基因组。一个例子是将您的权重表示为二进制字符串,并对字符串的每一位应用进化,这意味着每一位都有可能发生突变。这称为点突变。您可以应用许多其他突变,但它可以作为一个开始。

    您会注意到,您的特工不会过多地陷入局部最小值,因为有时一个小的基因变化会极大地改变表型/权重。

    好的,这听起来可能很复杂,但实际上并非如此。举个例子吧:

    假设你有一个以 10 为底的权重 42。这将是二进制的 101010。现在您已经在二进制表示的每一位上实现了 1% 的突变率。假设最后一位被翻转。然后我们有二进制的101011,或者十进制的43。没有那么大的变化。另一方面,对第二位执行相同操作会得到二进制的111010 或十进制的58。注意大跳跃。这就是我们想要的,让您的代理群体更快地搜索更大的解决方案空间。

    关于育种。你可以试试跨界。假设您有许多权重,每个权重都带有遗传编码。如果将整个基因组(所有二进制数据)表示为一个长二进制字符串,则可以组合两个父基因组的部分。再次举例。以下是“父亲”和“母亲”的基因组和表型:

    Weight Name:          W1     W2     W3     W4     W5
    Father Phenotype:     43     15     34     17     14
    Father Genome:    101011 001111 100010 010001 001110
    Mother Genome:    100110 100111 011001 010100 101000
    Mother Phenotype:     38     39     25     20     40
    

    您可以做的是在同一位置通过两个基因组绘制任意线,并将片段任意分配给孩子。这是一个跨界版本。

    Weight Name:          W1     W2     W3     W4     W5
    Father Genome:    101011 00.... ...... .....1 001110
    Mother Genome:    ...... ..0111 011001 01010. ......
    Child Genome:     101011 000111 011001 010101 001110
    Child Phenotype:      43      7     25     21     14
    

    这里前 8 位和后 7 位来自父亲,中间来自母亲。注意重量 W1 和 W5 完全来自父亲,而 W3 完全来自母亲。而 W2 和 W4 是组合。 W4几乎没有变化,而W2变化很大。

    我希望这能让您对如何进行遗传算法有所了解。也就是说,我建议您使用现代库而不是自己实现它,除非您这样做是为了学习。

    编辑:更多关于处理权重/二进制表示:

    • 如果您需要分数,您可以通过将分子和分母分隔为不同的权重来实现这一点,或者将其中一个作为常数,例如,4210 给出4.2。)
    • 大于 0 的约束是免费的。要真正得到负数,您需要对权重取反。
    • 您可以通过将权重除以该位字符串长度的最大可能值来获得小于 1 的约束。在上面的例子中,你有 6 位,最多可以变成 63。如果你在突变后得到一个以 10 为底的10101042 的二进制字符串,你做 42/63 得到 0.667 并且只能得到63/63 时高达 1.0。
    • 两个权重之和等于 1?如果你得到101010001000 对于W1W2,它给出42 和8,那么你可以去W1_scaled = W1 / (W1 + W2) = 0.84W2_scaled = W2 / (W1 + W2) = 0.16。这应该总是给你W1_scaled + W2_scaled = 1

    【讨论】:

    • 这很有趣。我实际上只是在遵循lethain.com/genetic-algorithms-cool-name-damn-simple 的基本思想。如何解释约束,即 w1+w2 = 1 和 0github.com/trevorstephens/gplearn
    • @Pii 我浏览了这篇博文。我觉得它缺少遗传算法的遗传编码部分。它确实在母亲和父亲之间有简单的交叉。您没有按照博客建议的方式进行操作。关于约束,最简单的方法是简单地杀死违反你约束的孩子。或者您可以缩放您的表型/权重。我会在上面答案的最后补充一点。
    • @Pii 我去寻找一个合理的 python 库。 Pyevolve 似乎符合要求。以下使用G1DBinaryString 的示例接近我的建议:pyevolve.sourceforge.net/…
    【解决方案2】:

    自从我被提及。

    我没有对父权重进行平均,而是使用父权重作为最小值/最大值来选择随机数。我还发现我必须稍微扩大范围(补偿当我平均两个统一随机数或 sqrt(2) 时标准偏差的减少,但我可能不准确)以抵抗向平均值的拉动。否则人口向平均水平收敛,无法逃脱。

    因此,如果父母的体重是 0.1 和 0.2,它可能会为孩子的体重选择一个介于 0.08 和 0.22 之间的随机数。

    后期编辑:一种我当时不知道的更被接受、研究和理解的方法是“差异进化”。

    【讨论】:

    • 您必须稍微扩大范围到底是什么意思?你描述的补偿我不清楚。
    • 组合数字而不是选择二元基因有一个缺点。如果没有任何选择,您仍然会看到总体快速收敛到一个中心值。我尝试进行补偿,以便收敛是选择而不是平均的结果。我不知道它的正确名称,因为遗传算法通常处理二进制基因(有时使用灰色编码权重)而不是浮点权重。
    • 如何解释随机突变?
    猜你喜欢
    • 1970-01-01
    • 2011-04-23
    • 1970-01-01
    • 2011-08-03
    • 2018-05-12
    • 2015-02-18
    • 2013-07-02
    • 1970-01-01
    相关资源
    最近更新 更多