avatarThe Pragmatic Programmers

Free AI web copilot to create summaries, insights and extended knowledge, download it at here

2351

Abstract

ir programs.</p><p id="8c6c">After you add opts to the signatures of run, you need to edit all of your functions to accept opts. Change the function signatures of all of the functions in genetic.ex to accept an optional opts parameter, like this:</p><div id="6dc8"><pre>​ ​<span class="hljs-function"><span class="hljs-keyword">def</span><span class="hljs-title">initialize</span></span>(genotype, opts \ []) ​<span class="hljs-keyword">do</span>​ ​ ​<span class="hljs-comment"># ...omitted...​</span> ​ ​<span class="hljs-keyword">end</span>​ ​ ​ ​<span class="hljs-function"><span class="hljs-keyword">def</span><span class="hljs-title">evaluate</span></span>(population, fitness_function, opts \ []) ​<span class="hljs-keyword">do</span>​ ​ ​<span class="hljs-comment"># ...omitted...​</span> ​ ​<span class="hljs-keyword">end</span>​ ​ ​ ​<span class="hljs-function"><span class="hljs-keyword">def</span><span class="hljs-title">select</span></span>(population, opts \ []) ​<span class="hljs-keyword">do</span>​ ​ ​<span class="hljs-comment"># ...omitted...​</span> ​ ​<span class="hljs-keyword">end</span>​ ​ ​ ​<span class="hljs-function"><span class="hljs-keyword">def</span><span class="hljs-title">crossover</span></span>(population, opts \ []) ​<span class="hljs-keyword">do</span>​ ​ ​<span class="hljs-comment"># ...omitted...​</span> ​ ​<span class="hljs-keyword">end</span>​ ​ ​ ​<span class="hljs-function"><span class="hljs-keyword">def</span><span class="hljs-title">mutation</span></span>(population, opts \ []) ​<span class="hljs-keyword">do</span>​ ​ ​<span class="hljs-comment"># ...omitted...​</span> ​ ​<span class="hljs-keyword">end</span></pre></div><p id="6802">Finally, pass opts to every function in run and evolve:</p><div id="211b"><pre>​ ​def​ run(genotype, fitness_function, max_fitness, opts \ []) ​<span class="hljs-built_in">do</span>​ ​ population = initialize(genotype) ​ population ​ |<span class="hljs-type">> evolve</span>(fitness_function, max_fitness, opts) ​ ​<span class="hljs-keyword">end</span>​ ​ ​def​ evolve(population, fitness_function, max_fitness, opts \ []) ​<span class="hljs-built_in">do</span>​ ​ population = evaluate(population, fitness_function, opts) ​ best = hd(population) ​ IO.write(​<span class="hljs-string">"​​\rCurrent Best: ​​#{​fitness

Options

_function.(best)​}​​"</span>​) ​ ​<span class="hljs-keyword">if</span>​ fitness_function.(best) == max_fitness ​<span class="hljs-built_in">do</span>​ ​ best ​ ​<span class="hljs-keyword">else</span>​ ​ population ​ |<span class="hljs-type">> select</span>(opts) ​ |<span class="hljs-type">> crossover</span>(opts) ​ |<span class="hljs-type">> mutation</span>(opts) ​ |<span class="hljs-type">> evolve</span>(fitness_function, max_fitness, opts) ​ ​<span class="hljs-keyword">end</span>​ ​ ​<span class="hljs-keyword">end</span></pre></div><p id="2d6e">For now, the only hyperparameter you’ll account for is population size. To do this, edit initialize/2 to look like this:</p><div id="d874"><pre>​ ​def​ initialize(geno<span class="hljs-keyword">type</span>, opts \ []) ​do​ ​ population_size = <span class="hljs-type">Keyword</span>.get(opts, ​:population_size​, <span class="hljs-number">100</span>) ​ for _ <- <span class="hljs-number">1.</span>.population_size, ​do​: geno<span class="hljs-keyword">type</span>.() ​ ​end​</pre></div><p id="65dc">Keyword.get/3 accepts a Keyword, a key, and a default value if there’s no value for the given key. Here you set the default population size to 100, which is sufficient for most genetic algorithms.</p><p id="1976">In later chapters, you’ll be introduced to more hyperparameters and learn to account for them so your algorithms are easily configurable.</p><p id="294c"><i>👈 <a href="https://readmedium.com/building-a-framework-for-genetic-algorithms-f876cfee3749">Building a Framework for Genetic Algorithms</a> | <a href="https://readmedium.com/table-of-contents-879fc8614df">TOC</a> | <a href="https://readmedium.com/solving-the-one-max-problem-again-2cf822b3be40">Solving the One-Max Problem Again</a> 👉</i></p><p id="3e19"><i>Genetic Algorithms in Elixir by Sean Moriarity can be purchased in other book formats <a href="https://pragprog.com/titles/smgaelixir">directly from the Pragmatic Programmers</a>. If you notice a code error or formatting mistake, please let us know <a href="https://readmedium.com/how-to-report-errata-4e164674347a">here</a> so that we can fix it.</i></p><figure id="0b58"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*U2E2a23SuM4520w9CUXSWw.jpeg"><figcaption></figcaption></figure></article></body>

