健身比例选择(轮盘赌选择)在Python(Fitness proportionate selecti

2019-06-23 23:56发布

我有具有属性健身对象(染色体)(chromosome.fitness是0和1之间)的列表

鉴于这种对象的列表,我怎么能实现它返回它的机会被选中的正比于它的健身一条染色体的功能? 也就是说,健身0.8染色体是两倍,可能被选择为一个有健身0.4。

我已经发现了一些Python和伪代码实现,但它们对于这个要求太复杂:该功能只需要一个染色体的列表。 染色体存储他们自己的健康,内部变量。

我已经写的实施是在我决定让染色体来存储自己的健身,所以是一个复杂得多,涉及荏苒列表和东西。

- - - - - - - - - - - - - - 编辑 - - - - - - - - - - - -------

谢谢Lattyware。 下面的函数似乎工作。

def selectOne(self, population):
        max     = sum([c.fitness for c in population])
        pick    = random.uniform(0, max)
        current = 0
        for chromosome in population:
            current += chromosome.fitness
            if current > pick:
                return chromosome

Answer 1:

有一个很简单的方法来选择字典的加权随机选择:

def weighted_random_choice(choices):
    max = sum(choices.values())
    pick = random.uniform(0, max)
    current = 0
    for key, value in choices.items():
        current += value
        if current > pick:
            return key

如果手边有一本字典,你不这样做,你可以对此进行修改你的类(因为你没有给它的更多详细信息,或生成词典:

choices = {chromosome: chromosome.fitness for chromosome in chromosomes}

假定该健身是一个属性。

下面是修改,以染色体的一个可迭代,再次,使得相同的推定功能的一个例子。

def weighted_random_choice(chromosomes):
    max = sum(chromosome.fitness for chromosome in chromosomes)
    pick = random.uniform(0, max)
    current = 0
    for chromosome in chromosomes:
        current += chromosome.fitness
        if current > pick:
            return chromosome


Answer 2:

使用numpy.random.choice。

import numpy.random as npr
def selectOne(self, population):
    max = sum([c.fitness for c in population])
    selection_probs = [c.fitness/max for c in population]
    return population[npr.choice(len(population), p=selection_probs)]


Answer 3:

from __future__ import division
import numpy as np
import random,pdb
import operator

def roulette_selection(weights):
        '''performs weighted selection or roulette wheel selection on a list
        and returns the index selected from the list'''

        # sort the weights in ascending order
        sorted_indexed_weights = sorted(enumerate(weights), key=operator.itemgetter(1));
        indices, sorted_weights = zip(*sorted_indexed_weights);
        # calculate the cumulative probability
        tot_sum=sum(sorted_weights)
        prob = [x/tot_sum for x in sorted_weights]
        cum_prob=np.cumsum(prob)
        # select a random a number in the range [0,1]
        random_num=random.random()

        for index_value, cum_prob_value in zip(indices,cum_prob):
            if random_num < cum_prob_value:
                return index_value


if __name__ == "__main__":
    weights=[1,2,6,4,3,7,20]
    print (roulette_selection(weights))
    weights=[1,2,2,2,2,2,2]
    print (roulette_selection(weights))


Answer 4:

我宁愿少行:

import itertools

def choose(population):
    bounds = list(itertools.accumulate(chromosome.fitness for chromosome in population))
    pick = random.random() * bounds[-1]
    return next(chromosome for chromosome, bound in zip(population, bounds) if pick < bound)


Answer 5:

import random

def weighted_choice(items):
    total_weight = sum(item.weight for item in items)
    weight_to_target = random.uniform(0, total_weight)
    for item in items:
        weight_to_target -= item.weight
        if weight_to_target <= 0:
            return item


文章来源: Fitness proportionate selection (roulette wheel selection) in Python