/
BasicGameModel.py
91 lines (67 loc) · 3.51 KB
/
BasicGameModel.py
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
from default_imports import *
from conf.ConfigWrapper import ConfigWrapper
import numpy as np
import logging
import os
from random import shuffle
from collections import namedtuple
from modules.game.Player import PlayerID
from modules.game.Game import Game
from keras.models import load_model, Model
from keras.layers import Dropout, Embedding, Reshape, Flatten, Dense, LSTM, Input, concatenate, Conv1D
from keras.optimizers import Adam
from keras.callbacks import TensorBoard
from functools import lru_cache
class BasicGameModel:
def __init__(self, config: ConfigWrapper, newmodel: bool = False):
self.config = config
self.model = self.createModel(newmodel)
def createModel(self, newmodel: bool = False):
if os.path.isfile(self.config["irwin model basic file"]) and not newmodel:
logging.debug("model already exists, opening from file")
m = load_model(self.config["irwin model basic file"])
m._make_predict_function()
return m
logging.debug('model does not exist, building from scratch')
moveStatsInput = Input(shape=(60, 8), dtype='float32', name='move_input')
pieceType = Input(shape=(60, 1), dtype='float32', name='piece_type')
pieceEmbed = Embedding(input_dim=7, output_dim=8)(pieceType)
rshape = Reshape((60,8))(pieceEmbed)
concats = concatenate(inputs=[moveStatsInput, rshape])
### Conv Net Block of Siamese Network
conv1 = Conv1D(filters=64, kernel_size=3, activation='relu')(concats)
dense1 = Dense(32, activation='relu')(conv1)
conv2 = Conv1D(filters=64, kernel_size=5, activation='relu')(dense1)
dense2 = Dense(32, activation='sigmoid')(conv2)
conv3 = Conv1D(filters=64, kernel_size=10, activation='relu')(dense2)
dense3 = Dense(16, activation='relu')(conv3)
dense4 = Dense(8, activation='sigmoid')(dense3)
f = Flatten()(dense4)
dense5 = Dense(64, activation='relu')(f)
convNetOutput = Dense(16, activation='sigmoid')(dense5)
### LSTM Block of Siamese Network
mv1 = Dense(32, activation='relu')(concats)
d1 = Dropout(0.3)(mv1)
mv2 = Dense(16, activation='relu')(d1)
c1 = Conv1D(filters=64, kernel_size=5, name='conv1')(mv2)
# analyse all the moves and come to a decision about the game
l1 = LSTM(64, return_sequences=True)(c1)
l2 = LSTM(32, return_sequences=True, activation='relu')(l1)
c2 = Conv1D(filters=64, kernel_size=10, name='conv2')(l2)
l3 = LSTM(32, return_sequences=True)(c2)
l4 = LSTM(16, return_sequences=True, activation='relu', recurrent_activation='hard_sigmoid')(l3)
l5 = LSTM(16, activation='sigmoid')(l4)
mergeLSTMandConv = concatenate([l5, convNetOutput])
denseOut1 = Dense(16, activation='sigmoid')(mergeLSTMandConv)
mainOutput = Dense(1, activation='sigmoid', name='main_output')(denseOut1)
model = Model(inputs=[moveStatsInput, pieceType], outputs=mainOutput)
model.compile(optimizer=Adam(lr=0.0001),
loss='binary_crossentropy',
metrics=['accuracy'])
return model
def predict(self, playerId: PlayerID, games: List[Game]) -> Opt[int]:
tensors = [game.tensor(playerId) for game in games]
return [None if t is None else int(100*self.model.predict([np.array([t[0]]),np.array([t[1]])])[0][0]) for t in tensors]
def saveModel(self):
logging.debug("saving model")
self.model.save(self.config["irwin model basic file"])