Skip to content
Ladofa edited this page Aug 25, 2018 · 14 revisions

개발 일지나 써보려고 합니다.

이전 상황

어찌저찌해서 MCTS 기반의 장기 알고리즘을 만들었습니다만.. 성능이 좋지 않습니다. 무엇보다 롤아웃 성능이 받쳐주지 않기 때문이겠죠. 현재의 수가 옳은지를 판단하기 위해서 몇 수십번의 롤아웃을 거치거나 가치망(value network)으로 판단하면 좋겠지만 몇 레벨 이상 내려가서 확인을 한 뒤에야 옳다는 것을 확인하네요. MinMax로 구현한 것 보다 기력이 떨어집니다. 어쨌든 MCTS구현 자체에는 문제가 없다는 결론을 내렸고, 이제 본격적인 딥러닝으로 넘어갑니다.

2017. 08. 29.

*현재 강화 학습을 이용하여 정책 네트워크를 훈련해보려고 합니다. 일절의 지도 학습 없이 강화 학습만으로 진행할 계획입니다. 얼마나 성능을 끌어올릴 수 있을지, 그리고 인간을 이길 정도가 되었을 때 장기 두는 모양이 어떠할지 궁금하네요.

*TensorFlow는 우선 파이썬으로 개발하고, TCP/IP로 C#과 통신하려고 합니다. 나중에 릴리즈 할 때는 닷넷 래퍼를 활용할 생각입니다.

2017. 09. 04.

*Policy Network를 만들 때, 바둑의 착수는 361가지지만 장기는 그렇지 않다. 일반적인 게임 탐색 범위는 40가지 정도의 경우의 수에 불과하겠지만 딥러닝 네트워크를 설계할 때는 가능한 모든 아웃풋을 출력 노드로 만들어두어야 한다. 기물의 시작지점->착수지점으로 생각해보면 시작지점 90 * 착수지점 90 = 8100 가지의 경우의 수를 모두 출력 노드로 만들어야 한다. 콘볼루션 필터가 3x3x56x56, stride=1일 경우 해당 네트워크의 아웃풋은 9x10x56, 갯수로는 5040이 된다. 이제 5040x8100의 FC를 만들면 대략 4000만개의 웨이트가 생성된다. 이 중, 대부분은 쓸데없는 것들이므로 드랍아웃이 필수.

출력노드의 갯수를 줄이기 위해 다양한 고민을 해봤다. 시작지점 대신 36개의 각 기물을 지정하고 착수지점만 고려하면 36x90=3240이 된다. 그런데 실제로 우리가 장기에서 전략을 짤 때, 졸1 졸2 졸3.. 구분하지 않으므로... 하여튼 좀 복잡해진다.

대신 90개의 모든 착수지점을 생각할 필요는 없을 것 같다. (0, 0)에서 출발해서 (8, 8)로 뛸 수 있는 기물은 없다. 포, 궁, 사, 졸 등 직선형 기물이 갈 수 있는 곳은 차가 갈 수 있는 곳의 부분집합이다. 마, 상만 따로 고려하면 된다. 그리고 각 개별 움직임에 대한 룩업 테이블을 만든다. [0] = (0, 0)->(0, 1) [1] = (0, 0)->(1, 2) ..와 같은 식이다. 이 룩업 테이블을 생성하는 프로젝트 genMoveSet을 만들었다. 그 결과 2443개의 공간이 생긴다. 5040x2443=약 1200만개. 중간에 512개짜리 히든레이어를 만들면 400만개정도의 웨이트를 조정한다. 히든레이어가 입출력 레이어보다 작으면 인코딩 효과가 있다. 어차피 탐색하는 경우의 수가 40가지 정도이므로 512개의 노드로 인코딩 좀 한다고 큰일은 안 나겠지?

2017. 09. 08.

