โœจ 2 - Genetic Algorithm Flow ์œ ์ „์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ ํ๋ฆ„

The modern understanding of evolution is based on the Darwin theory and genetics.
ํ˜„๋Œ€์˜ ์ง„ํ™”์— ๋Œ€ํ•œ ์ดํ•ด๋Š” ๋‹ค์œˆ ์ด๋ก ๊ณผ ์œ ์ „ํ•™์— ๊ธฐ๋ฐ˜ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

The mechanism of natural selection is known as the process of ensuring the stability and adaptation of species.
์ž์—ฐ ์„ ํƒ์˜ ๋ฉ”์ปค๋‹ˆ์ฆ˜์€ ์ข…์˜ ์•ˆ์ •์„ฑ๊ณผ ์ ์‘์„ ๋ณด์žฅํ•˜๋Š” ๊ณผ์ •์œผ๋กœ ์•Œ๋ ค์ ธ ์žˆ์Šต๋‹ˆ๋‹ค.

Strong and viable individuals survive, leaving offspring, to whom their characteristics are passed on.
๊ฐ•ํ•˜๊ณ  ์ƒ์กด ๊ฐ€๋Šฅํ•œ ๊ฐœ์ฒด๋Š” ์‚ด์•„๋‚จ์•„ ์ž์†์„ ๋‚จ๊ธฐ๋ฉฐ, ์ด๋“ค์—๊ฒŒ ์ž์‹ ์˜ ํŠน์„ฑ์ด ์ „๋‹ฌ๋ฉ๋‹ˆ๋‹ค.

๐Ÿ’ก whom : who๋Š” ์ฃผ์–ด ์—ญํ• ์„ ํ•  ๋•Œ ์‚ฌ์šฉํ•˜๊ณ  whom์€ ๋ชฉ์ ์–ด ์—ญํ• ์„ ํ•  ๋•Œ ์‚ฌ์šฉ
ใ…ค ์œ„ ๋ฌธ์žฅ์—์„œ๋Š” ๊ฐ•ํ•˜๊ณ  ์ƒ์กด ๊ฐ€๋Šฅํ•œ ๊ฐœ์ฒด์˜ ํŠน์„ฑ์„ ์ „๋‹ฌ๋ฐ›๋Š” โ€˜offspring(์ž์†)โ€˜์„ ๋ชฉ์ ์–ด๋กœ ์ง€์นญ

Weak individuals, on the contrary, perish without participating in reproduction.
๋ฐ˜๋ฉด์— ์•ฝํ•œ ๊ฐœ์ฒด๋Š” ๋ฒˆ์‹์— ์ฐธ์—ฌํ•˜์ง€ ๋ชปํ•˜๊ณ  ์†Œ๋ฉธ๋ฉ๋‹ˆ๋‹ค.

๐Ÿ’ก on the contrary : ๋ฐ˜๋Œ€๋กœ, ๋ฐ˜๋ฉด์—

A genetic algorithm is an approach that mimics the evolutionary search process.
์œ ์ „ ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ์ด๋Ÿฌํ•œ ์ง„ํ™”์  ํƒ์ƒ‰ ๊ณผ์ •์„ ๋ชจ๋ฐฉํ•œ ์ ‘๊ทผ ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค.

But what is evolution? What steps and stages does it consist of?
ํ•˜์ง€๋งŒ ์ง„ํ™”๋ž€ ๋ฌด์—‡์ผ๊นŒ์š”? ๊ทธ๊ฒƒ์€ ์–ด๋–ค ๋‹จ๊ณ„๋“ค๋กœ ์ด๋ฃจ์–ด์ ธ ์žˆ์„๊นŒ์š”?

In this chapter, we will look at the basic logical blocks of the genetic algorithm flow.
์ด๋ฒˆ ์žฅ์—์„œ๋Š” ์œ ์ „ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ํ๋ฆ„์˜ ๊ธฐ๋ณธ ๋…ผ๋ฆฌ ๋ธ”๋ก๋“ค์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.


๐Ÿ”ก ์ฃผ์š” ๋‹จ์–ด

์˜์–ด ๋‹จ์–ดํ•œ๊ธ€ ๋œป
modernํ˜„๋Œ€์˜
evolution์ง„ํ™”
Darwin theory๋‹ค์œˆ ์ด๋ก 
genetics์œ ์ „ํ•™
natural selection์ž์—ฐ ์„ ํƒ
stability์•ˆ์ •์„ฑ
adaptation์ ์‘
viable์ƒ์กด ๊ฐ€๋Šฅํ•œ
offspring์ž์†
characteristicํŠน์„ฑ
perish์†Œ๋ฉธํ•˜๋‹ค, ์ฃฝ๋‹ค
reproduction๋ฒˆ์‹
mimic๋ชจ๋ฐฉํ•˜๋‹ค
evolutionary์ง„ํ™”์˜
flowํ๋ฆ„
logical block๋…ผ๋ฆฌ ๋ธ”๋ก
genetic algorithm์œ ์ „ ์•Œ๊ณ ๋ฆฌ์ฆ˜
approach์ ‘๊ทผ ๋ฐฉ์‹
stage๋‹จ๊ณ„

โœจ 2 - Structure ๊ตฌ์กฐ

In this chapter, we will discuss the following topics:
์ด๋ฒˆ ์žฅ์—์„œ๋Š” ๋‹ค์Œ ์ฃผ์ œ๋“ค์— ๋Œ€ํ•ด ๋‹ค๋ฃฐ ๊ฒƒ์ž…๋‹ˆ๋‹ค:

  • Individual
    ๊ฐœ์ฒด

  • Fitness function
    ์ ํ•ฉ๋„ ํ•จ์ˆ˜

  • Population
    ๊ฐœ์ฒด๊ตฐ

  • Selection
    ์„ ํƒ

  • Crossover
    ๊ต์ฐจ

  • Mutation
    ๋Œ์—ฐ๋ณ€์ด

  • Genetic algorithm flow
    ์œ ์ „ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ํ๋ฆ„


โœจ 2.1 - Individual ๊ฐœ์ฒด

An individual is an object that represents a solution to a problem.
๊ฐœ์ฒด(individual)๋Š” ๋ฌธ์ œ์— ๋Œ€ํ•œ ํ•˜๋‚˜์˜ ํ•ด๊ฒฐ์ฑ…์„ ๋‚˜ํƒ€๋‚ด๋Š” ๊ฐ์ฒด์ž…๋‹ˆ๋‹ค.

The response parameters are determined by the genes that are contained in the individual.
๊ฐœ์ฒด์— ํฌํ•จ๋œ ์œ ์ „์ž์— ์˜ํ•ด ๋ฐ˜์‘ ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ ๊ฒฐ์ •๋ฉ๋‹ˆ๋‹ค.

๐Ÿ’ก be determined by ~: ~์— ์˜ํ•ด ๊ฒฐ์ •๋˜๋‹ค

Usually, there are two ways to create individuals:
๋ณดํ†ต ๊ฐœ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๋‘ ๊ฐ€์ง€๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค:

  • Random generation of an individual
    ๊ฐœ์ฒด๋ฅผ ๋ฌด์ž‘์œ„๋กœ ์ƒ์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•

  • Creating an individual with a specified set of genes
    ํŠน์ • ์œ ์ „์ž ์„ธํŠธ๋ฅผ ์‚ฌ์šฉํ•ด ๊ฐœ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•

In the case of our problem from Chapter 1, an individual is represented as follows:
CHAPTER 1์—์„œ์˜ ๋ฌธ์ œ์—์„œ๋Š” ๊ฐœ์ฒด๊ฐ€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ‘œํ˜„๋ฉ๋‹ˆ๋‹ค:


