소연이의 메모장
PyGAD를 활용한 유전 알고리즘의 구현 본문
1. PyGAD란?
PyGAD는 파이썬 언어에서 유전알고리즘을 쉽게 구현할 수 있도록 배포한 오픈소스이다.
직접 구현하지 왜 오픈소스를 활용하냐고?
인류의 편의를 위해 오픈 소스를 배포한 개발자들의 호의를 무시할 순 없지 않은가.
우리 친절한 개발자님의 깃허브는 아래와 같다.
피드백도 빠른 편이니 궁금하면 질문해도 좋다.
실제로 궁금한 걸 묻고 답변을 받았다!
아래는 PyGAD 설명서다.
유용한 함수들이 많으니 참고하여 적용해 보자.
PyGAD에서 제공한 순서도이다.
앞서 살펴본 것과 크게 다르지 않다는 것을 알 수 있다.
2. PyGAD의 예제 코드 설명
PyGAD 예제 코드는 NP-Hard에 속하는 조합 최적화 문제로서
6개의 항으로 몫이 44가 되는 최적의 값을 찾는 것이 목적이다.
y = f(w1:w6) = w1x1 + w2x2 + w3x3 + w4x4 + w5x5 + w6x6
where (x1,x2,x3,x4,x5,x6)=(4,-2,3.5,5,-11,-4.7) and y=44
우선 pip install을 이용해서 pygad를 설치한다.
pip install pygad
설치한 pygad와 numpy 라이브러리를 불러온다
import pygad
import numpy
예제에서는 초기값을 function_inputs와 같이 넣어주었다.
function_inputs = [4,-2,3.5,5,-11,-4.7]
desired_output = 44
몫이 44가 되는 값을 찾기 위해 예제에서는 아래와 같이 적합도 함수를 설정하였다.
def fitness_func(ga_instance, solution, solution_idx):
output = numpy.sum(solution*function_inputs)
fitness = 1.0 / (numpy.abs(output - desired_output) + 0.000001)
return fitness
# 적합도 함수를 변수에 저장한다.
fitness_function = fitness_func
초기값과 적합도 함수만 입력하면 GA구현은 사실 끝이다.
PyGAD에 내장된 함수를 사용하여 유전 알고리즘을 불러온다.
def on_start(ga_instance):
print("on_start()")
def on_fitness(ga_instance, population_fitness):
print("on_fitness()")
def on_parents(ga_instance, selected_parents):
print("on_parents()")
def on_crossover(ga_instance, offspring_crossover):
print("on_crossover()")
def on_mutation(ga_instance, offspring_mutation):
print("on_mutation()")
def on_generation(ga_instance):
print("on_generation()")
def on_stop(ga_instance, last_population_fitness):
print("on_stop()")
아래 코드에서는 유전 알고리즘에서의 파라미터 값을 조정할 수 있다.
ga_instance = pygad.GA(num_generations=3, ## Number of generations.
num_parents_mating=5, ## Number of solutions to be selected as parents.
fitness_func=fitness_function,
sol_per_pop=10, ## Number of solutions (i.e. chromosomes) within the population.
num_genes=len(function_inputs), ## Number of genes in the solution/chromosome.
on_start=on_start,
on_fitness=on_fitness,
on_parents=on_parents,
on_crossover=on_crossover,
on_mutation=on_mutation,
on_generation=on_generation,
on_stop=on_stop)
실행시킨다.
ga_instance.run()
3. 전체 코드
pip install pygad
import pygad
import numpy
function_inputs = [4,-2,3.5,5,-11,-4.7]
desired_output = 44
def fitness_func(ga_instance, solution, solution_idx):
output = numpy.sum(solution*function_inputs)
fitness = 1.0 / (numpy.abs(output - desired_output) + 0.000001)
return fitness
fitness_function = fitness_func
def on_start(ga_instance):
print("on_start()")
def on_fitness(ga_instance, population_fitness):
print("on_fitness()")
def on_parents(ga_instance, selected_parents):
print("on_parents()")
def on_crossover(ga_instance, offspring_crossover):
print("on_crossover()")
def on_mutation(ga_instance, offspring_mutation):
print("on_mutation()")
def on_generation(ga_instance):
print("on_generation()")
def on_stop(ga_instance, last_population_fitness):
print("on_stop()")
ga_instance = pygad.GA(num_generations=3,
num_parents_mating=5,
fitness_func=fitness_function,
sol_per_pop=10,
num_genes=len(function_inputs),
on_start=on_start,
on_fitness=on_fitness,
on_parents=on_parents,
on_crossover=on_crossover,
on_mutation=on_mutation,
on_generation=on_generation,
on_stop=on_stop)
ga_instance.run()
결과에 대한 그래프를 출력하고 싶을 땐 아래와 같은 코드를 활용하면 된다.
실제로 주피터에서 예제 코드를 실행하였고 출력값은 >>로 나타내었다.
# After the generations complete, some plots are showed that summarize the how the outputs/fitenss values evolve over generations.
ga_instance.plot_fitness()
위 그래프를 살펴보면 세대(Generation)가 거듭될수록 적합도(Fitness) 값이 높아지는 걸 볼 수 있다.
즉 진화하면서 몫이 44가 되는 최적의 값을 찾아가고 있는 것이다.
# Returning the details of the best solution.
solution, solution_fitness, solution_idx = ga_instance.best_solution()
print(f"Parameters of the best solution : {solution}")
print(f"Fitness value of the best solution = {solution_fitness}")
print(f"Index of the best solution : {solution_idx}")
>> Parameters of the best solution : [-0.63649561 -1.23770069 2.15119783 1.43895046 -2.15393229 -1.21023452]
>> Fitness value of the best solution = 28.800151921252137
>> Index of the best solution : 7
prediction = numpy.sum(numpy.array(function_inputs)*solution)
print(f"Predicted output based on the best solution : {prediction}")
>> Predicted output based on the best solution : 44.03472103906196
위에서 설정한 function_inputs = [4,-2,3.5,5,-11,-4.7] 가
solution = [-0.63649561,-1.23770069,2.15119783,1.43895046,-2.15393229,-1.21023452] 과
곱하고 더해지면 44.03472103906196가 나오기 때문에 best solution이라고 한다.
진짜일까?
진짜였다.
if ga_instance.best_solution_generation != -1:
print(f"Best fitness value reached after {ga_instance.best_solution_generation} generations.")
>> Best fitness value reached after3generations.
세 번째 세대에서 가장 최적의 값을 찾았다고 한다.
# Saving the GA instance.
filename = 'genetic' # The filename to which the instance is saved. The name is without extension.
ga_instance.save(filename=filename)
# Loading the saved GA instance.
loaded_ga_instance = pygad.load(filename=filename)
loaded_ga_instance.plot_fitness()
위 코드는 모델을 저장하고 다시 불러와서 그래프를 그리는 코드다.
PyGAD 설명은 여기까지!
다음 포스팅에서는 유전 알고리즘을 활용한 내 논문의 코드를 살펴보겠다.
궁금한 사람 손 🙋🏻♀️ 🙋🏻♀️ 🙋🏻♀️
'ML\DL > 알고리즘의 이해' 카테고리의 다른 글
유전 알고리즘을 활용한 음식 배달 최적화 기법 (0) | 2023.10.16 |
---|---|
Genetic Algorithm(GA) 유전 알고리즘의 이해 (0) | 2022.08.24 |