파이썬으로 고성능의? 아니 병렬화된 어떤 코드를 개발할 때, 항상 걸림돌이 되는 요소가 GIL(Global Interpreter Lock) 이다. ML 관련된 다양한 일들을 하면서, 파이썬이 상당히 각광받고 있는 것도 사실이지만, 반대로 이걸로 서비스를 개발하려고하면, 당면할 수 밖에 없는 문제가 바로 GIL 이다. 

어? 근데 파이썬도 스레드를 지원하잖아요? 라고 묻는다면, 그 스레드가 여러개가 동시에 동작하더라도, 결국엔 하나의 스레드만 파이썬 오브젝트에 접근할 수 밖에 없기 때문에, 사실상 Single-threaded 프로그램과 다를 바 없으며, 그래서 원한만큼 효율을 높이는 데에는 한계가 있음을 알 수 있다. 이러한 특징으로 파이썬에서는 병렬화된 프로그래밍을 한다고 하면, 프로세스를 늘리는 형태로 만드는 것이 일반적이라 할 수 있고, 특히나 Django 나 Flask 같은 웹서버는 ASGI 같은 미들웨어와 함께 운용되는 것을 볼 수 있다.

참 아쉬운건 그래서 왜 GIL 이 적용되냐 라는 건데, 이 부분이 일반적으로는 파이썬의 구현체인 CPython 에서 내부적으로 Thread-safety 하지 않기 때문이라고 알려져 있다. 이게 결국엔 메모리 관리 방식에 있어서 Reference Counting 으로 인한 것이 같은데, 내부적으로 언젠간 이에 대한 변수들의 관리를 mutex 와 같은 것들을 atomic 이나 다른 것들로 바꾼다면 좋아질 것 같다는 생각도 든다.

문제라면, 파이썬의 개발 주체들이 이야기 하듯, 변수 관리에 대한 다른 방법들을 적용했을 때, 다중 스레드가 아닌 싱글 스레드의 성능 저하가 발생하지 않는 방법이 있다면, 그 개선안을 받아들이고 진행할 거라고 했었던 것 같다. 정확한 레퍼런스는 찾아봐야겠는데, 하도 오래된 기억들이라... 이게 아마 2007년? 8년? 이었던 것 같은데... 아마도 누구나 예상하듯, 그런 방안은 아직은 없다. 거의 저하가 없어 보이는 그런 방법들은 일부 있지만, 구현 복잡도나 관리 복잡도 측면에서 범용화시키기 어려운 부분이 있다. 그로 인하여 사실 파이썬은 여전히 그 넓은 사용성과 편의성에도 불구하고, 고성능에는 어울리지 않는다는 생각이 많이 든다.

Pytorch 도 TF-serving 도 그런 측면에서 serving 툴은 c++, java 같은 언어들을 활용하는 것이겠지만, 한편으로는 아쉬운 생각이 든다.

꽤나 오랜만에 글을 쓰는 것 같은데, 참 오랫동안 ML 관련된 일을 하고 있다. 개인적으로는 backend, bigdata 관련 개발자이기도 하고, ML 을 오랫동안 하고 있다는 것 때문에 최근에 많이 요구하는 일들 중 하나가 serving 이다.  

serving 이 뭔데? 라고 물으신다면, scikit-learn/tensorflow/pytorch/mxnet 등등.. 다양한 ML 로 만들어진 Model을 서비스로 제공하는 방법을 말한다.

사실 scikit-learn 같은 경우엔 별 문제가 없다. scikit-learn 은 좀 헤비하다고 해도, 가벼운 수준이라 flask 같은 걸로 api 만들고, call 하면 그만이고, GPU 자원을 사용하는 것들도 없거나, 적어서 flask 만을 사용해도 별 무리가 없다. Tensorflow 도 마찬가지로 tf-serving 같은 것을 제공하기 때문에, model 에 대한 개발을 하고 있는 사람들이라면 큰 부담없이(?) serving 을 진행할 수 있다. 

근데, 참 곤란한게 pytorch 다. 아무래도 그간 research 에 대한 지원에 집중하였기 때문에, production level 로 넘어가는 데 있어서 tf-serving 같은 기능들이 없고, flask 로 만드는 model deployment 정도 샘플이 전부였는데, 이걸로 서비스 한다고하면, 솔직히 웃음밖에 안나온다.

왜냐면, CPU 만 사용하여 inference 를 한다면 그나마 별 문제는 없는데, 보통 속도 문제로 GPU를 필히 사용한다. 이 경우, 뒷단에서의 I/O 를 처리하는 것과 그 데이터가 도착하고나서 GPU 자원을 Sharing 하는 부분/Batching 처리/Queueing 등을 구현하기가 생각보다 까다롭다. 게다가 python 에서는 무조건 발목잡는 GIL 이 있기 때문에, 이걸 피하려고 하는 다양한 방법들을 생각해야 하는 것도 영 거지같다. 그리고 GPU 메모리 관리 측면에서 flask 같은 곳에서 여러개의 input 이 동시에 들어갈 때, pytorch가 동적으로 input 을 여러 개를 잡으려고 하면, 그만큼 GPU 메모리를 더 잡으려고 하다가 exception 이 발생하거나 그런 부분들이 영 핸들링하기가 어렵다.

그래서 다양한 방법들을 고민 했었는데, 비동기식 io/aiohttp 를 활용한 컨셉으로 고민한 [1]과 같은 훌륭한! 코드도 공유되어 있는 그런 자료도 있고, 이는 실제로 꽤 훌륭하게 동작한다. 물론 Batching 관련해서 문제가 있긴 하지만, 그런건 개인이 알아서 처리하는게 맞다고 본다. 어쨌든 대부분 Pytorch 가 이제 Research 측면에서 워낙에 대세가 되어 가고 있으니 많은 연구/개발이 진행되고 있긴 하지만, 결국엔 Pytorch 는 강력한 경쟁자(?)인 tensorflow 가 제공하는 tf-serving 의 편의성, 안정성 등이 그립다보니, pytorch 를 production level 에서 쓰는게 맞나 라는 고민이 계속 드는게 사실이다. 

하지만 역시 pytorch 도 마찬가지로 torchserve 를 들고 나왔다. 

https://pytorch.org/serve/

 

TorchServe — PyTorch/Serve master documentation

Shortcuts

pytorch.org

근데 한번 전체적으로 코드를 훑어봤는데, 아직은 많은 부분이 부족해 보인다. 왜냐하면 backend pipeline 만 flask 에서 java based 로 변경된 듯한 느낌이고, 본인들의 가속엔진인 torchscript 는 아직 미활용 상태라고 보는게 맞는 것 같다. tf-serving 에서 제공하는 여러 기능 중, model archive 라던가 이런것의 기초적인 상태를 제공하고 있는 것 같고, 어떤 방향으로 발전시킬 지는 모르겠지만, tf-serving 의 기능을 최대한 다 흡수했으면 좋겠고, 그보다 더 발전된 방향을 보여줬으면 좋겠다. 지금 코드 내부의 내용들이 S3 등 cloud 에 꽤 친숙한 사용을 위한 기능들 위주로 먼저 깊이있게 개발이 스타트 되는 것처럼 보이는데, 개인적으로는 On-premise 타겟으로 먼저 좀 챙겨주는게 좋지 않나 싶다. GPU Instance 솔직히 너무 비싸서... 