Import part

import random
from ch2.fitness import fitness
from ch2.settings import MIN_BORDER, MAX_BORDER

Individual class

class Individual:
    def __init__(self, gene_list, fitness_function) -> None:
        self.gene_list = gene_list
        self.fitness = fitness_function(self.gene_list[0])
 
    def __str__(self) -> str:
        return f"{self.gene_list[0]:.2f} -> {self.fitness:.2f}"
 
    def get_gene(self):
        return self.gene_list[0]

Individual creation

def create_random_individual():
    return Individual([random.uniform(MIN_BORDER, MAX_BORDER)], fitness)
 
def create_individual(gene):
    return Individual([gene], fitness)

ch2/settings.py

MIN_BORDER = -10
MAX_BORDER = 10

Here are some examples of typical problems and their solutions presented by individuals.
๋‹ค์Œ์€ ์ผ๋ฐ˜์ ์ธ ๋ฌธ์ œ๋“ค๊ณผ ๊ฐœ์ฒด๊ฐ€ ๊ฐ–๋Š”(ํ‘œํ˜„ํ•˜๋Š”) ํ•ด๊ฒฐ์ฑ…์˜ ์˜ˆ์‹œ์ž…๋‹ˆ๋‹ค.

๐Ÿ’ก presented by : ~์— ์˜ํ•ด ์ œ์‹œ๋œ, ๋ฐœํ‘œ๋œ, ์ œ๊ณต๋œ


Letโ€™s say we have a two-variables function, , as shown in the following figure.
๋‘ ๊ฐœ์˜ ๋ณ€์ˆ˜๋ฅผ ๊ฐ€์ง„ ํ•จ์ˆ˜ ๊ฐ€ ์•„๋ž˜ ๊ทธ๋ฆผ๊ณผ ๊ฐ™์ด ์ฃผ์–ด์กŒ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด๋ด…์‹œ๋‹ค.

image

If we are going to find the maxima of this function, then an individual will be represented as a pair
์ด ํ•จ์ˆ˜์˜ ์ตœ๋Œ“๊ฐ’์„ ์ฐพ์œผ๋ ค๋Š” ๊ฒฝ์šฐ, ๊ฐœ์ฒด๋Š” (x, y)๋กœ ์ด๋ฃจ์–ด์ง„ ์Œ์œผ๋กœ ํ‘œํ˜„๋ฉ๋‹ˆ๋‹ค.

๐Ÿ’ก maxima, minima : maximum, minimum์˜ ๋ณต์ˆ˜ํ˜•
ใ…ค ๋ผํ‹ด์–ด๋‚˜ ๊ทธ๋ฆฌ์Šค์–ด ๊ณ„์—ด ๋‹จ์–ด๋“ค์€ โ€˜์›๋ž˜ ๋ณต์ˆ˜ํ˜•โ€™๊ณผ ์˜์–ด์‹ โ€˜-(e)sโ€™ ๋ณต์ˆ˜ํ˜•์„ ๋ชจ๋‘ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
ใ…ค ์ผ๋ฐ˜์ ์œผ๋กœ ํ•™์ˆ ์ , ์ „๋ฌธ์ ์ธ ๋งฅ๋ฝ์—์„œ๋Š” โ€˜์›๋ž˜ ๋ณต์ˆ˜ํ˜•โ€™์„, ใ…ค ์ผ์ƒ์ ์ธ ๋งฅ๋ฝ์—์„œ๋Š” โ€˜-(e)sโ€™ ๋ณต์ˆ˜ํ˜•์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝํ–ฅ์ด ์žˆ์Šต๋‹ˆ๋‹ค.
ใ…ค โ€˜-umโ€™์œผ๋กœ ๋๋‚˜๋Š” ๋ผํ‹ด์–ด๋“ค์€ โ€™-umโ€™์„ โ€˜-aโ€™๋กœ ๋ฐ”๊พธ์–ด ๋ณต์ˆ˜ํ˜•์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค.


Traveling Salesman Problem - ์™ธํŒ์› ๋ฌธ์ œ

We have seven cities on the map, as shown in the following figure.
๋‹ค์Œ ๊ทธ๋ฆผ๊ณผ ๊ฐ™์ด ์ง€๋„ ์œ„์— 7๊ฐœ์˜ ๋„์‹œ๊ฐ€ ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด๋ด…์‹œ๋‹ค.

๐Ÿ’ก as shown in ~ : ~์— ๋‚˜ํƒ€๋‚œ ๋Œ€๋กœ, ~์—์„œ ๋ณด์—ฌ์ง€๋Š” ๊ฒƒ์ฒ˜๋Ÿผ

image

If we need to find the shortest way to visit all seven cities, then an individual will be represented as a sequence of numbers (1, 2, 3, 4, 5, 6, 7).
7๊ฐœ์˜ ๋„์‹œ๋ฅผ ๋ชจ๋‘ ๋ฐฉ๋ฌธํ•˜๋Š” ๊ฐ€์žฅ ์งง์€ ๊ฒฝ๋กœ๋ฅผ ์ฐพ์•„์•ผ ํ•œ๋‹ค๋ฉด, ๊ฐœ์ฒด๋Š” (1, 2, 3, 4, 5, 6, 7)๊ณผ ๊ฐ™์€ ์ˆซ์ž์˜ ์ˆœ์„œ๋กœ ํ‘œํ˜„๋ฉ๋‹ˆ๋‹ค.

๐Ÿ’ก be represented as ~ : ~๋กœ ํ‘œํ˜„๋˜๋‹ค, ~๋กœ ๋‚˜ํƒ€๋‚ด์–ด์ง€๋‹ค

For example, this individual (7, 2, 3, 6, 1, 4, 5) is describing this route, as shown in the following figure.
์˜ˆ๋ฅผ ๋“ค์–ด (7, 2, 3, 6, 1, 4, 5)๋ผ๋Š” ๊ฐœ์ฒด๋Š” ๋‹ค์Œ ๊ทธ๋ฆผ๊ณผ ๊ฐ™์€ ๊ฒฝ๋กœ๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

image

Each task requires the formation of its own individual.
๊ฐ ๋ฌธ์ œ๋Š” ๊ทธ์— ๋งž๋Š” ๊ฐœ์ฒด ๊ตฌ์กฐ๋ฅผ ํ•„์š”๋กœ ํ•ฉ๋‹ˆ๋‹ค.

Sometimes the structure of an individual can be quite complex.
๋•Œ๋กœ๋Š” ๊ฐœ์ฒด์˜ ๊ตฌ์กฐ๊ฐ€ ๊ฝค ๋ณต์žกํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


๐Ÿ”ก ์ฃผ์š” ๋‹จ์–ด

์˜์–ด ๋‹จ์–ดํ•œ๊ธ€ ๋œป
typical์ „ํ˜•์ ์ธ, ๋Œ€ํ‘œ์ ์ธ, ํ”ํ•œ
specified๋ช…์‹œ๋œ
representationํ‘œํ˜„
describing์„ค๋ช…ํ•˜๋Š”, ๋ฌ˜์‚ฌํ•˜๋Š”
creation์ƒ์„ฑ
uniform๊ท ์ผํ•œ, ๊ณ ๋ฅด๊ฒŒ ๋ถ„ํฌ๋œ
maximum (maxima)์ตœ๋Œ“๊ฐ’ (๋ณต์ˆ˜ํ˜•: maxima)
traveling salesman problem์™ธํŒ์› ๋ฌธ์ œ
sequence์ˆœ์„œ, ์‹œํ€€์Šค
complex๋ณต์žกํ•œ
quite๊ฝค, ์ƒ๋‹นํžˆ

