異なる形の遺伝的アルゴリズム

私は、最大化するための単純な遺伝的アルゴリズムを実装するコードを書いた:

f(x) = 15x - x^2

この関数の最大値は7.5です。したがって、コード出力は、母集団が整数であるため、7または8でなければなりません。私がコードを10回実行すると、10回のうち3回前後で7または8が得られます。交配確率は0.7、突然変異確率は0.001を選択しました。アルゴリズムをさらに改善するためにどのような変更を行う必要がありますか。また、異なる種類の遺伝的アルゴリズムは何ですか?

ここにコードです:

from random import *
import numpy as np

#fitness function
def fit(x):
    return 15*x -x**2
#covert binary list to decimal number
def to_dec(x):
    return int("".join(str(e) for e in x), 2)

#picks pairs from the original population
def gen_pairs(populationl, prob):
    pairsl = []
    test = [0, 1, 2, 3, 4, 5]
    for i in range(3):
        pair = []
        for j in range(2):
            temp = np.random.choice(test, p=prob)
            pair.append(populationl[temp].copy())
        pairsl.append(pair)

    return pairsl

#mating function
def cross_over(prs, mp):
    new = []
    for pr in prs:
        if mp[prs.index(pr)] == 1:
            index = np.random.choice([1,2,3], p=[1/3, 1/3, 1/3])
            pr[0][:index], pr[1][:index] = pr[1][:index], pr[0][:index]

    for pr in prs:
        new.append(pr[0])
        new.append(pr[1])

    return new

#mutation
def mutation(x):
    for chromosome in x:
        for gene in chromosome:
            mutation_prob = np.random.choice([0, 1], p=[0.999, .001])
            if mutation_prob == 1:
                #m_index = np.random.choice([0,1,2,3])
                if gene == 0:
                    gene = 1
                else:
                    gene = 0
    #generate initial population
    randlist = lambda n:[randint(0,1) for b in range(1, n+1)]
for j in range(10):
    population = [randlist(4) for i in range(6)]
    for _ in range(20):
        fittness = [fit(to_dec(y)) for y in population]

        s = sum(fittness)
        prob = [e/s for e in fittness]
        pairsg = gen_pairs(population.copy(), prob)

        mating_prob = []
        for i in pairsg:
            mating_prob.append(np.random.choice([0,1], p=[0.4,0.6]))

        new_population = cross_over(pairsg, mating_prob)
        mutated = mutation(new_population)
        decimal_p = [to_dec(i)for i in population]
        decimal_new = [to_dec(i)for i in new_population]
        # print(decimal_p)
        # print(decimal_new)
        population = new_population
    print(decimal_new)
ベストアンサー

あなたのコードに多くの注意を払うことなく、あなたのクロスオーバー率は低いかもしれません。あなたの突然変異率はあまりにも低く、あなたの人口は小さく、あなたは20代しか走っていません。あなたは何かを探すのに十分な検索をしていないだけです。あなたの最初の人口が6人か7人だったら、それを見つけることができます。そうでなければ、あなたは幸運になることを望むために一握りのクロスオーバーを得て、それで終わります。

あなたは4ビット* 6人= 1世代あたり24ビット* 20世代あります。
最高で、ここには480ビットの情報があり、突然変異演算子は1000ビットごとに1つのフリップを期待しています。

あなたはまた、選択圧迫で非常に深刻な問題を抱え、そのような小さな人口でさらに悪化した適性比例選択を使用して両親を選択します。このように見て、最初の人口(6、0、15、13、11、2)に対して次の6人を生成するとします。
f(6)は他のどの選択肢よりもかなり優れています。選択確率はおおよそ(0.36,0,0,0.17,0.29,0.17)です。だから、あなたは親プールが(6、13、6、11、11、2)のように見えると思うでしょう。明らかに正確な選択はランダムですが、それは分布に適合します。ここで6を6と11を11とペアにすると、同じ親のクロスオーバは全く反転できないため、別のコピーを作成することが保証されます。そして、あなたはまったく突然変異を持っていません(実質的に言えば)。だからあなたの人口は、最初のランダムな人口で見つけた最良のものにすばやく収束します。

クロスオーバはより良い個人を生み出すチャンスを持っています。なぜなら、最初の人口のサンプリングだけで期待していた〜10%の代わりに最適な30%の時間を見ているからです。しかし、それはそれについてです。あなたは信頼性の高い何かをするために十分な検索が行われていません。

再び、バグがあるかもしれません – 私は注意深く見ませんでした。

返信を残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です