From 241156da6f35cb888253e6b8814e7b61a76b4fc7 Mon Sep 17 00:00:00 2001 From: tslil Date: Sun, 30 Aug 2026 19:46:07 +0100 Subject: TD(lambda), and a big rework NOTE: 6x6 weights are as-yet untrained On the performance side: * switch from linked-list chaining hash table to direct mapping * cache check_win by hash * persist transposition tables across plies (this was a big deal and difficult to puzzle out) * add align directives to the network floats * prepare_nn_input gained a small LUT to avoid branching (i suppose you might call this 1D embedding) * apply mtune=native for the native builds On the correctness side: * Zobrist has now includes the ply parity * the network now predicts something in [-1, 1] using tanh (approximated by polynomials) * the training object is now MSE because we're learning a value estimate * use .clangd instead of compile_commands.json On the training side: * completely forgo human-derived data set * implement td(lambda), self-play, tournaments --- include/nn.h | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 78 insertions(+), 5 deletions(-) (limited to 'include/nn.h') diff --git a/include/nn.h b/include/nn.h index 5d1bf15..18e222a 100644 --- a/include/nn.h +++ b/include/nn.h @@ -1,5 +1,5 @@ /* - This file is part of ct. + This file is part of ctak. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -12,12 +12,85 @@ General Public License for more details. You should have received a copy of the GNU General Public License - along with ct. If not, see . + along with ctak. If not, see . */ +#ifndef NN_H +#define NN_H + #include +#include "weights_5.h" +#include "weights_6.h" + +// =================================================================== +// Helpers +// =================================================================== + +void nn_prepare_input(float *cur_board, tak_state_p state); + +#define RELU(x) ((x) = ((x) < 0) ? 0 : (x)) + +/* + * tanh via a degree-11 odd polynomial, least-squares fit of tanh on [-3, 3] + * (max absolute error ~4e-3), saturating to +-1 outside that interval. + */ +static inline float fast_tanh(const float x) { + if (x > 3.0f) + return 1.0f; + if (x < -3.0f) + return -1.0f; + const float x2 = x * x; + return x * (0.997136032f + x2 * (-0.305215124f + x2 * + (0.0832466371f + x2 * + (-0.0139947924f + x2 * + (0.00123106314f + x2 * -4.29748644e-05f))))); +} + +// =================================================================== +// Implementation of small neural networks +// =================================================================== + +static inline float eval_net(const float *board, const unsigned int n_inp, + const float *w, const float *biases, + const float *logit_w, const float logit_b, + const unsigned int n_dense) { + float dense1[FIVE_DENSE_NUM]; // FIVE_DENSE_NUM == SIX_DENSE_NUM + float z = logit_b; + + for (unsigned int d1 = 0; d1 < n_dense; d1++) { + float h = biases[d1]; + const float *wd = w + d1 * n_inp; + for (unsigned int fl = 0; fl < n_inp; fl++) + h += board[fl] * wd[fl]; + RELU(h); + dense1[d1] = h; + } + for (unsigned int d1 = 0; d1 < n_dense; d1++) + z += dense1[d1] * logit_w[d1]; + + return fast_tanh(z); +} + +// =================================================================== +// Interfaces to the two built-in evaluators +// =================================================================== + +static inline float five_nn_fn(tak_state_p state) { + static float cur_board[FIVE_INP_NUM] NN_ALIGNED; + + nn_prepare_input(cur_board, state); + return eval_net(cur_board, FIVE_INP_NUM, &five_dense_weights[0][0], + five_dense_biases, five_logit_weights, five_logit_bias, + FIVE_DENSE_NUM); +} + +static inline float six_nn_fn(tak_state_p state) { + static float cur_board[SIX_INP_NUM] NN_ALIGNED; -typedef float (*nn_function)(tak_state_p); + nn_prepare_input(cur_board, state); + return eval_net(cur_board, SIX_INP_NUM, &six_dense_weights[0][0], + six_dense_biases, six_logit_weights, six_logit_bias, + SIX_DENSE_NUM); +} -float nn1986_evaluate_black_win(tak_state_p state); -float nn2690_evaluate_black_win(tak_state_p state); +#endif -- cgit v1.3.1