import abc import json import numpy import scipy.linalg from keras import Sequential from keras.layers import Dense from keras.models import load_model model_types = {} class Model: @abc.abstractmethod def get_temperature(self, flat_history: numpy.array) -> float: pass @abc.abstractmethod def save(self, filename): pass @classmethod def load(cls, config, filename): return model_types[config['model_type']]._load(filename) @abc.abstractclassmethod def _load(cls, filename): pass @classmethod def generate(cls, config: dict): return model_types[config['model_type']].generate(config) class LinearModel(Model): def __init__(self, model): self.model = model def get_temperature(self, flat_history): return sum(numpy.multiply(self.model, flat_history)) def save(self, filename): with open(filename, 'w') as fp: json.dump(self.model.tolist(), fp) @classmethod def _load(cls, filename): with open(filename, 'r') as fp: model = json.load(fp) model = numpy.array(model) return cls(model) @classmethod def generate(cls, config: dict): from .ArgParser import get_sliding_window_from_config sliding_window = get_sliding_window_from_config(config) xs = [] ys = [] for x in sliding_window: xs.append(x.get_model_values()) ys.append(x.get_model_target()) return cls(scipy.linalg.lstsq(xs, ys)[0]) model_types['linear'] = LinearModel class NeuralModel(Model): def __init__(self, model): self.model = model def get_temperature(self, flat_history): state = numpy.reshape(flat_history, [1, len(flat_history)]) result = self.model.predict(state) return result[0][0] @staticmethod def _build_model(state_size): model = Sequential() model.add(Dense(int(state_size / 2) or 1, activation='linear', input_dim=state_size, kernel_initializer='random_uniform')) model.add(Dense(int(state_size / 4) or 1, activation='linear', kernel_initializer='random_uniform')) model.add(Dense(int(state_size / 8) or 1, activation='linear', kernel_initializer='random_uniform')) model.add(Dense(1, activation='linear', kernel_initializer='random_uniform')) model.compile(optimizer='adagrad', loss='mean_squared_error', metrics=['accuracy']) return model def save(self, filename): self.model.save(filename) @classmethod def _load(cls, filename): model = load_model(filename) return cls(model) @classmethod def generate(cls, config: dict): from .ArgParser import get_sliding_window_from_config sliding_window = get_sliding_window_from_config(config) window = next(sliding_window) model = cls._build_model(window.get_model_size()) xs = [] ys = [] for window in sliding_window: xs.append(window.get_model_values()) ys.append([window.get_next_value('temp_in')]) model.fit(numpy.array(xs), numpy.array(ys), epochs=config['model_epochs'], batch_size=32, shuffle=True) return cls(model) model_types['neural'] = NeuralModel class NeuralModelLess(NeuralModel): @staticmethod def _build_model(state_size): model = Sequential() model.add(Dense(int(state_size / 2) or 1, activation='linear', input_dim=state_size, kernel_initializer='random_uniform')) model.add(Dense(int(state_size / 4) or 1, activation='linear', kernel_initializer='random_uniform')) model.add(Dense(int(state_size / 8) or 1, activation='linear', kernel_initializer='random_uniform')) model.add(Dense(1, activation='linear', kernel_initializer='random_uniform')) model.compile(optimizer='adagrad', loss='mean_squared_error', metrics=['accuracy']) return model model_types['neural_less'] = NeuralModelLess class NeuralModelMore(NeuralModel): @staticmethod def _build_model(state_size): model = Sequential() model.add(Dense(int(state_size / 2) or 1, activation='linear', input_dim=state_size, kernel_initializer='random_uniform')) model.add(Dense(int(state_size / 4) or 1, activation='linear', kernel_initializer='random_uniform')) model.add(Dense(int(state_size / 8) or 1, activation='linear', kernel_initializer='random_uniform')) model.add(Dense(1, activation='linear', kernel_initializer='random_uniform')) model.compile(optimizer='adagrad', loss='mean_squared_error', metrics=['accuracy']) return model model_types['neural_more'] = NeuralModelMore class NeuralModelRelu(NeuralModel): @staticmethod def _build_model(state_size): model = Sequential() model.add(Dense(int(state_size / 2) or 1, activation='linear', input_dim=state_size, kernel_initializer='random_uniform')) model.add(Dense(int(state_size / 4) or 1, activation='relu', kernel_initializer='random_uniform')) model.add(Dense(int(state_size / 8) or 1, activation='relu', kernel_initializer='random_uniform')) model.add(Dense(1, activation='linear', kernel_initializer='random_uniform')) model.compile(optimizer='adagrad', loss='mean_squared_error', metrics=['accuracy']) return model model_types['neural_relu'] = NeuralModelRelu class NeuralModelReduced(NeuralModel): @staticmethod def _build_model(state_size): model = Sequential() model.add(Dense(int(state_size / 2) or 1, activation='linear', input_dim=state_size, kernel_initializer='random_uniform')) model.add(Dense(1, activation='linear', kernel_initializer='random_uniform')) model.compile(optimizer='adagrad', loss='mean_squared_error', metrics=['accuracy']) return model model_types['neural_half'] = NeuralModelReduced class NeuralModelSqueezeExpand(NeuralModel): @staticmethod def _build_model(state_size): model = Sequential() model.add(Dense(int(state_size / 2) or 1, activation='linear', input_dim=state_size, kernel_initializer='random_uniform')) model.add(Dense(int(state_size / 4) or 1, activation='linear', kernel_initializer='random_uniform')) model.add(Dense(int(state_size / 2) or 1, activation='linear', kernel_initializer='random_uniform')) model.add(Dense(1, activation='linear', kernel_initializer='random_uniform')) model.compile(optimizer='adagrad', loss='mean_squared_error', metrics=['accuracy']) return model model_types['neural_hqh'] = NeuralModelSqueezeExpand