私は遺伝的アルゴリズムについて、より良い任意の外部モジュール(単に標準ライブラリとnumpyのを少し)を使用せずに私のpythonを使用して最初から遺伝的アルゴリズムを構築しようとした概念を理解するために学んでいます
目標は、私はそれを文字列のハローを与え、スペース+ 26個の文字を定義している場合は、ターゲット文字列を見つけることで、巨大である26 ^ 5の可能性があります。このprobemを解決するためGAを使用することが必要。
私は、次の機能を定義しました。
人口の生成:我々は大きさ一定の集団を生成し、nおよび我々が発生し、ターゲットのn文字列が持つlen(target)
ランダムな文字で、我々はSTRのリストとして人口を返します
適合スコアを計算:位置の文字があればi
位置にある文字に等しくなり、我々はスコアをインクリメントし、ターゲットのI、ここでのコードは次のとおりです。
def fitness(indiv,target):
score = 0
#print(indiv," vs ",target)
for idx,char in enumerate(list(target)):
if char == indiv[idx]:
score += 1
else:
score = 0
return score
セレクト両親、保護者の間で交差し、子どもたちの新しい集団を生成します
ここではその責任の機能は以下のとおりです。
from numpy.random import choice
def crossover(p1,p2):
# we define a crossover between p1 and p2 (single point cross over)
point = random.choice([i for i in range (len(target))])
#print("Parents:",p1,p2)
# C1 and C2 are the new children, before the cross over point they are equalt to their prantes, after that we swap
c = [p1[i] for i in range(point)]
#print("Crossover point: ",point)
for i in range(point,len(p1)):
c.append(p2[i])
#print("Offsprings:", c1," and ", c2)
c = "".join(c)
# we mutate c too
c = mutate(c)
return c
def mutate(ind):
point = random.choice([i for i in range (len(target))])
new_ind = list(ind)
new_ind[point] = random.choice(letters)
return "".join(new_ind)
def select_parent(new_pop,fit_scores):
totale = sum(fit_scores)
probs = [score/totale for score in fit_scores]
parent = choice(new_pop,1,p=probs)[0]
return parent
私が使用して、その後、各個人(個別スコア/人口の合計スコア)の確率を計算することによって親を選択しています重み付けランダム選択(これはnumpyの機能である)親を選択する機能を。
クロスオーバーのために、私は子供の生成だc
とランダム分割ポイントを、このランダムポイントの前のすべての文字は、最初の親文字であり、分岐点以降のすべての文字は、親からの文字です。
それ以外にも、私たちは、人口(最高適合スコア)のうち最高の個人を取得し、目標、およびprint_bestを発見したかどうかをチェックshould_stopという関数を定義しました。
それから私は、上で定義されたすべての機能を使用して検索機能を作成しました:
def find(size,target,pop):
scores = [fitness(ind,target) for ind in pop]
#print("len of scores is ", len(scores))
#good_indiv = select_individuals(pop,scores)
#print("Length of good indivs is", len(good_indiv))
new_pop = []
# corssover good individuals
for ind in pop:
pa = select_parent(pop,scores)
pb = select_parent(pop,scores)
#print(pa,pb)
child = crossover(pa,pb)
#print(type(child))
new_pop.append(child)
best = print_best(new_pop,scores)
print("********** The best individual is: ", best, " ********")
return (new_pop,best)
n = 200
target = "hello"
popu = generate_pop(n,target)
#find(n,target,popu)
for i in range(1000):
print(len(popu))
data = find(n,target,popu)
popu = data[0]
print("iteration number is ", i)
if data[1] == target:
break
問題は、問題は、この例では、それはほんの数回の反復をとりながら、それは、それはハロー生成することshoudよりも、あまりにも多くの反復(200回の以上の反復時間のほとんどを)取っているということです。https://jbezerra.github.io/ -シェイクスピア・アンド・モンキー・問題/ index.htmlを
確かに問題は同じ方法でコード化されていない、私はPythonと、コードの物事への手続きの方法を使用しますが、ロジックは同じです。だから私は間違って何をやっていますか?
あなたは、時間の100%を変異させます。あなたは、フィット感の子孫を生成する可能性がある "、適切な両親を選択したが、その後、あなたは「それを捨てる」に可能性が高いではない以上だ突然変異を適用します。例えば、リンクはご提供振る舞うあなたは100%に変異率を上げる場合と同じ方法。
突然変異の目的は、あなたはすべての時間は、進化的アルゴリズムからずっと近いランダム探索に何かにこれをオンにそれを適用し、局所最適で立ち往生しているように見える場合は、別の方向に検索を「微調整」にあります。