โœจ 2.2 - Fitness Function ์ ํ•ฉ๋„ ํ•จ์ˆ˜

The fitness function is equivalent to the natural concept of the fitness of a living organism.
์ ํ•ฉ๋„ ํ•จ์ˆ˜๋Š” ์ƒ๋ฌผ ์œ ๊ธฐ์ฒด์˜ ์ž์—ฐ์ ์ธ ์ ํ•ฉ์„ฑ ๊ฐœ๋…์— ํ•ด๋‹นํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ’ก equivalent to ~ : ~์— ํ•ด๋‹นํ•˜๋Š”, ~์™€ ๋™๋“ฑํ•œ, ์ƒ์‘ํ•˜๋Š”

This function characterizes how well an individual is adapted to the environment.
์ด ํ•จ์ˆ˜๋Š” ๊ฐœ์ฒด๊ฐ€ ํ™˜๊ฒฝ์— ์–ผ๋งˆ๋‚˜ ์ž˜ ์ ์‘ํ–ˆ๋Š”์ง€๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

Depending on the problem to be solved, the best individual is considered to be the one whose objective function is maxima or minima.
ํ•ด๊ฒฐํ•˜๊ณ ์ž ํ•˜๋Š” ๋ฌธ์ œ์— ๋”ฐ๋ผ, ์ตœ์ ์˜ ๊ฐœ์ฒด๋Š” ๋ชฉ์  ํ•จ์ˆ˜๊ฐ€ ์ตœ๋Œ“๊ฐ’ ๋˜๋Š” ์ตœ์†Ÿ๊ฐ’์„ ๊ฐ€์ง€๋Š” ๊ฐœ์ฒด๋กœ ๊ฐ„์ฃผ๋ฉ๋‹ˆ๋‹ค.

๐Ÿ’ก Depending on ~ : ~์— ๋”ฐ๋ผ
๐Ÿ’ก is considered to be : ~๋ผ๊ณ  ๊ฐ„์ฃผ๋œ๋‹ค

For our problem of finding the maxima of sin(x) โˆ’ 0.5โ€ฏ|x|, the best individual will be the one with the maxima fitness function.
์šฐ๋ฆฌ๊ฐ€ ๋‹ค๋ฃจ๋Š” ์˜ ์ตœ๋Œ“๊ฐ’์„ ์ฐพ๋Š” ๋ฌธ์ œ์—์„œ๋Š”, ์ ํ•ฉ๋„ ํ•จ์ˆ˜์˜ ๊ฐ’์ด ๊ฐ€์žฅ ํฐ ๊ฐœ์ฒด๊ฐ€ ์ตœ์ ์˜ ๊ฐœ์ฒด๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.

Letโ€™s consider an example of calculating the fitness function
์ ํ•ฉ๋„ ํ•จ์ˆ˜๋ฅผ ๊ณ„์‚ฐํ•˜๋Š” ์˜ˆ์ œ๋ฅผ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.


Fitness function

def fitness(x):
    return np.sin(x) - .2 * abs(x)

Fitness of an individual

if __name__ == '__main__':
    from ch2.individual import Individual
    ind = Individual([1], fitness)
    print(f"Individual fitness: {ind.fitness}")

Result

0.6414709848078965

๐Ÿ”ก ์ฃผ์š” ๋‹จ์–ด

์˜์–ด ๋‹จ์–ดํ•œ๊ธ€ ๋œป
adapted์ ์‘๋œ, ์ ํ•ฉํ•œ
characterize~์˜ ํŠน์ง•์„ ๋‚˜ํƒ€๋‚ด๋‹ค

โœจ 2.3 - Population ๊ฐœ์ฒด๊ตฐ

A population is just a set of individuals.
๊ฐœ์ฒด๊ตฐ์€ ๋‹จ์ˆœํžˆ ๊ฐœ์ฒด๋“ค์˜ ์ง‘ํ•ฉ์ž…๋‹ˆ๋‹ค.

When we say that we are creating a random population, it means that we are simply creating a certain number of random individuals.
๋ฌด์ž‘์œ„ ๊ฐœ์ฒด๊ตฐ์„ ์ƒ์„ฑํ•œ๋‹ค๊ณ  ํ•  ๋•Œ, ์ด๋Š” ์ผ์ • ์ˆ˜์˜ ๋ฌด์ž‘์œ„ ๊ฐœ์ฒด๋“ค์„ ์ƒ์„ฑํ•œ๋‹ค๋Š” ์˜๋ฏธ์ž…๋‹ˆ๋‹ค.

๐Ÿ’ก a certain number of ~ : ์ผ์ •ํ•œ ์ˆ˜์˜ ~, ์–ด๋–ค ์ˆ˜์˜ ~

For each population, the following characteristics can be obtained:
๊ฐ ๊ฐœ์ฒด๊ตฐ์— ๋Œ€ํ•ด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํŠน์„ฑ๋“ค์„ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

  • Best individual: ๊ฐ€์žฅ ๋†’์€ ์ ํ•ฉ๋„ ๊ฐ’์„ ๊ฐ€์ง„ ๊ฐœ์ฒด
  • Best fitness: ๊ฐ€์žฅ ์šฐ์ˆ˜ํ•œ ๊ฐœ์ฒด์˜ ์ ํ•ฉ๋„ ๊ฐ’
  • Average fitness: ๊ฐœ์ฒด๊ตฐ ์ „์ฒด์˜ ํ‰๊ท  ์ ํ•ฉ๋„ ๊ฐ’

Letโ€™s build a population of 10 random individuals and evaluate its characteristics
๋ฌด์ž‘์œ„๋กœ 10๊ฐœ์˜ ๊ฐœ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ๊ฐœ์ฒด๊ตฐ์˜ ํŠน์„ฑ๋“ค์„ ํ‰๊ฐ€ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.


Import part

import random
import numpy as np
import matplotlib.pyplot as plt
 
from ch2.individual import create_random_individual
from ch2.fitness import fitness
from ch2.settings import MIN_BORDER, MAX_BORDER

Population methods

def get_best_individual(population):
    return max(population, key=lambda ind: ind.fitness)
 
def get_average_fitness(population):
    return sum([i.fitness for i in population]) / len(population)

Plotting the population on fitness curve

def plot_population(population):
    # best individual from the population
    best_ind = get_best_individual(population)
    # fitness of the best individual
    best_fitness = best_ind.fitness
    # average fitness of the population
    average_fitness = get_average_fitness(population)
 
    # plotting fitness curve
    x = np.linspace(MIN_BORDER, MAX_BORDER)
    plt.plot(x, fitness(x), '--', color='blue')
 
    # plotting whole population
    plt.plot(
        [ind.get_gene() for ind in population],
        [ind.fitness for ind in population],
        'o', color='orange'
    )
 
    # plotting best individual
    plt.plot(
        [best_ind.get_gene()], [best_ind.fitness],
        's', color='green'
    )
 
    # population average fitness
    plt.plot(
        [MIN_BORDER, MAX_BORDER],
        [average_fitness, average_fitness],
        color='grey'
    )
 
    plt.title(f"Best Individual: {best_ind}, Best Fitness: {best_fitness:.2f}\n"
              f"Average Population Fitness: {average_fitness:.2f}")
    plt.show()

Initialization of population

