가장 쉬운 유전 알고리듬 (genetic algorithms) 예제 [python] by 바죠


가장 쉬운 유전 알고리듬 (genetic algorithms) 예제 [python]

유전 알고리듬은 다음의 두가지를 필요로 한다.
1. 유전적 표현 (풀고있는 문제에 적합한 방식으로 정의함.)
2. 목적함수 (최적화를 시키고자 하는 함수를 정의함. 예를 들어 원하는 출력이 나올 때, 계산된 목적함수 값이 작아질 수 있도록 설계함.)



\[\vec{x}\]
\[f(\vec{x})\]
우리는 여러 가지 잠정적인 해들을 동시에 고려한다. 
여러 개의 해들
\[ \{ \vec{x}\}\]
여러 개의 목적함수들
\[\{f(\vec{x})\}\]


효율성을 더하기 위해서, 국소 최소화 알고리듬을 활용함. 오리지날 유전 알고리듬에 대한 변형이다. 대부분의 진화학습 방법에서 공통으로 적용되는 기법이다. x --> x*로 대체하는 것이 효율적이다 여기서 x*는 국소 최적화 과정을 거친 다음에 얻어지는 독립변수이다. 국소 최적화 알고리듬의 성능은 거의 발달할 수 있을 만큼 발달되어 있다. 특히, 도함수가 알려진 경우에 그렇다. 따라서, 국소 최적화 방법을 활용하지 않는 방법은 거의 대부분 비효율적이게 된다.

해를 실수형 벡터로 정의함. 많은 진화학습 방법에서 해는 일차원 벡터로 표현한다. 이것은 곧바로 교차, 변이 작업과 직접적으로 연결되어 있다. 이것을 1차원 표현방식이라고 한다. 1차원은 늘 편리하다.
반드시 변이와 교차를 둘 다 활용해야함.
목적함수에 따른 해들의 오름차순 정렬이 필요함.
해들의 정렬없이 유전 알고리듬을 구현할 수도 있다. 하지만, 목적함수 값 비교는 불가피하다.
왜냐하면, 우수한 해들에 대한 보다 많은 자식 생산의 기회를 부여하기 위해서 목적함수 값들 비교는 불가피하다.
개체에 대한 파이썬 클래스를 선언함으로써, 파이썬 언어에서 유전 알고리듬을 쉽게 구현할 수 있다.

파이썬 리스트를 이용한다. 
동일한 형식으로 정의된 객체를 다수 만들고 파이썬 리스트 항목으로 저장할 수 있다. 
그런데 객체가 클래스로 정의 된 것이 될 수도 있다. 파이썬 리스트는 매우 포괄적인 것을 하나의 항목으로 인정한다.
먼저 PARTICLE이라는 객체를 정의한다. [입자 하나에 대한 많은 정보를 가지고 있다. 위치, 속도, 목적함수 값, 역대 최적값, 역대 최적 위치] [입자마다 고유의 특성이 다를 수 있다.]
이것들로 구성된 또 다른 종류의 객체를 정의한다. [입자들로 구성된 무리를 정의한다.]
---------------------------------------------------------------------------------------------------------------------

import random
import numpy as np
from scipy.optimize import minimize
def functuser(x):
    case=3

    if case == 1:
       total=0.
       for j in range(len(x)):
           total+=(x[j])**2
    if case == 2:
#    Rastrigin
       total=10.*len(x)
       for j in range(len(x)):
           total+=x[j]**2-10.*np.cos(2.*np.pi*x[j])
    if case == 3:
#   Rosenbrock
       xarray0=np.zeros(len(x))
       for j in range(len(x)):
          xarray0[j]=x[j]
       total=sum(100.0*(xarray0[1:]-xarray0[:-1]**2.0)**2.0 + (1-xarray0[:-1])**2.0)
    if case == 4:
#   Styblinski-Tang
       total=0.
       for j in range(len(x)):
           total+=(x[j]**4-16.*x[j]**2+5.*x[j])/2.

    return total
