Pythonの進化計算のライブラリとしてDEAPが有名です。
遺伝的アルゴリズムのサンプルコードを実装していたところ、説明変数が変化していないのに目的関数が繰り返し評価されている現象に遭遇しました。
原因としてはDEAPのdocumentのサンプルコードに従った記述で関数の重複評価を許してしまう部分がありました。
その部分は下記の通りです。
# Apply crossover and mutation on the offspring
for child1, child2 in zip(offspring[::2], offspring[1::2]):
if random.random() < CXPB:
toolbox.mate(child1, child2)
del child1.fitness.values
del child2.fitness.values
for mutant in offspring:
if random.random() < MUTPB:
toolbox.mutate(mutant)
del mutant.fitness.values
このサンプルコードは解の交叉および変異を行っている部分です。
toolbox.mate(child1, child2)
やtoolbox.mutate(mutant)
において実際の交叉や変異が行われているのですが、同じ親を元にした交叉や解の次元が低い場合の変異では少ない回数で重複した説明変数が出てきます。
del ~~
の部分で説明変数が更新されているはずだから、適応度の計算をやり直すように値を消しておくのですが、上記のような例では重複した説明変数が出てくる可能性があります。
したがって、以下のように本当に説明変数が更新されたのかを判定することで目的関数の評価を重複した説明変数で行われることを避けられると考えられます。
import copy
# 交叉
for child1, child2 in zip(offspring[::2], offspring[1::2]):
if random.random() < CXPB:
before_child1 = copy.deepcopy(child1)
before_child2 = copy.deepcopy(child2)
toolbox.mate(child1, child2)
if before_child1 != child1:
del child1.fitness.values
if before_child2 != child2:
del child2.fitness.values
# 突然変異
for mutant in offspring:
if random.random() < MUTPB:
before_mutant = copy.deepcopy(mutant)
toolbox.mutate(mutant)
if before_mutant != mutant:
del mutant.fitness.values