컨트리뷰터를 하나씩 살펴보니 이해가 간다. AWS 쪽에서 만든 Multi-model-server 를 이쪽으로 가져오고 있는 것 같고, 대부분이 AWS 관련자들인 것 같으니 이럴 수 밖에.. ㅎㅎ 방향은 잘 모르겠지만, 어쨌든 또 하나의 좋은 툴이 개발되고 있는 건 바람직한 일인 것 같다.

 

[1] https://medium.com/@ngoodger_7766/fast-gpu-based-pytorch-model-serving-in-100-lines-of-python-ed0fabd8cffb

P.S. 개인적으론 참 즐거운 시대가 왔다. ML 관련된 study 를 십여년간 해오고 있는데, 최근에는 EA 관련된 기술들도 인정받고 있다는 것이 감격스럽기도 하고, 한편으로는 두렵기도 하다. Resource 독점의 시대가 오고 있다는 생각도 들어서...

  kalman filter는 대부분 잘 알고 있고, 대단히 많은 내용들이 알려져 있기 때문에 핵심이 되는 내용 몇 가지 내용만 기록해두려 한다.  wiki 나 다른 자료들을 보면, kalman filter가 prediction과 update라는 두 개의 흐름 구조를 갖고 있는 것을 쉽게 알 수 있다. 대체 prediction 과 update 는 어떤 원리를 기본으로 두고 하게 되는 것인가? 


1. gaussian

  kalman filter 의 update 는 bayes rule 을 기본으로 product 의 성질을 갖고 있다. 또한, prediction 은 convolution 연산에 해당(사실상 덧셈)하며, total probability 을 계산한다. 사실 이렇게 말로 써놓으면 뭔 말인가 싶은데, 그림으로 가볍게 살펴보면 그렇게 어렵지 않다. (물론, 개념적인 부분만 한정해서 그렇다.)


  여기 그렇게 많이 보던 gaussian 이다.  평균 μ 와 편차 σ 를 따르는 gaussian 함수는 상기의 수식과 같이 정의된다. 다들 알고 있는 바와 같이 대부분의 자연 현상을 모델링 하는데 있어서 가장 많이 사용하는 함수로 알려져 있다. kalman filter 는 gaussian 을 다루는 filter 라고 할 수 있는데, 대체 prediction 과 update 는 gaussian 과 무슨 상관이란 말인가?


  prediction 과 update 중 우선 update 를 살펴보면, 엄밀히 말하면, measurement update 인데, 위의 그림과 같이 구성되어 있다. 풀어서 설명을 하자면 prior p(x) 는 이전에 알고 있는 사전 지식에 해당한다고 생각하면 되고, measurement p(z|x) 는 센서로부터 취득된 데이터라고 생각하면 된다. 그리고 updated results 는 이러한 취득된 데이터로부터 갱신해 나가게 되는 새로운 확률분포 x 에 해당하는데, p(x|z) 를 계산하는데 bayes rule이 적용된다. 아래의 μ' 과 σ' 은 수식적으로 계산하는 부분을 정리했을 뿐이다. 즉, update 부분은 어떤 센서로부터 측정된 데이터를 알고자 하는 사전지식에 업데이트하기 위해 확률 분포를 정의하는 부분에 해당한다.


  prediction 은 그럼 무엇일까? prediction 은 더 단순하고 간단한데, 이미 알고 있던 확률 분포에 다른 확률분포를 합산하여 새로운 값으로 갱신하는 역할을 한다. 즉, total probability 의 개념이 적용되며, convolution(addition) 연산이 내부적으로 사용된다. 

  정리하자면, 결국 kalman filter의 풀이 방식을 보면 bayes rule을 기본으로 활용하고, 측정된 값을 토대로 예측하기 위한 확률 분포를 정의하고, 기존에 있던 값을 의미하는 확률 분포에 더하여 새로운 확률 분포 값으로 갱신해준다고 할 수 있다.

  그리고 위의 지식을 바탕으로 다시 해석해보자면, kalman filter 는 system 의 model 을 정의 했을 때, 그 모델의 노이즈나 에러에 해당하는 term 이  gaussian distribution 을 가진다고 가정하고, 위에 기반한 방식으로 system 에 발생하는 노이즈나 에러를 최소화 하는 형태로 시스템을 update 할 수 있다는 것이다. 그로 인해서 우리가 센서자체가 갖고 있는 노이즈들을 핸들링 하고, 더 정교한 tracking/estimation 등이 가능하다는 것인데... 얼마나 놀라운 일인가? 여기까지 공감이 간다면 kalman filter 는 대강 감이 올 것 같다.

  그리고 extended kalman filter 나 unscented kalman filter 나 결국 다 kalman filter 이기 때문에 같은 구조를 가지고 있다. 그런데 대체 왜 다른 형태로 정의된 3가지 kalman filter 가 있는 것일까?


2. modelling

  결국 kalman filter 에서 extended kalman filter, 그리고 unscented kalman filter 에 이르기까지 새로운 형태의 kalman filter 가 만들어지게 된 이유는 이 모델링 때문이다. 우리가 state transition equation 과 measurement equation 을 정의할 때, 부득이하게 non-linear term 이 발생하고, 여기서 이것을 handling 하기 위해 미분하여 jacobian 을 핸들링하게 되면, extended kalman filter 가 정의된다.

  조금 더 자세히 말하자면, system 의 특성을 볼 때, 특정 구간에서 linearization 을 통해 문제를 해결할 수 있다면, non-linear function 을 taylor expansion 으로 풀어내고, 그 구간 내에서 jacobian 을 계산하여 핸들링 하면 extended kalman filter 가 된다. 즉, kalman filter 자체가 linear system 을 가정하고 만들어졌기 때문에, 이에 대한 non-linear extension 이 extended kalman filter 가 된다. 그러므로 extended 하는 방식에 있어서 수많은 modification 이 있는데, 대부분 system modelling 에 따라서 linearization 을 하는 방법들에 포커스가 맞춰져 있다.

  또한, 여기서 한발 더 나아가서 이도저도 다 귀찮으니, state transition model 에 이러한 term 을 모조리 때려박고, gaussian process 로 모든걸 처리하게 되면 unscented kalman filter 가 정의된다. unscented kalman filter 는 일부 값을 sampling 하여, 임의로 약간의 변동성을 추가하여 그 값들을 가지고 gaussian distribution 을 계산하게 되는데, 엄밀히 말해 완벽하게 시스템을 모사하는 것을 목표로 하지 않는다. 다만, jacobian 을 계산하는 과정이 필요 없고, 그로 인하여 시스템의 모델링이 단순해지는 장점이 있지만, 통상적으로는 연산량은 unscented kalman filter 가 조금 더 많은 것으로 알려져 있다. (sigma rule 이나 계산 하는 방식에 대해서는 wiki 를 참고 하는게 좋다.)


