# Training a neural network on chess data

I have been writing a chess engine with a friend and the engine itself is really good already (2700+ CCRL). We had the idea to use a neural network to have a better evaluation of positions.

### Input to the network

because the output of the network greatly depends on which side has to move, we use the first half of the inputs to parse the position of who has to move and the second half for the opponent. In fact, we have for each piece and for each square an input which would result in 12x64 inputs. We had the idea to also include the opponent king position. So each side had 6x64 inputs and this for each square the opponent king can be -> 6x64x64. In total, this results in 12x64x64 binary input values where at maximum 32 are set.

### Layers

The next layer consists of 64neurons where the first 32 neurons only accept inputs from the first half of the input features and the last 32 only accept inputs from the second half of the input features.

It follows a layer with 32 neurons fully connected and the output layer has only a single output.

### Activation function

We use LeakyReLU at both hidden layers and a linear activation function at the output.

### Training

Initially, I wanted to train the network on about 1 million positions yet this is taking ages. The position itself has a target value in the range of -20 to 20. I am using stochastic gradient descent using ADAM with a learning rate of 0.0001 and MSE as the loss function.

The problem I have is that this is taking a very very long time to even train those 1 million positions. The target is to later train on 300M positions.

I am not sure where I could improve the training progress.

Below are the graphs which show the training progress over 1000 iterations

The change for each iteration looks like this:

I hope someone could give me one or two hints on what I could improve in order to train the network faster. I am very happy for any advice!

Greetings, Finn

# Edit 1

As suggested, I should convert my network to keras. I am having problems getting the sparse input to run.

import keras
from keras.layers import Input, Concatenate, Dense, LeakyReLU
from keras.models import Model
from keras import backend as K
import numpy as np

# trainX1 = tf.SparseTensor(indices=[[0,0], [0,1]], values=[1, 2], dense_shape=[1,24576])
# trainX2 = tf.SparseTensor(indices=[[0,0], [0,1]], values=[1, 2], dense_shape=[1,24576])
#
# trainY = np.random.rand(1)

trainX1 = np.random.random((10000,24576))
trainX2 = np.random.random((10000,24576))

trainY = np.zeros((10000,1))

#input for player to move
activeInput = Input((64*64*6,))
inactiveInput = Input((64*64*6,))

denseActive = Dense(64)(activeInput)
denseInactive = Dense(64)(inactiveInput)

act1 = LeakyReLU(alpha=0.1)(denseActive)
act2 = LeakyReLU(alpha=0.1)(denseInactive)

concat_layer= Concatenate()([act1, act2])
dense1 = Dense(32)(concat_layer)

act3 = LeakyReLU(alpha=0.1)(dense1)

output = Dense(1, activation="linear")(act3)

model = Model(inputs=[activeInput, inactiveInput], outputs=output)

# print(model.summary())

print(model.fit([trainX1,trainX2], trainY, epochs=1))



If I use sparse=True for the Dense layer, it will throw some exceptions. I am happy if someone could help me creating sparse input vectors.

• What hardware is it running on and what do you mean by a "long time" ? – Robert Long Jul 26 '20 at 7:37
• I implemented the code myself in c++. 1M forward iterations take about 1sec whereas 1M training iterations take about 15sec. I train on a single core on my AMD ryzen 3950x – Finn Eggers Jul 26 '20 at 7:39
• Maybe just try it on Colab with GPU? Also, unless you know what you’re doing and have enough time for optimizing the code, using ready software like TensorFlow or PyTorch would be more efficient. – Tim Jul 26 '20 at 7:50
• I dont use a GPU. I wrote everything from scratch but I sort of know what I am doing. I implemented full AVX2 support. I mean the speed itself really isnt the problem I think. The problem is more that its simply not converging as fast as it should – Finn Eggers Jul 26 '20 at 7:52
• @MichaelM I'm saying they should implement it in Torch or similar. – Robert Long Jul 26 '20 at 10:44

I think you need to consider running it on a GPU. Google Colab is free and Amazon AWS is very cheap. You seem to know what you are doing so you can probably get up and running with PyTorch very quickly. Once you compare the performance of the same network implemented on GPU vs your single processor setup, you will be in a better to position to know where to go next.

• the problem is that simply putting it onto the gpu wont help most likely. the biggest problem here is the immense size of the input. I managed to handle the sparse input on the CPU and effectively only use about 1000 weights per iteration of the first layer. if I would use tensorflow or pytorch or sth like that, it wouldnt be able to understand that sparse input – Finn Eggers Jul 26 '20 at 8:03
• Torch supports sparse tensors – Robert Long Jul 26 '20 at 8:13
• mhm i will have a look at it. thank you – Finn Eggers Jul 26 '20 at 8:22
• No worries. Good luck, it's an interesting project! – Robert Long Jul 26 '20 at 8:24
• Yes I did. the error started going up. both for sgd and adam – Finn Eggers Jul 26 '20 at 18:21

You could also try the CPU-friendly NNUE alternative. It is currently been developed for chess by the Stockfish team and seems to give good results. It is easy to use and train the networks, and it should be much easier than the hard-way. I've been working on the Stockfish team, and I think I could also help you with your engine if you wish (I'm also working on my own chess engine). Regards and good luck!

• thats what we are trying :) – Finn Eggers Jul 29 '20 at 18:19
• It would be amazing if you could help us! If you like, you can add me on discord: Luecx#0540 – Finn Eggers Jul 29 '20 at 18:21
• What language are you using for the engine? – player1 Jul 29 '20 at 18:24
• C++. I also added AVX support – Finn Eggers Jul 29 '20 at 18:24
• Okay, fine. Does it support UCI commands? – player1 Jul 29 '20 at 18:25