Training a Chess AI using TensorFlow

Nihal Puram
4 min readSep 14, 2021

--

Using the power of deep learning and Stockfish to train a neural network to play the game of chess.

Why am I doing this?

To put it plainly, I love chess. Don’t get me wrong, I’m not a great player. But, I have been playing chess since I was 5 or 6. Although I have never been good enough to compete, the game has been around me a lot and it's a part of my life.

recently during the lockdown, I have started playing chess again and it really piqued my interest. But after being exposed to machine learning and deep learning I always wanted to build my own ChessBot/ChessAI.

Chess Stock Image from ADOBE

First step of course is to come up with a plan and here’s mine

  • Make a dataset of chess position and their evaluations with Stockfish
  • Make a regression model that evaluates a position (like Stockfish)

Installing Stockfish

Now that we know what to do, it's time to first install stockfish. You can clone my GitHub repo here (contains all files including stockfish).

To generate the board and dictate the general play we will use the python-chess library.

I will be sharing some code and the key ideas and concepts that are involved, the complete code can be found here.

# this function will create our x (board)
def random_board(max_depth=200):
board = chess.Board()
depth = random.randrange(0, max_depth)
for _ in range(depth):
all_moves = list(board.legal_moves)
random_move = random.choice(all_moves)
board.push(random_move)
if board.is_game_over():
break
return board
# this function will create our f(x) (score)
def stockfish(board, depth):
with chess.engine.SimpleEngine.popen_uci('stockfish/13/bin/stockfish') as sf:
result = sf.analyse(board, chess.engine.Limit(depth=depth))
score = result['score'].white().score()
return score

Using this code we can evaluate any chess position. A positive number “White is winning” or a negative number meaning “Black is winning”. Using this function we can create a dataset that can evaluate a set of random positions. We can then create a model that can use this information to evaluate future predictions.

Creating the dataset

Now we need to convert the board representation to something meaningful. A 3d matrix of sizes 8 x 8 x 14 where 8x8 represents the board and the 14 represents the 7 different pieces.

squares_index  =  {  'a':  0,  'b':  1,  'c':  2,  'd':  3,  'e':  4,  'f':  5,  'g':  6,  'h':  7  }def square_to_index(square):
letter = chess.square_name(square)
return 8 - int(letter[1]), squares_index[letter[0]]

def split_dims(board):
# this is the 3d matrix
board3d = numpy.zeros((14, 8, 8), dtype=numpy.int8)
for piece in chess.PIECE_TYPES:
for square in board.pieces(piece, chess.WHITE):
idx = numpy.unravel_index(square, (8, 8))
board3d[piece - 1][7 - idx[0]][idx[1]] = 1
for square in board.pieces(piece, chess.BLACK):
idx = numpy.unravel_index(square, (8, 8))
board3d[piece + 5][7 - idx[0]][idx[1]] = 1
aux = board.turn
board.turn = chess.WHITE
for move in board.legal_moves:
i, j = square_to_index(move.to_square)
board3d[12][i][j] = 1
board.turn = chess.BLACK
for move in board.legal_moves:
i, j = square_to_index(move.to_square)
board3d[13][i][j] = 1
board.turn = aux
return board3d

This function above maps the pieces to the squares and stacks them into an array of sizes (8,8,14). We can use this multi-dimensional array as an input into our Convolutional Neural Network(CNN) to predict our evaluation.

Building the model

I have made a function through which you can train a model on a parameter of depth. Its a simple Convolutional layer with a flatten layer proceeding it. It contains a ‘same’ padding parameter as we do not want to change the overall dimensions of the input during the flow.

def build_model(conv_size, conv_depth):
board3d = layers.Input(shape=(14, 8, 8))
x = board3d
for _ in range(conv_depth):
x = layers.Conv2D(filters=conv_size, kernel_size=3,
padding='same', activation='relu')(x)
x = layers.Flatten()(x)
x = layers.Dense(64, 'relu')(x)
x = layers.Dense(1, 'sigmoid')(x)
return models.Model(inputs=board3d, outputs=x)

There are a bunch of designs you can try I’ve experimented with a few ones. You can find them in my repo.

Results

The only step left is to train the model. I’ve trained my models on google colab. and tested them out on my local machine. I have run the following tests:

  1. AI (white) vs Stockfish (Black)
  2. AI (white) vs AI (Black)
  3. AI (white) vs Human (Black) — me

What I have learned from these results is that the AI knows how to play chess, but it doesn't really play at a good level. Stockfish was very easily able to beat it, this was expected as the AI was trying to imitate stockfish and we can’t expect it to be better than the data it was trained on. My over the board rating is around 1300 elo and I was comfortably able to beat it. My guesstimate is that this AI might be around 600 elo or even lower like a beginner in the game. It starts off well, but makes blunders quite often and ends up losing the games. I will try other methods like reinforcement learning later on. You can contact me at my socials linked below and with that peace out!

--

--

Nihal Puram

I’m Nihal Puram. I’m an aerospace engineering student at IIT Madras. I am also a Self-Taught programmer/Deep learning Engineer.