LoginSignup
0
1

More than 3 years have passed since last update.

遺伝的アルゴリズムで関数の最適値を求める(その2)

Last updated at Posted at 2020-08-14

前回

前回作成したコード
https://qiita.com/nmat0031785/items/ceea6f78ab71e9956fce

最適化結果の記録

前回使用したalgorithms.eaSimpleは各世代の統計量しか残せない。
全個体の設計変数と適応度が残せるように改良する。

初期個体群の生成、評価

まずは初期個体のみ適応度を計算する。
その後、設計変数と適応度、世代(初期世代なので0)、個体番号をpd.DataFrameに保存する。

sample_GA.py
# 初期個体群を生成
pop = toolbox.population_guess()

# 初期個体の適応度の評価
fitnesses = toolbox.map(toolbox.evaluate, pop)
for ind, fit in zip(pop, fitnesses):
    ind.fitness.values = fit
fits = [ind.fitness.values[0] for ind in pop]

# 初期個体をlogbookに格納
logbook = pd.DataFrame([])
t1 = pd.DataFrame(pop)
t1.columns = ["x1", "x2"]
t1 = t1.assign(fits=fits, generation=0, ids=range(len(pop)))
logbook = logbook.append(t1)

進化ループ

進化ループに入る。offspring = toolbox.select(pop, POP_SIZE)で、POP_SIZE分の個体を初期個体群popから改めて選択し直している。これにより初期個体群と進化ループの個体群の数を変更する事が可能。
for分で各世代の個体に乱数を与え、CX_PBMUT_PBに引っかかった個体を交叉、変異の対象としている。その後、新しい個体について適応度を再評価し、pd.DataFrameに追記していく。

sample_GA.py
# パラメータ
N_GEN = 20       # 繰り返し世代数
POP_SIZE = 100   # 集団内の個体数
CX_PB = 0.8      # 交叉確率
MUT_PB = 0.05    # 変異確率

# 進化ループ開始
g = 0
while g < N_GEN:
    g = g + 1

    # 次世代個体の選択・複製
    offspring = toolbox.select(pop, POP_SIZE)
    offspring = list(map(toolbox.clone, offspring))

    # 交叉
    for child1, child2 in zip(offspring[::2], offspring[1::2]):
        # 交叉させる個体を選択
        if random.random() < CX_PB:
            toolbox.mate(child1, child2)
            # 交叉させた個体は適応度を削除する
            del child1.fitness.values
            del child2.fitness.values

    # 変異
    for mutant in offspring:
        # 変異させる個体を選択
        if random.random() < MUT_PB:
            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

    # 新世代の全個体の適応度の抽出
    fits = [ind.fitness.values[0] for ind in pop]

    # logbookに格納
    t1 = pd.DataFrame(pop)
    t1.columns = ["x1", "x2"]
    t1 = t1.assign(fits=fits, generation=g, ids=range(POP_SIZE))
    logbook = logbook.append(t1)

    # デバッグ
    print(t1)
terminal
・
・
・
-- Generation 20 --
          x1        x2        fits  generation  ids
0  -1.582142 -3.130247 -106.764537          20    0
1  -1.582142 -3.130247 -106.764537          20    1
2  -1.582142 -3.130247 -106.764537          20    2
3  -1.582142 -3.130247 -106.764537          20    3
4  -1.582142 -3.130247 -106.764537          20    4
..       ...       ...         ...         ...  ...
95 -1.582142 -3.130247 -106.764537          20   95
96 -1.582142 -3.130247 -106.764537          20   96
97 -1.582142 -3.130247 -106.764537          20   97
98 -1.582142 -3.130247 -106.764537          20   98
99 -1.582142 -3.130247 -106.764537          20   99

[100 rows x 5 columns]

保存

結果をCSVで保存する。

sample_GA.py
logbook.to_csv("result.csv", sep=",", index=None, header=None)

まとめ

各個体の設計変数、適応度の出力。
次回は結果の可視化まで。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1