3. 정리

  사실 말로 주절주절 적어두어서 이걸 보고 다른 사람들도 kalman filter 를 완전히 이해할 수 있을지 애매하다. 개인적으로는 가장 중요한 직관적인 요소가 gaussian distribution 과 bayes rule 이 결합되었을 때, 어떻게 변화하는가에 대한 부분이라 그 부분에 포커스를 맞추어 정리해두었다. 물론, modelling 부분에 적어두었지만, 사실 kalman filter 류의 가장 key 는 model 이다. system 을 modelling 한 결과에 따라서 다른 종류의 filter 를 사용하게 되고, 대부분의 실세계 문제에는 extended kalman filter 가 제일 좋은 성능을 보여준다. 그러나 system modelling, 그리고 이것에 대한 미분식의 도출이 그렇게 쉽지 않기 때문에 다들 머리 싸매고 고생한다.

  직관적으로 우리가 kalman filter 를 볼 땐, 상기 그림과 같이 확률분포가 계속 업데이트 되어 점점 좁고 뾰족한 형태로 변해가야 정상이다. 그렇지 않다면 설계를 잘못한 탓일 확률이 높다. 그 바탕에는 저런 직관적인 요소가 있고, 그 background 에 있는 수학적 요소와 기타 보다 자세한 내용들은 다른 reference 를 참고하면 좋을 것 같다. 여기서 이야기 하고 싶은 것은 kalman filter 는 남들 이야기하는 바와 같이 system 의 error/noise 를 핸들링 하는데, 대체 어떤 식으로 변하는 지에 대한 직관적 이해 정도이다.

쉬운건데, 이상하게 매번 걸리적거리고 피곤하게 처리하는 내용이라 정리해놓는다.


1. 아래 홈페이지에서 Preconditions에 Windows/Unix 링크 다운

https://support.hdfgroup.org/HDF5/release/cmakebuild.html


2. 어딘가에 압축 풀어놓기.. or 설치


3. HDF5-1.10.1-Linux.sh 실행 


여기까진 뭐 그냥 쉽게 잘 간다.


마무리로  .bashrc 든 윈도우 환경이든

HDF5_DIR=뭔가설치된 폴더/cmake 지정

example) export HDF5_DIR=/usr/local/HDF_Group/HDF5/1.10.1/share/cmake


위에 HDF5_DIR 지정해주면, cmake 에서 hdf5 에 대한 내용들을 인식하여 처리할 수 있다.

글을 안쓰고 있는 것은 아닌데, 대부분 일하고 관계가 있는 내용들이라 비공개로 작성 중이다.

 

어쩌다보니 꽤 오래전에 했었던 일들을 다시 꺼내야하는 일들이 계속 생기고 있는데,

차라리 그런 내용들은 하나씩 오픈하면서 내용을 같이 업데이트 하는 것도 괜찮지 않을까 싶다.

 

하나씩 꺼내보자면,

1. extended kalman filter

2. reinforcement learning ( including deep- )

3. multi-objective optimization ( especially evolutionary algorithms )

 

왠지 예감에는 비공개로 써놓은거 하나씩 오픈해도 될 것 같다. 깊은 내용은 아니지만...

최근에 Multi- 혹은 Many-objective 에 대한 연구를 진행하고 있다. 회사에서 필요한 부분도 있지만, 오랫동안 개인적으로 연구해오던 테마이기도 하기 때문에, 꽤 많은 자료를 다시 살펴보고 연구를 진행하고 있다.


만약, 목적함수의 개수가 하나라고 가정하자. 이 경우에는 최소 혹은 최대라는 하나의 값으로 수렴해나갈 수 있다. 그러나 Trade-off 관계에 있는 2개의 목적함수를 사용할 경우에 한쪽이 상승할 경우, 필연적으로 다른 한쪽은 낮아질 수 밖에 없다. 만약 3개 이상의 목적함수가 각각이 상보적인 관계일 경우, 값의 방향성을 어떻게 잡아가야 하는 지는 더욱 모호해질 수 밖에 없다.


이러한 문제들에 대한 보편적 접근 방식은 Weight 를 적용하여 목적함수에 대한 가중을 두어 수렴시키는 방식이다. 예를 들면 보행 로봇의 직진성과 좌/우 흔들림에 대해서 직진성에 0.8, 좌/우 흔들림에 0.2 와 같은 식으로 가중치를 두어 더 빠르게 움직이는 것을 더 중요하다고 보는 식이다.


우리가 정확하게 어떤 Spec 을 주고, 그 Spec에 맞도록 학습/최적화를 진행한다고 할 때에는 관계가 없을 수도 있다. 그러나 때로는 이 가중치를 정의하기 어려운 경우가 있을 수 있다. 그리고 정 반대로 수 많은 선택지를 만들어내고, 그 속에서 무엇인가를 고르고 싶은 경우도 있다.


Multi- 혹은 Many-objective 에 대한 연구는 이러한 방향성을 가지고 있다. 즉, 기존에 Weight 를 주어 하나의 값으로 수렴시키는 것을 목적으로 했다면, 이 연구는 어떻게 더 넓게 해를 표현할 수 있는지에 관심을 갖는다. 그리고 Trade-off 관계에 있는 다양한 해를 효율적으로 찾아가는데에 목적을 갖는다. 이렇기에 현실 문제에 적용하기가 좋은 특징이 있어서, 많은 관심을 갖고 연구를 진행하고 있다.


다음에는 관련해서 진행되어온 연구들을 정리할 예정이다.  --> 과연 이걸 언제쯤 하나씩 하게될까...

진화 연산은 여러면에서 매력적입니다. 공간에 대한 분포를 잘 모르고, 문제정의만 하면 왠만큼 해를 구할 수 있다는 것이야 말로 엄청난 매력이라 할 수 있죠. 복잡한 수학이 들어가 있지도 않고, 알고리즘만 이해할 수 있으면 누구나 쉽게 구현하고 접근할 수 있습니다. 이런 장점으로 많은 사랑을 받아왔죠.


그러나 이 부분이 진화 연산의 장점이면서 동시에 한계입니다. Evolutionary Strategies 나 기타 Covariance Matrix Adaptation 기법 등이 나왔지만, 여긴 수학의 영역에 약간의 진화연산의 Mutation 의 기법이 들어갔다고 보는게 맞을 것 같습니다. 또는 Mutation 이라는 것이 확률적이라 표현하는 확률의 기법이 들어갔다고도 볼 수 있겠네요. 거의 Random 에 가까운 속성으로 인하여, 해를 찾아도 왜 찾았을 까에 대해서 물음표가 생기고, 다시 한번 수행하더라도 꼭 그렇게 찾을 수 있다는 보장을 하기도 어렵습니다.


