19

属性フィットネスを持つオブジェクト (染色体) のリストがあります (chromosome.fitness は 0 と 1 の間です)

そのようなオブジェクトのリストが与えられた場合、選択される可能性がその適合度に比例する単一の染色体を返す関数をどのように実装できますか? つまり、適応度 0.8 の染色体は、適応度 0.4 の染色体の 2 倍の確率で選択されます。

Python と疑似コードの実装をいくつか見つけましたが、この要件には複雑すぎます。関数には染色体のリストしか必要ありません。染色体は、自身の適応度を内部変数として保存します。

私がすでに書いた実装は、染色体がそれ自身の適応度を保存できるようにする前のものでした。そのため、はるかに複雑で、zip リストなどを含むものでした。

- - - - - - - - - - - - - - 編集 - - - - - - - - - - - -------

ありがとうラティウェア。次の関数が動作するようです。

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
4

6 に答える 6

17

辞書から加重ランダム選択を選択する非常に簡単な方法があります。

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
于 2012-04-25T21:29:11.910 に答える
1
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))
于 2016-06-26T06:43:49.500 に答える
-1
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
于 2012-04-25T21:29:37.613 に答える