diff options
| author | tslil clingman <tslil@posteo.de> | 2023-01-15 16:03:37 +0100 |
|---|---|---|
| committer | tslil <tslil@posteo.de> | 2026-08-28 19:37:41 +0100 |
| commit | ee216c008a188a9436fedb85c70ee5d1719733b1 (patch) | |
| tree | f1d8fa5efd71851dd4f8d3e2b26b1f95a6086cb9 /include/nn1986.c | |
| parent | 7cf3a656d0c923dd92025c09747461f2f2d1bed0 (diff) | |
new neural network arch (faster + better) & minor changes + fixes
Gone is the convolutional neural network, for it turns out not only is
it more difficult to train, but all of the extra information about
board layers didn't make much of a difference at this size.
So cnn1986 has been replaced by nn1986, a standard, two-layer, dense
nn configured as a binary classifier and (mis)used in that capacity.
Note: total number of parameters is unchanged.
HARK: this new nn exposes a bug somewhere in ctak. Run ctlm with
self-play to see the completely borked board state at the end.
Diffstat (limited to 'include/nn1986.c')
| -rw-r--r-- | include/nn1986.c | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/include/nn1986.c b/include/nn1986.c new file mode 100644 index 0000000..b9c551c --- /dev/null +++ b/include/nn1986.c @@ -0,0 +1,81 @@ +/* + This file is part of ct. + + 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 + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + 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/>. +*/ + +#include "nn1986.h" +#include "tak.h" +#include "weights.h" + +// =================================================================== +// Implementation of a small neural network +// =================================================================== + +static float cur_board[INP_NUM]; +static float dense1[DENSE_NUM]; +static float output[2]; + +#define RELU(x) ((x) = ((x) < 0) ? 0 : (x)) +float nn1986_evaluate_black_win(void) { + /* --------------- * + * Populate input * + * --------------- */ + for (unsigned int y = 0; y < board_size; y++) { + for (unsigned int x = 0; x < board_size; x++) { + const unsigned int loc = x + y * board_size; + const unsigned int count = COUNT_AT(loc); + float lookup = 0; + if (count > 0) { + if (STONE_AT(loc) == STONE_STANDING) { + lookup = (colours[loc] & 1) ? +0.25 : -0.25; + } else if (STONE_AT(loc) == STONE_CAPSTONE) { + lookup = (colours[loc] & 1) ? +1.00 : -1.00; + } else { + lookup = (colours[loc] & 1) ? +0.50 : -0.50; + } + } + cur_board[3 + loc] = lookup; + } + } + /* ------------------ * + * Convolution layer * + * ------------------ */ + // Add input of flat counts and ply parity + cur_board[0] = (ply & 1) ? 1 : -1; + cur_board[1] = (float)(white_count & 127) / 21.0; + cur_board[2] = (float)(black_count & 127) / 21.0; + /* ------------------ * + * First dense layer * + * ------------------ */ + for (unsigned int d1 = 0; d1 < DENSE_NUM; d1++) { + dense1[d1] = dense1_biases[d1]; + for (unsigned int fl = 0; fl < 3 + 5 * 5; fl++) { + dense1[d1] += cur_board[fl] * dense1_weights[d1][fl]; + } + RELU(dense1[d1]); + } + /* ------------- * + * Output layer * + * ------------- */ + for (uint8_t k = 0; k < 2; k++) { + output[k] = output_bias[k]; + for (unsigned int d2 = 0; d2 < DENSE_NUM; d2++) { + output[k] += dense1[d2] * output_weights[k][d2]; + } + RELU(output[k]); + } + const float norm = output[0] + output[1]; + return (2 * output[0] / norm) - 1; +} |