Understanding Hyperparameters

Genetic Algorithms in Elixir — by Sean Moriarity (24 / 101)

👈 Building a Framework for Genetic Algorithms | TOC | Solving the One-Max Problem Again 👉

In machine learning, hyperparameters refer to the parts of the algorithm you set before the algorithm starts training. Internally, the algorithm learns parameters that help it perform a task. Externally, the programmer controls parameters that dictate how the algorithm trains.

In the context of genetic algorithms, hyperparameters refer to things like population size, mutation rate, and so on, that you choose before running the algorithm.

Because your hyperparameters can have a huge impact on the outcome of your algorithms, it’s important that you’re able to rapidly change them. To ensure you can change hyperparameters without too much of a headache, you need to implement a simple configuration mechanism into your framework that separates the hyperparameters from the overall structure of the algorithm.

To start, change the signature of both run/3 and evolve/4 to accept an additional parameter:

​ ​defrun(genotype, fitness_function, max_fitness, opts \\ []) ​do​
​ ​# ...omitted...​
​ ​end​
​ ​defevolve(population, fitness_function, max_fitness, opts \\ []) ​do​
​ ​# ...omitted...​
​ ​end

opts \\ [] indicates an optional parameter that will default to an empty list if you pass nothing in its place. You can use opts to pass hyperparameters in a Keyword list. Using a parameter like opts is a common paradigm for Elixir programs.

After you add opts to the signatures of run, you need to edit all of your functions to accept opts. Change the function signatures of all of the functions in genetic.ex to accept an optional opts parameter, like this:

​ ​definitialize(genotype, opts \\ []) ​do​
​   ​# ...omitted...​
​ ​end​
​ 
​ ​defevaluate(population, fitness_function, opts \\ []) ​do​
​   ​# ...omitted...​
​ ​end​
​ 
​ ​defselect(population, opts \\ []) ​do​
​   ​# ...omitted...​
​ ​end​
​ 
​ ​defcrossover(population, opts \\ []) ​do​
​   ​# ...omitted...​
​ ​end​
​ 
​ ​defmutation(population, opts \\ []) ​do​
​   ​# ...omitted...​
​ ​end

Finally, pass opts to every function in run and evolve:

​ ​def​ run(genotype, fitness_function, max_fitness, opts \\ []) ​do​
​   population = initialize(genotype)
​   population
​   |> evolve(fitness_function, max_fitness, opts)
​ ​end​
​ ​def​ evolve(population, fitness_function, max_fitness, opts \\ []) ​do​
​   population = evaluate(population, fitness_function, opts)
​   best = hd(population)
​   IO.write(​"​​\rCurrent Best: ​​#{​fitness_function.(best)​}​​"​)
​   ​if​ fitness_function.(best) == max_fitness ​do​
​     best
​   ​else​
​     population
​     |> select(opts)
​     |> crossover(opts)
​     |> mutation(opts)
​     |> evolve(fitness_function, max_fitness, opts)
​   ​end​
​ ​end

For now, the only hyperparameter you’ll account for is population size. To do this, edit initialize/2 to look like this:

​ ​def​ initialize(genotype, opts \\ []) ​do​
​   population_size = Keyword.get(opts, ​:population_size​, 100)
​   for _ <- 1..population_size, ​do​: genotype.()
​ ​end​

Keyword.get/3 accepts a Keyword, a key, and a default value if there’s no value for the given key. Here you set the default population size to 100, which is sufficient for most genetic algorithms.

In later chapters, you’ll be introduced to more hyperparameters and learn to account for them so your algorithms are easily configurable.

👈 Building a Framework for Genetic Algorithms | TOC | Solving the One-Max Problem Again 👉

Genetic Algorithms in Elixir by Sean Moriarity can be purchased in other book formats directly from the Pragmatic Programmers. If you notice a code error or formatting mistake, please let us know here so that we can fix it.

Smgaelixir
Recommended from ReadMedium