흡사, 문제 풀이를 로또와 같이 한다고 느끼는 사람도 있을 것 입니다. 아직은 주어진 해 공간에 대해 모두 시험해볼 수 없으니 이것을 대체하여 로또의 확률을 느끼는 것과 같이 대량의 시험을 해보는 그런 상황으로 비추어지기도 할 것이고, 언젠가 양자컴퓨터나 기타 더 강력한 컴퓨팅 환경이 주어졌을 때, 모든 경우의 수에 대해 시뮬레이션을 해보고 그 결과를 얻어내는 것과 진화 연산의 차이가 없어지는 날이 오겠죠.


이런 한계는 Genetic Programming 에서 더 심하게 나타납니다. 우리는 주어진 수식에 대해 파라미터를 계산하거나 신경망이나 기타 접근 방식을 통해 수식 자체를 근사화하여 모사하는 행위를 하지만, 이것은 값을 따라가도록 하는 어떤 방향성을 Loss-function 으로 정의하여 그 근거를 가지고 있습니다. 물론, Back-propagation 이 편미분이 연속적으로 연결되어 있는 chain-rule 이라는 것도 확인할 수 있습니다.


그러나 수식 자체를 Tree 형태로 표현한 것에 대해서 수식 자체가 갖는 공간적 표현을 수학적으로 모사하지 못합니다. (지금은 하고 있는데, 제가 모르고 있는 것일 수도... ) Tree 의 특정 위치를 교환하거나, 전혀 다른 Sub-tree 로 교체하여 수식을 풀어나간다고 하지만, 그 자체에 대해 어떤 수학적 근거를 갖는지에 대해서는 설명하기가 어렵습니다. 특히나 Fitness function 의 정의가 어떤 방향으로 유도한다고는 하지만, 이것이 항상 그 방향으로 유도되어 나아가는 것도 아니라는 것을 확인할 수 있습니다.


예전에 Tree 의 Distance Metric 을 정의한 여러가지 사례가 있었는데, 이 Distance Metric 은 비교적 Tree 의 차이에 대해 정의할 수 있었고, 이 Metric 을 통해서 특정 Tree 형태로 수렴할 수 있도록 Guidance 로 사용할 수 있었습니다. 문제는 Tree 의 구조적 형태가 좋은 해와 그렇지 않은 해를 구분하기에는 적절치 않았다는 것에 있었죠. 즉, 우리가 어떤 형태의 Tree 로 해를 유도한다고 해도, 사실 그 구조를 가진 해가 좋은 해인지를 판별할 방법이 없었습니다.


Genetic Programming 이나 Grammatical Evolution 은 진화 연산 중에서 Tree 구조를 사용하여 새로운 구조를 만들어나 갈 수 있다는 장점이 있지만, 반면 연속적인 시간 변화에 대한 값으로 주어진 결과물을 모사하기 위한 어떤 구조를 만들어낸다는 측면에서 2차원으로 주어진 데이터를 전혀 다른 공간의 형태로 Mapping 하는 일종의 Black-box Optimization 으로 생각하기에 아직은 수학적으로 접근할 수 있는 부분에 한계가 있는 것 같습니다.


언젠가는 연속적인 시계열 데이터나 기타 일련의 알고리즘을 Tree 나 다른 형태로 Mapping 하는 수학적 방법에 대한 제안이 있을지 모르겠습니다만, 이러한 부분이 극복되지 않는다면 결국 진화연산은 항상 랜덤에 의존하는 그런 최적화 방식으로 치부되지 않을까 싶습니다. Schema 이론이나 기타 몇가지 이론이 있지만, 그렇다 해도 말이죠.

#1. 대학교/대학원 시절에 전공으로 일반적으로 잘 연구하지 않는 진화연산(Evolutionary Computation)과 로보틱스(Robotics)라는 분야를 선택하게 되었습니다. 그러다보니 혹시라도 있을지 모르는 같은 분야를 연구하는 누군가를 찾아보기 위해, 그리고 그 당시에 그런 분들과의 교류를 위해 한창 블로그에 공부하던 여러가지 내용들을 정리하고 있었습니다.


회사에 들어가고 나서, 한번 내용들을 전체적으로 다시 정리해서 하나씩 꺼내야지 마음 먹었던게 벌써 5년이 지났지만, 이것저것 일들에 시달리고 나니, 그럴 엄두가 안나고 있습니다.


그래서 옛날에 썻었던 글들을 다시 카테고리로 정리하여, 그냥 옛날 내용 그대로 공개하려고 합니다. 어쩌면 상당히 오래된 이야기이고, 전혀 쓸모없는 고대의 유물일 수도 있고, 과거에 공부하며 정리했던 내용들이라 전혀 맞지 않지만 마구마구 적어놓았던 그런 이야기일 수 있습니다. 개인적으로는 부끄러운 이야기일 수도 있고, 어떻게 이렇게 글을 못썼지 라는 생각과 함께 자괴감이 들 수도 있는 그런 이야기일 수 있지만, 다시 한번 기존에 있었던 내용들과 함께 시작해보려고 합니다.


그리고 그 내용들은 하나씩 하나씩, 최근의 트랜드를 정리하고 공부해가며, 그 내용들을 추가하면서 수정하려 합니다.


#2. 저는 과거에서부터 지금까지 여전히 사람이 신경망이나 어떤 머신 러닝 알고리즘의 흐름 구조를 만들고 설계하는 데에는 한계가 있을 수 밖에 없고, 결국 스스로 진화하는, 그리고 스스로 학습해 나아갈 수 있는 알고리즘이 반드시 필요할 수 밖에 없을 것이라고 생각합니다. 페드로 도밍고스의 마스터알고리즘에서 말하는 4개의 마스터 알고리즘이 하나되는 궁극의 알고리즘이 탄생하는 그런 일들이 언젠가는 이루어질 것이라 생각하는 것이죠.


그런 의미에서 저와 비슷한 누군가에게 진화연산은 여전히 매력적일 수 있는 하나의 알고리즘이라 생각되네요. 학습 모델들도 Unsupervised 형태의 Generative Model 로서의 트렌드가 점점 이어져감에 따라 언젠가는 다시금 중요하게 쳐다보는 그런 날이 있지 않을까 생각합니다. 물론 그날이 절대 오지 않을 수도. 그리고 지금의 진화연산과는 전혀 다른 형태가 나타날 수도 있겠지만요.


아... 그렇다고 제가 마스터알고리즘에서 말하는 진화주의자는 아닙니다. 실질적으로 현재의 진화연산의 한계는 매우 뚜렷하게 알고 있기 때문입니다. 자원이 받쳐준다면, 한번 극복해보고 싶긴 합니다... 할 수 있을 것 같다는 확신도 있고...


#3. 확실히 세상이 바뀌어가고 있다는 사실에 대해 많이 느끼는 것은 산업용 솔루션을 만드는 우리 회사같은 곳에서도 결정론적 모델만이 정답이 아닐 수 있다는 것에 대해 아주 조금은 의식한다는 것이네요. 참... 이걸 5년전에 의식해주셨으면, 얼마를 더 앞서갔을까 하는 아쉬움이 있지만... 물론 그건 지나간 시간에 대한 아쉬움일 뿐 입니다. 앞으로 다가올 시간에 대한 기대감은 다른 형태로 꿈꿔야하지 않을까요...