if __name__ == '__main__':
    # PARAMETER: the size of initial population
    POPULATION_SIZE = 10
    random.seed(22)
 
    # Generating random population
    population = [create_random_individual() for _ in range(POPULATION_SIZE)]
 
    # plotting the distribution of the population on fitness curve
    plot_population(population)

Letโ€™s take a look at the following figure to understand the visualization of random population: ๋ฌด์ž‘์œ„ ๊ฐœ์ฒด๊ตฐ์˜ ์‹œ๊ฐํ™”๋ฅผ ์ดํ•ดํ•˜๊ธฐ ์œ„ํ•ด ๋‹ค์Œ ๊ทธ๋ฆผ์„ ์‚ดํŽด๋ด…์‹œ๋‹ค.

image


๐Ÿ”ก ์ฃผ์š” ๋‹จ์–ด

์˜์–ด ๋‹จ์–ดํ•œ๊ธ€ ๋œป
population๊ฐœ์ฒด๊ตฐ, ๊ฐœ์ฒด ์ง‘ํ•ฉ
random๋ฌด์ž‘์œ„์˜
characteristicํŠน์„ฑ
best individual์ตœ์šฐ์ˆ˜ ๊ฐœ์ฒด
best fitness์ตœ๊ณ  ์ ํ•ฉ๋„
average fitnessํ‰๊ท  ์ ํ•ฉ๋„
evaluateํ‰๊ฐ€ํ•˜๋‹ค
distribution๋ถ„ํฌ
gene์œ ์ „์ž (๊ฐœ์ฒด๋ฅผ ํ‘œํ˜„ํ•˜๋Š” ๊ฐ’)
plot์‹œ๊ฐํ™”ํ•˜๋‹ค, ๊ทธ๋ž˜ํ”„๋ฅผ ๊ทธ๋ฆฌ๋‹ค
border๊ฒฝ๊ณ„, ๋ฒ”์œ„
initialization์ดˆ๊ธฐํ™”

โœจ 2.4 - Selection ์„ ํƒ

Selection is necessary to select more adapted individuals for crossing.
์„ ํƒ์€ ๊ต๋ฐฐ์— ์ฐธ์—ฌํ•  ๋” ์ ์‘๋ ฅ์ด ๋†’์€ ๊ฐœ์ฒด๋“ค์„ ๊ณ ๋ฅด๊ธฐ ์œ„ํ•ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

NOTE: Selection is the first genetic operation to be performed on a population.
์ฐธ๊ณ : ์„ ํƒ์€ ๊ฐœ์ฒด๊ตฐ์— ๋Œ€ํ•ด ์ˆ˜ํ–‰๋˜๋Š” ์ฒซ ๋ฒˆ์งธ ์œ ์ „ ์—ฐ์‚ฐ์ž…๋‹ˆ๋‹ค.

As a result of selection, the individuals that are selected will participate in the process of generating a new population.
์„ ํƒ ๊ฒฐ๊ณผ๋กœ, ์„ ํƒ๋œ ๊ฐœ์ฒด๋“ค์ด ์ƒˆ๋กœ์šด ๊ฐœ์ฒด๊ตฐ์„ ์ƒ์„ฑํ•˜๋Š” ๊ณผ์ •์— ์ฐธ์—ฌํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

Selection itself does not generate the new population; it is only responsible for selecting individuals that can leave the offspring.
์„ ํƒ ์ž์ฒด๋Š” ์ƒˆ๋กœ์šด ๊ฐœ์ฒด๊ตฐ์„ ์ƒ์„ฑํ•˜์ง€ ์•Š์œผ๋ฉฐ, ๋‹จ์ง€ ์ž์†์„ ๋‚จ๊ธธ ์ˆ˜ ์žˆ๋Š” ๊ฐœ์ฒด๋“ค์„ ์„ ํƒํ•˜๋Š” ์—ญํ• ๋งŒ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

As an example, consider tournament selection, where one must choose three different random individuals from the population, and from these three, they choose the best one.
์˜ˆ๋ฅผ ๋“ค์–ด ํ† ๋„ˆ๋จผํŠธ ์„ ํƒ ๋ฐฉ๋ฒ•์—์„œ๋Š” ๊ฐœ์ฒด๊ตฐ์—์„œ ์„ธ ๊ฐœ์˜ ๋ฌด์ž‘์œ„ ๊ฐœ์ฒด๋ฅผ ์„ ํƒํ•œ ๋’ค, ์ด๋“ค ์ค‘ ๊ฐ€์žฅ ์šฐ์ˆ˜ํ•œ ๊ฐœ์ฒด๋ฅผ ๊ณ ๋ฆ…๋‹ˆ๋‹ค.

Details of the selection mechanisms will be discussed in Chapter 3.
์„ ํƒ ๋ฉ”์ปค๋‹ˆ์ฆ˜์˜ ์„ธ๋ถ€ ์‚ฌํ•ญ์€ 3์žฅ์—์„œ ๋‹ค๋ฃฐ ์˜ˆ์ •์ž…๋‹ˆ๋‹ค.


Tournament selection method

def select_tournament(population, tournament_size):
    new_offspring = []
    for _ in range(len(population)):
        candidates = [random.choice(population) for _ in range(tournament_size)]
        new_offspring.append(max(candidates, key=lambda ind: ind.fitness))
    return new_offspring

Applying selection to random population

if __name__ == '__main__':
    random.seed(29)
    # PARAMETER: the size of initial population
    POPULATION_SIZE = 5
 
    # Generating random population
    generation_1 = [create_random_individual() for _ in range(POPULATION_SIZE)]
 
    # Population after applying selection
    generation_2 = select_tournament(generation_1, 3)
 
    # Printing results
    print("Generation 1")
    [print(ind) for ind in generation_1]
 
    print("Generation 2")
    [print(ind) for ind in generation_2]

Result

Generation 1  
0.96 -> 0.63  
-3.08 -> -0.67  
6.90 -> -0.80  
-4.23 -> 0.04  
0.21 -> 0.16  
 
Generation 2  
-4.23 -> 0.04  
0.96 -> 0.63  
-4.23 -> 0.04  
0.96 -> 0.63  
0.21 -> 0.16  

As you can see from the example, the most adapted individuals were admitted to selection.
์˜ˆ์ œ์—์„œ ๋ณผ ์ˆ˜ ์žˆ๋“ฏ์ด, ๋” ์ ํ•ฉํ•œ ๊ฐœ์ฒด๋“ค์ด ์„ ํƒ๋˜์–ด ๋‹ค์Œ ์„ธ๋Œ€๋กœ ์ด์–ด์กŒ์Šต๋‹ˆ๋‹ค.

๐Ÿ’ก admit to ~ : ~์— ํ—ˆ์šฉ๋˜๋‹ค, ๋ฐ›์•„๋“ค์—ฌ์ง€๋‹ค
were admitted to selection : ์„ ํƒ ๊ณผ์ •์— ํฌํ•จ๋˜์—ˆ๋‹ค


๐Ÿ”ก ์ฃผ์š” ๋‹จ์–ด

์˜์–ด ๋‹จ์–ดํ•œ๊ธ€ ๋œป
selection์„ ํƒ
genetic operation์œ ์ „ ์—ฐ์‚ฐ
adapted์ ์‘๋œ, ์ ํ•ฉํ•œ
offspring์ž์†, ํ›„์†
candidateํ›„๋ณด
mechanism๋ฉ”์ปค๋‹ˆ์ฆ˜, ์ž‘๋™ ๋ฐฉ์‹
generation์„ธ๋Œ€
participate์ฐธ์—ฌํ•˜๋‹ค
responsible for~์„ ๋‹ด๋‹นํ•˜๋Š”, ์ฑ…์ž„์ง€๋Š”

