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 /src/nn_train.py | |
| 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 'src/nn_train.py')
| -rw-r--r-- | src/nn_train.py | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/src/nn_train.py b/src/nn_train.py new file mode 100644 index 0000000..12ce868 --- /dev/null +++ b/src/nn_train.py @@ -0,0 +1,106 @@ +# cnn_train.py, train a small CNN to recognise winning Tak positions +# +# Copyright (C) 2021, tslil clingman +# +# 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 this program. If not, see <https://www.gnu.org/licenses/>. + + +# Loading data +import pandas as pd +import numpy as np + +# Output of weights +from tensorflow import transpose + +# Building models +from tensorflow.keras.models import Model +from tensorflow.keras.layers import Input, Dense + + +def load_data(size): + output_len = 2 + # Load training data + tr_fn = "data/training-"+str(size)+".csv" + training_csv = pd.read_csv(tr_fn) + training_data = training_csv + training_input = np.array(training_data.iloc[:, 0:-output_len]) + training_outcome = np.array(training_data.iloc[:, -output_len:]) + # Load validation data + val_fn = "data/validation-"+str(size)+".csv" + val_data = pd.read_csv(val_fn) + val_input = np.array(val_data.iloc[:, 0:-output_len]) + val_outcome = np.array(val_data.iloc[:, -output_len:]) + return ((training_input, training_outcome), (val_input, val_outcome)) + + +def train(size, model, data, iterations=1, epochs=10, batch=None): + (tra_input, tra_outcome), (val_input, val_outcome) = data + results = [] + for i in range(0, iterations): + print("Iteration {0}/{1}".format(i+1, iterations)) + model.fit(tra_input, tra_outcome, epochs=epochs, + validation_data=(val_input, val_outcome), + verbose=True, batch_size=batch) + val_res = model.evaluate(val_input, val_outcome, verbose=False) + tra_res = model.evaluate(tra_input, tra_outcome, verbose=False) + results.append((tra_res, val_res)) + print(val_res) + write_weights(model, i+1, (tra_res, val_res)) + print("\nScores") + for i, data in enumerate(results): + print(f"Iteration {i}: {data}") + return results + + +def make_model(size, magic): + inputs = Input(shape=(size * size + 3,)) + model = inputs + model = Dense(magic, activation="relu", use_bias=True)(model) + model = Dense(2, activation="relu", use_bias=True)(model) + model = Model(inputs=inputs, outputs=model) + model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy']) + model.summary() + return model + + +def write_weights(model, iteration, performance): + def fix(val): + string = str(np.array(val).tolist()) + string = string.replace("[", "{").replace("]", "}") + return string + dense1_weights = transpose(model.trainable_variables[0], perm=[1, 0]) + dense1_biases = model.trainable_variables[1] + output_weights = transpose(model.trainable_variables[2], perm=[1, 0]) + output_bias = model.trainable_variables[3] + # Prepare output + to_output = [("dense1_weights[DENSE_NUM][INP_NUM]",dense1_weights) + ("dense1_biases[DENSE_NUM]", dense1_biases), + ("output_weights[2][DENSE_NUM]", output_weights), + ("output_bias[2]", output_bias)] + # Write to file + f = open("weights-"+str(iteration)+".txt", "w") + f.write("/*\n") + model.summary(print_fn=lambda l: f.write(" * "+l+"\n")) + f.write(" * "+str(performance)+"\n*/\n\n") + f.write("#include \"weights.h\"\n\n") + for (name, val) in to_output: + f.write("const float "+name+" =\n"+fix(val)+";\n\n") + f.close() + + +data = load_data(5) +model = make_model(5, 64) + +print("Before training", model.evaluate(data[1][0], data[1][1], verbose=False, batch_size=16)) +results = train(5, model, data, iterations=1, epochs=10, batch=None) |
