diff options
author | InigoGutierrez <inigogf.95@gmail.com> | 2022-06-18 14:44:38 +0200 |
---|---|---|
committer | InigoGutierrez <inigogf.95@gmail.com> | 2022-06-18 14:44:38 +0200 |
commit | e9af1d809f25f6499a9aeb43264ce809118e63e8 (patch) | |
tree | df849383ea7bcd31ac18ff08f9f9dd7586ea37c6 /imago/engine/keras | |
parent | faea06ac8d0dc92edb9ca0f2b6aacf79f640ace7 (diff) | |
download | imago-e9af1d809f25f6499a9aeb43264ce809118e63e8.tar.gz imago-e9af1d809f25f6499a9aeb43264ce809118e63e8.zip |
Testing working neural network.
Diffstat (limited to 'imago/engine/keras')
-rw-r--r-- | imago/engine/keras/__init__.py | 0 | ||||
-rw-r--r-- | imago/engine/keras/neuralNetwork.py | 83 |
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 |