私はこの1か月間この問題を研究し、いくつかの興味深い発見をしました。
- 不透明なポリゴンを使用すると、レンダリングのパフォーマンス(さらには適応度関数のパフォーマンス)が1桁向上します。
- すべての点で、大幅な大きな変更よりも多くの小さな変更を優先します...
- 新しいポリゴンを追加するときは、ランダムな座標で頂点を割り当てるのではなく、1ピクセルのサイズを指定します。これにより、生存の可能性が高まります。
- 新しい頂点を追加するときは、ランダムな位置にドロップするのではなく、ポリゴン内の既存の頂点と同じ位置を指定します。ポリゴンを目立った方法で変更することはありませんが、「頂点の移動」ミューテーションが以前よりも多くの頂点を移動するための扉を開きます。
- 頂点を移動するときは、キャンバス全体にまたがるのではなく、多くの小さな移動(一度に3〜10ピクセル)を優先します。
- 時間の経過とともに突然変異を減衰させる場合は、変化の確率ではなく、変化の量を減衰させます。
- ダンピングの影響は最小限です。上記の手順(小さな変更を優先)を実行した場合、実際に湿らせる必要はないはずです。
- クロスオーバーミューテーションは使用しないでください。それは高い突然変異率を導入しますが、これは早い段階で素晴らしいですが、ほとんど収束している画像は小さな突然変異を除いてすべてを拒否するため、非常に迅速に高い突然変異が問題になります。
- フィットネス評価機能で画像を拡大縮小しないでください。これは私が理解するのに少し時間がかかりました。入力画像が200x200であるが、フィットネス評価者がフィットネススコアを生成する前に画像を100x100に縮小すると、フィットネス関数には表示されないがエンドユーザーには明らかに間違っているステーキ/エラーラインを含む候補ソリューションが生成されます。適応度関数は、画像全体を処理するか、まったく処理しない必要があります。より良い解決策は、適応度関数がピクセルの100%を処理するように、ターゲット画像を全面的にスケーリングすることです。100x100が小さすぎて画面に表示できない場合は、画像を拡大するだけです。これで、ユーザーは画像をはっきりと見ることができ、フィットネス機能には何も欠けていません。
- 自己交差するポリゴンの作成を防ぎます。それらは決して良い結果をもたらさないので、突然変異がそれらを作成するのを防ぐことによってアルゴリズムを大幅にスピードアップすることができます。自己交差するポリゴンのチェックを実装することは、お尻の痛みでしたが、最終的には問題を起こす価値がありました。
フィットネススコアを変更して、非表示のポリゴンを削除しました(純粋にパフォーマンス上の理由から):
fitness += candidate.size();
これは、フィットネススコアがゼロになることは決してないことを意味します。
ポリゴンの最大数を50から65535に増やしました。
私が最初にWatchmakerのMonaLisaの例を実行しようとしたとき、それは何日も実行され、ターゲット画像に近いものは何も見えませんでした。Rogerのアルゴリズムは優れていましたが、1時間後も停滞していました。新しいアルゴリズムを使用して、15分以内にターゲットイメージを再作成することができました。フィットネススコアは150,000ですが、肉眼では候補者は元の候補とほぼ同じに見えます。
私は、人口全体が時間とともに進化していることを示す診断ディスプレイをまとめました。また、特定の時点で母集団内でアクティブな一意の候補の数もわかります。数値が小さい場合は、差異がないことを示します。人口圧力が高すぎるか、突然変異率が低すぎます。私の経験では、まともな人口には少なくとも50%のユニークな候補者が含まれています。
この診断ディスプレイを使用して、アルゴリズムを調整しました。ユニークな候補の数が少なすぎるときはいつでも、私は突然変異率を上げます。アルゴリズムが急速に停滞しているときはいつでも、私は母集団で何が起こっているのかを調べました。突然変異の量が多すぎることに気付くことがよくあります(色や頂点の動きが速すぎます)。
私はこの問題を研究するために先月過ごして良かったです。GAの性質について多くのことを教えてくれました。これは、コードの最適化よりも設計と関係があります。また、最も適切な候補者だけを研究するのではなく、人口全体がリアルタイムで進化するのを監視することが非常に重要であることも発見しました。これにより、どの突然変異が効果的であるか、突然変異率が低すぎるか高すぎるかをかなり迅速に発見できます。
フィットネス評価者にユーザーに表示されるのとまったく同じ画像を提供することが非常に重要である理由について、さらに別の重要な教訓を学びました。
私が報告した元の問題を思い出すと、評価前に候補画像が縮小されていたため、多くのピクセルが検出/修正を回避できるようになりました。昨日、ユーザーに表示される画像のアンチエイリアシングを有効にしました。評価者が100%のピクセルを表示している(スケーリングが行われていない)限り、安全であると考えましたが、これでは不十分であることがわかりました。
次の画像を見てください。
アンチエイリアシングが有効:

アンチエイリアシングが無効になっています:

それらは、アンチエイリアシングが有効または無効になっているまったく同じ候補を示しています。アンチエイリアスバージョンには、候補がスケーリングされているときに見た問題と同様に、顔全体にエラーの「ストリーク」があることに注意してください。候補には、「ストリーク」(サブピクセル精度でレンダリングされたポリゴン)の形で画像にエラーを導入するポリゴンが含まれている場合があります。興味深いのは、エイリアシングによってこれらのエラーが抑制されるため、エバリュエーター関数がエラーを認識しないことです。その結果、ユーザーには、適応度関数が修正することのない大量のエラーが表示されます。おなじみですか?
結論として、ユーザーに表示するのとまったく同じ画像を常に(常に!)適応度関数に渡す必要があります。転ばぬ先の杖 :)
遺伝的アルゴリズムはとても楽しいです。自分で遊んでみることをお勧めします。