โœจ 2.5 - Crossover ๊ต์ฐจ

Crossover is the process of generating new offspring.
๊ต์ฐจ(crossover)๋Š” ์ƒˆ๋กœ์šด ์ž์†์„ ์ƒ์„ฑํ•˜๋Š” ๊ณผ์ •์ž…๋‹ˆ๋‹ค.

The main purpose of crossover is the exchange of genetic information, and to transfer the accumulated experience to the offspring.
๊ต์ฐจ์˜ ์ฃผ์š” ๋ชฉ์ ์€ ์œ ์ „ ์ •๋ณด๋ฅผ ๊ตํ™˜ํ•˜๊ณ , ๋ถ€๋ชจ์˜ ์ถ•์ ๋œ ๊ฒฝํ—˜์„ ์ž์†์—๊ฒŒ ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

The child should not be very different from the parents.
์ž์†์€ ๋ถ€๋ชจ์™€ ํฌ๊ฒŒ ๋‹ค๋ฅด์ง€ ์•Š์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค.

Crossover mechanisms will be discussed in detail in Chapter 4.
๊ต์ฐจ ๋ฉ”์ปค๋‹ˆ์ฆ˜์— ๋Œ€ํ•œ ์ž์„ธํ•œ ๋‚ด์šฉ์€ 4์žฅ์—์„œ ๋‹ค๋ฃน๋‹ˆ๋‹ค.

Consider an example of crossover, in which we take the gene of both parents and randomly select the gene of the child in the range that is determined by the genes of the parents.
๋‹ค์Œ์€ ๋ถ€๋ชจ ์–‘์ชฝ์˜ ์œ ์ „ ์ •๋ณด๋ฅผ ํ™œ์šฉํ•˜์—ฌ, ๊ทธ ๋ฒ”์œ„ ๋‚ด์—์„œ ์ž์†์˜ ์œ ์ „์ž๋ฅผ ๋ฌด์ž‘์œ„๋กœ ์„ ํƒํ•˜๋Š” ๊ต์ฐจ ์˜ˆ์ œ์ž…๋‹ˆ๋‹ค.

๐Ÿ’กin which : ๊ทธ ์•ˆ์—์„œ, ๊ทธ ๊ณผ์ •์—์„œ, ๊ทธ ์ƒํ™ฉ์—์„œ


Import part

import random
import numpy as np
import matplotlib.pyplot as plt
 
from ch2.individual import create_random_individual, create_individual
from ch2.fitness import fitness
from ch2.settings import MIN_BORDER, MAX_BORDER

Crossover implementation

def gene_constraints(g, min_=MIN_BORDER, max_=MAX_BORDER):
    """
    Limits gene value inside interval [min_, max_]
    """
    if max_ and g > max_:
        g = max_
    if min_ and g < min_:
        g = min_
    return g
 
def crossover_blend(g1, g2, alpha=0.3):
    """
    Gene blending. Explained in Chapter 4.
    """
    shift = (1. + 2. * alpha) * random.random() - alpha
    new_g1 = (1. - shift) * g1 + shift * g2
    new_g2 = shift * g1 + (1. - shift) * g2
    return gene_constraints(new_g1), gene_constraints(new_g2)
 
def crossover(ind1, ind2):
    """
    Individual crossover
    """
    offspring_genes = crossover_blend(ind1.get_gene(), ind2.get_gene())
    return [create_individual(offspring_genes[0]),
            create_individual(offspring_genes[1])]

Applying crossover to random individuals

if __name__ == '__main__':
    random.seed(30)
    # Pair of random individuals
    p_1 = create_random_individual()
    p_2 = create_random_individual()
 
    # Offspring of individuals
    offspring = crossover(p_1, p_2)
    c_1 = offspring[0]
    c_2 = offspring[1]
 
    # Visualization
    x = np.linspace(MIN_BORDER, MAX_BORDER)
    plt.plot(x, fitness(x), '--', color='blue')
 
    plt.plot(
        [p_1.get_gene(), p_2.get_gene()],
        [p_1.fitness, p_2.fitness],
        'o', markersize=15, color='orange'
    )
 
    plt.plot(
        [c_1.get_gene(), c_2.get_gene()],
        [c_1.fitness, c_2.fitness],
        's', markersize=15, color='green'
    )
 
    plt.title("Circle: Parents, Square: Children")
    plt.show()

Letโ€™s take a look at the following figure to understand crossover:
์ด์ œ ๊ทธ๋ฆผ 2.5๋ฅผ ํ†ตํ•ด ๊ต์ฐจ ๊ณผ์ •์„ ์‹œ๊ฐ์ ์œผ๋กœ ์ดํ•ดํ•ด๋ด…์‹œ๋‹ค.

image


๐Ÿ”ก ์ฃผ์š” ๋‹จ์–ด

์˜์–ด ๋‹จ์–ดํ•œ๊ธ€ ๋œป
crossover๊ต์ฐจ (์ž์† ์ƒ์„ฑ ๊ณผ์ •)
offspring์ž์†, ํ›„์†
gene์œ ์ „์ž
genetic information์œ ์ „ ์ •๋ณด
blendingํ˜ผํ•ฉ, ๋ธ”๋ Œ๋”ฉ
exchange๊ตํ™˜
constraints์ œ์•ฝ ์กฐ๊ฑด, ์ œํ•œ
accumulate์ถ•์ ํ•˜๋‹ค
randomly๋ฌด์ž‘์œ„๋กœ
range๋ฒ”์œ„
visualization์‹œ๊ฐํ™”
square์‚ฌ๊ฐํ˜• (์—ฌ๊ธฐ์„  ์ž์†์„ ์˜๋ฏธํ•˜๋Š” ๊ทธ๋ž˜ํ”ฝ)
circle์›ํ˜• (์—ฌ๊ธฐ์„  ๋ถ€๋ชจ๋ฅผ ์˜๋ฏธํ•˜๋Š” ๊ทธ๋ž˜ํ”ฝ)

โœจ 2.6 - Mutation ๋Œ์—ฐ๋ณ€์ด

Mutation is a random change that an individualโ€™s genes undergo.
๋Œ์—ฐ๋ณ€์ด๋Š” ๊ฐœ์ฒด์˜ ์œ ์ „์ž๊ฐ€ ๊ฒช๋Š” ๋ฌด์ž‘์œ„์ ์ธ ๋ณ€ํ™”์ž…๋‹ˆ๋‹ค.

๐Ÿ’ก undergo : (์–ด๋–ค ๊ณผ์ •, ๋ณ€ํ™”, ๊ฒฝํ—˜ ๋“ฑ์„) ๊ฒช๋‹ค, ๋ฐ›๋‹ค, ๊ฒฝํ—˜ํ•˜๋‹ค

Mutation is the factor that drives the development of evolution.
๋Œ์—ฐ๋ณ€์ด๋Š” ์ง„ํ™”๋ฅผ ์ด๋„๋Š” ์ฃผ์š”ํ•œ ์›๋™๋ ฅ์ž…๋‹ˆ๋‹ค.

Each child contains something that neither of his parents has.
๊ฐ ์ž์†์€ ๋ถ€๋ชจ ์ค‘ ๋ˆ„๊ตฌ์—๊ฒŒ๋„ ์—†๋Š” ๋ฌด์–ธ๊ฐ€๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๐Ÿ’ก neither of A and B : A์™€ B ๋‘˜ ๋‹ค ~์•„๋‹ˆ๋‹ค, ์–ด๋А ์ชฝ๋„ ~์•„๋‹ˆ๋‹ค
๐Ÿ’ก neither of A = A ๋‘˜ ์ค‘ ์–ด๋А ์ชฝ๋„ ์•„๋‹ˆ๋‹ค