드디어 Reignforcement방식의 학습을 돌리기 시작했다. 입력으로 10x9x118, conv 5x5x192 1개, 3x3x192 4개 ?x2551 fc 1개.. VCC에 비하면 그렇게 많은 양도 아닌데 회사컴퓨터로 돌려보면 학습이 너~~무 더디게 진행되어 돌덩이를 주무르는 기분이다. conv1개만 쓰면 빨리 빨리 되는데.. 괜히 욕심을 내어 random init 상태에서 강화학습으로만 알고리즘을 만들려니 일단 가능한 수에 대한 학습도 힘들다. 나중에 인간장기 기보를 모아서 학습을 진행해봐야겠다. 학습속도와 별개로 데이터를 처리하는데 오버헤드가 많다. CPU-GPU가 할 수 있는 일을 멀티테스크로 처리하든지 하고, 쓸데없는 메모리 복사, 데이터 가공을 줄이는 최적화가 필요하다.

2017. 09. 18.

여러 번의 삽질 끝에 학습이 돌아가기 시작한다. 일단 128개의 필터, 5x5 1개, 3x3 5개의 conv레이어 + 4096 fc 히든 레이어를 탑재하려고 한다. 알파고에는 없는 히든 레이어를 둔 이유는 디코딩이 필요하다고 생각했기 때문이다. 알파고는 착수점만 아웃풋으로 내지만 야매장기는 시작점->착수점의 모든 경우의 수가 2550개이다. 알파고는 2차원 데이터를 일렬로 벡터화하지만 야매장기는 아웃풋이 4차원이므로 디코딩 레이어가 필요하다고 생각했다.

conv가 쌓일 수록 더 많은 영역을 커버할 수 있다. 예를 들어 5x5 1개는 특정 x,y의 값을 4칸까지 전파시킨다. 3x3은 2칸까지 전파시킨다. 알파고는 5x5 한개와 3x3 10개로 이루어져 있는데, 전파 범위가 24이다. 바둑판의 사이즈 19x19보다 약간 큰 사이즈. 이런 식으로 생각하여 야매장기에서는 5x5 1개와 3x3 5개를 사용, 14의 전파범위를 갖는다.

softmax_cross_entropy_with_logits 함수 내에 이미 softmax 연산이 포함된 걸 모르고 tf.nn.softmax를 거친 값을 넣었더니 학습이 안 되는 것이었다. 이걸 몰라서 열흘동안 삽질만 했다.

Reignforcement를 학습시키기 전에 그냥 랜덤 착수를 학습시킨다. 2551개의 아웃풋 중에 인풋 장기판을 기준으로 가능한 수는 겨우 30개 남짓이다. 맨땅에서 Reignforcement를 학습시키려고 하면 네트워크는 불가능한 수만 뱉어낸다. 우선 랜덤 착수(가능한 수 중에서 뽑는다)를 학습시켜서 네트워크가 최소한 장기 룰에 맞는 결과를 내도록 학습 시킨 뒤 Reignforce 방법을 동원할 것이다. 시작부터 랜덤한 수를 200개까지 뽑아서 장기를 진행시킨 후, 학습에는 20수 이상부터 진행된 기보만 넣는다. 테스트는 1~19수까지의 진행으로 한다. 네트워크가 보내온 확률 분포 중 룰에 맞는 값의 비율을 따져서 학습이 되는지 확인한다...... 결과는 0.09 언저리에서 정체되는구만.. 학습률은 AdamOptimizer(1)이다. 아웃풋 노드의 개수를 더 줄일 수 있다면 이와 같은 고생도 덜 하게 될 것 같은데.. 더 이상 방법이 떠오르지 않는다.

2017. 09. 23.

학습을 진행할수록 느끼는 건 네트워크는 무조건 클 수록 좋다는 거. 단순한 학습 속도는 느리지만 네트웍의 크기만큼 더 학습이 잘 되기 때문에 결과적으로는 오히려 학습 속도가 빠르다는 느낌을 준다. 문제는 로딩하는데 너무 오래 걸린다는 거지.

단순한 강화학습만으로는 너무 오랜 세월이 걸린다. 학습 속도가 문제가 아니라 학습 자료를 만드는 과정이 너무 오래걸린다. 어떻게 하면 최적의 속도로 강화학습을 진행할 수 있을까.