Tensorflow 를 돌리면서, 현재쓰는 650M 이 여러모로 부족하여 새로 영입했다.


확실히 빨라지긴 했는데, 같이 일하는 분의 GTX950M 에 비해서 그렇게까지 큰 성능 향상이 있는지는 잘 모르겠다.


역시 뒷자리가 5라서 서로 비슷한가 싶기도 한데... 벤치마크 자료에 비해 생각보다 미비하다.


그런데 데이터 셋을 크게 늘리니 빨라지긴 하는데...


근데 데이터 셋이 작을때 성능을 기대하고 있었는데 아쉽다.



예전에 tensorflow 를 처음 사용할 때, 리눅스 설치때문에 엄청나게 고생했었던 기억이 있다.


특히나 CUDA를 사용하는 부분에서, 노트북(GT 650M 사용)이 개발환경이다보니 일반적인 설치파일을 그냥 다운받는 것으로는 문제가 있어 많은 시간이 소모되었었는데,


얼마 전에 Ubuntu 16.04 버전으로 버전업하고, 그때의 과정을 되풀이 했는데, 너무나 쉽게 되었다.


1. Ubuntu 16.04 버전 설치


2. 그래픽카드 드라이버 설치

    sudo add-apt-repository ppa:graphics-drivers/ppa

    sudo apt-get install nvidia-370   

    설치 이후 재부팅하여, nvidia-settings 로 정상 설치 확인


3. CUDA 설치

    sudo apt-get install nvidia-cuda-toolkit

    example 이 필요하면, nvidia 사이트에서 다운


4. cuDNN 설치

    /usr/include, /usr/lib 에 설치함(기존에는 /usr/local/cuda ... 에 설치)

    CUDA v7.5 기준 v5 설치


5. anaconda2 설치

    https://www.continuum.io/downloads

 

6. tensorflow 설치 (설치시점에는 v0.11 사용함)

    http://tensorflow.org 참조


세상에... nouveau blacklist 따위도 필요 없고, 그냥 잘 된다.

진작 16.04 로 옮겨갈걸 그랬네...;;

예전에 처음 신경회로망을 배우고, 알고리즘으로 학습을 모사할 수 있다는 것에 대해서 상당한 매력을 느꼈었는데, 잘 정제되어 있는 학습데이터가 없이는 결과가 좋지 않았기에 그 이후로 크게 관심을 두고 있지는 않았었다. 한동안 그러다가 비전과 관련한 분야에 대해 공부하면서, 특징점을 추출하기 위한 부분을 신경망을 활용하여 드라마틱한 성능의 향상을 보여주는 것을 보고 다시 관심을 가지게 되었었다.

 

신경망에 대해 다시 관심을 갖기 시작했던 때에는 호기심에 한창 CUDA로 GA에서 실수최적화 기법을 사용하는 알고리즘들을 병렬화시키는 부분에 대한 개발하고 있었다. 그래서 처음에는 당연히 가중치 계산에 대해서 예전보다 더 큰 규모의 신경망을 보다 빠르게 학습시키는 것에 대해서만 생각하고 있었다. 

 

CUDA 를 처음 활용하면서, 그때 오류역전파 알고리즘을 구현하고, 10계층에 5천개 정도의 뉴런을 학습시키는 프로그램을 만들어 돌리면서, 진짜 빠르다는 생각은 하고 있었지만, 사실 제대로 최적화가 안되었었다. 아주 단순한 문제에 대해서 5천개의 뉴런을 학습한다는 게 가당키나 한 말인가? Learning Set이 5천개의 뉴런을 학습시킬 만큼 다양한 데이터 셋을 갖출리가 만무했고, 당연히 결과는 수렴 속도는 진짜 빠르네 였을 뿐이다. 물론, 그 당시에는 왜 안될까에 대해서 계속 의문이 있었을 뿐이었지만...

 

시간이 좀 지나고 나서, CNN 과 RNN 에 대해서 알게 되었다. 처음 CNN 이나 RNN 을 접했을 때에는 그 부분에 대해 정확히 이해하지 못하고, 단순히 더 계층화 되고, 다른 형태의 전달함수를 사용하지 했을것 같다는 정도로 생각했던게 문제 였다. 결론적으로 다시 하나씩 곱씹어보고 당연히 비전쪽에 잘 맞춰져 동작할 수 있겠구나 라는 생각이 들게 되었지만... 이 시점에 나는 학습데이터를 충분히 확보하지 못하는 시점에도 어느정도의 목표를 향해 결과를 보여줄 수 있는 특성이 있는 진화 신경망 쪽에 더 관심이 많았다.

 

회사에 오고나서는 신경망이나 진화연산과 같은 머신러닝 기법을 사용하기가 참 힘들었다. 가장 큰 장벽은 확률적. 그리고 언제나 동일한 해를 보장하지는 않는다는 점. 그런 부분을 이해시키는 것이 너무 말도 안되는 일이었다. 내가 일하는 곳이 산업용 로봇을 만드는 곳이니 당연한 것이기도 했다. 비교적 최근에 다시 고장예지나 다른 분야에 이러한 기법들을 사용할 수 있다는 것에 대해서 사람들이 인지하기 시작한건 참 다행이라 생각한다.

 

어쨌든, 신경망은 CNN과 RNN 이후로 눈부신 발전을 거듭하고 있고, 더 많은 연구자들과 함께 획기적인 결과물들이 쏟아져 나오고 있다. 놀랍고, 경이롭다. 언젠가는 내가 연구하는 여러가지 기법들 중, 나로 인하여 이러한 폭발적인 연구 성과를 보여줄 수 있기를 희망한다.

 

 

이책의 저자인 페드로 도밍고스는 기호주의자(Inverse Deduction), 연결주의자(Back-propgation), 진화주의자(Genetic Programming), 베이즈주의자(Bayesian Inference), 유추주의자(Support Vector Machine)로 머신러닝의 다섯 종족을 구분해두었다.

 

머신러닝의 기본서 같은 책이라 추천받아 봤는데, 세상에나... 난 진화연산을 머신러닝의 한 분파로 분류해줄 줄은 몰랐다.

 

진화연산을 공부하면서 항상 고민되던 부분이 어떻게하면, 진화의 부분을 학습과 같이 수행할 수 있도록 하는가에 대한 것이었다. 예를 들면 역전파 알고리즘은 항상 결과의 피드백으로 가중치의 값을 변경해나아가는데, 이 과정을 하나의 목표를 향한 학습이라 볼 수 있다.

 