If the trees begin to grow taller then a child of a horse, whose neck is slightly longer than its parents, will be able to find food for itself more easily, which means it will be more adapted to life and will be able to pass on this feature to its offspring.
๋‚˜๋ฌด๊ฐ€ ๋” ํ‚ค๊ฐ€ ์ปค์ง€๊ธฐ ์‹œ์ž‘ํ•˜๋ฉด, ๋ชฉ์ด ๋ถ€๋ชจ๋ณด๋‹ค ์•ฝ๊ฐ„ ๋” ๊ธด ๋ง์˜ ์ž์†์€ ์Šค์Šค๋กœ ๋” ์‰ฝ๊ฒŒ ๋จน์ด๋ฅผ ์ฐพ์„ ์ˆ˜ ์žˆ๊ฒŒ ๋˜๊ณ , ์ด๋Š” ๊ทธ ์ž์†์ด ์‚ถ์— ๋” ์ž˜ ์ ์‘ํ•˜๊ฒŒ ๋˜๋ฉฐ ์ด ํŠน์ง•์„ ์ž์†์—๊ฒŒ ๋ฌผ๋ ค์ค„ ์ˆ˜ ์žˆ๋‹ค๋Š” ๋œป์ž…๋‹ˆ๋‹ค.

This is exactly how, by accumulating positive mutations from generation to generation, a horse can evolve into a giraffe.
๋ฐ”๋กœ ์ด๋ ‡๊ฒŒ ์„ธ๋Œ€๋ฅผ ๊ฑฐ์ณ ์œ ์ตํ•œ ๋Œ์—ฐ๋ณ€์ด๋ฅผ ์ถ•์ ํ•จ์œผ๋กœ์จ, ๋ง์ด ๊ธฐ๋ฆฐ์œผ๋กœ ์ง„ํ™”ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

More on the mechanisms of mutations will be discussed in Chapter 5.
๋Œ์—ฐ๋ณ€์ด ๋ฉ”์ปค๋‹ˆ์ฆ˜์˜ ์ž์„ธํ•œ ์„ค๋ช…์€ 5์žฅ์—์„œ ๋‹ค๋ฃน๋‹ˆ๋‹ค.


Import part

import random
import numpy as np
import matplotlib.pyplot as plt
 
from ch2.individual import create_random_individual, create_individual
from ch2.fitness import fitness
from ch2.settings import MIN_BORDER, MAX_BORDER

Mutation implementation

def gene_constraints(g, min_=MIN_BORDER, max_=MAX_BORDER):
    """
    Limits gene value inside interval [min_, max_]
    """
    if max_ and g > max_:
        g = max_
    if min_ and g < min_:
        g = min_
    return g
 
def mutate_gaussian(g, mu, sigma):
    """
    Gaussian Mutation. Explained in Chapter 5.
    """
    mutated_gene = g + random.gauss(mu, sigma)
    return gene_constraints(mutated_gene)
 
def mutate(ind):
    """
    Mutation of Individual
    """
    return create_individual(mutate_gaussian(ind.get_gene(), 0, 1))

Applying mutation to random individual

if __name__ == '__main__':
    random.seed(37)
    # Random Individual
    individual = create_random_individual()
 
    # Mutated Individual
    mutated = mutate(individual)
 
    # Visualization
    x = np.linspace(MIN_BORDER, MAX_BORDER)
    plt.plot(x, fitness(x), '--', color='blue')
 
    plt.plot(
        [individual.get_gene()],
        [individual.fitness],
        'o', markersize=20, color='orange'
    )
 
    plt.plot(
        [mutated.get_gene()],
        [mutated.fitness],
        's', markersize=20, color='green'
    )
 
    plt.title("Circle: Before Mutation, Square: After Mutation")
    plt.show()

Letโ€™s take a look at the following figure of mutation (Figure 2.6) for an understanding.
๊ทธ๋ฆผ 2.6์„ ํ†ตํ•ด ๋Œ์—ฐ๋ณ€์ด์˜ ๊ณผ์ •์„ ์‹œ๊ฐ์ ์œผ๋กœ ์ดํ•ดํ•ด๋ด…์‹œ๋‹ค.

image


๐Ÿ”ก ์ฃผ์š” ๋‹จ์–ด

์˜์–ด ๋‹จ์–ดํ•œ๊ธ€ ๋œป
mutation๋Œ์—ฐ๋ณ€์ด
gene์œ ์ „์ž
random change๋ฌด์ž‘์œ„ ๋ณ€ํ™”
evolution์ง„ํ™”
offspring์ž์†, ํ›„์†
develop๋ฐœ๋‹ฌํ•˜๋‹ค, ๋ฐœ์ „ํ•˜๋‹ค
solutionํ•ด๋ฒ•
constraint์ œ์•ฝ, ์ œํ•œ
gaussian mutation๊ฐ€์šฐ์‹œ์•ˆ ๋Œ์—ฐ๋ณ€์ด (์ •๊ทœ๋ถ„ํฌ ๊ธฐ๋ฐ˜ ๋ณ€ํ™”)
mutate๋Œ์—ฐ๋ณ€์ด ์‹œํ‚ค๋‹ค
mutated individual๋Œ์—ฐ๋ณ€์ด๋œ ๊ฐœ์ฒด
before / after์ด์ „ / ์ดํ›„
visualization์‹œ๊ฐํ™”

โœจ 2.7 - Genetic Algorithm Flow

Letโ€™s put this all together!
์ด์ œ ์ง€๊ธˆ๊นŒ์ง€ ๋ฐฐ์šด ๋‚ด์šฉ์„ ๋ชจ๋‘ ํ•ฉ์ณ๋ด…์‹œ๋‹ค!

The whole GA flow looks like how it appears in the following figure (Figure 2.7).
์œ ์ „ ์•Œ๊ณ ๋ฆฌ์ฆ˜(GA)์˜ ์ „์ฒด ํ๋ฆ„์€ ์•„๋ž˜์˜ ๊ทธ๋ฆผ 2.7์ฒ˜๋Ÿผ ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค.

image

There are various conditions for stopping the GA, for example:
GA(์œ ์ „ ์•Œ๊ณ ๋ฆฌ์ฆ˜)๋ฅผ ์ค‘๋‹จํ•˜๋Š” ์กฐ๊ฑด์—๋Š” ์—ฌ๋Ÿฌ ๊ฐ€์ง€๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

Finding an acceptable solution
์ˆ˜์šฉ ๊ฐ€๋Šฅํ•œ ํ•ด๋ฅผ ์ฐพ์•˜์„ ๋•Œ

Reaching a certain number of generations
์ผ์ •ํ•œ ์„ธ๋Œ€ ์ˆ˜์— ๋„๋‹ฌํ–ˆ์„ ๋•Œ

Decrease in qualitative improvements in the population
๊ฐœ์ฒด๊ตฐ์˜ ์งˆ์  ํ–ฅ์ƒ์ด ๊ฐ์†Œํ•  ๋•Œ

In our example, GA will simply stop after 10 generations.
์šฐ๋ฆฌ ์˜ˆ์ œ์—์„œ๋Š” GA๊ฐ€ 10์„ธ๋Œ€ ํ›„์— ๋‹จ์ˆœํžˆ ์ข…๋ฃŒ๋ฉ๋‹ˆ๋‹ค.

