最初に
前回はOverviewを見ていったので、さらに詳しいチュートリアルについて見ていきたいと思います。元のドキュメントはこちら。
Creating Types
このチュートリアルではcreatorを使用した型の作り方、toolboxを使用した初期化の仕方について見ていきます。
Fitness
Fitnessというクラスは機能する為にweightsという属性を必要とする抽象クラスです。適応度を最小化する際は負の重みを、最大化する際には正の重みをつけていきます。下の例では、一つの目的関数において、FitnessMinと名付けられた適応度を最小化していくようにしています。
creator.create("FitnessMin", base.Fitness, weights=(-1.0,))
関数create()は少なくとも2つの引数を必要とします。新しく作成するクラスの名前とその基となるクラスです。後続の引数は、そのクラスの引数になります。Fitnessのドキュメントで述べられているように、単一目的も多目的の物も同じように扱えるようにweightsはタプルでないといけません。FitnessMultiも同じように作れます。
creator.create("FitnessMulti", base.Fitness, weights=(-1.0, 1.0))
このコードは一つ目の目的関数の値を最小化する事を、二つ目の目的関数は最大化していく事を表しています。また、それぞれの目的関数自体の重みを変えることにも使用できます。これは、weightsは数字はどのような実数でもよく、符号が最大化か最小化を判断するものだということを表しています。weightsが役に立つ例としてはNSGA-IIのcrowding distanceソートなどがあります。
Individual
進化的アルゴリズム(GA、GP、ES、PSO、DE、...)の異なるフレーバーを考えるだけで、極めて多種多様な個体が可能であり、全ての型を開発者が利用できるようにすることはできません。ここではcreatorを使用して個体を作成し、Toolboxで初期化していく方法について見ていきます。
注意!!
もし、numpy.ndarrayを継承したい場合は、必ずInheriting from NumpyのチュートリアルとOne Max Problem: Using Numpyの例を見るべき。
List of Floats
最初に作られた個体はシンプルなFloatのリストになります。このような個体を生み出す為に、creatorを使用して、fitness属性を持ちList型を継承したIndividualクラスを作成する必要があります。
import random
from deap import base
from deap import creator
from deap import tools
creator.create("FitnessMax", base.Fitness, weights=(1.0,))
creator.create("Individual", list, fitness=creator.FitnessMax)
IND_SIZE=10
toolbox = base.Toolbox()
toolbox.register("attr_float", random.random)
toolbox.register("individual", tools.initRepeat, creator.Individual,
toolbox.attr_float, n=IND_SIZE)
新しく紹介するregister()メソッドには少なくとも2つの引数、具体的にエイリアスとこのエイリアスに割り当てられる関数が必要です。この2つに続く引数はその関数が呼ばれた時に引き渡されるものになります(functools.partial()みたいな感じ)。したがって、上記のコードはtoolboxにattr_floatとindividualの二つのエイリアスを作成しています。最初のものはrandom.random()にリダイレクトされます。二つ目のものはinitRepeat()へのショートカットになります。つまり、container引数にcreator.Individualクラス、そのfuncとしてtoolbox.attr_float()、さらにその繰り返しの回数としてIND_SIZEをそれぞれ固定しています。
今、toolbox.individual()を呼ぶと、固定された引数と共にinitRepeat()が呼ばれ、IND_SIZEの単一目的のfitness属性を最大化するFloatの値で構成される完全なcreator.Individualを返します。
下の例のようにarray.arrayやnumpy.ndarrayを継承することも可能です。
creator.create("Individual", array.array, typecode="d", fitness=creator.FitnessMax)
creator.create("Individual", numpy.ndarray, fitness=creator.FitnessMax)
arraysを継承する場合は初期化にあたって、元のクラスのようにtypecodeを指定してあげる必要があります。
Permutation
Permutation表現の個体は、一般的なリスト個体とほぼ同じです。事実、どちらともList型を継承しています。唯一の違いはリストを連続したFloatで埋める代わりに、ランダムな順序を生成し、それを個体にしてあげる必要があります。
import random
from deap import base
from deap import creator
from deap import tools
creator.create("FitnessMin", base.Fitness, weights=(-1.0,))
creator.create("Individual", list, fitness=creator.FitnessMin)
IND_SIZE=10
toolbox = base.Toolbox()
toolbox.register("indices", random.sample, range(IND_SIZE), IND_SIZE)
toolbox.register("individual", tools.initIterate, creator.Individual,
toolbox.indices)
最初に登録した関数indicesはrandom.sample()を与えられた範囲から抽出されたIND_SIZEの数で固定された引数とともにリダイレクトされます。二つ目に登録されたindividualは引数containerにcreator.Individualクラスが、generatorにtoolbox.indices()へのエイリアスがセットされたinitIterate()へのリダイレクトが登録されます。
toolbox.individual()を呼び出すとinitIterate()が固定された引数と共に呼び出され、単一目的のfitness属性が最小化されるような順列で構成された完全なcreator.Individualが返されます。
最後に
元のドキュメントではまだ続いているのですが、今の所絶対必要ではないかなという気がしたので、このチュートリアルはここまでにして、とりあえず次のチュートリアルを見ていきたいと思います。必要そうだったら足していきます。
それにしても、まだきちんと全ての日本語の用語を把握している訳ではないのでもっと勉強しないとなぁ、なんて思いました。直訳ごめんなさい。
進化的計算フレームワークDEAP (1) Overview
進化的計算フレームワークDEAP (3) Operators and Algorithms
進化的計算フレームワークDEAP (4) One Max Problem