그런데, 진화 연산에서의 선택은 많은 부분에 있어서 랜덤이다. 물론 진화연산을 이용한 수치최적화 부분에서의 일부 연산 방식의 경우, 결과값을 기반으로하여 점점 본래의 값을 변화시켜 나아가기 때문에 일종의 학습처럼 보일 수 있다. 그러나 유전프로그래밍의 연산자는 트리의 어떤 한 노드를 선택하여 하위 전체 노드를 변경하거나, 랜덤으로 특정 노드를 특정 트리나, 노드로 변경하는 방식이 대부분이다. 그렇기에 이를 학습이라보기는 항상 어렵다고 생각하고 있었는데, 이를 머신러닝의 한 분류로 넣어줄 줄은 몰랐다.

 

이 책에서도 물론 의문을 제기하고 있긴 하다. 여전히 유전프로그래밍이 문제를 해결하는 방식이 수많은 탐색공간을 뒤지는 탐색의 결과인지, 진화를 모델링한 것의 효과인지는 불분명 하지만... 이라는 단서를 달아서. 그리고 나 역시도, 이 부분에 대해서 공감은 하지만, 순수한 랜덤 탐색으로만 찾아낼 수 있는 결과에 비해 항상 더 우수한 결과를 보여줄 수 있는 것은 진화의 모델링에 의한 결과라고 생각한다.

 

아무튼 흥미로운 관점이고, 머신러닝의 다른 부분에 대해서도 다시 간단하게 살펴볼 수 있는 좋은 기회였다.

이번엔 무슨 내용을 어떻게 할지 정하지 않았네요.

 

그건 차차 생각하고.

 

뭔가 새로운 것들.

 

뭔가 다른 것들을 다시 한번 생각해볼랍니다.


본래 쿼티자판덕분에 참 잘쓰던 모토쿼티인데, 사실 좀 느린감이 없지않아 있었습니다.
오늘자인지 프로요 업데이트가 나왔길래 바로 달렸습니다.
업데이트 후에 버벅버벅 하시길래 그냥 아무생각없이 공장초기화를 수행 했습죠;

애초에 포맷하려고 마음 먹었던지라... 아무 미련없이 질러주시고, 부팅하고 나니 신세계네요
공장초기화 방법 - http://blog.naver.com/PostView.nhn?blogId=ajg147&logNo=100116711177


1. 기본 런처도 꽤 빠르게 반응함

  이거 별거 아니지만 좀 충격입니다. 처음에 모토쿼티 부팅후에 버벅버벅 거리는 그 기본 런쳐를 보고 엄청난 실망감이 들었었는데, 이번엔 아니군요. 런쳐프로 깔았을때 느끼는 그 속도 수준으로 잘 움직여서 상당히 놀랐습니다;; 프로요빨인가요 뭔가요 이건;

2. 퀵오피스 업데이트

 겁나 후즐근했었던 관상용 퀵오피스가 업데이트하면서 확 달라 졌네요. 심지어 문서편집도 된다니...;;

3. 키보드 패턴 일부 변화

  이전과 달리 한영 전환이라던가, 하는 부분이 다르게 변했습니다. 물론 애초에 쿼티자판만 두들겨대던 인간인지라 전혀 관계 없었지만... 어쨌든 변했습니다. 편해진건지는 애시당초 써보질 않아서 모르겠습니다 -_-;;;;;

4. 일부 기본앱 추가

 뉴스와 날씨라는 게 생겼는데.. 음.. -_-ㅋㅋ 뭐 그냥 왜추가했는지 ;;;

어쨌든...
각설하고 많이 좋아졌습니다;
확실히 더 빠르고 좋은건 틀림없네요 ㅋ

그러면서 다시 런쳐프로를 깔아서 쓰고있습니다
더빨라졌어요! ㅎㅎ

P.S. 저만 그런가... -_- 왠지 모토롤라는 사실 좀 불안하네요;;


추가!

맞다.. 테터링이 생겼습니다 !
이걸 빼먹을뻔했군요!! 3G 모바일 핫스팟 이라는게 생겨서 뭔가 했더니, 스스로 AP 역할을 하게 해주는 것이더군요
이젠 PDANET 안쓰고 테터링할 수 있네요 ㅎㅎ
해보니까 PC에서도 인식 잘되고 아주아주 좋습니다 ㅋ
  1. 모토쿼티 유저 2011.03.11 17:45

    후기 잘 봤습니다. 보아하니 모토쿼티가 제대로 지원된거 같더군요.

    • shhyun shhyun 2011.03.11 18:57 신고

      그런거 같아요. 확실히 많이 좋아졌다는 느낌이 팍드네요.
      특히 퀵오피스의 경우에는 좀 각성의 느낌이고 진짜;;
      로이는 욕 바가지로 먹더니 쿼티에서 정신좀 차린거 같다는 생각이드네요 ㅎㅎ

  CGP는 본래 논리 회로에 대해서 많이 사용되기 때문에, 별 관심이 없다가 최근에 몇가지 가능성을 보고 찾게된 이론이다. Linear GP 나 CGP 등 사실 Tree 기반의 GP 보다 구현이 쉽기 때문에 찾아보게 된 이유도 있다. 우선 기법에 대해 살펴보면 아래와 같다.

  기존의 Tree 기반의 Genetic Programming과는 약간 다른 Integer String 으로 개체를 구성한다. 하나의 개체는 아래의 그림과 같이 구성할 수 있는데,


  (1) (2) 는 입력을 의미하고, (3) 은 해당 노드의 연산자를 의미한다. 즉, 1, 2 로 부터의 입력을 3 의 처리를 거쳐 output 1 을 만들어내는 식인데, 이때 CGP 에서 출력은 사용자가 지정하는 것이 아니라 자동으로 지정되는 형태를 갖는다. 이는 CGP 가 Feedforward 형태의 흐름을 갖기 때문이며, Feedback 에 의한 루프 구성을 막기 위함이기도 하다. 만약 루프가 구성될 경우, 조건의 역할을 하는 함수가 아닐 경우, 이를 빠져나갈 방법이 묘연하여 무한 루프에 빠지게될 수 있고, 일정 횟수를 반복시킨다고 할 경우에 발생하는 효과는 오히려 루프를 이용하지 않는 것 보다 못할 수 있다.
  그리고 이러한 형태의 블록이 여러개가 다중으로 연결될 수 있으며, 아래와 같이 구성될 수 있다.



  이와 같이 여러개의 블럭을 사용하여 프로그램을 구성할 수 있으며, 점선으로 표시한 부분과 같이 연결이 이어지지 않는 부분도 발생할 수 있다. 이는 자동으로 할당된 출력이 다음 블럭의 어떠한 부분에도 연결되지 않는 경우 발생한다. 그리고 CGP 는 기존 트리기반의 GP 와 달리 항상 고정된 행과 열의 크기 만큼의 프로그램을 가지고 있는데, 초기에는 거의 모든 노드들이 연결된다. 그러나 시간이 지나면 지날 수록 이와 같은 연결되지 않는 부분이 발생하고, 이러한 작용에 의해 일종의 잉여 혹은 중복 공간(Redundancy)의 제거 효과가 나타날 수 있다. 
  CGP 는 위와 같은 다중의 형태로 인해 기존 GP와는 달리 단일 표현의 개체를 통해 다중의 출력을 얻어낼 수 있는데, 내가 이를 활용하게 된 이유는 바로 이것 때문이다. 기존의 로봇 게이트 진화에 사용했던 다중트리(Multi-tree) 기법은 서로 각각의 트리가 어떠한 관계도 없이 진화한다. 그러나 CGP 에서는 은연중에 서로간의 연결이 공유될 수 있기 때문에 완벽하게 독립된 형태가 아닌 어느정도 의존성을 갖는 형태로 진화하게 된다. 그러므로 각각의 관절의 움직임에 대해 기존의 GP 보다 효율적이며 유기적인 움직임을 보여줄 수 있을 거라고 기대할 수 있다.
  물론 멀티트리를 사용할 경우에도 이에 추가적으로 ADF(Automatic Defined Functions)를 적용할 경우, 비슷한 효과를 낼 수 있지만, ADF의 개수나 크기에 대한 정의를 어떻게 할 지가 큰 문제가 될 수 있다. 이 경우 크기와 개수가 커질 경우, 해공간의 크기가 매우 크게 확장될 수 있고, Koza 외의 다른 사람들이 ADF 를 잘 적용하지 않는 데에는 그만한 이유가 있다고 생각해볼 수 있다.
  그러나 CGP에도 단점은 있는데, 일반적인 GP에서는 ERC(Ephemeral Random Constants)라 하여 임의의 상수값이 트리의 어느 부분에나 적용될 수 있지만, CGP 에서는 그럴 수 없다. 제한된 입력값을 사용하기 때문에 발생할 수 있으며, 이 부분이 극복되지 않는 한 아래의 논문[1]에서도 언급한 것과 같이 Symbolic Regression 문제에 대해 완벽하게 적용되긴 어려울 것이다.
  그럼에도 CGP 는 하나의 표현으로 다중의 출력을 낼 수 있다는 면에서 충분히 매력적이다. 시뮬레이션 로봇 모델을 통해 실험을 하고 있으며, 기존의 GP 보다 더 빠르며 안정적인 보행 자세를 몇가지 얻어낼 수 있었다.

