aboutsummaryrefslogtreecommitdiff
path: root/include/nn.h
diff options
context:
space:
mode:
authortslil <tslil@posteo.de>2026-08-30 19:46:07 +0100
committertslil <tslil@posteo.de>2026-09-02 12:13:01 +0100
commit241156da6f35cb888253e6b8814e7b61a76b4fc7 (patch)
treee562029445b1473cc89590793f32c561540d621c /include/nn.h
parent696c3808220ea9d8c604939894a2d509f05cc4c6 (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.h83
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