aboutsummaryrefslogtreecommitdiff
path: root/imago/engine/keras
diff options
context:
space:
mode:
authorInigoGutierrez <inigogf.95@gmail.com>2022-06-18 14:44:38 +0200
committerInigoGutierrez <inigogf.95@gmail.com>2022-06-18 14:44:38 +0200
commite9af1d809f25f6499a9aeb43264ce809118e63e8 (patch)
treedf849383ea7bcd31ac18ff08f9f9dd7586ea37c6 /imago/engine/keras
parentfaea06ac8d0dc92edb9ca0f2b6aacf79f640ace7 (diff)
downloadimago-e9af1d809f25f6499a9aeb43264ce809118e63e8.tar.gz
imago-e9af1d809f25f6499a9aeb43264ce809118e63e8.zip
Testing working neural network.
Diffstat (limited to 'imago/engine/keras')
-rw-r--r--imago/engine/keras/__init__.py0
-rw-r--r--imago/engine/keras/neuralNetwork.py83
2 files changed, 70 insertions, 13 deletions
diff --git a/imago/engine/keras/__init__.py b/imago/engine/keras/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/imago/engine/keras/__init__.py
diff --git a/imago/engine/keras/neuralNetwork.py b/imago/engine/keras/neuralNetwork.py
index d0b7798..26cb19e 100644
--- a/imago/engine/keras/neuralNetwork.py
+++ b/imago/engine/keras/neuralNetwork.py
@@ -1,50 +1,67 @@
"""Keras neural network."""
import os.path
+import numpy
+from copy import deepcopy
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras.models import Sequential, load_model
-from tensorflow.keras.layers import Activation, Dense
+from tensorflow.keras.layers import Dense, Flatten
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.metrics import categorical_crossentropy
-modelFile = 'models/imagoKerasModel.h5'
+from imago.data.enums import Player
+
+defaultModelFile = 'models/imagoKerasModel.h5'
DEF_BOARD_SIZE = 9
+PLAYER_ID = 1
+OPPONENT_ID = -1
class NeuralNetwork:
def __init__(self, modelPath="", boardSize=DEF_BOARD_SIZE):
- self.path = modelFile
+ self.path = defaultModelFile
if modelPath != "":
+ self.path = modelPath
+ try:
self.model = self._loadModel(modelPath)
- else:
+ except FileNotFoundError:
self.model = self._initModel(boardSize)
def _initModel(self, boardSize=DEF_BOARD_SIZE):
model = Sequential([
Dense(units=16, activation='relu', input_shape=(boardSize,boardSize)),
Dense(units=32, activation='relu'),
- Dense(units=2, activation='softmax')
+ Dense(units=boardSize, activation='softmax')
])
model.summary()
model.compile(
optimizer=Adam(learning_rate=0.0001),
- loss='sparse_categorical_crossentropy',
+ loss='categorical_crossentropy',
metrics=['accuracy']
)
return model
- def _trainModel(self, boardSize=DEF_BOARD_SIZE):
+ def trainModel(self, games):
+ trainMoves = []
+ targets = []
+ for game in games:
+ for move in self._movesToTrainMoves(game):
+ trainMoves.append(move)
+ for target in self._movesToTargets(game):
+ targets.append(target)
+ trainMoves = numpy.array(trainMoves)
+ targets = numpy.array(targets)
self.model.fit(
- x=scaled_train_samples,
- y=train_labels,
+ x=trainMoves,
+ y=targets,
validation_split=0.1,
batch_size=10,
epochs=30,
- shuffle=True,
+ shuffle=False,
verbose=2
)
@@ -53,7 +70,47 @@ class NeuralNetwork:
if os.path.isfile(modelPath):
return load_model(modelPath)
else:
- raise Exception("Keras neural network file not found at %s" % modelPath)
+ raise FileNotFoundError("Keras neural network file not found at %s" % modelPath)
+
+ def saveModel(self, modelPath=""):
+ if modelPath != "":
+ self.model.save(modelPath)
+ else:
+ self.model.save(self.path)
+
+ def _movesToTrainMoves(self, moves):
+ trainMoves = []
+ for move in moves:
+ trainMove = self._moveToTrainMove(move)
+ trainMoves.append(trainMove)
+ return trainMoves
+
+ def _moveToTrainMove(self, move):
+ player = move.getPlayer()
+ return self._boardToPlayerContext(move.board.board, player)
+
+ def _boardToPlayerContext(self, board, player):
+ """Converts to a board where PLAYER_ID marks the stones who made the move and
+ OPPONENT_ID marks the stones of the other player."""
+ boardRows = len(board)
+ boardCols = len(board[0])
+ contextBoard = numpy.zeros( (boardRows, boardCols), dtype = int)
+ for row in range(boardRows):
+ for col in range(boardCols):
+ if board[row][col] != Player.EMPTY:
+ if board[row][col] == player:
+ contextBoard[row][col] = PLAYER_ID
+ else:
+ contextBoard[row][col] = OPPONENT_ID
+ return contextBoard.tolist()
- def _saveModel(self, modelPath):
- self.model.save(modelPath)
+ def _movesToTargets(self, moves):
+ targets = []
+ for move in moves:
+ target = numpy.zeros(
+ (move.board.getBoardHeight(),
+ move.board.getBoardWidth()),
+ dtype = float)
+ target[move.getRow()][move.getCol()] = 1
+ targets.append(target.tolist())
+ return targets