前回の続き
前回投稿した パラメーターフリー遺伝的アルゴリズムでディープラーニングのハイパーパラメータを解く で説明できていなかったことを少し補足するのと、一部機能追加したので触れておきます。
GAAP
PfGA(パラメーターフリー遺伝的アルゴリズム)が比較的小家族で世代交代していく方法であることに対して、GAAPというPfGAの進化版も発表されています。これは優秀な両親はたくさんの子供を作ることができる、というルールが追加されたものです。よって、母集団はPfGAよりも増えていきますが、通常のGAではこちらの方が優秀な結果がでることが多いようです。
今回はディープラーニングが適合度評価の対象になるため、前回の記事で記載したように母集団はできるだけ少ない方が時間的問題から良いことから、GAAPは採用しませんでした。
エリート保存の法則
GAでは母集団が毎回入れ替わりますが、場合によっては最も優秀なゲノムも入れ替わってしまうことがあります。その結果、次世代以降の適合度評価が下がるケースが発生してました。
エリート保存の法則はこれを避けるルールで、当世代の母集団で最優秀ゲノムは無条件に次世代に残る権利を得られるというものです。PfGAやGAAPでは、結果的にこのルールが適用されています。
移住型GA
このエリートを活用した移住型GAとう手法も発表されています。これは、複数の母集団を作り、それぞれで世代交代しながら進化させていく並列GAのようなものですが、それぞれの母集団でレコード更新した優秀なゲノムは他の母集団に一定確率で移住(というかコピー)する権利を得るというのが特徴です。
このルールによって、複数の母集団が切磋琢磨(?)しながら進化していくことになり、通常のGAではこれが最も良い結果を出します。今回は母集団が増えること自体が時間的にNGなため見送りました。
初期母集団へのエリートゲノム投入
実は今回、ある事件が起きまして・・・(学習中のPCがWindowsUpdateの自動更新で再起動されたw)せっかく良い感じに成長していたゲノムが消えてしまいました。初歩的なミスですねw
幸い、下記のようなログを出していたので、最優秀ゲノムの遺伝子の値は残ってたため、これを再度学習開始する際に、初期ゲノムとして注入しようと思い、機能追加しました。
gen:1 best-value:0.6301846504211426 best-gene:[0.0001, 5, 0.5, 0.5, 0.7, 0.7, 2, 1.0, <class 'chainer.optimizers.ada_delta.AdaDelta'>]
gen:2 best-value:0.6301846504211426 best-gene:[0.0001, 5, 0.5, 0.5, 0.7, 0.7, 2, 1.0, <class 'chainer.optimizers.ada_delta.AdaDelta'>]
まず、下記のようにPFGAクラスの初期化の際に、エリートゲノムが指定されていたら、それを初期母集団とするコードを追加しました。
class PFGA():
def __init__(self, gene_len, evaluate_func=None, better_high=True, mutate_rate=0.05, elite=None):
self.family = []
self.gene_len = gene_len
self.evaluate_func = evaluate_func
self.better_high = better_high
self.mutate_rate = mutate_rate
self.generation_num = 0
if elite is not None:
for e in elite:
self.add_elite_population(e)
def add_elite_population(self, elite_gene):
new_gene = []
new_gene.append(elite_gene)
new_gene.append(None)
self.family.append(new_gene)
次に、ディープラーニング側の評価用クラスでエリートゲノムの遺伝子値を0~1のFloat値に変換するコードを準備します。
class Evaluate_cnn():
def add_elite(self, gene):
elite_gene = []
for i in range(len(gene)):
x = self.gene_list[i].index(gene[i])
elite_gene.append((x / len(self.gene_list[i]) + (0.5 / len(self.gene_list[i]))))
return elite_gene
最後にディープラーニング側の初期化時点で、ゲノムの遺伝子値を複数(下記例では1固体)指定するだけで、いきなり優秀な母集団で学習開始することができます。
elite_genom = []
elite_genom.append(ev.add_elite([0.0001, 5, 0.5, 0.5, 0.7, 0.7, 2, 1.0, optimizers.AdaDelta]))
ga = PFGA(9, evaluate_func=ev.evaluate, better_high=True, mutate_rate=0.25, elite=elite_genom)
とりあえずはこれだけです。