diff options
| author | tslil <tslil@posteo.de> | 2026-08-30 19:46:07 +0100 |
|---|---|---|
| committer | tslil <tslil@posteo.de> | 2026-09-02 12:13:01 +0100 |
| commit | 241156da6f35cb888253e6b8814e7b61a76b4fc7 (patch) | |
| tree | e562029445b1473cc89590793f32c561540d621c /include/nn.h | |
| parent | 696c3808220ea9d8c604939894a2d509f05cc4c6 (diff) | |
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
Diffstat (limited to 'include/nn.h')
| -rw-r--r-- | include/nn.h | 83 |
1 files changed, 78 insertions, 5 deletions
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 <https://www.gnu.org/licenses/>. + along with ctak. If not, see <https://www.gnu.org/licenses/>. */ +#ifndef NN_H +#define NN_H + #include <tak.h> +#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 |
