aboutsummaryrefslogtreecommitdiff
path: root/src/nn_train.py
blob: 03852f563ecd51df95c4ca13475ad2aa45df0c67 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# 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(size, model, str(i+1).zfill(len(str(iterations))), (tra_res, val_res))
    print("\nScores")
    for i, data in enumerate(results):
        print(f"Iteration {i+1}: {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(size, model, iteration, performance):
    def fix(val):
        string = str(np.array(val).tolist())
        string = string.replace("[", "{").replace("]", "}")
        return string
    size_str = "five" if size==5 else "six"
    dense_weights = transpose(model.trainable_variables[0], perm=[1, 0])
    dense_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 = [(f"{size_str}_dense_weights[{size_str.upper()}_DENSE_NUM][{size_str.upper()}_INP_NUM]", dense_weights),
                 (f"{size_str}_dense_biases[{size_str.upper()}_DENSE_NUM]", dense_biases),
                 (f"{size_str}_output_weights[2][{size_str.upper()}_DENSE_NUM]", output_weights),
                 (f"{size_str}_output_bias[2]", output_bias)]
    # Write to file
    f = open(f"{size_str}_weights-"+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(f"#include \"weights_{size}.h\"\n\n")
    for (name, val) in to_output:
        f.write("const float "+name+" =\n"+fix(val)+";\n\n")
    f.close()


for size in (5,6):
    data = load_data(size)
    model = make_model(size, 64)
    print("Before training", model.evaluate(data[1][0], data[1][1], verbose=False, batch_size=16))
    results = train(size, model, data, iterations=5, epochs=10, batch=128)