def call(self, inputs, **kwargs): x, tau = inputs tmp = self.e(x) tmp = tfk_multiply([tau, tmp]) # element wise multiplication res = self.d(tmp) # no addition of x # res = tfk_add([x, tmp]) return res
def call(self, inputs): x, tau = inputs tmp = self.e(x) tmp = tfk_multiply([tau, tmp]) # element wise multiplication tmp = self.d(tmp) res = tfk_add([x, tmp]) return res
def build_model(self): """build the neural network used as proxy, in this case a leap net.""" if self._model is not None: # model is already initialized return self._model = Sequential() inputs_x = [ Input(shape=(el, ), name="x_{}".format(nm_)) for el, nm_ in zip(self._sz_x, self.attr_x) ] inputs_tau = [ Input(shape=(el, ), name="tau_{}".format(nm_)) for el, nm_ in zip(self._sz_tau, self.attr_tau) ] # tensor_line_status = None if self._idx is not None: # line status is encoded: 1 disconnected, 0 connected # I invert it here if self._where_id == "x": self.tensor_line_status = inputs_x[self._idx] elif self._where_id == "tau": self.tensor_line_status = inputs_tau[self._idx] else: raise RuntimeError("Unknown \"where_id\"") self.tensor_line_status = 1.0 - self.tensor_line_status # encode each data type in initial layers encs_out = [] for init_val, nm_ in zip(inputs_x, self.attr_x): lay = init_val if self._scale_input_enc_layer is not None: # scale up to have higher dimension lay = Dense(self._scale_input_enc_layer, name=f"scaling_input_encoder_{nm_}")(lay) for i, size in enumerate(self.sizes_enc): lay_fun = self._layer_fun(size, name="enc_{}_{}".format(nm_, i), activation=self._layer_act) lay = lay_fun(lay) if self._layer_act is None: # add a non linearity if not added in the layer lay = Activation("relu")(lay) encs_out.append(lay) # concatenate all that lay = tf.keras.layers.concatenate(encs_out) if self._scale_main_layer is not None: # scale up to have higher dimension lay = Dense(self._scale_main_layer, name="scaling_inputs")(lay) # i do a few layer for i, size in enumerate(self.sizes_main): lay_fun = self._layer_fun(size, name="main_{}".format(i), activation=self._layer_act) lay = lay_fun(lay) if self._layer_act is None: # add a non linearity if not added in the layer lay = Activation("relu")(lay) # now i do the leap net to encode the state encoded_state = lay for input_tau, nm_ in zip(inputs_tau, self.attr_tau): tmp = LtauNoAdd(name=f"leap_{nm_}")([lay, input_tau]) encoded_state = tf.keras.layers.add([encoded_state, tmp], name=f"adding_{nm_}") # i predict the full state of the grid given the input variables outputs_gm = [] model_losses = {} # model_losses = [] lossWeights = {} # TODO for sz_out, nm_ in zip(self._sz_y, self.attr_y): lay = encoded_state if self._scale_input_dec_layer is not None: # scale up to have higher dimension lay = Dense(self._scale_input_dec_layer, name=f"scaling_input_decoder_{nm_}")(lay) lay = Activation("relu")(lay) for i, size in enumerate(self.sizes_out): lay_fun = self._layer_fun(size, name="{}_{}".format(nm_, i), activation=self._layer_act) lay = lay_fun(lay) if self._layer_act is None: # add a non linearity if not added in the layer lay = Activation("relu")(lay) # predict now the variable name_output = "{}_hat".format(nm_) # force the model to output 0 when the powerline is disconnected if self.tensor_line_status is not None and nm_ in self._line_attr: pred_ = Dense(sz_out, name=f"{nm_}_force_disco")(lay) pred_ = tfk_multiply((pred_, self.tensor_line_status), name=name_output) else: pred_ = Dense(sz_out, name=name_output)(lay) outputs_gm.append(pred_) model_losses[name_output] = "mse" # model_losses.append(tf.keras.losses.mean_squared_error) # now create the model in keras self._model = Model(inputs=(inputs_x, inputs_tau), outputs=outputs_gm, name="model") # and "compile" it self._schedule_lr_model, self._optimizer_model = self._make_optimiser() self._model.compile(loss=model_losses, optimizer=self._optimizer_model)