class PARTICLE:
    def __init__(self,startx0,ptbmp,pmut,pcross,xbounds,lverbo):
        self.position_i=[]
        self.position_best_i=[]
        self.obj_best_i=9e99
        self.obj_i=9e99
        self.dimensions=len(startx0)
        self.ptbmp=ptbmp+(random.random()-0.5)*0.2
        self.pmut=pmut+(random.random()-0.5)*0.1
        self.pcross=pcross+(random.random()-0.5)*0.1
        if self.pmut > 0.999 or self.pmut < 0.001:
           self.pmut=random.random()
        if self.pcross > 0.999 or self.pcross < 0.001:
           self.pcross=random.random()
        if lverbo:
           print(self.ptbmp,self.pmut,self.pcross)
        for j in range(self.dimensions):
            self.position_i.append(startx0[j]*(1.+(random.random()-0.5)*2.))
        if random.random() < 0.8:
           for j in range(self.dimensions):
               self.position_i[j]=xbounds[j][0]+(xbounds[j][1]-xbounds[j][0])*random.random()
        for j in range(self.dimensions):
            if self.position_i[j] > xbounds[j][1]:
               self.position_i[j]=xbounds[j][0]+(xbounds[j][1]-xbounds[j][0])*random.random()
            if self.position_i[j] < xbounds[j][0]:
               self.position_i[j]=xbounds[j][0]+(xbounds[j][1]-xbounds[j][0])*random.random()
        self.position_best_i=self.position_i.copy()
    def evaluate(self,objfunct):
#       self.obj_i=objfunct(self.position_i)
        xarray0=np.zeros(self.dimensions)
        for j in range(self.dimensions):
            xarray0[j]=self.position_i[j]
        res=minimize(objfunct,xarray0,method='nelder-mead',options={'xtol':1e-6,'disp':True})
        self.position_i=res.x.copy()
        self.obj_i=res.fun
        if self.obj_i < self.obj_best_i :
           self.position_best_i=self.position_i.copy()
           self.obj_best_i=self.obj_i
    def update_mutationcrossover(self,x1vec,x2vec):
        if random.random() < 0.5:
           for j in range(self.dimensions):
               self.position_i[j]=x1vec[j]
               if random.random() < self.pmut:
                  self.position_i[j]=x1vec[j]*(1.+(random.random()-0.5)*self.ptbmp)
        else:
           for j in range(self.dimensions):
               self.position_i[j]=x1vec[j]
               if random.random() < self.pcross:
                   self.position_i[j]=x2vec[j]
    def update_position(self,xbounds):
        for j in range(self.dimensions):
            if self.position_i[j] > xbounds[j][1]:
               self.position_i[j]=xbounds[j][0]+(xbounds[j][1]-xbounds[j][0])*random.random()
            if self.position_i[j] < xbounds[j][0]:
               self.position_i[j]=xbounds[j][0]+(xbounds[j][1]-xbounds[j][0])*random.random()
