【问题标题】:Roulette wheel selection with positive and negative fitness values for minimization具有正负适应度值的轮盘赌轮选择以进行最小化
【发布时间】:2017-11-09 20:13:17
【问题描述】:

我正在做一个遗传算法,每个人都会产生 3 个新的后代。使用适应度函数评估新个体,该函数可能返回负值和正值。如果我想最小化,使用轮盘赌选择在后代之间进行选择的正确方法是什么?

适应度函数的一些可能值是:fitness_offspring_1 = -98.74; fitness_offspring_2 = -10.1; fitness_offspring_3 = 100.31

我正在研究 Python,但我只需要这个想法,因此我可以自己实现它。

【问题讨论】:

  • 在传统的遗传算法中,您使用选择方法来选择合适的个体进行交配,而不是选择哪些后代生活(所有后代都生活在普通遗传算法中)。我没有看到你的策略,这是你的错误还是你在构建自定义算法?
  • @umutto 这不是错误。这个想法是以三种不同的方式使一个人变异,这样你就有了三个新的后代。然后你应该使用轮盘赌选择其中之一。
  • 好吧,轮盘赌可能有点过头了,但它可能也很好用,而且它仍然是一种快速算法。我会给你一个简单的伪代码,你可以从中实现。

标签: python genetic-algorithm roulette-wheel-selection


【解决方案1】:

轮盘赌选择只是分配与个人适应度成比例的概率值。然后从该分布中随机选择。适合的人被选中的机会更大,而不太适合的人获得的机会更低。

您可以通过使用后代列表而不是个体来轻松地将其调整为您的代码。

让我们从 python 中的简单伪代码实现开始,您可以根据需要对其进行修改:

fitness_sum = sum([ind.fitness for ind in individuals])
probability_offset = 0

for ind in individuals:
    ind.probability = probability_offset + (ind.fitness / fitness_sum)
    probability_offset += ind.probability

r = get_random_float()

selected_ind = individuals[0] # initialize
for ind in individuals:
    if ind.probability > r:
        break; 
    selected_ind = ind

现在,上面的代码(根据轮盘的性质)假设所有适应度值都是正数。因此,在您的情况下,我们需要对其进行规范化。您可以简单地将所有值与最小后代的绝对值相加。但这会使它的概率为 0,所以你可以简单地给 all 添加一个偏差来给它一点机会。

让我们看看它如何处理简单的值,比如 [1, 5, 14]

fitness_sum = 20
previous_probability = 0

# iterating first for loop:
individual[0].fitness => 0 + 1 / 20 = 0.05
individual[1].fitness => 0.05 + 5 / 20 = 0.3 
individual[2].fitness => 0.3 + 14 / 20 = 1

# We created the wheel of probability distributions, 
# 0 - 0.05 means we select individual 0
# 0.05 - 0.3 means we select individual 1 etc...

# say our random number r = 0.4

r = 0.4
selected_ind = individual_0

# iterating second for loop:
# 0.05 > 0.4 = false
selected_ind = individual_0
# 0.3 > 0.4 = false
selected_ind = individual_1
# 1.0 > 0.4 = true
break

我确信您可以搜索 Python 中更好的伪代码或实现。只是想给你一个想法。

【讨论】:

  • 如果我这样做,具有最高适应度值的个体将获得最高的被选中机会,我不希望这样。我正在研究一个最小化问题。在您的 [1, 5, 14] 示例中,第一个人(适应度 = 1 的人)应该有最高的机会被选中。
  • @n23 对,我完全忘记了。您可以通过 max_fitness-individual_fitness 或 1/individual_fitness 将其转化为最大化问题。
  • 我必须在哪里执行此操作? @umutto
  • @n23 哪里有ind.fitness,IE:把fitness_sum = sum([ind.fitness for ind in individuals])改成fitness_sum = sum([max_fitness-ind.fitness for ind in individuals])和(ind.fitness / fitness_sum)改成((max_fitness-ind.fitness) / fitness_sum)
【解决方案2】:

这是我在 JavaScript 中实现它的方式,给你一个大致的概念:

    var totalFitness = 0;
    var minimalFitness = 0;

    for(var genome in this.population){
      var score = this.population[genome].score;
      minimalFitness = score < minimalFitness ? score : minimalFitness;
      totalFitness += score
    }

    minimalFitness = Math.abs(minimalFitness);
    totalFitness += minimalFitness * this.popsize;

    var random = Math.random() * totalFitness
    var value = 0;

    for(var genome in this.population){
      genome = this.population[genome];
      value += genome.score + minimalFitness;
      if(random < value) return genome;
    }

    // if all scores equal, return random genome
    return this.population[Math.floor(Math.random() * this.population.length)];

但是,正如@umutto 所提到的,这使得具有最低 分数的基因组没有机会 被选中。所以你可以人为地为每个基因组添加一点适应度,这样即使是最低的个体也有机会。注意:我没有在上面提到的@umutto 代码中实现那个小偏差。

【讨论】:

    【解决方案3】:

    要使用轮盘选择进行最小化,您必须执行两个预处理步骤:

    1. 你必须去掉负的适应度值,因为适应度值代表选择概率,不能为负。最简单的方法是从所有适应度值中减去最低(负)值。最低适应度值现在为零。
    2. 为了最小化,您必须还原适应度值。这是通过将适应度值设置为最大适应度 - 适应度来完成的。具有最佳适应度的个体现在具有最高的适应度值。

    转换后的适应度值现在输入到正常轮盘赌选择器中,该选择器选择适应度最高的个体。但本质上你是在做一个最小化。

    Java GA Jenetics 正在以这种方式进行最小化。

    【讨论】:

    • max fitness - fitness 比 1/fitness 更好吗?
    • 如果你做 1/fitness,你会改变适应度比例,这对适应度 proportional 选择器不利。如果您正在进行 rank 选择,它将提供相同的结果。
    猜你喜欢
    • 2018-04-23
    • 2018-07-04
    • 2021-06-02
    • 1970-01-01
    • 2012-02-04
    • 2014-05-25
    • 1970-01-01
    • 1970-01-01
    • 2010-09-15
    相关资源
    最近更新 更多