Pythonで実数値遺伝的アルゴリズムの性能を評価してみる ~その２~

#はじめに
前回の投稿[Pythonで実数値遺伝的アルゴリズムの性能を評価してみる](https://qiita.com/SwitchBlade/items/8f07b78f3922607a7ca3)の投稿の課題の一つであったBLX-α以外の交叉法としてUNDXの実装を行いました。

#UNDXとは
実数値GAの交叉に親を3つ用いる(BLX-αは2つ)ようにした手法で、変数間の依存関係に強い手法とされています。
なお、世代交代時に子との入れ替えの対象となる親は2つだけです。

詳細は以下の論文を参照してください。

[実数値GAのフロンティア](https://www.jstage.jst.go.jp/article/tjsai/24/1/24_1_147/_pdf)
[単峰性正規分布交叉を用いた実数値遺伝的アルゴリズムによる光学系の最適化](https://annex.jsap.or.jp/photonics/kogaku/public/28-12-kaisetsu1.pdf)

#実装
githubに置いています。
https://github.com/SwitchBladeJW/RCGA

#評価方法
前回と同様のベンチマーク関数を用いて、BLX-αとUNDXの性能を評価しました。

世代交代モデルはMGGを用いています。 致死個体に対する対応は前回から変更しています。

- 世代交代数：2個体(エリート選択：1個体、ルーレット選択：1個体)
- 致死個体(任意のパラメータが探索範囲を超えた個体) への対応：評価対象から外す

交叉のパラメータは以下の通りです。

- BLX-α(α=0.5)
- UNDX(α=0.5、β=0.35)

##Rastrigin関数
- 多峰性関数
- 探索範囲：-5.12～5.12
- 大域的最適解 ： = 0 , (x[i] = 0)
- 2次元のグラフ

![Rastrigin.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438288/e7a74826-0852-e24f-0d1f-34266255416e.png)

###2次元
- 最大世代数：100世代
- 集団数：30個体
- 生成子個体数: 60個体/世代
- 初期集団の分布：-5.12～-2.0(次元数が少ないので、最適解を外して分布させています)

個体の分布表示です。青が集団、赤が最良個体です。加えて、親の選択と子の生成も表示するようにしています。
プロットの凡例です。
![プロット凡例.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438288/dcb4a0e7-fd8a-210a-7120-1a193f6984cf.jpeg)

| 交叉法   | プロット              | 
|:-----------------:|:------------------:|
| BLX-α | ![Rastrigin_p2_g100_BLX_20190706_1104.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438288/f451064b-ee6c-ff3c-93bd-fcc9331ba046.gif) |
|UNDX|![Rastrigin_p2_g100_UNDX_20190706_1103.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438288/ef46f8cb-6908-2e44-09d7-24636c3d3aea.gif)| 

特徴としては、BLX-αは選択された親に対して、X軸・Y軸方向に長方形で子が分布します。
親1と2をつなぐ直線の周辺に楕円形に子が分布します。


##RosenBrock関数
- 単峰性関数
- 探索範囲：-2.048～2.048
- 大域的最適解 ： =0 、(x[i] = 1)
- 2次元のグラフ

![Rosenbrock.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438288/a7c2c9b7-c7f3-7ee8-4009-c30b49728c23.png)

###20次元
- 最大世代数：100000世代
- 集団数：50個体
- 生成子個体数: 200個体/世代

![RosenBrock_p20_g100000.csv.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438288/e6cf6ff6-f4f6-2a74-ded2-88dc5605573d.png)
UNDXでは30000世代で最適解を求めることができていますが、BLX-αでは100000世代でも最適解を求めることができていません。RosenBrock関数は変数間の依存関係がある関数なので、UNDXが有効に働いていると思われます。


##Schwefel関数
- 多峰性関数
- 探索範囲：-512～512
- 大域的最適解 ： ≒0 、(x[i] = 420.9687)
- 2次元のグラフ

![Schwefel.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438288/d22f90b9-e908-e34d-7a46-8f8414a88756.png)


###10次元
- 最大世代数：30000世代
- 集団数：300個体
- 生成子個体数: 200個体/世代

![Schwefel_p10_g30000.csv.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438288/4f525f69-9a16-afc8-3f5a-4c5bfa31acab.png)
前回、致死個体の対処方法を「探索範囲を超えたパラメータを限界値に設定する」にしていて、BLX-αで局所解にはまっていましたが、致死個体の対処方法を変更することで改善されました。

BLX-αとUNDXとも最適解を求めることができていますが、BLX-αの方が早く収束しています。すべてに万能な手法はないってことですね。


#学習時間に関して
ColaboratoryでRosenBrock関数20次元100000世代の学習時間の計測を行いました。
()内は致死固体を除いた評価回数(評価関数を使った回数)です。致死個体がなければ、1世代につき202回です。

| 環境                  | BLX-α |   UNDX|
|:---------------------|------:|-------:|
| Colaboratory(CPU)    |  40分(20186185回) | 37分(20193164回)  | 
| Colaboratory(GPU)    |  40分(20186482回) | 35分(20193868回) | 
※2019.07.06時点での時間です。

- 一般的にはUNDXの方が計算コストが大きいのですが、UNDXの方が処理が早く終わっていました。UNDXの方はforループを完全に排除して作ることができたので、その辺りが聞いてるのかなと思います。pythonでforループは鬼門ですね。
- CPUとGPUの処理速度がほとんど変わりませんでした。GPUに適したコーディングにしないとあまり恩恵はないかもしれません。