PyGAD는 Genetic Algorithm을 사용할 수 있게 하는 파이썬의 오픈소스입니다. PyGAD는 다양한 종류의 crossover, mutation, parent selection을 지원합니다. 또한, fitness function을 커스터마이징함으로써 다양한 유형의 문제를 최적화 할 수 있습니다.
소스코드를 통한 구현 예시입니다.
이번 포스팅의 예에서는 함수 가 주어져 있고, 로 정의되어 있다고 가정합니다.
함수 가 에 근접하게 하는 최적의 는 무엇일까요?
우리는 이 함수를 최적화 하기 위해서 GA 알고리즘을 사용합니다.
우선 필요한 라이브러리들을 다운받아 줍니다.
!pip install pygad
import pygad
import numpy
import math
파라미터들을 초기화합니다.
num_generations = 100 # Number of generations. - 10, 50, 100
num_parents_mating = 40 # Number of solutions to be selected as parents in the mating pool.
sol_per_pop = 50 # Number of solutions in the population; number of chromosomes 5, 20, 50
num_genes = len(function_inputs)
input 데이터, target output, 파라미터 의 범위, 그리고 fitness function을 정의합니다.
function_inputs = [4,-2,3.5,5,-11,-4.7] # Function inputs.
desired_output = 44 # Function output.
range_ben = [{'low': -30, 'high': 30}, {'low': -30, 'high': 30}, {'low': -30, 'high': 30}, {'low': -30, 'high': 30}, {'low': -30, 'high': 30}, {'low': -30, 'high': 30}]
def fitness_func(ga_instance, solution, solution_idx):
# original test function :
output = numpy.sum(solution*function_inputs)
fitness = 1000- (numpy.abs(output - desired_output) + 0.000001) # performing minimization desired_output=y=44
return fitness
다음 on_generation()
메소드는 각 generation별 GA의 결과값을 보여줍니다.
last_fitness = 0
def on_generation(ga_instance):
global last_fitness
print("Generation = {generation}".format(generation=ga_instance.generations_completed))
print("Fitness = {fitness}".format(fitness=ga_instance.best_solution(pop_fitness=ga_instance.last_generation_fitness)[1]))
print("Change = {change}".format(change=ga_instance.best_solution(pop_fitness=ga_instance.last_generation_fitness)[1] - last_fitness))
last_fitness = ga_instance.best_solution(pop_fitness=ga_instance.last_generation_fitness)[1]
GA를 실행하기 전 파라미터들을 셋팅해줍니다.
ga_instance = pygad.GA(num_generations=num_generations,
num_parents_mating=num_parents_mating,
sol_per_pop=sol_per_pop,
num_genes=num_genes,
gene_type=float,
gene_space=range_ben,
fitness_func=fitness_func,
on_generation=on_generation)
GA를 실행합니다. 후속 세대로 갈수록, 점점 fitness value와 우리의 target output값이 비슷해지는 것을 확인할 수 있습니다.
ga_instance.run()
output:
Generation = 1
Fitness = 997.9177930856762
Change = 997.9177930856762
Generation = 2
Fitness = 998.9081446191583
Change = 0.9903515334821122
Generation = 3
Fitness = 998.9081446191583
Change = 0.0
...
Generation = 98
Fitness = 999.9986527749419
Change = 0.0
Generation = 99
Fitness = 999.9986527749419
Change = 0.0
Generation = 100
Fitness = 999.9986527749419
Change = 0.0
실행 후 Generation-Fitness plot
을 통해 진행과정을 확인할 수 있습니다. 20세대 이후부터는, 거의 Fitness value가 converge된 것을 확인할 수 있습니다.
ga_instance.plot_fitness()
best_solution()
메소드를 통해 GA를 사용한 최적의 솔루션 결과를 확인할 수 있습니다.
# Returning the details of the best solution.
solution, solution_fitness, solution_idx = ga_instance.best_solution(ga_instance.last_generation_fitness)
print("Parameters of the best solution : {solution}".format(solution=solution))
print("Fitness value of the best solution = {solution_fitness}".format(solution_fitness=solution_fitness))
print("Index of the best solution : {solution_idx}".format(solution_idx=solution_idx))
prediction = numpy.sum(numpy.array(function_inputs)*solution)
print("Predicted output based on the best solution : {prediction}".format(prediction=prediction))
if ga_instance.best_solution_generation != -1:
print("Best fitness value reached after {best_solution_generation} generations.".format(best_solution_generation=ga_instance.best_solution_generation))
output:
Parameters of the best solution : [ 0.61901556 -13.35517528 17.16683406 -10.2892967 -9.90693565
21.87208391]
Fitness value of the best solution = 999.9986527749419
Index of the best solution : 0
Predicted output based on the best solution : 44.00134622505814
Best fitness value reached after 10 generations.
GA instance를 로컬에 저장합니다.
# Saving the GA instance.
filename = 'genetic' # The filename to which the instance is saved. The name is without extension.
ga_instance.save(filename=filename)
저장한 GA instance를 다시 불러와 사용할 수 있습니다.
# Loading the saved GA instance.
loaded_ga_instance = pygad.load(filename=filename)
loaded_ga_instance
이 외에도, GA 파라미터(the number of generations, population size)를 조정하거나, 다른 Fitness functions들을 사용하여 다양한 실험들을 해볼 수 있습니다.