이 몇 달 동안 혼신을 다 해서 만들고 있는 게 있었습니다.


게임하는 인공지능입니다.


요즘 대세가 기계학습(머신러닝)이잖아요.


제가 만든 것이 아래 영상에 있어요.



저는 이것을 보상중추가 있는 인공신경망이라고 부릅니다.


인공신경망이란, 사람이 공학적인 방법으로 생물의 신경을 모사한 것입니다.


컴퓨터과학자 입장에서 신경망은 데이타가 어떻게 저장될지를 정의하는 추상적인 자료구조입니다.


그리고 그 신경망에 대해 가하는 연산을 정의하는 것은 미리 프로그램된 학습규칙과 보상이라는 생득관념입니다.


여기에서의 학습규칙은 유전 알고리즘이며, 신경망과 그 유전 알고리즘이 학습의 지표로 삼는 보상은 생물이 선천적으로 얻는 상벌의 감각과 같기 때문에 그 보상을 평가하고 그에 따라 신경망을 개선시키는 프로그램을 보상중추라고 했어요.





적용해 보고 싶었던 기계학습 기법은 텍사스 오스틴(대학교)의 Kenneth O. Stanley 박사님이 개발하신 NEAT(NeuroEvolution of Augmenting Topologies)입니다.


이 기법으로 슈퍼마리오를 플레이하는 AI를 유튜브에서 본 이후로 언젠가는 구현해 봐야겠다고 생각했거든요.


처음에는 한두 달 하고 끝내려고 했는데 생각보다 대형 프로젝트더군요.


이걸 만들어야겠다고 처음 생각한 것이 작년 10월에 아래 글을 적을 때부터였던 것 같습니다.


2018/10/09 - [잡담] - 유전자, 염색체, 유전체의 차이점 간단 요약


그리고는 10월 11월에는 언노운치트 같은 사이트 기웃거리면서 게임 해킹하는 법만 실컷 배웠어요.


제일 먼저 인공지능에게 게임을 시킬 수가 있어야 하니까요.


그 이후에는 이 한 편의 논문만 보고 바닥부터 기어올라가면서 A부터 Z까지 모든 것을 한 땀 한 땀 새로 만들었습니다.


개발에 사용한 언어는 C랑 Makefile 아주 조금 빼고는 전부 Go 언어입니다.


Go 언어를 쓴 이유는 두 가지입니다.


- 오픈소스의 정신이 잘 살아 있으며, 돈 없고, 백(Back) 없고, 혼자 필요한 것을 찾아서 공부하는 사람들을 위해서 모든 것이 아주 잘 준비되어 있습니다.


- 몇 번 연습 삼아 클라이언트 수정을 Go 언어로 해 보면서 C/C++ 이상으로 게임 해킹하기 좋은 언어가 Go 언어라는 확신을 얻었기 때문입니다.


2018/10/09 - [Methods] - Go 언어로 메모리 조작과 API 후킹을 구현하기 (윈도우즈 앱 리버스 엔지니어링)

2018/10/09 - [Methods] - 한글을 배운 윈도우 계산기 (Windows 10 UWP 앱 리버싱)


그밖에 Go 언어로 다른 사람들이 만들어 놓은 NEAT 라이브러리가 있는 것은 봤는데 태반은 아예 제대로 작동하지도 않고 영 엉망이더라고요.


실은 처음에는 텍사스 오스틴(NEAT 원작자와 같은 소속 학교)의 염진석씨가 구현해 둔 이것을 그대로 가져다가 쓰려고 했는데...


https://github.com/jinyeom/neat


나중에 코드를 자세히 들여다 보니 개체의 변이인가 교배인가가 제대로 구현이 안 되어 있습니다.


결국 염진석씨 구현에서는 다른 건 안 보고 작명만 좀 퍼왔어요.


yaricom/goNEAT이라는 구현이 오리지널 구현이랑 거의 똑같고 잘 되기는 하는 것 같은데 코딩 스타일이 카멜이 아니라 snake_case라는 점이 마음에 안 들었습니다.


구성이나 인터페이스도 직관적이지 않고요.


그래서 직접 구현했지요.


구현하면서 가장 참고할 만했던 코드는 2002년 당시 원작자의 오리지널 구현이랑 SethBling MarI/O입니다.

나머지 구현은 위 두 구현의 유사품에 불과하거나, 그렇지 않은 경우 참고하기 약간 어려운 점이 있어요.

그렇게 해서 거의 완성해 두고 위 첨부 스샷에 보이는 신경망을 만들어 사진 찍은 것이 올해 3월 초입니다.


나머지 시간에는 하이퍼 파라미터를 깔짝거리고 테스트 수행을 몇 번 하면서 노트북의 GPU/CPU 파워를 혹사시켰을 뿐이죠.


노트북에 물리적인 손상이 있을 때까지 풀가동하였습니다.


내가 가지고 있는 유일한 PC가 그 노트북 한 대뿐임에도 말이에요.


그래서 테스트를 중단한 상태에요.


지금도 팬이 자기 멋대로 돌아가요.


논문에서 대충 읽고 넘어간 부분은 나중에 테스트를 해 보면 무조건 발목을 잡더군요.

결과물은 그렇게 논문을 몇 번 다시 읽고 꼼꼼한 수정을 거쳐서 만든 물건입니다.


아래 깃헙 주소로 올려 두었어요.


https://github.com/NaniteFactory/naneat


아래 주소에서 API 레퍼런스도 제공합니다.


https://godoc.org/github.com/NaniteFactory/naneat


패키지 이름은 NaNEAT이고, OpenGL 백엔드로 신경망의 실시간 시각화를 지원하는 것이 다른 라이브러리와의 차별점입니다.


멀티 스레딩 기반으로, Go의 장점을 십분 발휘하여 자원의 수직적 확장이 아닌 수평적 스케일링이 가능토록 설계된 것이 특징입니다.


그러니까, 이 라이브러리로 만든 서비스에 Dockerfile 작성해서 잔뜩 배포하면 꽤 어려운 문제도 재미있게 쉽게 풀 수 있지 않을까 하고 기대하고 있습니다.



Top