最初に
進化計算をするためのPythonライブラリdeapについて、色々ドキュメントを探して見たものの、よくわからなかったので公式のドキュメントを自分的に訳していきたいと思います。
あくまで、自分のメモ用なので、暖かい目で見てください。
参考にした元のサイトはこちら。その中のまずはOverviewから。
Overview
Types
最初にすることは、問題に対して適した型を考えることです。使用可能な型を探す代わりに、自分で作ることもできます。作るにはcreatorというモジュールを使用します。適切な型を作るのは難しいと感じられるかもしれませんが、creatorを使用すると非常に簡単になります。何と一行でできるのです。下の例を見ていきましょう。FitnessMinというクラスを最小化問題のために作成し、IndividualクラスはList型から作られる、計算された適応度をセットするためのものです。
from deap import base, creator
creator.create("FitnessMin", base.Fitness, weights=(-1.0,))
creator.create("Individual", list, fitness=creator.FitnessMin)
これで終わり。さらに詳しいことはCreating Typesチュートリアルを見るべし。
Initialization
型が作れたら作ったものを、ランダムな値だったり推測した値で埋めたい時があります。DEAPはそれらを簡単に行うことができるメカニズムを持っています。toolboxはそれらに必要な初期化子を含む、全ての種類のツールコンテナです。次の例の最後の行ではランダムなFloat型の値を持つ個体と、その個体を含む集団の初期化を行なっています。
import random
from deap import tools
IND_SIZE = 10
toolbox = base.Toolbox()
toolbox.register("attribute", random.random)
toolbox.register("individual", tools.initRepeat, creator.Individual,
toolbox.attribute, n=IND_SIZE)
toolbox.register("population", tools.initRepeat, list, toolbox.individual)
これは、ランダムなFloat型で初期化された個体から集団を初期化する関数を作成します。関数はデフォルトの引数と与えられた名前でツールボックスに登録されます。例えば*toolbox.population()*を呼べば集団を作成することができます。さらに詳しいことはCreating Typesのチュートリアルだったりいろんな例を見るべし。
Operator
Operaterはtoolsモジュールで既に実装されているものを除いてinitializerに似ています。
一度Perfectなものを選んだら、toolboxに登録するだけです。また、評価関数を作成する必要があります。これがDEAPの主な流れです。
def evaluate(individual):
return sum(individual),
toolbox.register("mate", tools.cxTwoPoint)
toolbox.register("mutate", tools.mutGaussian, mu=0, sigma=1, indpb=0.1)
toolbox.register("select", tools.selTournament, tournsize=3)
toolbox.register("evaluate", evaluate)
登録した関数はtoolboxにて名前が付け直されoperaterの名前に依存しない一般的なアルゴリズムになります。また、適応度はiterableでないといけません。これが関数evaluateでタプルを返している理由です。詳しいことはOperators and Algorithmsのチュートリアルとかいろんな例を見るべし。
Algorithms
全ての準備が整いました。それでは、自分たちのアルゴリズムを試してみましょう。普通はメイン関数の中で行います。完全性のために、完全な世代アルゴリズムを開発してみましょう。
def main():
pop = toolbox.population(n=50)
CXPB, MUTPB, NGEN = 0.5, 0.2, 40
# 集合を評価している
fitnesses = map(toolbox.evaluate, pop)
for ind, fit in zip(pop, fitnesses):
ind.fitness.values = fit
for g in range(NGEN):
# 次の世代を選択する
offspring = toolbox.select(pop, len(pop))
# 選んだ個体のクローンを作る
offspring = map(toolbox.clone, 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
# 無効な適応度をもつ個体を評価する
invalid_ind = [ind for ind in offspring if not ind.fitness.valid]
fitnesses = map(toolbox.evaluate, invalid_ind)
for ind, fit in zip(invalid_ind, fitnesses):
ind.fitness.values = fit
# 母集団は全て子集団に置き換わる
pop[:] = offspring
return pop
algorithmsモジュールのなかの4つのアルゴリズムを使用することも可能です。また、このモジュール中のvariationsと呼ばれる、いくつかのbuilding blocksから作られるものも使用可能です。
最後に
一応、Overviewの内容でした。一部、よくわからなかったところは直訳で失礼しています。特に最後の方は自分でもよくわかっていません。完全性のために、完全な世代アルゴリズムを~とは一体どうゆう意味なのか..
正直、大まかな流れはわかったものの、詳しい使い方は自分もよくわからなかったので、それぞれの詳しいチュートリアルを見ていきたいと思っています。
進化的計算フレームワークDEAP (2) Creating Types
進化的計算フレームワークDEAP (3) Operators and Algorithms
進化的計算フレームワークDEAP (4) One Max Problem