강화학습이 너무 오래걸려서 일단 기존의 기보를 학습해보기로 했다. 모든 착수점을 학습하고 덤으로 경기 승패에 따라 value network도 학습했다. 약 50만착수점 정도 되면 더 이상 loss가 줄어들지 않는다. 이 상태에서 MCTS를 적용해서 두어보면 정말 신기하게 사람처럼 둔다. 문제는 내가 떡수를 두었을 때 대처를 못 한다는 것이다. 차길을 열어서 먹으라고 대줘도 먹지 않는다. 이유는 학습 기보에 나처럼 바보같은 플레이를 하는 기보가 없었기 때문이다. 나랑 게임한 기보를 학습시키면 나아지려나 생각도 해봤는데, 그렇게 하면 차길을 열어준 뒤, 상대방이 안 먹으면 내가 상대방 차를 먹는 전략(?)을 배우게 될까봐 그것도 안 될 것 같다. 강화학습에 대한 고민이 커지고 있다.

정상적으로 두면 대강 인간처럼 두는 것 같지만

장을 대줘도 먹지 않으며

차를 대줘도 안 먹는다.

2017. 09. 27.

강화학습의 일환으로 완전 랜덤 전략 vs PseudoYame 의 경기를 학습시켰다. 슈도야매는 본격 야매 이전에 대충 MCTS를 테스트하고자 만들었는데, 일단 보이면 먹고 보는 경향이 강하다. 그래도 위의 학습 결과처럼 대줘도 안 먹는 경우는 없을 것이다.

둘 간의 승률은 슈도야매의 99.999퍼센트 승리로 나타난다. 학습 결과를 레알야매에 태워서 시합해보니 여전히 바보같이 대줘도 안 먹는다. 내가 보여주는 패턴과 랜덤이 보여주는 패턴이 다른 것이다. 아직까지는 인공지능이라기보다 기보를 저장하는 룩업테이블같다.

2017. 09.28

강화학습 재도전, PseudoYame vs Policy Network 의 경기를 학습한다. 일단 PseudoYame의 전략은 그대로 베낄 수 있을 것으로 예상되는데, 더욱 기대하는 것은 PolicyNetwork가 PseudoYame를 완전히 제압하는 수준으로 학습되는 것이다. 매 경기의 결과가 실시간으로 PolicyNetwork에 학습이 되기 때문에, PseudoYame는 똑같은 실력을 보이지만 PolicyNetwork는 매 경기마다 점점 기력이 향상되어야 한다.

2018. 8.25

한참 회사 일이 바빠서 버려두는 동안 알파 제로도 나오고, 텐서플로우도 몇 번의 버전업을 거쳤다. 아무도 관심을 가져주지 않으면 나 역시 관심을 안 가지겠는데 스타가 4개나 달리고 포크도 1개 있다... 도대체 이 시시한 프로젝트에 스타를 달아주는 마음씨가 너무 고마워서 그냥 버려둘 수가 없었다.

그래서 알파 제로 까지는 아니더라도 기존의 코드를 수정해서 어느 정도 요즘 텐서플로우에 맞게 고치려고 한다. 학습도 기존의 C#과 파이썬의 하이브리드 형식에서 파이썬만 이용해서 학습하도록 고친다. 하여튼 최신의 텐서플로우 학습 코드 형태로 고칠 계획인데..

그렇게 하려니 장기 게임과 관련된 로직을 예전에 C#으로 짰던 걸 파이썬으로 다시 짜야 한다. 에라 모르겠다, 그냥 해 본다. 하여 예전 코드를 천천히 살펴보니 버그가 너무 많아서 얼굴이 화끈화끈. 가장 치명적인 문제점으로 데이터 학습 과정에서 한의 착수를 학습할 경우, 위 아래를 뒤집어야 하는데, 판은 뒤집혔으나, 한(yo)과 초(my)의 장기알 코드를 바꾸지 않았던 것이다. 아래쪽에는 무조건 초 장기알이 위치하고 위쪽에는 무조건 한 장기알이 위치하도록 디자인한 것은 나인데... 그 규칙을 지키지 않았으니 학습이 제대로 될 리가 없다. 그 외에 기억나지 않는 짜잘한 버그들도 많다. 하여튼 마개조를 해보려고 한다.

예전 코드는 착수 가능 위치 계산을 빠르게 하기 위해 다소 복잡한 테크닉을 썼었는데, 설명 없이 이해하기는 쉽지 않을 것 같다. 다시 그렇게 구현하기도 귀찮고 해서 그런 테크닉을 제외한다. 아마 속도는 더 느려질 것 같다.