
체스 AI라고 하면 대부분 스톡피시부터 떠올립니다. 스톡피시는 가능한 수를 엄청나게 탐색하고, 그중 가장 강한 수를 고르는 방식입니다. 하지만 제가 만들고 싶었던 것은 단순히 강한 AI가 아니었습니다.
제가 원한 것은 인간의 대국만 학습하고, 인간이 둘 법한 수를 선택하는 AI였습니다. 계산기처럼 완벽한 수만 찾는 것이 아니라 실제 고수들의 기풍과 실수, 선호하는 형태까지 어느 정도 따라 하는 AI를 만들어 보고 싶었습니다.
제가 원한 것은 인간의 대국만 학습하고, 인간이 둘 법한 수를 선택하는 AI였습니다. 계산기처럼 완벽한 수만 찾는 것이 아니라 실제 고수들의 기풍과 실수, 선호하는 형태까지 어느 정도 따라 하는 AI를 만들어 보고 싶었습니다.
인간 기보를 학습 데이터로 사용했다
학습 데이터는 2000~2400 Elo 구간의 인간 대국으로 구성했습니다. 최종적으로 정리한 데이터는 약 85,682,704 ply였습니다. ply는 한쪽이 말을 한 번 움직인 것을 뜻합니다.
이 가운데 훈련 데이터는 77,155,648개, 검증 데이터는 4,263,904개였습니다. 데이터에는 현재 체스판 상태, 실제로 인간이 둔 수, 양쪽 플레이어의 Elo, 대국 결과 같은 정보가 들어갔습니다.
Stockfish가 계산한 정답 수나 평가값은 넣지 않았습니다. Stockfish의 판단을 넣으면 결국 인간 기보를 사용하는 의미가 줄어들기 때문입니다. 이 AI는 끝까지 인간이 실제로 둔 수와 대국 결과만 보고 학습하도록 만들었습니다.
다만 데이터의 Elo 분포는 완전히 균등하지 않았습니다.
2000~2099: 약 49.34%
2100~2199: 약 28.41%
2200~2299: 약 15.37%
2300~2399: 약 6.84%
평균 Elo는 약 2124였습니다. 높은 Elo로 갈수록 기보가 적었기 때문에 나중에는 Elo별 모델을 따로 사용하거나 여러 모델을 합치는 방법도 시험하게 됐습니다.
이 가운데 훈련 데이터는 77,155,648개, 검증 데이터는 4,263,904개였습니다. 데이터에는 현재 체스판 상태, 실제로 인간이 둔 수, 양쪽 플레이어의 Elo, 대국 결과 같은 정보가 들어갔습니다.
Stockfish가 계산한 정답 수나 평가값은 넣지 않았습니다. Stockfish의 판단을 넣으면 결국 인간 기보를 사용하는 의미가 줄어들기 때문입니다. 이 AI는 끝까지 인간이 실제로 둔 수와 대국 결과만 보고 학습하도록 만들었습니다.
다만 데이터의 Elo 분포는 완전히 균등하지 않았습니다.
2000~2099: 약 49.34%
2100~2199: 약 28.41%
2200~2299: 약 15.37%
2300~2399: 약 6.84%
평균 Elo는 약 2124였습니다. 높은 Elo로 갈수록 기보가 적었기 때문에 나중에는 Elo별 모델을 따로 사용하거나 여러 모델을 합치는 방법도 시험하게 됐습니다.
첫 번째 모델은 Policy였다
가장 먼저 만든 것은 Policy 모델입니다. Policy는 현재 체스판을 보고 다음에 둘 가능성이 높은 수들을 예측합니다.
예를 들어 현재 위치에서 인간 고수들이 주로 Nf3, Bc4, d4를 뒀다면, AI도 이 수들에 높은 확률을 주도록 학습합니다. 반드시 가장 강한 수를 고르는 것이 아니라 인간들이 실제로 선호한 수를 재현하는 방식입니다.
학습이 끝난 모델은 policy_v1_best.pt로 저장했습니다. 이후 GUI에서 Temperature와 Top-K 값을 조절할 수 있게 만들었습니다.
Temperature가 낮으면 가장 확률이 높은 수를 안정적으로 선택하고, 높이면 확률이 조금 낮은 수도 선택합니다. Top-K는 Policy가 제시한 후보 중 몇 개까지 고려할지를 결정합니다.
Policy만 사용해도 AI는 체스 규칙에 맞게 수를 두고 인간 기보와 비슷한 오프닝을 진행했습니다. 하지만 문제가 있었습니다. Policy는 다음 수가 인간답다는 것은 알지만, 그 수를 둔 뒤 실제로 유리해지는지는 제대로 판단하지 못했습니다.
예를 들어 현재 위치에서 인간 고수들이 주로 Nf3, Bc4, d4를 뒀다면, AI도 이 수들에 높은 확률을 주도록 학습합니다. 반드시 가장 강한 수를 고르는 것이 아니라 인간들이 실제로 선호한 수를 재현하는 방식입니다.
학습이 끝난 모델은 policy_v1_best.pt로 저장했습니다. 이후 GUI에서 Temperature와 Top-K 값을 조절할 수 있게 만들었습니다.
Temperature가 낮으면 가장 확률이 높은 수를 안정적으로 선택하고, 높이면 확률이 조금 낮은 수도 선택합니다. Top-K는 Policy가 제시한 후보 중 몇 개까지 고려할지를 결정합니다.
Policy만 사용해도 AI는 체스 규칙에 맞게 수를 두고 인간 기보와 비슷한 오프닝을 진행했습니다. 하지만 문제가 있었습니다. Policy는 다음 수가 인간답다는 것은 알지만, 그 수를 둔 뒤 실제로 유리해지는지는 제대로 판단하지 못했습니다.
Value 모델을 추가했다
이 문제를 해결하기 위해 Value 모델을 추가했습니다.
Value는 현재 체스판에서 어느 쪽이 이길 가능성이 높은지를 -1부터 +1 사이의 값으로 평가합니다. 백이 유리하면 양수, 흑이 유리하면 음수에 가까운 값을 출력하도록 만들었습니다.
Value 모델 역시 Stockfish 평가값이 아니라 실제 인간 대국의 승패 결과를 기준으로 학습했습니다. 사용한 Value 모델의 파라미터 수는 438,801개로 비교적 작게 구성했습니다. RTX 4070 Laptop 8GB에서도 학습하고 실행할 수 있어야 했기 때문입니다.
최대 8 epoch까지 학습하도록 했고, 검증 성능이 더 이상 좋아지지 않으면 조기에 학습을 멈추도록 설정했습니다. 학습된 모델은 value_v1.pt와 value_v1_best.pt로 저장했습니다.
Value는 현재 체스판에서 어느 쪽이 이길 가능성이 높은지를 -1부터 +1 사이의 값으로 평가합니다. 백이 유리하면 양수, 흑이 유리하면 음수에 가까운 값을 출력하도록 만들었습니다.
Value 모델 역시 Stockfish 평가값이 아니라 실제 인간 대국의 승패 결과를 기준으로 학습했습니다. 사용한 Value 모델의 파라미터 수는 438,801개로 비교적 작게 구성했습니다. RTX 4070 Laptop 8GB에서도 학습하고 실행할 수 있어야 했기 때문입니다.
최대 8 epoch까지 학습하도록 했고, 검증 성능이 더 이상 좋아지지 않으면 조기에 학습을 멈추도록 설정했습니다. 학습된 모델은 value_v1.pt와 value_v1_best.pt로 저장했습니다.
Policy, Value, Search를 결합했다
최종 구조는 다음과 같습니다.
Policy가 인간이 둘 법한 후보 수를 고릅니다.
Search가 후보 수들을 제한적으로 가상 전개합니다.
Value가 전개된 체스판이 어느 쪽에 유리한지 평가합니다.
탐색 점수와 Policy 확률을 합쳐 최종 수를 선택합니다.
모든 합법 수를 똑같이 탐색하면 너무 느려집니다. 그래서 Policy가 먼저 후보를 줄이고, 그 후보들만 Negamax 방식으로 탐색하도록 했습니다.
최종 점수에는 Value의 평가뿐 아니라 Policy의 log probability 보너스도 더했습니다. 이렇게 하면 탐색 결과가 조금 좋다는 이유만으로 인간이라면 거의 두지 않을 이상한 수를 선택하는 현상을 줄일 수 있습니다.
결국 이 AI는 신경망만 사용하는 것도 아니고, 검색만 사용하는 것도 아닙니다. 인간의 착수 분포를 학습한 신경망과 제한적인 수읽기를 결합한 구조입니다.
Policy가 인간이 둘 법한 후보 수를 고릅니다.
Search가 후보 수들을 제한적으로 가상 전개합니다.
Value가 전개된 체스판이 어느 쪽에 유리한지 평가합니다.
탐색 점수와 Policy 확률을 합쳐 최종 수를 선택합니다.
모든 합법 수를 똑같이 탐색하면 너무 느려집니다. 그래서 Policy가 먼저 후보를 줄이고, 그 후보들만 Negamax 방식으로 탐색하도록 했습니다.
최종 점수에는 Value의 평가뿐 아니라 Policy의 log probability 보너스도 더했습니다. 이렇게 하면 탐색 결과가 조금 좋다는 이유만으로 인간이라면 거의 두지 않을 이상한 수를 선택하는 현상을 줄일 수 있습니다.
결국 이 AI는 신경망만 사용하는 것도 아니고, 검색만 사용하는 것도 아닙니다. 인간의 착수 분포를 학습한 신경망과 제한적인 수읽기를 결합한 구조입니다.
탐색량 폭발 문제
Search를 처음 붙였을 때는 속도가 너무 느렸습니다. 탐색 깊이를 조금만 높여도 후보 수가 계속 늘어나면서 계산량이 폭발했습니다.
특히 상대도 Policy 후보 중 최선의 수를 둔다고 가정해야 했기 때문에, 내 후보 수와 상대 후보 수가 반복해서 곱해졌습니다. 이 상태에서는 한 수를 결정하는 데 지나치게 오랜 시간이 걸렸습니다.
그래서 Search v3 Fast에서는 다음 요소를 유지하면서 불필요한 탐색을 줄였습니다.
체크와 강제수 처리
메이트 감지
상대의 최선 대응 탐색
Policy를 이용한 후보 제한
중복 계산 감소
필요한 위치만 Value로 평가
완전히 깊게 읽는 AI는 아니지만, Policy만 사용할 때보다 큰 실수를 줄이면서 실행 속도도 어느 정도 확보할 수 있었습니다.
특히 상대도 Policy 후보 중 최선의 수를 둔다고 가정해야 했기 때문에, 내 후보 수와 상대 후보 수가 반복해서 곱해졌습니다. 이 상태에서는 한 수를 결정하는 데 지나치게 오랜 시간이 걸렸습니다.
그래서 Search v3 Fast에서는 다음 요소를 유지하면서 불필요한 탐색을 줄였습니다.
체크와 강제수 처리
메이트 감지
상대의 최선 대응 탐색
Policy를 이용한 후보 제한
중복 계산 감소
필요한 위치만 Value로 평가
완전히 깊게 읽는 AI는 아니지만, Policy만 사용할 때보다 큰 실수를 줄이면서 실행 속도도 어느 정도 확보할 수 있었습니다.
직접 대국할 수 있는 GUI를 만들었다
학습만 하고 끝내면 실제 기풍을 확인하기 어려워서 대국용 GUI도 만들었습니다.
GUI에서는 다음 기능을 조절할 수 있습니다.
사람 대 AI
AI 대 AI
AI Elo 설정
Temperature
Top-K
탐색 깊이
Policy와 Value 모델 선택
대국 PGN 저장
저장된 PGN에는 사용한 모델, epoch, Temperature, Top-K, 양쪽 Elo 등의 정보도 기록하도록 했습니다. 덕분에 설정별 대국 결과를 비교하고 어떤 조건에서 AI가 이상한 수를 두는지 추적할 수 있었습니다.
GUI에서는 다음 기능을 조절할 수 있습니다.
사람 대 AI
AI 대 AI
AI Elo 설정
Temperature
Top-K
탐색 깊이
Policy와 Value 모델 선택
대국 PGN 저장
저장된 PGN에는 사용한 모델, epoch, Temperature, Top-K, 양쪽 Elo 등의 정보도 기록하도록 했습니다. 덕분에 설정별 대국 결과를 비교하고 어떤 조건에서 AI가 이상한 수를 두는지 추적할 수 있었습니다.
완성된 AI의 한계
이 AI가 곧바로 2000 Elo 이상의 실력을 내는 것은 아닙니다. 학습 데이터에 2000~2400 Elo 기보가 들어 있다고 해서 모델 실력도 자동으로 그 수준이 되는 것은 아니기 때문입니다.
특히 다음 상황에서 약점이 나타났습니다.
학습 데이터에 드문 포지션
긴 전술을 읽어야 하는 상황
복잡한 엔드게임
강제 메이트가 멀리 있는 상황
높은 Elo 구간의 부족한 데이터
Policy가 좋은 수를 후보에서 제외한 상황
Search는 Policy가 제시한 후보만 살펴보기 때문에 진짜 좋은 수가 후보에 들어오지 않으면 찾을 수 없습니다. Value도 실제 승패만 보고 학습했기 때문에 세밀한 기물 우세나 장기적인 포지션 평가에는 한계가 있습니다.
그래도 결과는 흥미로웠습니다. Stockfish처럼 매 순간 가장 정확한 수만 두지는 않지만, 인간 기보에서 자주 등장한 오프닝과 전개 방식을 선택했습니다. 설정을 바꾸면 안정적으로 두거나, 조금 더 다양한 수를 시도하도록 만드는 것도 가능했습니다.
특히 다음 상황에서 약점이 나타났습니다.
학습 데이터에 드문 포지션
긴 전술을 읽어야 하는 상황
복잡한 엔드게임
강제 메이트가 멀리 있는 상황
높은 Elo 구간의 부족한 데이터
Policy가 좋은 수를 후보에서 제외한 상황
Search는 Policy가 제시한 후보만 살펴보기 때문에 진짜 좋은 수가 후보에 들어오지 않으면 찾을 수 없습니다. Value도 실제 승패만 보고 학습했기 때문에 세밀한 기물 우세나 장기적인 포지션 평가에는 한계가 있습니다.
그래도 결과는 흥미로웠습니다. Stockfish처럼 매 순간 가장 정확한 수만 두지는 않지만, 인간 기보에서 자주 등장한 오프닝과 전개 방식을 선택했습니다. 설정을 바꾸면 안정적으로 두거나, 조금 더 다양한 수를 시도하도록 만드는 것도 가능했습니다.
앞으로 개선할 부분
앞으로는 다음 부분을 개선할 생각입니다.
Elo 구간별 데이터 불균형 완화
Elo별 모델을 결합하는 앙상블
Value 모델의 평가 정확도 향상
Search 속도 최적화
반복 포지션과 엔드게임 처리 개선
유사한 인간 기보를 검색하는 기능 결합
AI 대 AI 자동 대국을 이용한 설정 비교
이 프로젝트의 목표는 Stockfish를 이기는 것이 아닙니다. 인간의 대국을 보고 인간다운 판단 방식을 일반화할 수 있는지 확인하는 것이 목표입니다.
아직 완성된 것은 아니지만, 인간 기보만으로 Policy를 학습하고 Value와 Search를 결합해 실제 대국까지 가능한 형태를 만들었습니다. 단순히 체스 수를 추천하는 모델에서 시작해, 이제는 인간의 선택을 흉내 내면서 제한적인 수읽기까지 하는 AI가 됐습니다.
Elo 구간별 데이터 불균형 완화
Elo별 모델을 결합하는 앙상블
Value 모델의 평가 정확도 향상
Search 속도 최적화
반복 포지션과 엔드게임 처리 개선
유사한 인간 기보를 검색하는 기능 결합
AI 대 AI 자동 대국을 이용한 설정 비교
이 프로젝트의 목표는 Stockfish를 이기는 것이 아닙니다. 인간의 대국을 보고 인간다운 판단 방식을 일반화할 수 있는지 확인하는 것이 목표입니다.
아직 완성된 것은 아니지만, 인간 기보만으로 Policy를 학습하고 Value와 Search를 결합해 실제 대국까지 가능한 형태를 만들었습니다. 단순히 체스 수를 추천하는 모델에서 시작해, 이제는 인간의 선택을 흉내 내면서 제한적인 수읽기까지 하는 AI가 됐습니다.