游戏玩家启发式评估函数优化中的遗传算法

这是对如何为游戏创建一个好的评估函数?问题中由@David给出的回答的回应(这是第一个回答)。

背景:我正在使用遗传算法来优化使用极小极大/alpha-beta剪枝(带有迭代加深)的游戏玩家的超参数。特别是,我想使用遗传算法来优化启发式(评估)函数的参数。我使用的评估函数是:

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

唯一需要优化的参数是w,范围在[0,1]之间。

这是我如何编程实现遗传算法的:

  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))?


回答:

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

你会注意到你的智能体不会那么容易陷入局部最小值,因为有时一个小的基因变化可以极大地改变表型/权重。

这听起来可能很复杂,实际上并不复杂。让我给你举个例子:

假设你有一个基数为10的权重42。这在二进制中是101010。现在你对二进制表示的每个位实施了1%的变异率。假设最后一位被翻转了。那么我们得到的二进制是101011,或者十进制中的43。变化不大。另一方面,如果对第二位进行同样的操作,你会得到二进制111010或十进制58。注意这个大的跳跃。这正是我们想要的,让你的智能体群体更快地搜索更大的解空间。

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

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

你可以做的是在两个基因组的相同位置画任意线,并任意分配这些段给子代。这是一种交叉版本。

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

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

我希望这能给你一些关于如何进行遗传算法的见解。话虽如此,我建议使用现代库而不是自己实现,除非你是为了学习。

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

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

Related Posts

Keras Dense层输入未被展平

这是我的测试代码: from keras import…

无法将分类变量输入随机森林

我有10个分类变量和3个数值变量。我在分割后直接将它们…

如何在Keras中对每个输出应用Sigmoid函数?

这是我代码的一部分。 model = Sequenti…

如何选择类概率的最佳阈值?

我的神经网络输出是一个用于多标签分类的预测类概率表: …

在Keras中使用深度学习得到不同的结果

我按照一个教程使用Keras中的深度神经网络进行文本分…

‘MatMul’操作的输入’b’类型为float32,与参数’a’的类型float64不匹配

我写了一个简单的TensorFlow代码,但不断遇到T…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注