私は最近Redditを閲覧していて、「JavaScript遺伝的アルゴリズム」の例へのリンクを投稿しました。私は遺伝的アルゴリズムとプログラミングの概念に本当に魅了されてきましたが、いくつかのグーグルを使った後でも、少し混乱したままです。どのように機能しますか?
ボキャブラリーの用語は他の何よりも私を混乱させていると思います。簡単な例と説明をいただければ幸いです。遺伝的プログラミングの概念と、それを自分のプロジェクトにどのように実装できるか、そしてその理由は?
私は最近Redditを閲覧していて、「JavaScript遺伝的アルゴリズム」の例へのリンクを投稿しました。私は遺伝的アルゴリズムとプログラミングの概念に本当に魅了されてきましたが、いくつかのグーグルを使った後でも、少し混乱したままです。どのように機能しますか?
ボキャブラリーの用語は他の何よりも私を混乱させていると思います。簡単な例と説明をいただければ幸いです。遺伝的プログラミングの概念と、それを自分のプロジェクトにどのように実装できるか、そしてその理由は?
回答:
遺伝的プログラミングよりも遺伝的アルゴリズムについて話しているように聞こえますが、ここでの理解への私の貢献です。
GAを構成する部分の観点からGAを考えると便利です。
だから、何らかの問題があるとしましょう。最初に必要なのは、ソリューションがどのように見えるかを表現する方法です。都市A、B、C、D、Eで巡回セールスマンの問題が発生した場合、都市の名前の配列[B、C、A、D、E]がどのように見えるかを既に知っています。
これが遺伝子です。
それ以外の場合、問題の潜在的な解決策として知られています。スティーブンA.ロウが言及したように、ビット文字列は遺伝子をエンコードする一般的な方法ですが、それは必要ではありません。特定のことが簡単になるだけです。重要な部分は、この配列のような方法でソリューションを表す方法があることです。
今。解決策が適切であるかどうかをどのように知っていますか?教えてくれる機能と、ソリューションを評価する機能が必要です。したがって、TSPでは、パス[B、C、A、D、E]を使用して移動距離を測定する機能があります。割り当てる「グレード」は単に移動距離である場合がありますが、より複雑な問題では、移動のコストなどを含めることができます。
これがフィットネス機能です。
だから今、あなたは潜在的なソリューションを取り、それが良いかどうかを調べることができます。次は何ですか?
次に、第一世代を開始する必要があります。したがって、ランダムソリューションの束を生成します。それらが良いかどうかは関係ありません。これが最初の、つまりシードの母集団です。これを遺伝子プールと呼ぶことができます。
したがって、最初の遺伝子プールを取得し、フィットネス関数をそれらすべてに適用して、すべてにグレードを付けます。今、あなたはそれらのうちの2つを取り、それらから新しい人口を作る必要があります-次世代のために。誰を選択しますか?さて、あなたは必ずしもフィットの最も適するものだけを選択したくはありません。それはいくつかの問題につながる可能性があります。代わりに、選択機能が必要です。
視覚化が容易な選択方法の1つは、一種のホイールを使用することです。各遺伝子はホイール上のスライスであり、フィットネススコアはスライスの大きさを示します(フィットネスが良いほど、スライスは大きくなります)。ホイールを指すピンを置き、スピンを与えます(つまり、乱数を生成します)。ピンは最初の親を指します。2番目の親に対して再度実行します。
次に、新しい子を作成する必要があります。親を組み合わせて、新しい母集団を作成します。これを行うにはさまざまな方法がありますが、それらはすべてクロスオーバー関数と呼ばれます。それらを半分に分割し、親の間で半分を交換するか、何らかのインターリーブを行うことができます。これは、新しい子供を産む哺乳類の親に非常に似ています->彼らは両方とも新しい子供に彼らの遺伝子を提供します。
この新世代ができたら、ランダムでありながらまれな突然変異を各子に投げ込みます。私はしばしば突然変異率が1%未満で発生するのを見てきました。突然変異の機能は、ランダムにあなたのコードされた遺伝子で何かを変更します。遺伝子がビット文字列の場合、ビットを入れ替えることができます。都市の配列の場合、リスト内の2つの都市を入れ替えることができます。重要な部分は、それが比較的まれな発生であり、物事を混乱させることです。
希望する世代数になるまで、またはフィットネス機能が一貫して高いフィットネススコアを持つ親を生成し、(うまくいけば、すべてを正しければ)最適なソリューションになるまで、このプロセスを繰り返します。
それは少し冗長だったので、比phorで要約しましょう:
お役に立てれば。
問題の解決策をビット列としてエンコードする
エンコードされたソリューションにビット文字列がどれだけ「良い」かを評価する関数(「フィットネス」関数と呼ばれる)を記述します-結果は通常0から1の間の数値です
これらのビット列の束をランダムに生成し、それらの適合性を評価します
いくつかの束(通常はより適切なもの)を選択し、それらを半分に切り、半分を交換していくつかの新しいビット文字列を作成します(クロスオーバー)
その後、時々、新しいビット文字列のいくつかのビットをランダムに反転します(突然変異)
良い解決策が発展するまで繰り返す
なぜこれを行うか:いくつかの問題には非常に大きな解空間があり、すべての可能性を評価するのは現実的ではありません(巡回セールスマン問題を参照)
本「検索、最適化、機械学習における遺伝的アルゴリズム」を強くお勧めします
遺伝的プログラミングは、コンピューターにプログラムを作成させる方法です!
MS Wordのような「プログラム」を考えないで、「プログラム」を次のように考えてください。
function(x){ return x*2; }
この関数(またはプログラム)自体には、存在する理由はありません。問題の解決策を探しています。2つの数値の合計を見つける必要がある場合は、電卓を開いて計算を行うだけです。誰かがあなたに、次の表を与えたとの間の関係を把握するためにあなたを尋ねた場合result
とx
とy
:
x y result
99 1 (3.02)
79 88 2.01
21 62 5.01
84 52 (6.58)
12 70 5.54
67 18 0.73
このデータは「トレーニング」データです。コンピューターはこのデータを使用していくつかの仮説を生成し、実際のデータに対してテストします。
統計情報がわからないとし、この問題を自分で判断するのは難しすぎると判断した場合、コンピューターにそれを判断させることができます。
コンピューターに100万の回答を生成させ、それらのいずれかが固執するかどうかを確認します(推測... 100万回!)。次に、いくつかの推測の例を示します。
function(x,y){ return x+y; } // wrong
function(x,y){ return x/1*1*1*1*1*1+y; } //wrong, silly
これを知っているかもしれないし、知らないかもしれませんが、関数またはプログラムはツリーとして表すこともできます。たとえば、2番目の関数は次のようになります。
(+ (/ x (* 1 (* 1 (* 1 (* 1 (* 1 1)))) y)
このようにインデントすることで、ツリーのように見せることができます(ただし、逆ポーランド記法とlisp構文を調べてください...しかし、このようなプログラムをすぐに表す理由は理解できます)。
(+
(/ x
(* 1
(* 1
(* 1
(* 1
(* 1 1))))
y)
(+
との2つの「葉」を持つ最上部にあり/
、y
。/
自体には複数の子があります。)
これが、遺伝的プログラミングの「木」について多くを読む理由です。いずれにせよ、我々はの値に差し込むx
とy
、この関数に、それは私たちに間違った答えを与えます。ただし、これをランダムに生成したため、驚くことではありません。
次に、このようなソリューションを100万個生成することにしました。それらはすべて間違っています。ただし、いくつかの答えは他の答えよりも正しい答えに近いことがわかります。つまり、一部のソリューションは他のソリューションよりも「適合」しています。コンピュータは「正しい」と「間違っている」ことを知らないので、独自の「フィットネス機能」を提供する必要があることに注意してください。この関数は、潜在的なソリューションであるトレーニングデータを渡され、このソリューションがどの程度「適合」しているかをGPシステムに伝える役割を果たします。ご想像のとおり、この関数は何百万回も実行されます。
遺伝的プログラミングが野生の推測と異なる理由は次のとおりです。さらに100万回の推測を行うことにしました。ただし、もう少し賢くします。推測の上位10%(実際の値に近いもの)を取得し、それらを第2世代の一部にします。また、これらのソリューションの多くを使用し(おそらく同じ10%...覚えていない)、「それらを混在させる」ことを決定します。
2つのソリューションをランダムに選択し、サブツリーをランダムに選択して、スワップを開始します。そのため、ソリューションAの一部はソリューションBに、その逆も同様です-あなたはそれらを「クロス」しました。また、いくつかの解決策を取り、それらを単純に「変更」します...いくつかのサブツリーを取得し、少し「それを台無しにします」
これを考える良い方法は次のとおりです。あなたのお母さんとお父さんは、髪の色、身長、病気の可能性など、特定の属性を持っています。あなたの両親がオリンピック選手だったら、あなたもスーパーアスリートになりますよね?さて、生物学者、社会学者、そして歴史家でさえ、この考えに問題を抱えているかもしれませんが、コンピューター科学者はここで優生学の道徳に関心がありません。彼らはソリューションを提供する「システム」が非常に良い仕事をしているのを見たので、ソフトウェアでモデル化することにしました。
それが実際に生物学と一致しないが、それでも良い答えを提供する場合...多くのコンピューター科学者が集合的に「おい、用語に感謝します」と言います。また、すべてのあなたの兄弟姉妹は、まったく同じではないことに注意してください...彼らが同じ親を持っているとしても。各人は、何らかの理由で突然変異する遺伝子を持っています(生物学者にこれを見せないでください、用語は多くの用語の背後にある動機を理解することです)。
だから今、私たちはコンピューターに何百万ものプログラムを生成させ、そのフィットネスを測定しています。最良の解決策は、次世代にも存続します。また、「突然変異」し、「集団」をクロスオーバーします(遺伝学と生物学の言語がどのように使用されているかに注意してください)。第2世代が作成されると、フィットネスが再び測定されます。この世代には前世代の最高のソリューションがあり、最高のソリューションを(普通の人口とともに-多様性を維持するために)交差させて変異させたため、この世代は前世代よりも少なくとも少し優れているはずです。
これを非常に多くの世代にわたって続けています。正しい答えが得られるまで、各世代は(できれば)より良いソリューションを提供します。例えば:
(+ (- 2.2 (/ x 11) (* 7 (cos y))))
これをよく見てください、これは正しいです!
(これをhttp://en.wikipedia.org/wiki/Genetic_programmingからコピーしました。これにはこのツリーのグラフィック表現もあります)
+, -, *, /, cos, sin, tan
GPシステムで使用可能な「端末」()をどのように決定するか、フィットネス関数をどのように記述するか、(1 + cos)
または(2 / "hello")
(他の多くの)のような無意味なプログラムをシステムがどのように処理するかなど、いくつかの重要な問題があります。
方程式を発展させるのはかなり退屈です。端末セットが次のようになっている場合(火、敵の検知、移動など)にさらに興味をそそられ、フィットネス機能はあなたの健康と武道モンスターの死体の数を測定します。
私はこれのほとんどをメモリから書きましたが、これは基本的な考え方です。私は大学時代にいくつかのGPを行いました。あなたは間違いなくそれをいじる必要があります。すべての用語を理解することを心配せずに、無料のGPシステムをダウンロードし、いくつかの例を実行して感じて、あなた自身の興味深い例を作成してください(異なるデータセット間の関係を見つけ、ゲームに接続してみてください) APIなど)
Fittestのサバイバル:Windowsフォームでの自然選択は、私が遺伝的プログラミングをどのように紹介したかを示しています。コードはダウンロードして簡単に読むことができます。欠点は、GPが実行時に作成されたコードを実行する手段を必要とすることであり、記事が作成された時点では、C#はこのタスクにはあまり適していませんでした。そのため、この例ではCodeDOMを使用して実行時にコードを生成、コンパイル、実行します。これにより、さらに複雑なレイヤーが追加されます。
それ以来、物事は変化しました。今では.NETが独自のExpressionTree APIを持っているので、おそらく記事で説明されているものよりもC#でよりエレガントなGP実装が可能になります。しかし、GPがどのように機能するかを理解するには十分です。
ここでは、GPで無料の電子ブックをダウンロードできます。これには、非常に短いJavaコードの例も含まれています。