Genetic algorithm has special parameters:
์œ ์ „ ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ๋ช‡ ๊ฐ€์ง€ ํŠน๋ณ„ํ•œ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๊ฐ€์ง‘๋‹ˆ๋‹ค.

Crossover probability: The probability of crossing.
๊ต์ฐจ ํ™•๋ฅ : ๋‘ ๊ฐœ์ฒด๊ฐ€ ๊ต์ฐจํ•  ํ™•๋ฅ ์ž…๋‹ˆ๋‹ค.

Mutation probability: The probability of mutation.
๋Œ์—ฐ๋ณ€์ด ํ™•๋ฅ : ๊ฐœ์ฒด๊ฐ€ ๋Œ์—ฐ๋ณ€์ด๋ฅผ ๊ฒช์„ ํ™•๋ฅ ์ž…๋‹ˆ๋‹ค.


Import part

import random
 
from ch2.crossover import crossover
from ch2.individual import create_random_individual
from ch2.mutate import mutate
from ch2.population import plot_population
from ch2.selection import select_tournament

Example of genetic algorithm flow

if __name__ == '__main__':
    # PARAMETERS
    POPULATION_SIZE = 10
    CROSSOVER_PROBABILITY = 0.8
    MUTATION_PROBABILITY = 0.1
    MAX_GENERATIONS = 10
 
    random.seed(29)
 
    # Initial random population
    population = [create_random_individual() for _ in range(POPULATION_SIZE)]
 
    for generation_number in range(MAX_GENERATIONS):
        # SELECTION OPERATION
        selected = select_tournament(population, 3)
 
        # CROSSOVER
        crossed_offspring = []
        for ind1, ind2 in zip(selected[::2], selected[1::2]):
            if random.random() < CROSSOVER_PROBABILITY:
                # Applying crossover to pair of individuals
                children = crossover(ind1, ind2)
                crossed_offspring.append(children[0])
                crossed_offspring.append(children[1])
            else:
                # Passing individuals further without crossover
                crossed_offspring.append(ind1)
                crossed_offspring.append(ind2)
 
        # MUTATION
        mutated = []
        for ind in crossed_offspring:
            if random.random() < MUTATION_PROBABILITY:
                # Applying mutation to an individual
                mutated.append(mutate(ind))
            else:
                # Passing individual further without mutation
                mutated.append(ind)
 
        # Next generation
        population = mutated
 
        # Visualize population for current generation
        plot_population(population)

image

The preceding figure (2.8) shows the result of the genetic algorithm.
๊ทธ๋ฆผ 2.8์€ ์œ ์ „ ์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ ๊ฒฐ๊ณผ๋ฅผ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

As expected, after 10 generations, all individuals settled in the most favorable place for them.
์˜ˆ์ƒ๋Œ€๋กœ 10์„ธ๋Œ€๊ฐ€ ์ง€๋‚œ ํ›„, ๋ชจ๋“  ๊ฐœ์ฒด๋“ค์€ ์ž์‹ ๋“ค์—๊ฒŒ ๊ฐ€์žฅ ์œ ๋ฆฌํ•œ ์œ„์น˜์— ์ž๋ฆฌ์žก์•˜์Šต๋‹ˆ๋‹ค.

The best solution to our problem is approximately 1.4, at which point the function sin(x) - 0.5โ€ฏ|x| reaches a value of 0.71.
์šฐ๋ฆฌ ๋ฌธ์ œ์˜ ์ตœ์  ํ•ด๋Š” ๋Œ€๋žต 1.4์ด๋ฉฐ, ์ด ์ง€์ ์—์„œ ํ•จ์ˆ˜ sin(x) - 0.5โ€ฏ|x|์˜ ๊ฐ’์€ 0.71์— ๋„๋‹ฌํ•ฉ๋‹ˆ๋‹ค.


๐Ÿ”ก ์ฃผ์š” ๋‹จ์–ด

์˜์–ด ๋‹จ์–ดํ•œ๊ธ€ ๋œป
stopping condition์ค‘๋‹จ ์กฐ๊ฑด
acceptable solution๋งŒ์กฑํ•  ๋งŒํ•œ ํ•ด
qualitative improvement์งˆ์  ํ–ฅ์ƒ
parameter๋งค๊ฐœ๋ณ€์ˆ˜, ํŒŒ๋ผ๋ฏธํ„ฐ
crossover probability๊ต์ฐจ ํ™•๋ฅ 
mutation probability๋Œ์—ฐ๋ณ€์ด ํ™•๋ฅ 
select (selection)์„ ํƒํ•˜๋‹ค / ์„ ํƒ
crossover๊ต์ฐจ (์ž์† ์ƒ์„ฑ)
mutate (mutation)๋Œ์—ฐ๋ณ€์ด ์‹œํ‚ค๋‹ค / ๋Œ์—ฐ๋ณ€์ด
offspring์ž์†, ํ›„์†
favorable์œ ๋ฆฌํ•œ
visualize์‹œ๊ฐํ™”ํ•˜๋‹ค
settled์ž๋ฆฌ์žก๋‹ค, ์ •์ฐฉํ•˜๋‹ค

โœจ 2 - Conclusion ๊ฒฐ๋ก 

We examined step by step what a genetic algorithm is.
์šฐ๋ฆฌ๋Š” ์œ ์ „ ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด ๋ฌด์—‡์ธ์ง€ ๋‹จ๊ณ„๋ณ„๋กœ ์‚ดํŽด๋ณด์•˜์Šต๋‹ˆ๋‹ค.

We covered evolutionary concepts โ€“ individual, fitness function, population, selection, crossing, mutation.
๊ฐœ์ฒด, ์ ํ•ฉ๋„ ํ•จ์ˆ˜, ๊ฐœ์ฒด๊ตฐ, ์„ ํƒ, ๊ต์ฐจ, ๋Œ์—ฐ๋ณ€์ด ๊ฐ™์€ ์ง„ํ™” ๊ฐœ๋…๋“ค์„ ๋‹ค๋ฃจ์—ˆ์Šต๋‹ˆ๋‹ค.

And as a result, we have found the solution to the problem of finding the maxima of the function sin(x) - 0.5โ€ฏ|x| using a genetic algorithm.
๊ทธ๋ฆฌ๊ณ  ๊ทธ ๊ฒฐ๊ณผ, ์œ ์ „ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์‚ฌ์šฉํ•˜์—ฌ ํ•จ์ˆ˜ sin(x) - 0.5โ€ฏ|x|์˜ ์ตœ๋Œ“๊ฐ’์„ ์ฐพ๋Š” ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

In the following chapters, we will take a closer look at the operations โ€“ selection, crossing, and mutation.
๋‹ค์Œ ์žฅ๋“ค์—์„œ๋Š” ์„ ํƒ, ๊ต์ฐจ, ๋Œ์—ฐ๋ณ€์ด ์—ฐ์‚ฐ์— ๋Œ€ํ•ด ์ข€ ๋” ์ž์„ธํžˆ ์‚ดํŽด๋ณผ ๊ฒƒ์ž…๋‹ˆ๋‹ค.


โœจ 2 - Points to remember: ๊ธฐ์–ตํ•  ์ 

GA flow consists of the following steps: Initialization of random population, selection, crossover, and mutation.
GA์˜ ํ๋ฆ„์€ ๋‹ค์Œ ๋‹จ๊ณ„๋“ค๋กœ ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค: ๋ฌด์ž‘์œ„ ๊ฐœ์ฒด๊ตฐ ์ดˆ๊ธฐํ™”, ์„ ํƒ, ๊ต์ฐจ, ๊ทธ๋ฆฌ๊ณ  ๋Œ์—ฐ๋ณ€์ด.