class GA():
    def __init__(self, objfunct, startx0, xbounds, ptbmp=0.1, pmut=0.5, pcross=0.5, nparticles=50, maxiter=50000, verbose=False):
        obj_best_g=9e99
        position_best_g=[]
        swarm=[]
        x1vec=[]
        x2vec=[]
        nsubpop=0
        for _ in range(nparticles):
            swarm.append(PARTICLE(startx0,ptbmp,pmut,pcross,xbounds,verbose))
        it=0
        while it < maxiter:
            if verbose:
               print(f'iter: {it:>6d} best solution: {obj_best_g:16.8e}')
               if True and nparticles > 4:
                  print('lowest five')
                  abc=np.zeros(nparticles)
                  abcvec=np.zeros((nparticles,len(startx0)))
                  for i in range(nparticles):
                      abc[i]=swarm[i].obj_best_i
                      abcvec[i]=swarm[i].position_best_i
                  idx=abc.argsort()
                  abc=abc[idx]
                  abcvec=abcvec[idx,:]
                  print(abc[0],abc[1],abc[2],abc[3],abc[4])
                  print(abcvec[0,:])
                  print(abcvec[1,:])
                  print(abcvec[2,:])
                  print(abcvec[3,:])
                  print(abcvec[4,:])
            for i in range(nparticles):
                swarm[i].evaluate(objfunct)
                if swarm[i].obj_i < obj_best_g :
                   position_best_g=list(swarm[i].position_i)
                   obj_best_g=float(swarm[i].obj_i)
            for i in range(nparticles):
                i1=int(random.random()*nparticles) ; i2=int(random.random()*nparticles) ; k1=i2
                if swarm[i1].obj_best_i < swarm[i2].obj_best_i :
                   k1=i1
                for _ in range(nsubpop-1):
                    i1=int(random.random()*nparticles)
                    if swarm[i1].obj_best_i < swarm[k1].obj_best_i :
                       k1=i1
                i1=int(random.random()*nparticles) ; i2=int(random.random()*nparticles) ; k2=i2
                if swarm[i1].obj_best_i < swarm[i2].obj_best_i :
                   k2=i1
                for _ in range(nsubpop-1):
                    i1=int(random.random()*nparticles)
                    if swarm[i1].obj_best_i < swarm[k2].obj_best_i :
                       k2=i1
                x1vec=list(swarm[k1].position_best_i)
                x2vec=list(swarm[k2].position_best_i)
                swarm[i].update_mutationcrossover(x1vec,x2vec)
                swarm[i].update_position(xbounds)
            it+=1
        print('\nfinal solution:')
        print(f'   > {position_best_g}')
        print(f'   > {obj_best_g}\n')
        if True:
           abc=np.zeros(nparticles)
           abcvec=np.zeros((nparticles,len(startx0)))
           for i in range(nparticles):
               abc[i]=swarm[i].obj_best_i
               abcvec[i]=swarm[i].position_best_i
           idx=abc.argsort()
           abc=abc[idx]
           abcvec=abcvec[idx,:]
           for i in range(nparticles):
               print(abc[i])
               print(abcvec[i,:])

startx0=[]
xbounds=[]
for j in range(10):
    startx0.append(0.)
for j in range(len(startx0)):
    xbounds.append((-20., 20.))
GA(functuser, startx0, xbounds, ptbmp=0.1, pmut=0.5, pcross=0.5, nparticles=50, maxiter=50000, verbose=True)


---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------
geneticalgorithm · PyPI
import numpy as np
from geneticalgorithm import geneticalgorithm as ga
def f(X):    
    return np.sum(X)
varbound=np.array([[0,10]]*3)
model=ga(function=f,dimension=3,variable_type='real',variable_boundaries=varbound)
model.run()
---------------------------------------------------------------------------------------------------------------------

import numpy as np
import os
import os.path
from scipy.optimize import dual_annealing
from scipy.optimize import minimize
from scipy import optimize
def append_new_line(file_name, text_to_append):
    with open(file_name, "a+") as file_object:
        file_object.seek(0)
        data = file_object.read(100)
        if len(data) > 0:
            file_object.write("\n")
        file_object.write(text_to_append)
def append_multiple_lines(file_name, lines_to_append):
    with open(file_name, "a+") as file_object:
        appendEOL = False
        file_object.seek(0)
        data = file_object.read(100)
        if len(data) > 0:
            appendEOL = True
        for line in lines_to_append:
            if appendEOL == True:
                file_object.write("\n")
            else:
                appendEOL = True
            file_object.write(line)

lw = [-15.0] * 10
up = [15.0] * 10
if True:
   ret = dual_annealing(func, bounds=list(zip(lw, up)), seed=1234, maxiter=20)
if False:
   ret=optimize.differential_evolution(func, bounds=list(zip(lw, up)), maxiter=10)
if False:
   x0=[ 0. for i in range(10)]
   ret = minimize(func, x0, method='Nelder-Mead', tol=1e-6)
lines=[]
lines.append(str(ret.fun))
for i in range(len(ret.x)):
    lines.append(str(ret.x[i]))
append_multiple_lines('./OUTPUT', lines)

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

핑백

덧글

댓글 입력 영역

최근 포토로그



MathJax