저는 아주 오랫동안 체스를 쳐왔고, CS를 시작한 이후로 항상 체스 봇을 만들고 싶었습니다. 드디어 해냈어?.
여기 내 봇(검은색)이 나(흰색)를 짓밟는 영상이 있습니다.
chess.com 프로필은 다음과 같습니다: https://www.chess.com/member/chessables_with_chat_gpt.
git clone https://github.com/samliu21/chess-ai
실행하세요. cd chess-ai
사용하여 해당 디렉토리로 이동하세요.python -m venv .
source bin/activate
로 활성화하십시오.python -m pip install -r requirements.txt
사용하여 필요한 종속성을 설치합니다.cd gui
사용하여 올바른 디렉토리로 이동하고 python main.py
호출하여 플레이하세요! 저는 표준 PGN 형식의 게임이 포함된 공식 Lichess 데이터베이스를 사용했습니다. 데이터 정리 프로세스는 다음과 같습니다.
pgn-extract
사용하여 FEN을 추가하세요. 자세한 내용은 data_cleaning
폴더를 참고하세요.
처음에는 minimax 알고리즘과 쌍을 이루는 보드 평가 신경망을 만들려고 했습니다. 이 접근 방식에는 두 가지 문제가 있었습니다.
평가 네트워크가 내 기대에 미치지 못했습니다. 물질적 불균형은 감지할 수 있지만 단순한 장군은 감지할 수 없습니다.
체스의 행동 공간이 크기 때문에 미니맥스 알고리즘은 알파-베타 가지치기로 최적화된 경우에도 매우 느립니다.
이러한 요인들이 함께 초기 아이디어를 폐기하고 다른 것을 시도하게 만들었습니다.
GUI는 pygame
및 python-chess
모듈을 사용하여 손으로 제작되었습니다.
이 아키텍처는 Standford 논문에서 크게 영감을 받았습니다.
AI는 두 가지 모델을 사용합니다. 둘 다 보드 위치를 입력으로 받고 소프트맥스 확률의 8x8
매트릭스를 출력합니다. "모델에서"는 밖으로 이동할 사각형을 예측하고 "모델로"는 안으로 이동할 사각형을 예측합니다.
이 접근 방식은 예를 통해 가장 잘 설명됩니다. 시작 보드 위치와 이동을 고려하십시오: Nf3
. 이 움직임의 평가는 from 모델의 g1
제곱 값과 to 모델의 f3
제곱 값을 곱한 것입니다.
모든 합법적인 움직임 중에서 가장 큰 제품이 선택된 움직임입니다.
신경망은 6개의 컨벌루션 레이어, 그 뒤에 2개의 아핀 레이어와 출력 레이어로 구성됩니다. 아키텍처에 대한 보다 자세한 스케치는 아래에서 확인할 수 있습니다.
Model: "model"
__________________________________________________________________________________________________
Layer (type) Output Shape Param # Connected to
==================================================================================================
input_1 (InputLayer) [(None, 8, 8, 12)] 0 []
conv2d (Conv2D) (None, 8, 8, 32) 3488 ['input_1[0][0]']
batch_normalization (BatchNorm (None, 8, 8, 32) 128 ['conv2d[0][0]']
alization)
activation (Activation) (None, 8, 8, 32) 0 ['batch_normalization[0][0]']
conv2d_1 (Conv2D) (None, 8, 8, 64) 18496 ['activation[0][0]']
batch_normalization_1 (BatchNo (None, 8, 8, 64) 256 ['conv2d_1[0][0]']
rmalization)
activation_1 (Activation) (None, 8, 8, 64) 0 ['batch_normalization_1[0][0]']
conv2d_2 (Conv2D) (None, 8, 8, 256) 147712 ['activation_1[0][0]']
batch_normalization_2 (BatchNo (None, 8, 8, 256) 1024 ['conv2d_2[0][0]']
rmalization)
activation_2 (Activation) (None, 8, 8, 256) 0 ['batch_normalization_2[0][0]']
concatenate (Concatenate) (None, 8, 8, 512) 0 ['activation_2[0][0]',
'activation_2[0][0]']
conv2d_3 (Conv2D) (None, 8, 8, 256) 1179904 ['concatenate[0][0]']
batch_normalization_3 (BatchNo (None, 8, 8, 256) 1024 ['conv2d_3[0][0]']
rmalization)
activation_3 (Activation) (None, 8, 8, 256) 0 ['batch_normalization_3[0][0]']
concatenate_1 (Concatenate) (None, 8, 8, 320) 0 ['activation_3[0][0]',
'activation_1[0][0]']
conv2d_4 (Conv2D) (None, 8, 8, 256) 737536 ['concatenate_1[0][0]']
batch_normalization_4 (BatchNo (None, 8, 8, 256) 1024 ['conv2d_4[0][0]']
rmalization)
activation_4 (Activation) (None, 8, 8, 256) 0 ['batch_normalization_4[0][0]']
concatenate_2 (Concatenate) (None, 8, 8, 288) 0 ['activation_4[0][0]',
'activation[0][0]']
conv2d_5 (Conv2D) (None, 8, 8, 256) 663808 ['concatenate_2[0][0]']
batch_normalization_5 (BatchNo (None, 8, 8, 256) 1024 ['conv2d_5[0][0]']
rmalization)
activation_5 (Activation) (None, 8, 8, 256) 0 ['batch_normalization_5[0][0]']
dense (Dense) (None, 8, 8, 256) 65792 ['activation_5[0][0]']
batch_normalization_6 (BatchNo (None, 8, 8, 256) 1024 ['dense[0][0]']
rmalization)
dense_1 (Dense) (None, 8, 8, 64) 16448 ['batch_normalization_6[0][0]']
batch_normalization_7 (BatchNo (None, 8, 8, 64) 256 ['dense_1[0][0]']
rmalization)
dense_2 (Dense) (None, 8, 8, 1) 65 ['batch_normalization_7[0][0]']
batch_normalization_8 (BatchNo (None, 8, 8, 1) 4 ['dense_2[0][0]']
rmalization)
softmax (Softmax) (None, 8, 8, 1) 0 ['batch_normalization_8[0][0]']
==================================================================================================
Total params: 2,839,013
Trainable params: 2,836,131
Non-trainable params: 2,882
__________________________________________________________________________________________________