개발 중단된지도 오래되었고, 현재 최신버전의 컴파일러에서 컴파일은 되지만 링크가 되지 않는 문제가 있다.
http://www.hyperdrifter.com/software/tutorial/compiling_galib_using_microsoft_visual_cpp.html
위의 링크에서 말하는대로 컴파일하면 링크이상없이 잘 수행되는 것을 확인할 수 있고,
첨부된 파일은 귀찮고 단지 library 파일만 쓰고싶은 사람을 위한 것이다.
어쩌면 대단히 중요한 일
처음 목표는 GA 의 연산과정중 Evaluation 만을 CUDA 로 수정하여 속도를 가속화시키는 것
그러나
이를 실제 코드로 구현하여 수행해 보았더니 생각보다 빠른 속도가 안나온다
그 이유인즉 CPU -> GPU 간 Memory Copy 연산 및 GPU 상의 Memory Allocation 때문인데, 다른 여러 논문에서 GPU 로 GA 를 수행할 때 속도가 증가되었다고 했던 것들을 검토해 보았더니 전부 GPU 상에서 모든 유전 연산을 수행하고 있었다.
분명 단일 연산만을 놓고 보았을 때는 GPU 상에서 Evaluation 을 한번 처리한 것이 가장 빠르지만, 유전 연산을 CPU 상에서 하게되면, 결국 Memory 할당과 복사를 반복하게 되어 속도가 느려지는 것이다. Evaluation 연산을 하기 위해서는 반드시 GPU 상의 메모리에 CPU 의 현재 상태를 복사해야 하니까 결국 이것때문에 반복적인 메모리 복사가 수행될 수 밖에 없는 것.
그렇다면 결론은 GPU 상에서 모든 연산을 처리하는 것인가?
뭐 중요한 요소중에 하나는 내 GPU 가 Geforce G105M 256M 이기 때문에 큰 메모리 할당도 어려울 뿐아니라, Stream Processor 수도 부족해서 제 속도 나오긴 어려울 수 밖에 없다는 건데...
동일한 실험 조건
static const int POPSIZE = 5000;
static const int MAXGENS = 100;
static const int ITERATION = 200;
static const int NVARS = 10;
GPU 상의 실험 결과(Geforce G105M 256MB)
Durations : 14118.000000 ms
CPU 상의 실험 결과(Intel Core2Duo P8600@2.4Ghz, 4 GB ram)
Durations : 10998 ms
다음엔 Geforce GTX270 876MB 에서 테스트 해볼 예정.
과연 어느정도 시점에서 Evaluation 작업만을 수행할 때 GPU 사용 작업이 속도가 대폭 상승할 수 있을 것인가?
GA 나 GP 와 같은 진화 알고리즘에서 무시할 수 없는 문제 중에 하나가 조기수렴 문제이다. 이를 해결 하기 위한 여러 가지 방법들이 제안되고 있으며, 대표적으로 유전 연산자의 조절, 선택 연산자의 조절, 군집 형태의 조절 등이 있다. 그 중에서도 다중의 군집 사용과 그것의 조절에 대해서 설명한다.
2. 다중 군집(Multi Population)
군집은 다수의 개체가 하나의 그룹으로 묶여있는 단위이다. 본래 GA 나 GP 에서는 단일의 군집을 사용하여 연산을 수행했었다. 그러나 단일 군집의 효율성을 증가 시키기 위해 군집을 여러 개로 나누어 사용하는 다중 군집 방식이 도입되기 시작했다. 초기에는 군집을 격리시켜 각각의 군집으로 분류해서 이를 발전시켜나가는 방식이 수행 되었으나, 후에는 이 군집들간의 몇몇 데이터를 서로 다른 군집으로 이동시켜서 이를 발전시켜 나가는 방식이 수행되곤 했다.
서로 다른 군집들간의 데이터가 어떤 원리에 의해 이동을 하는지에 따라 여러 가지 방식이 존재한다. 가장 기본적인 형태로 원형이주가 있고, 발전된 형태로 HFC 나 ALPS 와 같이 특정 조건에 의해 서로 다른 군집으로 격리 시키는 형태가 있다. 이 방식들은 전체적으로 알고리즘 자체의 조기수렴은 방지 하면서 최적해를 찾아가는 성능은 발전 시키는 방향을 염두로 설계한 방식들이다.
3. 원형 이주 방식(Ring Migration)
원형 이주 방식은 군집들 간의 데이터 이동 방향이 하나의 흐름을 가진다. 그리고 일정한 주기마다 특정 개체를 다음의 군집으로 이동시키는 방식이다. 이 때, 이동되는 개체들을 수용할 공간을 할당하는 방식과 이동 시킬 개체를 선택하는 방식의 조절이 가능하며, 이에 따라서 각기 다른 효과가 나타난다.
일반적으로 많이 쓰이는 방식은 가장 높은 적합도의 개체를 다음 군집의 가장 적합도가 낮은 개체로 대체 시키는 방식이고, 일반적으로 해당 군집의 10%의 개체를 변경하는 방식을 사용한다. 여기서 너무 많은 개체를 변경하는 방식을 사용할 경우 전체적으로 군집 전체가 비슷한 개체들로 수렴해버리는 현상이 나타나며, 이로 인해 오히려 더 빠르게 조기수렴하는 현상이 나타나는 경우도 있다.
4. 주입형 이주 방식(Injection Migration)
주입형 이주 방식은 여러 개의 개체군에서 최고의 적합도를 갖는 개체들이 한 군집으로 모여 경쟁을 하는 방식이다. 기본적인 원리는 가장 좋은 형질의 유전자들끼리의 교배를 통해 좀 더 좋은 결과를 기대하는 방식이지만, 여러 군집이 수렴될 경우에 오히려 비슷한 유전자들이 하나의 군집에 모이게 되어 조기에 수렴하는 결과가 나타나는 경우도 있다.
주입형 이주 방식도 원형 이주 방식과 같이 일정 주기에 약 10% 의 개체를 주입 받아 사용하는 것이 대부분이며, 단일 적합도 함수를 가진 경우보다는 다수의 적합도 함수를 갖는 경우에 주로 사용된다.
5. HFC(Hierarchical Fair Competition) (1)
HFC는 교육이론으로부터 파생된 군집의 교환 방식이다. 일반적인 교육 시스템은 같은 학년의 학생들, 즉 비슷한 수준의 학생들끼리의 경쟁을 모토로 한다. 그러나 일반적 진화연산의 경우에는 적합도가 높고 낮음에 관계 없이 모두 같은 환경에서 경쟁을 하게 된다. 이로 인해 적합도가 높은 개체만이 살아남고, 적합도가 낮은 개체가 비록 좋은 형질을 지녔더라도 이것이 보존되지 않는 현상이 발생한다.
HFC 에서는 이러한 불공정한 막기 위해 적합도에 따른 개체간의 분류가 이루어지고, 이를 이용해 적합도가 비슷한 개체들끼리만 공정한 경쟁을 하도록 한다. 이로 인해 조기수렴 효과가 억제되는 효과를 가지며, 적합도는 낮을 지라도 우수한 형질을 가지고 있는 개체들이 탈락되는 현상을 억제하는 효과를 가진다. 구체적인 알고리즘의 여러 가지의 파라미터 및 제한 요건은 아래에 정리되어 있다.
(*)HFC 모델의 구성요소
The Hierarchical Organization of Subpopulations to Establish a Fitness Gradient
낮은 적합도의 개체들은 낮은 레벨에 머무는 것을 허용한다.
낮은 적합도의 개체들은 더 낮은 레벨의 군집으로 이주할 수 있다.
허용 범위의 적합도 아래로 생성된 자손들은 해제시킬 수 있으며, 반복적으로 연산을 수행할 수 있다.
그들의 부모보다 낮은 적합도를 가진 생성된 어떠한 자손도 해제 당할 수 있다.
선택된 부모로부터 생성된 자손들은 적어도 한 부모의 적합도보다 높은 경우 생성될 수 있다.
Random Individual Generator : The Source of Genetic Material
최하위 레벨의 군집은 지속적으로 새로운 임의의 개체를 유입한다.
The Migration Policy from Lower to Higher Fitness Levels
몇몇 레벨의 군집에서 해당 군집의 허용 범위에 적합하며 이주되는 개체들은 몇몇의 적합도가 좋지 않은 개체들을 대체하게 된다.
만약에 허용된 버퍼로부터 개체가 이주된 후에 빈 공간이 생기게 되거나 혹은 그 허용 버퍼에 빈 공간이 생길 경우, 그것은 현재 멤버로부터 변이 연산을 수행하거나 두 개의 멤버를 크로스 오버 연산하여 필요한 만큼의 새로운 개체로 추가하거나, 더 낮은 레벨로부터 개체를 이주할 수 있다.(최 하위 레벨의 개체는 새롭게 생성하여 추가한다.)
이주는 오직 한 레벨에 대해서만 허용한다.
Setting the Parameters of the HFC Model
적합도 레벨의 개수,
각 레벨의 적합도 범위
6. ALPS(Age-Layered Population Structure) (2)
ALPS 는 HFC 와 비슷한 개념을 가지고 탄생한 알고리즘이다. ALPS 에서 공정한 경쟁의 요소로 사용되는 것은 개체의 나이가 된다. 여기서 나이란 해당 개체가 얼마나 오랜 시간 동안 진화가 되어 왔느냐를 의미하는 것이다. 즉, 비슷한 시간 동안 진화가 되어온 개체 들 간의 교배만을 허용하는 알고리즘이다.
마찬가지로 HFC 와 같이 조기수렴의 효과를 획기적으로 억제하는 효과를 보여주며, 특히 매우 어려운 문제에서 아주 오랜 세대에 걸쳐 진화연산을 수행할 때에 그 효과가 뛰어난 것으로 알려져 있다.