[1]       Miller J. F, Thomson P., Cartesian Genetic Programming, In Proceedings of the 3rd European Conference on Genetic Programming, Springer, LNCS 1802, 2000, 121-132.

(*) 위의 그림들은 논문에 사용될 그림이기 때문에, 만약 사용하신다면 반드시 코멘트를 남겨 주셔야합니다.

ReadyFor4GB 라는 프로그램을 사용해서 윈 7 32비트에서도 메모리를 4기가 모두 사용할 수 있는 것으로 알려져 있습니다.
4GB(3.11GB 사용가능) 과 같이 4GB를 쓰는데 왠지 4GB를 다 못쓰는것 같아서 좀 아까운 기분도 들고 저도 한번 사용해 봤는데, 부작용이 발생했습니다. 

Firewire 관련 부작용인데, PCMCIA Express 타입의 IEEE1394 카드에 Firewire 형태의 외부 카메라를 연결했는데, 인식만 되고 사용이 전혀 되지 않았습니다.

PC <-> IEEE1394 상의 데이터 전송 대역폭이 모자라서 데이터 전송이 불가능하다는 메세지가 계속 나타나더군요. 본래 잘 쓰던 카메라라 당연히 잘 될거라 생각했는데 안되니 좀 어이가 없었습니다. 원인을 한시간 가까이 찾아 헤메다가 이전에 쓰던거라 그 중간에 바꾼게 뭔가 찾아보니 ReadyFor4GB 설정 외에는 없더군요.

다시 본래 윈도우로 부팅해서 해보니 아무 이상없이 잘 됩니다. 이전에 어딘가 글에서 4GB(3.11GB 사용가능) 등의 메세지가 나타날때 나머지 공간이 나타나지 않는 이유가 사전에 장치를 위한 메모리 할당이라는 글을 본 거 같은데, 이런일을 겪어보니 왠지 그 이유가 아닌가 생각이 듭니다.

혹시라도 Firewire 형태로 연결되는 카메라를 쓰시는분이 문제가 생긴다면 한번쯤 의심해보셔도 될 것 같습니다.
이전에 간단하게 만들어두었던 SGA의 Fitness Evaluation 동작만을 CUDA 에서 실행하는 코드

난 지금까지 이걸 올렸다고 생각하고 있었는데, 다시보니 그게 아니었다.
이건 뭐 XX도 아니고...;;

(*) 일단 코드는 최적화는 전혀 되어 있지 않은 상태이며, 오히려 기본 GA보다도 Evaluation 성능이 떨어질 수 있다.

컴파일 환경은 쓰고싶은대로 아무거나 써도 이상이 없을 코드이며, 이전엔 Visual Studio 2008 에서 작업했었다.

CUDA에 대해서 가장 기본적인 코드라고 생각해도 될 코드이기때문에
혹시라도 이런 종류의 알고리즘을 다뤄보고 싶으신분은 살펴보면 좋을 것 같다.
  1. 별다섯개 2010.11.22 16:29

    이뭐병?? ㅋㅋㅋ힘내시구료!!

로봇 게이트 생성 기법을 4족 보행 -> 휴머노이드로 이전하면서, 해공간의 특성 분석이 필요해서 몇가지 샘플트리에 대해 적합도 공간 변화가 어떤지 체크해본 그래프이다. 4족 보행 로봇의 경우 네 발로 지탱하는 특성 때문에, 안정성에 대한 지표가 크게 변하지 않지만, 휴머노이드는 넘어짐이라는 특성이 발생하기 때문에 아주 작은 변화에도 결과에 매우 큰 영향을 주는 현상이 나타날 수 있다고 생각했고, 그것을 증명하기 위한 그래프 자료이다.

아래와 같은 각각의 트리에서 ERC 값, 즉 실수값을 P1, P2, ... ,P8 의 변수로 표현하여, 각각 0.001 씩 증가시키면서 해공간의 변화를 나타낸 것이다. x 축은 0.001씩 몇번이나 증가 시켰는지를 의미하며, y 축은 적합도값을 의미한다.

HP:
 (/ (/ X -1.23399)
    (- X -0.34431))
KP:
 (/ (+ (sin 0.41949)
       (* -0.09291 X))
    (/ (cos 0.20874)
       (sin 0.41949)))
AP:
 (- -0.44653 -0.39964)

적합도 함수는 거리를 기반으로 한 형태이며, fitness = 0.8 * 전진거리 - 0.2 * 좌,우 틀어짐 으로 사용한다. 또한, 넘어지거나 유도한 방향으로 움직이지 않을 경우, 적합도를 0 으로 할당한다.


