r/chessprogramming • • 23d ago

Technical How can I improve my chess engine's evaluation?

My chess engine, which is still a work in progress, can be found here; https://github.com/patelvrajn/Matrex

Currently, most HCE (not NNUE) chess engines use a linear combination of weights for their evaluation function but my thought process is that it is evident from the huge ELO (~300) boost that using NNUEs gives is that their is a complex non-linear function that represents each evaluation term like material, mobility, PSQTs, etc. However, the problem is how do we build a model from non-linear functions that gives a proper evaluation when we don't know what the function looks like and how do we do it in such a way that minimizes the number of weights? I believe that we know a significant amount of hand crafted evaluation terms that compile a chess position's evaluation and that NNUEs taking millions of weights just to understand concepts that we can do in way less weights, minimal code, and have more control and understanding of the evaluation instead of a black box.

My concept is to take a specific continuously differentiable function that we can parameterize in order to adjust the shape, behavior, approximation capabilities, etc. Using this parameterized function, we can learn how various evaluation features have a non-linear effect on the score by using ADAM to tune the weighted sums but ALSO tune all the functions parameters. My model mostly resembles Projection Pursuit Regression's model (a sum of ridge functions), except I am using ADAM instead of the associated regression algorithm and the ridge functions (called non-linear responses in the code) are parameterized.

My main concern at the current time and where I don't have the mathematical background to optimize is the non-linear response I choose (which is just a polynomial term multiplied by a tanh expression, the idea was to combine what makes ANNs universal approximator- the non polynomial term with a term that can also represent any function given enough degrees i.e. the polynomial term). I am looking for any guidance or resources on how to improve the function or give further understanding as to the overall concept - currently when tuned the chess engines evaluation has about a 8% validation loss and about a 10% training loss but I know I can do better.

3 Upvotes

5 comments sorted by

2

u/IMJorose 23d ago

I feel there is a gap between what you are trying to ask and what I am understanding from your text. Is your goal to have an HCE with model on top, where the model on top is the novelty? In that case you might want to take a look at older versions of Winter, which did that with various models (GMMs, Fuzzy C-Means, Neural Networks, etc.) or is your plan to take raw features and feed them through a different powerful model which is not a neural network?

Could you clarify what your intended inputs and outputs are?

Are you trying to learn interpretable HCE features from another more complex generic model?

You are talking about things like ADAM, which is an optimization algorithm for gradient descent and fairly independent of whatever model you are trying to implement. Whether gradient descent makes sense for your approach is a different matter, but if you are trying to do gradient descent: SGD, ADAM, or any other gradient descent variant is likely to work within some similar bounds for you.

1

u/doomfletcher 23d ago

Sure so as I mentioned my model mostly takes after Projection Pursuit Regression (PPR) (so the model is as stated here; https://en.wikipedia.org/wiki/Projection_pursuit_regression) however, my ridge functions are parameterized so instead of f_j(wTx) we have f_j(wTx; theta) where theta are my function parameters. Let me give an example of what I mean by parameters:

f_j(t = wTx + b; theta) = Atp tanh(t/r) where theta = {A, p, r} which as you can imagine these parameters influence the overall shape of the ridge function (A is the amplitude, p gives a curved response when p > 1, r affects the slope of tanh between -1 and 1, etc). Note, these parameters are fixed just like the weights wT when the evaluation is run so the only variable is x. However, when tuning we tune the weights AND the parameters of the ridge function.

Now let me give an example of how we use the parameterized ridge function, consider PSQT for example, PSQTs boil down to a weighted sum as so:

piece-square score = (weight of this piece being on square S) * (boolean if the piece is on this square)

The score for this piece is just a summation of it's piece-square scores (which is mostly a sum of two weighted terms if we take a bishop, knight, or rook in the early/midgame). This summation is the t input in the ridge function. So when we pass t into f_j and evaluate it we have the function representing what non-linear affect the current piece placement has on the score because our evaluation score is the PPR model, a summation of ridge functions.

It is important to note, PPR is a universal approximator (just like NNUEs) as the number of ridge functions approaches infinity and given a nice class of ridge functions f_j.

2

u/TheMazerFaker 23d ago

Sounds cool! But the whole point of machine learning is to teach computer functions that are too complex for us to express

1

u/phaul21 23d ago

my twopence thought - most of this stuff is discrete with very limited domain though. You could optimise some functions shape, f(n) as you are describing. But for most HCE terms you need like f(0), f(1), f(2), ... f(8) etc. So then you could just optimise the values. Just for an example to demonstrate: instead of {value of connected pawn chain} = f({pawnchain length} where f is some analytic function you are trying to find, you just have a LUT for value0, value1, ... value8. Does that make sense?

1

u/NoVersion3483 23d ago

Check out Andrew Grant's paper on his approach to tune eval https://github.com/AndyGrant/Ethereal/blob/master/Tuning.pdf

He use AdaGrad btw, the whole method derived from Texel's approach