(*) 약 10만 세대까지는 비슷하지만, 그 세대수가 80만, 100만이 넘어서는 경우에는 확실한 성능차를 보여줌. ((2)참조)
이 ALPS 알고리즘의 구체적인 파라미터나 제한요소들은 아래에 정리되어 있다.
7. 정리
이주 방식 자체는 조기수렴의 감소를 타겟으로 계획된다. 어떤 특정 문제에 대해 연산 자체의 획기적 성능 개선이나 전체적인 리소스의 점유와 같은 것을 염두 하는 것이 아니다. 이주 방식은 오히려 어떠한 문제에서든지 연산 자체의 효율성을 극대화 시켜주는 것을 타겟으로 하기 때문에 범용적인 사회적 문제나 현상을 토대로 알고리즘 화 된 것이 많다. 그러므로 실제적인 문제의 해결에 있어서 문제의 성질에 따른 연산자의 선택이 가장 우선적이며, 그 연산자의 올바른 발전 양상을 유도할 수 있는 이주 방식의 설정은 부차적인 문제가 될 수 있다.
1. Jianjun Hu, Erik Goodman, Kisung Seo, Zhun Fan, Rondal Rosenberg The Hierarchical Fair Competition(HFC) Framework for Suitable Evolutionary Algorithms. Evolutionary Computation, 2005.
2. G. S. Hornby, "ALPS : The Age-Layered Population Structure for Reducing the Problem of Premature Convergence. " GECCO'06, pp. 815-822, July 8–12, 2006.
대단한건 아니지만;;
어쨌든,
(1) 조기수렴 문제?
조기수렴 문제의 해결에 대해서 연구를 좀 했습니다.
그러던 중에 나온 많은 알고리즘들,
적합도 공유방식(Fitness Sharing),
군중 분산 방식(?, 말이 좀 이상합니다만, 본래는 Crowding 방식입니다. 제 생각에 저 표현이 의미와 잘 부합되는것 같습니다.),
다중군집을 기반으로한 새로운 모델들(Multi-pop 을 기반으로한 HFC(Hierarchical Fair Competition) 혹은 ALPS(Age-Layered Population Structure))
이 있습니다.
우선 적합도 공유방식은 적합도가 높은 개체들이 적합도가 낮은 개체들에게 자신의 적합도를 나눠준다고 생각하면 간단합니다. 즉, 비슷한 수준의 적합도를 이용해서 다른 적합도 낮은 개체들도 선택될 확률을 높혀주는 것 입니다.
군중분산방식은 매 세대의 끝에 유저가 선택해준 갯수만큼의 개체를 주위의 개체들에 비해 개체의 본래 타입이 틀린 개체들로 강제적으로 대체시켜주는 방식입니다. 많은 다양성의 확보를 통해 본래의 수렴속도를 늦추는 것이 초점입니다.
다중 군집 기반으로한 모델들은 여러개의 군집으로 나눌때, HFC 같은 경우는 적합도를 기반으로하여 나누게 됩니다. 적합도가 높은 개체는 상위 군집, 낮은 개체를 하위 군집 등으로 분류를 하고 격리시킨후에 교배연산을 수행합니다. 기본 생각은 초등학생은 초등학생끼리, 대학생을 대학생끼리 경쟁을 시켜야 좋은 결과가 나오지 않겠냐 라는 것입니다. ALPS 는 개체들의 나이를 이용해 격리시켜서 교배연산을 수행 합니다. 마찬가지로 비슷한 연령대의 경쟁이 가장 효율적이지 않은가 라는 것에서 시작되었다고 보면 됩니다.
(2) HFC 모델의 단점
위와 같이 조기수렴 문제를 해결하기 위한 많은 방법들이 있습니다. 하지만 위의 방법들은 단점을 가지고 있습니다. HFC 의 다층 군집화 를 하나의 군집으로 만든 CHFC(Continuous HFC) 모델이 있습니다. 이 모델은 다층이 아닌 단일군집에서 HFC의 격리 수용모델을 구현 한 모델입니다. 성능이 기본적 알고리즘 보단 좋았지만, 다른 HFC모델에 비해서 뛰어난 성능을 보여주지는 못했습니다. 저는 그중에서도 위의 CHFC 모델을 타겟으로 잡고 개선을 시도했습니다. 그래서 우선 단점에 대해서 생각해 보았습니다.
첫번째 단점으로는 적합도만을 가지고 군집화를 이룬다는 것이라고 생각했습니다. 왜냐하면 만약에 적합도, 즉 해석된 상태의 결과물이 나쁜 결과를 갖고 있다고 해도 잠재적인 성능향상의 요소를 가지고 있을지도 모르는 것 입니다. 단일 군집에서는 완전 격리효과가 떨어지기 때문에 위의 잠재적 성능향상 요소를 잃게 될 확률이 높다고 생각했습니다.
둘째로는 일반적 세대형 알고리즘(Generational)에 있다고 생각했습니다. 일반적인 세대형 알고리즘이란 한 세대에서 다음 세대로 세대를 넘어갈때에 군집 전체가 바뀌는 것을 의미합니다. 이는 점진적 알고리즘(Steady-State) 에 비해서 수렴속도가 매우 빨라지는 것을 확인할 수 있습니다. 하나의 군집을 이용하는 CHFC의 경우에는 이것이 더 가속화 될 것이라고 판단 했습니다.
세번째로는 매우 큰 군집(여기서 군집이란 총 개체수를 의미합니다)을 가지고 있어야 한다는 것 입니다. 개체의 수가 적을 경우에는 상대적으로 다음 세대로 넘어갈때에 수렴이 급격히 일어나기 때문에, 일정수 이상(약 500~1000개 이상)의 개체를 확보하지 못할 경우에는 HFC나 CHFC 알고리즘의 지연효과가 거의 나타나지 않을 수가 있습니다.
(3) 퍼지추론 기반의 유전알고리즘 선택 연산자
그래서 퍼지추론을 이용해서 잠재적 성능향상이 있을수 있는 개체들을 골라내서 그들간의 경쟁을 유도해 보자는 게 제 의견입니다. 퍼지 추론은 여기서 데이터의 분류 방법이 됩니다. 즉, 기존의 HFC나 CHFC 등이 유도하는 군집화를 퍼지추론의 모호성을 통해 간접적으로 유도해 낼 수 있으며, 잠재적 성능향상이 가능할 법한 개체들에 대해 경쟁을 유도하기 때문에 기존의 알고리즘 보다 나은 성능을 보여 줄 것이라고 판단 했습니다.
하지만 퍼지 추론을 통해 나타난 결과로서 무조건적인 경쟁을 시킬 경우에는 마찬가지로 급격한 수렴을 보일수 있다고 생각했습니다. 그래서 임의의 개체풀 N 에서 몇개만 추려내서 경쟁시키는 방식을 이용 했습니다.
(4) 퍼지모델
간단한 간략추론 방식을 이용했습니다. 전반부 변수 2개는 적합도와 유사도, 후반부 변수 1개는 계층 으로 이용했으며, 멤버쉽 함수로는 가우시안 함수를 이용했습니다.
(5) 성능 및 결과
첨부해놓은 발표자료를 첨부해 보시면 됩니다. 전체적으로 이번에 제시한 연산자가 좋은 성능을 발휘한 것을 확인하실 수 있고, 다른 알고리즘 들에 비해서 더 높은 강인성을 가지고 있는 것을 확인하실 수 있습니다.
(6) 결론
이번 발표때 말씀드린 연산자는 퍼지추론 기반의 유전알고리즘 선택 연산자 입니다. 정확히 의도하고자 하는 것은 기존에 이용하던 적합도 단일 기반의 선택 연산자보다 거기에 다른 요소를 추가해서 기준으로 이용하게 되면, 기존의 다중군집 알고리즘의 효과를 얻을 수 있으면서, 좋은 결과를 도출시킬수 있다고 생각한 것 입니다. 결과적으로 당장의 논문에서 제시한 Deceptive문제에 대해서는 좋은 결과를 얻었습니다만, 문제가 다르게 될 경우에는 퍼지 함수의 조정이 이루어 져야 좋은 결과를 도출 시킬 수 있다고 판단합니다. 소수의 군집으로도 어려운 난이도의 문제를 해결할 수 있고, 구현자체도 어려운 편이 아니기 때문에 임베디드 시스템이나 로봇분야와 같이 제한된 리소스에서 결과를 내야하는 분야에 적용해보면 좋은 결과가 나오리라고 생각 합니다.
오늘은 실수최적화 문제에서 이용되는 CX 연산자중
지난번에 다루었던 Arithmetical Crossover[Michalewicz 1996] 의 변형판에 대해서 다루겠습니다.
기존 Arithmetical Crossover 의 특징에 대해 간략하게 알아보면
1. 적용이 쉽다.
매우 단순한 알고리즘으로 구성되어 있기 때문에 적용이 쉽습니다. 물론 random 으로 lambda 값을 산출해 내는 과정에 어떤 알고리즘을 적용시키느냐가 관건이 되지만( 사실 시간에 의한 난수값이 출력되는 것은 신뢰도나 정확도면에서 그다지 높지 않기때문에 다른 알고리즘에서는 잘 쓰이지 않는 경향이 있습니다. ) 그 부분에 대해서만 제외한다면, 서로의 Chrom 값에 lambda 값의 곱과 1- lambda 값의 곱만으로 새로운 Individual 을 만들어 낼 수 있습니다. 이런 면에서 Arithmetical CX 는 적용이 매우 쉬운 CX 연산자 임을 알 수 있습니다.
2. Local Search 에 적합한 연산자
다음 글에서 Local Search 와 Global Search 에 대해서 자세히 알아볼 것이지만, 우선 Local Search 라는 것은 값 자체를 크게 변화없이 조금조금씩 변화시킴으로써 올바른 값으로 수렴해 나가는 원리 입니다. 그렇기에 Local Search 에 적합한 변모를 보이고 있고, 조기 수렴하는 경향을 보이게 됩니다.
3. Individual 전체를 변화시키는 연산자
Artithmetical CX 는 Individual 전체를 변화시키게 됩니다. 일부만을 변화시키는 것이 아니라 모든 Chrom 에 걸쳐 연산이 이루어 지기 때문에 Individual 전체를 변화시킵니다. 이는 초기에 전체적으로 좋은 변화를 이끌어 낼 수 있지만, 실제 이상적인 값에 도달하기 위해서 일부분만을 수정하게 되는 일에 약한 면모를 보이기 때문에 정밀한 최적화 작업에는 적합하지 않음을 의미합니다.
위의 특징을 살펴보시면 아시겠지만, Arithmetical CX 는 초보적인 알고리즘이고, 구현이 쉽고 적당한 결과값을 알아내는 데에 적합합니다. 고로 매우 정교한 작업에는 적합하지 않음을 알 수 있습니다. 하지만 잘 생각해보시면 Individual 전체가 변화하는 문제 때문에 최적화가 거의다 끝날무렵에 미묘한 변화치에 대한 것들을 제대로 캐치하지 못함을 알 수 있습니다. 이런 특징적인 면을 개선시켜서 나온 연산자가 바로 오늘 설명할 수정단순교배(Modified Simple Crossover) 입니다.
-- 사실 이 연산자는 유전알고리즘과 그 응용(진 강규 저) 에도 소개되어 있기에 저작권 문제도 있을 것 같고 해서 제가 소개하기가 조금 껄끄러운게 사실입니다. 저자 이신 진 강규님께서 2000년 도에 직접 작업하신 연산자 인 것 같습니다. 그렇기에 자세한 설명에 대한 것은 위의 책을 참고하시거나 진 강규님의 논문을 참고하시는 것이 좋을 것 같습니다. 저는 개략적인 설명만을 해보겠습니다. --
오랜만에 GA 관련 포스팅 입니다.
예전에 한번 설명 드렸지만, GA 는 원래 Bit 형태의 유전자를 이용해서 연산을 하게 됩니다.
이 Bit 형태의 유전자를 이용해서 연산을 하게 되면,
Bit -> Real Number -> Bit 의 변환과정을 거쳐서 적합도평가(Fitness Evaluation)가 이루어집니다.
결과적으로 변환 과정의 해상도(Bit 의 갯수를 얼마나 더 확장시키는지)가 성능에 어느정도 영향을 미치는 꼴이 됩니다. 이 문제에 대해 간단한 예제로 설명하자면 밑의 More 부분을 클릭하시면 됩니다.
---------------------More------------------------
Object-Oriented Foundations:
Open BEAGLE generic EA framework:
GA framework (linear representations):
GP framework:
Co-evolution framework:
두껍게 표시해 놓은 부분이 제가 생각하기에 다른 알고리즘에 비해서 뛰어나다고 할 수 있는 기능들 입니다.
이중에 Generational, steady-state 의 두가지 기능은 그 두가지 알고리즘의 성능차이에 대한 측면에서도 매우 좋은 기능으로 보입니다. 하지만 워낙에 많은 기능이 지원되어 있기때문에 양 자체도 방대하고 소스를 파악하기가 조금 힘들고, 다른 프로그램과 서로 링크시키는 것이 힘들기 때문에 저는 개인적으로 별로 선호하지 않습니다.
2. ECJ(http://cs.gmu.edu/~eclab/projects/ecj/)
ECJ는 이 분야에서 매우 유명한 분이신 Sean Luke 씨가 있는 그룹에서 만든 EC 엔진 입니다.
특징적인 것은 Java 를 베이스로 만들어졌다는 것이고, 그렇기 때문에 플랫폼에 종속적이지 않은 형태로 어느 플랫폼에서든 이용할 수 있다는 것 입니다.
밑의 표는 위의 홈페이지에서 발췌 했습니다.
General Features
|
GP Features
|
GALOPPS extends the SGA capabilities several fold:
GA 에서 만약 우리가 어떤 새로운 방식의 CX 나 MUT 혹은 기타 MultiPOP 의 이주계획을 만들었다고 가정해봅시다.
하지만 우리는 이 알고리즘이 이전의 알고리즘에 비해 어느정도의 개선 정도를 갖고 있는지 혹은 어려운 문제를 풀어갈 수 있는 능력이 있는지에 대한 여부를 알 수가 없습니다.
어디까지나 이런점에서 더 개선된 성능을 보여줄 것이라고 추측을 하는 것입니다.
하지만 우리는 그것의 성능여부를 증명을 해야 겠죠?
그렇기 때문에 여러가지 수학적인 복잡한 문제들이 나를 GA 혹은 기타 알고리즘으로 풀어달라고 기다리고 있습니다.
GA 에 대해 조금 공부를 하신분들은 De jong 의 Test Problem 에 대해서 들어보셨을 것입니다. 이것은 확장이 가능한 문제로서 문제 자체를 아주 어려운 고급의 문제로 확장이 가능한 문제입니다. 하지만 이 문제는 수학적인 문제이기 때문에 구현이 까다롭습니다.
제가 여기서 말하려고 하는 것은 Deceptive Problem 입니다. 이 문제들은 구현 자체도 간단하고 확장 또한 아주 쉽습니다. 그리고 알고리즘 자체가 지역극소점에 빠지는 현상을 유도적으로 만들어 냅니다. 하지만 영리한 알고리즘은 그것을 피해가는 경향을 나타나게되고 최종적으로 해답을 만들어 내게 됩니다.
가장 간단한 f3deceptive 에 대해서 살펴보면 다음과 같습니다.
3비트를 한 묶음으로 보고 하나의 Problem 단위로 생각을 합니다. 조건식은 다음과 같습니다.
000 = 0.9
001 = 0.8
011 = 0
111 = 1
이것이 끝입니다..... 뒤에 적힌 수치는 Fitness 의 값입니다.
만약 0 이 3개 있을경우 0.9 의 Fitness 값을 반환하고, 0 이 2개 있을 경우 0.8, 1개는 0, 그리고 1이 3개가 있을 경우에는 1 의 Fitness 값을 반환하게 됩니다.
이것은 알고리즘 자체가 해답을 0으로 몰고나아가게 되는 현상을 유도하게 됩니다. 111이 분명 최고의 Fitness 값을 지닌 해답이지만, 0이 많아 질수록 Fitness 값이 좋아지는 현상을 보여주기 때문에 알고리즘이 0을 해답으로 생각하고 모든 비트가 0으로 수렴하게 되는 지역 극소에 빠질 확률이 매우 높아집니다. 알고리즘의 성능이 좋다면 짧은 시간 내에 111 을 찾아내는 것입니다.
사실 이걸 1 Problem 에서 본다면 아주 쉬운 문제지요. 하지만 이 문제는 확장가능한 문제이기에 자주 쓰입니다. 보통 200~300 Problem 정도를 해결하려고 하면 정말 좋은 알고리즘의 경우에 10만 Evaluation(1) 정도에 해결하게 됩니다.
오늘은 갑자기 벤치마크 문제에 대해 다뤘기 때문에 기존에 정리하지 않았던 말들도 쓰이고 난잡한 면이 조금 보입니다. 하지만 벤치마크 문제에 대해 논한 것은 기본적인 것에 대해서는 전부 정리를 했다고 판단되기 때문입니다.
다음 번에는 SGA (Simple Genetic Algorithm) 에 f3deceptive 를 구현한 것을 Source 와 함께 정리해 보도록 하겠습니다. 또 다음번 글을 언제 쓸지는 모르겠지만 -_-;;; 최대한 빨리 정리하도록 하겠습니다.
(1) Evaluation -> GA가 몇번이나 Fitness 값을 계산했는지를 기록하는 변수
몇가지 용어에 대해서 정리해 보도록 하겠습니다.
사실 GA 에서는 크게 2가지의 알고리즘으로 나뉘어 있고
흐름에 의한 알고리즘 자체의 차이가 있을뿐이지
용어에 대해서는 차이가 없습니다.
하지만 GA 를 구현한 프로그램들마다
용어자체에 약간의 차이를 두고 구현되어 있는 경우가 있습니다.
그에 대해서 한번 생각해 보기 위해 용어에 대해 정리해 보는 것입니다.
가장 하위계층의 개체부터 개체의 조합. 그리고 연산자까지 정리해보도록 하겠습니다.
먼저 하나의 개체는 일반적으로 다음과 같이 되어 있습니다.
Chromosome - 유전자표현
Fitness - 적합도
OBJ(x) - 유전자표현을 10진수로 변환한것, 다른형태로 표현하기도 합니다.
parent1 -
parent2 - parent1과 2는 현재의 개체가 Crossover로 부터 다시 생성되었을 때
이 두 개체의 부모개체가 되는 유전자의 번호입니다.
일반적으로 하나의 개체를 표현하는데에 저 다섯가지의 요소로서 구성됩니다.
저 개체는 Individual 이라고 표현하고 개체라고 합니다.
Individual < Population < Multi-population
이런식으로 되어 있습니다.
각각의 Individual 이 모인 집합을 Population 이라고 하고
Population 이 모인 집합을 Multi-population 이라고 합니다.
Multi-population 에 대해서는 나중에 소개를 하겠지만
대부분의 실제 알고리즘에서는 다수의 Population 을 이용해서
서로간의 연산 알고리즘이 이루어 집니다.
복잡해지는 관계로 다음에 추후 이야기 하겠습니다.
그리고 연산자에 대해서 간단히 용어정리를 하겠습니다.
CX = Crossover 를 의미하는 것입니다.
제가 지난번에 Crossover 연산에 대해 간략하게 소개 했습니다.
그런 식으로 이루어지는 일련의 연산들을 Crossover 라고 합니다.
더 자세하게는 다음에 소개하겠습니다.
MUT = Mutation 을 의미합니다.
역시 마찬가지로 다음에 소개 하겠습니다.
(소개할 내용이 무지하게 많습니다;;)
SELECT = 말그대로 선택 연산자입니다.
INV = Inversion , 역위 연산자 입니다. 거의 쓰지 않습니다만
몇몇 알고리즘에서는 여전히 이용합니다. 역시 나중에 설명하겠습니다.
사실 이 외에도 엄청나게 다양한 용어의 정리가 필요합니다.
하지만 가장 기본이 되는 저 틀은 거의 변하지 않습니다.
다음번에는 CX 연산자들에 대해서 소개하겠습니다.
몇회에 걸쳐서 소개해 보겠습니다.
오늘은 GA 의 간단한 예제에 대해서 올려봅니다.
우선 하나의 가정을 하죠.
다음과 같은 수식이 있고 그것의 범위를 다음과 같이 할당해 줍니다.
우리는 이 수식의 최대값을 알아내려고 하는 것입니다.
y = x^2 - 2*x + 4
x = [ -10 , 10 ]
이렇다고 가정을 해보는 것입니다.
위 문제는 누구라도 간단하게 구할수 있는 문제이지만 그냥 하나의 예로서 들어본 것입니다.
그렇다면 GA 의 흐름에서 이 문제를 어떤 식으로 풀어나가는지 알아보도록 하죠.
우리는 GA 연산에서 쓰일 몇가지 구체적인 변수에 대해 설정을 해 줘야 합니다.
우선 GA 에서 초기화에 몇가지의 개체를 이용할 것인지 설정해 줘야 하고,
몇개의 비트로서 그 개체에 대해 표현을 할지도 결정을 해 줘야 합니다.
어느정도 확률로서 Crossover 와 Mutation 연산을 수행하게 할지도 설정을 해 줘야 합니다.
그리고 몇 세대 정도 계산을 해 나갈지에 대해서도 설정을 해야 하죠
우선 초기 개체의 수를 설정을 합니다. 5개로 가정을 하고,
그리고 하나의 개체는 5개의 비트를 이용한다고 가정해 봅시다.
Crossover 와 Mutation 확률 90% 와 10%로 각각 설정을 한다고 가정 하죠.
그리고 5세대만 진행한다고 가정을 해 봅시다.
------------------------------------------------------------------------------------
먼저 여기서 설명드릴게 하나 있는데
5개의 비트를 이용해서 하나의 개체를 만들었는데,
그 개체를 x 의 범위에 한정 시킨 10진수로 변환을 해야 한다는 문제가 있습니다.
이 문제는 일반적으로 다음과 같은 방법으로 해결합니다.
(Max - Min ) * (x의 개체를 10진수로 변환한것 / (2^개체의 비트수) - 1 ) + Min
이런방식으로 해결을 합니다.
만약 지금과같이 5개의 비트로서 Max값이 10이고 Min 값이 -10 이고
x 가 11111 이 나왔다고 가정을 하죠. 그럼 이것을 10진수로 바꾸면 31이 됩니다.
(10 - -10 ) * ( 31 / 2^5 -1 =31 ) - 10
이라고 한다면 20 * ( 1 ) - 10 으로 최대값 10이 나오게 됩니다.
------------------------------------------------------------------------------------
다음과 같이 초기 개체가 생성 되었다고 가정을 해 보죠
1. 10101 ==> 21 ==> 3.5484
2. 11000 ==> 24 ==> 5.4839
3. 00010 ==> 2 ==> -8.7097
4. 00101 ==> 5 ==> -6.7742
5. 10001 ==> 17 ==> 0.96774
원래개체 ==> 10진수로 변환 ==> -10~10의 범위 한정
그리고 이것에 대해 위에서 설명드린 10진수로의 변환을 거친 후,
평가의 작업을 하게 됩니다.
위의 우리가 가정한 y의 방정식인 x^2 - 2*x + 4 에 대입을 하면
1. 9.4943
2. 23.1054
3. 97.2783
4. 63.4382
5. 3.0010
이 값을 각 개체의 Fitness(적합도) 값으로 갖게 되는 것입니다.
그리고 우리는 이 값을 토대로 선택의 작업을 하게 됩니다.
균등한 선택을 이용한다고 가정하면 각각의 개체들은 2번정도로 거의 동등한 선택을 받게됩니다. 거의 2번이라고 한다는 것은 3번이 선택될수도 있고 1번이 선택될수도 있기 때문입니다.
어디까지나 랜덤한 확률에 의한 선택이기 때문입니다.
우선 편하게 1,2 2,4 4,5 가 Crossover 에 이용되었다고하고 3번이 Mutation 되었다고 합시다.
그렇다면 Crossover 연산이 이루어지게 되는데 이연산은 각각의 개체들을 서로 교배시킨다고 말씀 드렸습니다. 이 연산에도 많은 방식이 있는데 우선 One Point Crossover 를 이용한다고 해보죠. 이것은 다음과 같은 방식의 연산입니다. 자세한 것은 추후 설명 하겠습니다.
현재 1,2 번 개체가 선택 되었고, 만약 Crossover Point 를 4번이라고 잡았다고 합시다.
Crossover Point 라는 것은 그 위치에서부터 뒤에있는 모든 비트에 대해 서로 교배를 하겠다는 것입니다.
그러므로 1,2 번 개체는 10101 과 11000 이었으므로 다음과 같이 계산이 되게 됩니다.
1 0 1 0 1
| | <--- 두 개체의 교환.
1 1 0 0 0
1번은 10100 2번은 11001 이런식으로 형태가 변하게 되는 것입니다.
그리고 뒤이어 2,4 4,5 번에 대해서도 연산을 수행하게 되면 각각 다음과 같이 됩니다.
2번 11001 4번 00101 --> 변환후 2번 11001 4번 00101
4번 00101 5번 10001 --> 변환후 4번 00101 5번 10001
그렇게 Crossover 연산이 끝난 후에는 각각의 유전자는 다음과 같은 형태를 지니게 됩니다.
1. 10100
2. 11001
3. 00010
4. 00101
5. 10001
이제 Mutation 연산을 수행하게 됩니다. 여기서는 3번에 대해 4번째 비트가 Mutation 되었다고 가정 합니다.
00010 --> 00000 이런식으로 선택된 비트를 반전시켜 버리는 것입니다.
결국 한세대의 연산이 모두 끝난후에 유전자는 다음과 같이 바뀌었습니다.
1. 10100 ==> 2.9032
2. 11001 ==> 6.1290
3. 00000 ==> -10
4. 00101 ==> -6.7742
5. 10001 ==> 0.96774
그리고 이 유전자에 대해 재 평가 작업이 이루어지게 됩니다.
결론적으로
1. 6.6222
2. 29.3066
3. 124
4. 63.4382
5. 3.0010
이런 Fitness 값을 갖게 되고 GA 는 결과적으로 x 값 -10 y 값 124 의 최대값에 도달했습니다.
GA 의 알고리즘은 이와 같은 방식으로 수행이 되는 것입니다.
각각의 연산자들은 매우 많은 종류가 있고
여기서는 가장 기본적인 연산자들에 대해서만 예제를 수행했습니다.
내일은 용어에 대해서 정리를 해보겠습니다.
각 알고리즘의 형태마다 쓰이는 용어가 조금씩 차이를 보이기때문에
조금은 정리해볼 필요가 있습니다.
P.S 제가 이런것을 하는데는 제 개인이 배운것에 대한 정리도 하는 것이고
다른 사람들로부터 제가 잘못 알고 있거나 틀린것에 대해서 알고자 하는 것도 있습니다.
GA 는 하나의 알고리즘으로서 기본적으로 다음과 같은 순서로 동작합니다.
(여기서 설명하는 것은 일반적인 알고리즘이고 변형된 알고리즘으로서 Steady-State 알고리즘이 있습니다.)
1. 초기화(Initialize)
유전자 개체를 초기화 합니다.
임의로 지정한 수치 만큼의 유전자를 생성해 내는 것입니다.
2. 평가(Evaluate)
위에 생성된 유전자 개체에 대해 평가를 합니다.
평가의 기준은 사용자가 만드는 것입니다.
생성된 유전자가 문제에 어느정도 적합한 유전자 인지 평가하는 것입니다.
3. 반복(Loop)
여기서 부터는 몇가지 반복작업이 계속 이루어 집니다.
반복이 멈추는 조건은 사용자가 지정한 최대 세대수[1]에 도달하거나
사용자가 지정한 최대조건에 도달 했을 경우 입니다.
멈추지 않을경우 밑에 작업을 순서대로 반복 수행 하게 됩니다.
(1) 선택(Selection)
선택도 하나의 연산입니다.
여러가지 방식이 있으며 가장 평가가 좋은 유전자를 선택할 수도 있습니다.
아니면 랜덤하게 선택할 수도 있는 것입니다.
문제에 맞게 선택연산자를 선택해 주면 됩니다.
여기서 선택된 유전자는 다음의 교배, 돌연변이 연산자에 이용 됩니다.
(2) 교배(Crossover)
유전자 알고리즘의 가장 핵심이 되는 부분이라고 할 수 있습니다.
각각의 선택된 유전자 개체에 대해 교배가 이루어 지는 부분입니다.
유전자의 일부분을 다른 상대방 유전자의 일부분과 교체 하는 등의 연산입니다.
이것을 통해 개선이 이루어질 수 있습니다. 물론 성능이 떨어질 수도 있죠.
대부분의 연산은 이것을 통해 이루어 집니다.
(3) 돌연변이(Mutation)
돌연변이 연산은 유전자의 일부분을 임의대로 변경해버리는 것입니다.
교배와 다른점이라면 교배는 한 쌍의 유전자를 서로 교체 하는 등 같이 연산되는 것이지만
이것은 하나의 유전자의 일부분을 랜덤하게 교체시켜 버리는 것입니다.
그것으로서 유전자가 파괴될수도 있지만 의외로 좋은 유전자가 될수도 있기때문에
아주 적은 확률로서 이루어지게 합니다.
(4) 재조합(Recombination)
이것은 위의 교배와 돌연변이의 연산자로서 새로 변경된 유전자들을 모아서 새로운 세대를
생성하는 것입니다. 이것이 이루어지면 한 세대가 지났다고 할 수 있습니다.
(5) 평가(Evaluate)
다시 평가 작업입니다. 새로 교배와 돌연변이를 통해 생성된 유전자를 평가하는 것입니다.
유전자의 성능의 개선여부에 대해 확인할 수 있습니다.
(6) 통계(Statistics)
평가가 이루어진 유전자에 대한 통계를 냅니다.
주로 개체의 최대,최소,평균 성능에 대해 통계를 냅니다.
위와 같은 반복적 작업을 통해 개체의 상태를 개선시켜 나가고 문제의 해답을 알아내는 알고리즘이 GA 입니다.
최대한 수학적인 요소는 제거하고 가장 간단한 상태의 GA 에 대해 설명했습니다. 내일은 간단한 예에 대해 올려보도록 하겠습니다.