โจ 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_BORDERIndividual 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 = 10Here 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.
๋ ๊ฐ์ ๋ณ์๋ฅผ ๊ฐ์ง ํจ์ ๊ฐ ์๋ ๊ทธ๋ฆผ๊ณผ ๊ฐ์ด ์ฃผ์ด์ก๋ค๊ณ ๊ฐ์ ํด๋ด
์๋ค.
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 ~ : ~์ ๋ํ๋ ๋๋ก, ~์์ ๋ณด์ฌ์ง๋ ๊ฒ์ฒ๋ผ
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)๋ผ๋ ๊ฐ์ฒด๋ ๋ค์ ๊ทธ๋ฆผ๊ณผ ๊ฐ์ ๊ฒฝ๋ก๋ฅผ ๋ํ๋
๋๋ค.
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_BORDERPopulation 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: ๋ฌด์์ ๊ฐ์ฒด๊ตฐ์ ์๊ฐํ๋ฅผ ์ดํดํ๊ธฐ ์ํด ๋ค์ ๊ทธ๋ฆผ์ ์ดํด๋ด ์๋ค.
๐ก ์ฃผ์ ๋จ์ด
| ์์ด ๋จ์ด | ํ๊ธ ๋ป |
|---|---|
| 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_offspringApplying 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_BORDERCrossover 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๋ฅผ ํตํด ๊ต์ฐจ ๊ณผ์ ์ ์๊ฐ์ ์ผ๋ก ์ดํดํด๋ด
์๋ค.
๐ก ์ฃผ์ ๋จ์ด
| ์์ด ๋จ์ด | ํ๊ธ ๋ป |
|---|---|
| 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_BORDERMutation 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์ ํตํด ๋์ฐ๋ณ์ด์ ๊ณผ์ ์ ์๊ฐ์ ์ผ๋ก ์ดํดํด๋ด
์๋ค.
๐ก ์ฃผ์ ๋จ์ด
| ์์ด ๋จ์ด | ํ๊ธ ๋ป |
|---|---|
| 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์ฒ๋ผ ๊ตฌ์ฑ๋ฉ๋๋ค.
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_tournamentExample 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)
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) ํ์ ๊ณผ์ ์ ์ด๋ป๊ฒ ๋ฌ๋ผ์ง๊น์?
โ๏ธ ๋์ฐ๋ณ์ด๋ ์๋ก์ด ํด๋ฅผ ๋ง๋ค์ด๋ด๋ ์ญํ ์ ํฉ๋๋ค.
ใ ค ๋์ฐ๋ณ์ด๋ฅผ ์ ๊ฑฐํ๋ฉด, ๊ฐ์ฒด๊ตฐ์ ๊ธฐ์กด ์ ์ ์ ์์์๋ง ๊ต์ฐจํ๊ฒ ๋์ด ํ์ ์์ญ์ด ์ ํ๋ฉ๋๋ค.
ใ ค ๊ฒฐ๊ณผ์ ์ผ๋ก ์ ์ญ ์ต์ ํด์ ๋๋ฌํ์ง ๋ชปํ๊ณ ๊ตญ์ ์ต์ ํด์ ๋จธ๋ฌผ ๊ฐ๋ฅ์ฑ์ด ๋์์ง๋๋ค.