결과를 보면 실수값의 아주 미묘한 변화에도 해 특성이 매우 심하게 변동됨을 확인할 수 있다.
그러나 P5 변수 후반부를 보면, 크게 변동하지 않는 후반부(71~이후)가 발생하는데, 이는 조금은 의외의 결과이다. P4, P5, P6 모두 초기값이 양수이며, 동일한 형태로 증가하고, 최종적으로 증가된 결과가 시뮬레이터에 정밀하게 반영되기 어려울 수 있는데, P4, P6 는 중간에 적합도값이 음수값으로 크게 가라앉는 형태를 확인할 수 있다. 그러나 P5 에서는 71~이후 의 결과가 계속적으로 동일한 결과가 나타났으며, 생각과는 다른 해공간 특성을 가지는 것을 확인할 수 있다.

결론적으로 저러한 예외가 발생함에도 불구하고, 아주 미묘한 실수값에 의해 매우 큰 변동 수치의 적합도를 갖는다는 사실에는 변함이 없다. 즉, GP 자체의 구조적 튜닝도 매우 중요하지만, 이러한 문제의 경우 파라미터 수치의 중요성도 매우 높다는 사실을 확인할 수 있다.
내가 주로 연구하는 것은 최적화(Optimization)이다. 학습에 대해서는 분명 최적화만큼의 지식이 없으며, 이에 대해 여전히 상당한 혼란을 겪고 있음을 사전에 밝힌다.

최적화는 일반적으로 수학에서 많이 쓰이는 용어이며, 가장 대표적인 예로는 실수 최적화가 있다. 어떠한 주어진 함수 f(x) 의 최대 혹은 최소 값을 찾아내는 문제로서, 미분이 가장 대표적으로 사용되는 기법이다. f'(x) = 0 인 지점을 변곡점이라 하고, 이 변곡점들에서 최대, 최소값이 발견될 수 있다. 유전 알고리즘이나 진화 전략(Evolutionary Strategies) 혹은 PSO(Particle Swarm Optimization) 기법들 또한 이런 최적화를 위한 도구이며, 종종 최적화라는 이름으로 언급되곤 한다.

학습(Learning)이라는 이름으로 불리는 기법들이 있다. 일반적으로 최적화 라는 의미와 비교되는 것은 Machine Learning 에 대한 이야기 인데, 상당히 애매한 부분이 있다. 유전 프로그래밍(Genetic Programming)은 분명 최적화 기법이다. 그런데 어떤 의미로서는 Machine Learning 의 한 부류로 분류되기도 한다[각주:1]. 신경회로망(Artificial Neural Network)은 어떤 의미에서는 학습도 최적화도 아니라고 생각할 수 있다. 그것 자체로는 아무것도 할 수 없고, 이를 특정한 트레이닝 모델에 대해 "학습"을 시켜야 이를 하나의 알고리즘으로서 적용할 수 있다.

사실 학습과 최적화에 대한 경계에 대해 가장 큰 의문이 생긴 이유가 "신경회로망" 때문이다. 분명 신경회로망은 어떠한 학습 데이터에 대해 최적의 가중치값을 갖게 하기 위해 "학습" 이라는 과정을 수행한다고 한다. 문제는 여기서 발생하는데, 신경회로망의 대표적인 학습 방법으로는 오류역전파 알고리즘(BP, Back-Propagation)이 있고, 이는 특정한 트레이닝 세트에 대해 발생하는 오차를 앞에 있는 노드에 반영 시켜 해당 오차를 점점 줄여나가는 것이다. 그리고 LMA(Levenberg-Marquardt Algorithm)이 있는데, 이는 가우스-뉴튼 메소드의 확장으로서 Non-linear least square problem 을 해결하는데 사용한다.

바로 여기서 발생한 문제다. 분명 LMA 알고리즘은 Non-linear least square problem 에 대한 최소의 error 값을 찾아내기 위한 알고리즘이다. 또한, 이 알고리즘은 최적화 알고리즘의 성능 테스트에 대표적으로 사용되는 Rosenbrock Problem 을 해결하기 위한 방법으로도 사용된다. 그런데 이를 신경회로망에서는 학습 알고리즘으로 분류하기도 한다[각주:2].

분명 어딘가에선 "학습" 이라는 이름으로 불리고 있지만, 이것들이 엄밀히말하면 "학습"이라고 할 수 있을까? 만약, 위의 논문에서 사용하는 바와 같이 신경회로망의 "학습"을 위한 도구로서 사용된 알고리즘을 "최적화"라는 기법으로 말하지 않고, "학습"이라는 기법으로 소개한다면, 그렇다면 NEAT(Neuro-Evolution of Augmenting Topologies)와 같은 기법[각주:3] 또한 최적화라 분류하지 말고, "학습" 이라는 형태로 분류해야 하는가? (NEAT는 유전 알고리즘을 통해 신경회로망을 구축하고 가중치값을 조절하는 기법이다.)

학습이건 최적화건 본질적으로는 중요하지 않을 수도 있다. 어디까지나 내 생각이지만, 사람이 느끼기에 학습이라 불린다면, 어떠한 것이든 적응할 수 있을 것 같고, 인간이 학습한다는 것을 생각하기 때문에 보다 나은 어떠한 결과물을 만들어낼 것이라는 일종의 기대감 같을 것을 줄 수도 있다. 그런데 최적화라 한다면, 분명 이는 어떠한 특정한 환경에 대해 최적의 결과를 만들어낼 것 같은 기대감을 갖게 한다. 분명 하나의 기법에 대해 다른 용어를 사용해서 나타낸 것이지만, 이것이 적용될 환경에 대해 나타날 결과가 다르게 느껴질 수 있다는 것이다. 나만 그렇게 생각할 수도 있지만 말이다.

어쩌면 학습과 최적화라는 용어는 좀 더 명확하게 표기해야되는 것이 아닐까? 어떤것들은 어떠한 특정 목적에만 딱 부합될 수 있는 최적화의 접근방식인데도 학습이라는 표현을 사용하곤 한다. 물론 최적화 접근 방식인데도 학습이라는 용어를 쓰는데는 그만한 이유가 있겠지만, 이것에 대해 적용된 기법 자체에 초점을 두고 명확하게 표현하는 것이 좋지 않을까?

  1. http://en.wikipedia.org/wiki/Machine_learning 물론 위키의 신뢰성을 봤을 땐, 누군가 편집한 사람의 개인적인 의견일 확률도 높다. [본문으로]
  2. Bogdan M. Wilamowski, "Neural Network Architectures and Learning Algorithms, How Not to Be Frustrated with Neural Networks", IEEE INDUSTRIAL ELECTRONICS MAGAZINE, DECEMBER 2009. [본문으로]
  3. http://www.cs.ucf.edu/~kstanley/neat.html [본문으로]
GAlib 가 가볍고 잘 만든 Genetic Algorithm Library 인데

개발 중단된지도 오래되었고, 현재 최신버전의 컴파일러에서 컴파일은 되지만 링크가 되지 않는 문제가 있다.

http://www.hyperdrifter.com/software/tutorial/compiling_galib_using_microsoft_visual_cpp.html

위의 링크에서 말하는대로 컴파일하면 링크이상없이 잘 수행되는 것을 확인할 수 있고,

첨부된 파일은 귀찮고 단지 library 파일만 쓰고싶은 사람을 위한 것이다.

+ Recent posts