aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortslil <tslil@posteo.de>2021-01-05 21:39:41 -0500
committertslil <tslil@posteo.de>2026-08-28 19:37:41 +0100
commit467128c57e23785abc3e80462c05c2f2abbc0679 (patch)
treefb7df0b86879f61743656117f1c74ec8fc2e8544
parent8a231c52d56e011b42fa854542670c5b41801d47 (diff)
Experimenting with training nn
-rwxr-xr-xextract.sh (renamed from data/extract.sh)8
-rw-r--r--src/pptdb.c68
-rw-r--r--src/train5.py51
3 files changed, 93 insertions, 34 deletions
diff --git a/data/extract.sh b/extract.sh
index 285be26..4ded1c0 100755
--- a/data/extract.sh
+++ b/extract.sh
@@ -9,9 +9,10 @@ and (result != '1/2-1/2');"
}
extract() {
+ cd data
for size in 5 6; do
echo Extracing games of size "$size"...
- sqlite3 "$db_file" "$(query $1 $size)" > "playtak-$size"
+ sqlite3 "$db_file" "$(query $1 $size)" | shuf > "playtak-$size"
done
}
@@ -22,7 +23,6 @@ fi
extract notation,result
echo Preparing pptdb
-cd ..
if [ ! -f "pptdb" ]; then
make pptdb
fi
@@ -41,3 +41,7 @@ for i in 5 6; do
mv "data/shuf-$i.csv" "data/training-$i.csv"
echo
done
+
+
+shuf -n50000 data/good-playtak-5 > data/smalltak-5 && ./pptdb 5 data/smalltak-5 generate && \
+head -n1 data/training-5.csv > t && tail -n+2 data/training-5.csv > test.csv && shuf test.csv >> t && mv t test.csv
diff --git a/src/pptdb.c b/src/pptdb.c
index 34056c4..712aabc 100644
--- a/src/pptdb.c
+++ b/src/pptdb.c
@@ -4,35 +4,43 @@
#include <tak.h>
+float max_flats;
uint64_t heights[16];
+int result, generate;
FILE *training_fh = NULL;
-int wc_col, bc_col, wc_row, bc_row, result, generate;
static void
write_input(void) {
// Four numbers for capstone coords (col,row)
- fprintf(training_fh,"%d,%d,%d,%d,",wc_col,wc_row,bc_col,bc_row);
// Two numbers for flats remaining
- fprintf(training_fh,"%d,%d,",white_count & 127, black_count & 127);
+ fprintf(training_fh,"%.6f,%.6f,",
+ (float)(white_count & 127)/max_flats,
+ (float)(black_count & 127)/max_flats);
// Two layers of board_size * board_size:
- int h, t; uint16_t mask;
+ float t; int h; uint16_t mask;
for (int k = 0; k < board_size * board_size; k++) {
- // stacks encoded as balanced ternary without capstones and walls
- t = 0; mask = 1;
+ // stacks encoded as balanced ternary, without caps and walls
+ t = 0;
h = COUNT_AT(k);
- if (STONE_AT(k)) h--;
- while (h-->0) {
- t *= 3;
- t += (colours[k] & mask) ? +1 : -1;
- mask <<= 1;
+ if (h>0) {
+ mask = 1<<(h-1);
+ /* if (STONE_AT(k) != STONE_FLAT) h--; */
+ while (h-->0) {
+ t += (colours[k] & mask) ? +1.0 : -1.0;
+ t /= 3;
+ mask >>= 1;
+ }
}
- fprintf(training_fh,"%d,",t);
+ fprintf(training_fh,"%.6f,",t);
}
+ int val;
for (int k = 0; k < board_size * board_size; k++) {
- // walls with +- 1
- if (COUNT_AT(k) && STONE_AT(k) == STONE_STANDING)
- fprintf(training_fh,"%d,",(colours[k] & 1) ? +1 : -1);
- else fputs("0,", training_fh);
+ val = 0;
+ if (COUNT_AT(k)) {
+ if (STONE_AT(k) == STONE_STANDING) val = (colours[k] & 1) ? +1 : -1;
+ else if (STONE_AT(k) == STONE_CAPSTONE) val = (colours[k] & 1) ? +2 : -2;
+ }
+ fprintf(training_fh,"%d,",val);
}
}
@@ -51,17 +59,7 @@ parse_line(const char *pt, const ssize_t read) {
if (idx + 3 < read) {
switch (pt[idx+3]) {
case 'W': { stone = STONE_STANDING; break; }
- case 'C': {
- if (current_colour == C_BLACK) {
- bc_col = col + 1;
- bc_row = row + 1;
- } else {
- wc_col = col + 1;
- wc_row = row + 1;
- }
- stone = STONE_CAPSTONE;
- break;
- }
+ case 'C': { stone = STONE_CAPSTONE; break; }
default: { stone = STONE_FLAT; break; }
}
} else {
@@ -102,7 +100,7 @@ parse_line(const char *pt, const ssize_t read) {
// Generate training data
if (generate) {
write_input();
- fprintf(training_fh,"%d,%d\n", result, 1-result);
+ fprintf(training_fh,"%d\n", result);
}
// Parse next action
while (idx<read && pt[idx++]!=',');
@@ -135,19 +133,25 @@ main(int argc, char **argv) {
if (argc > 3 && (!strncmp("generate", argv[3], 8))) {
generate=1;
+ max_flats = (size == 5) ? 21.0 : 30.0;
snprintf(td_fn, 64, "data/training-%d.csv",size);
training_fh = fopen(td_fn, "w");
if (training_fh == NULL) exit(EXIT_FAILURE);
+ // Write header
+ fputs("\"White flats\",\"Black flats\",",training_fh);
+ for (int k = 0; k < size*size; k++)
+ fprintf(training_fh,"\"Stack %d\",",k);
+ for (int k = 0; k < size*size; k++)
+ fprintf(training_fh,"\"Wall %d\",",k);
+ fputs("\"Outcome\"\n",training_fh);
} else generate=0;
while ((read = getline(&line, &len, playtak_fh)) != -1) {
// Reset everything
reset_state(size);
- bc_col = 0; wc_col = 0;
- bc_row = 0; wc_row = 0;
// Store the result of this game
- if (line[read-4] == '0') result = 1;
- else result = 0;
+ if (line[read-4] == '0') result = 0;
+ else result = 1;
// Parse the line
r = parse_line(line,read-4);
// Adjust counts if we're not generating training data
diff --git a/src/train5.py b/src/train5.py
new file mode 100644
index 0000000..225068b
--- /dev/null
+++ b/src/train5.py
@@ -0,0 +1,51 @@
+import tensorflow as tf
+import pandas as pd
+import numpy as np
+
+from tensorflow.keras.models import Sequential
+from tensorflow.keras.layers import BatchNormalization
+from tensorflow.keras.layers import Conv2D
+from tensorflow.keras.layers import MaxPooling2D
+from tensorflow.keras.layers import Activation
+from tensorflow.keras.layers import Flatten
+from tensorflow.keras.layers import Dropout
+from tensorflow.keras.layers import Dense
+
+model = Sequential([
+ Conv2D(5, kernel_size=3, padding='same', input_shape=(5, 5, 2)),
+ MaxPooling2D(pool_size=(2, 2), strides=None),
+ Activation("relu"),
+ Flatten(),
+ Dense(10, activation="relu"),
+ Dense(8, activation="relu"),
+ Dense(1, activation="sigmoid")
+
+ # Dense(40, activation="relu", input_shape=(52,)),
+ # Dense(10, activation="relu"),
+ # Dense(5, activation="relu"),
+ # Dense(1, activation="sigmoid")
+])
+
+model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
+
+model.summary()
+
+csv = pd.read_csv("data/test.csv")
+
+training_data = csv.copy().head(5000)
+training_outcome = training_data.pop('Outcome')
+
+training_input = training_data.copy()
+training_input = training_input.drop(columns=training_data.keys()[0:2])
+train = np.array(training_input)
+train = train.reshape((training_input.shape[0], 5, 5, 2))
+
+model.fit(train, training_outcome, epochs=20)
+
+test_data = csv.copy().head(10000)
+test_data = test_data.drop(columns=test_data.keys()[0:2])
+test_outcome = test_data.pop('Outcome')
+test_input = np.array(test_data)
+test_input.reshape((test_data.shape[0], 5, 5, 2))
+test_loss, test_acc = model.evaluate(test_input, test_outcome, verbose=2)
+print('\nTest accuracy:', test_acc)