GA has the following tunable parameters: Population size, crossover probability, mutation probability, and maximum number of generations.
GA๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์กฐ์ • ๊ฐ€๋Šฅํ•œ ๋งค๊ฐœ๋ณ€์ˆ˜๋“ค์„ ๊ฐ€์ง‘๋‹ˆ๋‹ค: ๊ฐœ์ฒด๊ตฐ ํฌ๊ธฐ, ๊ต์ฐจ ํ™•๋ฅ , ๋Œ์—ฐ๋ณ€์ด ํ™•๋ฅ , ๊ทธ๋ฆฌ๊ณ  ์ตœ๋Œ€ ์„ธ๋Œ€ ์ˆ˜.


โœจ 2 - Multiple choice questions ๊ฐ๊ด€์‹ ๋ฌธ์ œ

1. We want to find the minima of the function sin(x) โ€“ 0.5โ€ฏ|x|. What will the fitness function look like?
์šฐ๋ฆฌ๋Š” ํ•จ์ˆ˜ sin(x) โ€“ 0.5โ€ฏ|x|์˜ ์ตœ์†Ÿ๊ฐ’์„ ์ฐพ๊ณ ์ž ํ•ฉ๋‹ˆ๋‹ค. ์ ํ•ฉ๋„ ํ•จ์ˆ˜๋Š” ์–ด๋–ค ํ˜•ํƒœ์ผ๊นŒ์š”?

  • sin(x)
  • โœ… sin(x) โ€“ 0.5โ€ฏ|x|
  • |x|
  • sin(x) + 0.5โ€ฏ|x|

2. We want to find the minima of the function sin(x) โ€“ 0.5โ€ฏ|x|. How will we determine the best individual?
์šฐ๋ฆฌ๋Š” ํ•จ์ˆ˜ sin(x) โ€“ 0.5โ€ฏ|x|์˜ ์ตœ์†Ÿ๊ฐ’์„ ์ฐพ๊ณ ์ž ํ•ฉ๋‹ˆ๋‹ค. ์ตœ์ ์˜ ๊ฐœ์ฒด๋Š” ์–ด๋–ป๊ฒŒ ๊ฒฐ์ •ํ• ๊นŒ์š”?

  • Individual with highest fitness function: sin(x) โ€“ 0.5โ€ฏ|x|
    ์ ํ•ฉ๋„ ํ•จ์ˆ˜ ๊ฐ’์ด ๊ฐ€์žฅ ๋†’์€ ๊ฐœ์ฒด : sin(x) โ€“ 0.5โ€ฏ|x|
  • โœ… Individual with lowest fitness function: sin(x) โ€“ 0.5โ€ฏ|x| ์ ํ•ฉ๋„ ํ•จ์ˆ˜ ๊ฐ’์ด ๊ฐ€์žฅ ๋‚ฎ์€ ๊ฐœ์ฒด : sin(x) โ€“ 0.5โ€ฏ|x|

3. What is the correct sequence of steps in GA flow?
์œ ์ „ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ํ๋ฆ„์—์„œ ์˜ฌ๋ฐ”๋ฅธ ๋‹จ๊ณ„ ์ˆœ์„œ๋Š” ๋ฌด์—‡์ธ๊ฐ€์š”?

  • crossover, selection, mutation
    ๊ต์ฐจ, ์„ ํƒ, ๋Œ์—ฐ๋ณ€์ด
  • mutation, crossover, selection
    ๋Œ์—ฐ๋ณ€์ด, ๊ต์ฐจ, ์„ ํƒ
  • โœ… selection, crossover, mutation ์„ ํƒ, ๊ต์ฐจ, ๋Œ์—ฐ๋ณ€์ด
  • selection, mutation, crossover
    ์„ ํƒ, ๋Œ์—ฐ๋ณ€์ด, ๊ต์ฐจ

โœจ 2 - Questions ์งˆ๋ฌธ

1. Say we have two individuals ind1 and ind2. And ind1.fitness is lower than ind2.fitness. After tournament selection ind1 is selected, but ind2 is not. Is this possible?
๋‘ ๊ฐœ์ฒด ind1๊ณผ ind2๊ฐ€ ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•ฉ์‹œ๋‹ค. ind1์˜ ์ ํ•ฉ๋„(fitness)๊ฐ€ ind2๋ณด๋‹ค ๋‚ฎ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ํ† ๋„ˆ๋จผํŠธ ์„ ํƒ ํ›„ ind1์ด ์„ ํƒ๋˜๊ณ , ind2๋Š” ์„ ํƒ๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฐ ์ผ์ด ๊ฐ€๋Šฅํ• ๊นŒ์š”?

โœ”๏ธ ํ† ๋„ˆ๋จผํŠธ ์„ ํƒ์€ ๋ฌด์ž‘์œ„๋กœ ์„ ํƒ๋œ ํ›„๋ณด๋“ค ์ค‘์—์„œ ๊ฐ€์žฅ ์ ํ•ฉํ•œ ๊ฐœ์ฒด๋ฅผ ๊ณ ๋ฅด๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค.
ใ…ค ๋งŒ์•ฝ ind2๊ฐ€ ํ† ๋„ˆ๋จผํŠธ์— ํฌํ•จ๋˜์ง€ ์•Š์•˜๊ณ , ind1์ด ํฌํ•จ๋˜์–ด ๋‹ค๋ฅธ ์•ฝํ•œ ๊ฐœ์ฒด๋“ค๊ณผ ๊ฒฝ์Ÿํ–ˆ๋‹ค๋ฉด ใ…ค ind1์ด ์„ ํƒ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

2. What happens if we remove the mutation from our genetic algorithm? (MUTATION_PROBABILITY = 0) How will the search process change?
์šฐ๋ฆฌ์˜ ์œ ์ „ ์•Œ๊ณ ๋ฆฌ์ฆ˜์—์„œ ๋Œ์—ฐ๋ณ€์ด๋ฅผ ์ œ๊ฑฐํ•˜๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ์š”? (MUTATION_PROBABILITY = 0) ํƒ์ƒ‰ ๊ณผ์ •์€ ์–ด๋–ป๊ฒŒ ๋‹ฌ๋ผ์งˆ๊นŒ์š”?

โœ”๏ธ ๋Œ์—ฐ๋ณ€์ด๋Š” ์ƒˆ๋กœ์šด ํ•ด๋ฅผ ๋งŒ๋“ค์–ด๋‚ด๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.
ใ…ค ๋Œ์—ฐ๋ณ€์ด๋ฅผ ์ œ๊ฑฐํ•˜๋ฉด, ๊ฐœ์ฒด๊ตฐ์€ ๊ธฐ์กด ์œ ์ „์ž ์•ˆ์—์„œ๋งŒ ๊ต์ฐจํ•˜๊ฒŒ ๋˜์–ด ํƒ์ƒ‰ ์˜์—ญ์ด ์ œํ•œ๋ฉ๋‹ˆ๋‹ค.
ใ…ค ๊ฒฐ๊ณผ์ ์œผ๋กœ ์ „์—ญ ์ตœ์ ํ•ด์— ๋„๋‹ฌํ•˜์ง€ ๋ชปํ•˜๊ณ  ๊ตญ์†Œ ์ตœ์ ํ•ด์— ๋จธ๋ฌผ ๊ฐ€๋Šฅ์„ฑ์ด ๋†’์•„์ง‘๋‹ˆ๋‹ค.