예제 #1
0
    def custom_train_step(self, data):
        """
        Custom training logic

        :param data:
        :return:
        """
        data = data_adapter.expand_1d(data)
        x, y, sample_weight = data_adapter.unpack_x_y_sample_weight(data)

        with tf.GradientTape() as tape:
            y_pred = self.keras_model(x, training=True)
            loss = self.keras_model.compiled_loss(
                y,
                y_pred,
                sample_weight,
                regularization_losses=self.keras_model.losses)
            if self.task == 'regression':
                variance_loss = mse_var_wrapper(y_pred[0], x['labels_err'])
                output_loss = mse_lin_wrapper(y_pred[1], x['labels_err'])
            elif self.task == 'classification':
                output_loss = bayesian_categorical_crossentropy_wrapper(
                    y_pred[1])
                variance_loss = bayesian_categorical_crossentropy_var_wrapper(
                    y_pred[0])
            elif self.task == 'binary_classification':
                output_loss = bayesian_binary_crossentropy_wrapper(y_pred[1])
                variance_loss = bayesian_binary_crossentropy_var_wrapper(
                    y_pred[0])
            else:
                raise RuntimeError(
                    'Only "regression", "classification" and "binary_classification" are supported'
                )
            loss = output_loss(y['output'], y_pred[0]) + variance_loss(
                y['variance_output'], y_pred[1])

        # apply gradient here
        if version.parse(tf.__version__) >= version.parse("2.4.0"):
            self.keras_model.optimizer.minimize(
                loss, self.keras_model.trainable_variables, tape=tape)
        else:
            tf.python.keras.engine.training._minimize(
                self.keras_model.distribute_strategy, tape,
                self.keras_model.optimizer, loss,
                self.keras_model.trainable_variables)

        self.keras_model.compiled_metrics.update_state(y, y_pred,
                                                       sample_weight)

        return {m.name: m.result() for m in self.keras_model.metrics}
예제 #2
0
    def model(self):
        input_tensor = Input(shape=self._input_shape, name='input')
        labels_err_tensor = Input(shape=(self._labels_shape,), name='labels_err')

        cnn_layer_1 = Conv1D(kernel_initializer=self.initializer, padding="same", filters=self.num_filters[0],
                             kernel_size=self.filter_len, kernel_regularizer=regularizers.l2(self.l2))(input_tensor)
        activation_1 = Activation(activation=self.activation)(cnn_layer_1)
        dropout_1 = MCDropout(self.dropout_rate, disable=self.disable_dropout)(activation_1)
        cnn_layer_2 = Conv1D(kernel_initializer=self.initializer, padding="same", filters=self.num_filters[1],
                             kernel_size=self.filter_len, kernel_regularizer=regularizers.l2(self.l2))(dropout_1)
        activation_2 = Activation(activation=self.activation)(cnn_layer_2)
        maxpool_1 = MaxPooling1D(pool_size=self.pool_length)(activation_2)
        flattener = Flatten()(maxpool_1)
        dropout_2 = MCDropout(self.dropout_rate, disable=self.disable_dropout)(flattener)
        layer_3 = Dense(units=self.num_hidden[0], kernel_regularizer=regularizers.l2(self.l2),
                        kernel_initializer=self.initializer,
                        activation=self.activation)(dropout_2)
        activation_3 = Activation(activation=self.activation)(layer_3)
        dropout_3 = MCDropout(self.dropout_rate, disable=self.disable_dropout)(activation_3)
        layer_4 = Dense(units=self.num_hidden[1], kernel_regularizer=regularizers.l2(self.l2),
                        kernel_initializer=self.initializer,
                        activation=self.activation)(dropout_3)
        activation_4 = Activation(activation=self.activation)(layer_4)
        output = Dense(units=self._labels_shape, name='output')(activation_4)
        output_activated = Activation(activation=self._last_layer_activation)(output)
        variance_output = Dense(units=self._labels_shape, activation='linear', name='variance_output')(activation_4)

        model = Model(inputs=[input_tensor, labels_err_tensor], outputs=[output, variance_output])
        # new astroNN high performance dropout variational inference on GPU expects single output
        model_prediction = Model(inputs=[input_tensor], outputs=concatenate([output, variance_output]))

        if self.task == 'regression':
            variance_loss = mse_var_wrapper(output, labels_err_tensor)
            output_loss = mse_lin_wrapper(variance_output, labels_err_tensor)
        elif self.task == 'classification':
            output_loss = bayesian_categorical_crossentropy_wrapper(variance_output)
            variance_loss = bayesian_categorical_crossentropy_var_wrapper(output)
        elif self.task == 'binary_classification':
            output_loss = bayesian_binary_crossentropy_wrapper(variance_output)
            variance_loss = bayesian_binary_crossentropy_var_wrapper(output)
        else:
            raise RuntimeError('Only "regression", "classification" and "binary_classification" are supported')

        return model, model_prediction, output_loss, variance_loss
예제 #3
0
    def compile(self,
                optimizer=None,
                loss=None,
                metrics=None,
                weighted_metrics=None,
                loss_weights=None,
                sample_weight_mode=None):
        if optimizer is not None:
            self.optimizer = optimizer
        elif self.optimizer is None or self.optimizer == 'adam':
            self.optimizer = Adam(learning_rate=self.lr,
                                  beta_1=self.beta_1,
                                  beta_2=self.beta_2,
                                  epsilon=self.optimizer_epsilon,
                                  decay=0.0)
        if metrics is not None:
            self.metrics = metrics
        if self.task == 'regression':
            if self._last_layer_activation is None:
                self._last_layer_activation = 'linear'
        elif self.task == 'classification':
            if self._last_layer_activation is None:
                self._last_layer_activation = 'softmax'
        elif self.task == 'binary_classification':
            if self._last_layer_activation is None:
                self._last_layer_activation = 'sigmoid'
        else:
            raise RuntimeError(
                'Only "regression", "classification" and "binary_classification" are supported'
            )

        self.keras_model, self.keras_model_predict, self.output_loss, self.variance_loss = self.model(
        )

        if self.task == 'regression':
            self._output_loss = lambda predictive, labelerr: mse_lin_wrapper(
                predictive, labelerr)
        elif self.task == 'classification':
            self._output_loss = lambda predictive, labelerr: bayesian_categorical_crossentropy_wrapper(
                predictive)
        elif self.task == 'binary_classification':
            self._output_loss = lambda predictive, labelerr: bayesian_binary_crossentropy_wrapper(
                predictive)
        else:
            raise RuntimeError(
                'Only "regression", "classification" and "binary_classification" are supported'
            )

        # all zero losss as dummy lose
        if self.task == 'regression':
            self.metrics = [mean_absolute_error, mean_error
                            ] if not self.metrics else self.metrics
            self.keras_model.compile(optimizer=self.optimizer,
                                     loss=zeros_loss,
                                     metrics=self.metrics,
                                     weighted_metrics=weighted_metrics,
                                     sample_weight_mode=sample_weight_mode)
        elif self.task == 'classification':
            self.metrics = [categorical_accuracy
                            ] if not self.metrics else self.metrics
            self.keras_model.compile(optimizer=self.optimizer,
                                     loss=zeros_loss,
                                     metrics={'output': self.metrics},
                                     weighted_metrics=weighted_metrics,
                                     sample_weight_mode=sample_weight_mode)
        elif self.task == 'binary_classification':
            self.metrics = [binary_accuracy
                            ] if not self.metrics else self.metrics
            self.keras_model.compile(optimizer=self.optimizer,
                                     loss=zeros_loss,
                                     metrics={'output': self.metrics},
                                     weighted_metrics=weighted_metrics,
                                     sample_weight_mode=sample_weight_mode)

        # inject custom training step if needed
        try:
            self.custom_train_step()
        except NotImplementedError:
            pass
        except TypeError:
            self.keras_model.train_step = self.custom_train_step

    # inject custom testing  step if needed
        try:
            self.custom_test_step()
        except NotImplementedError:
            pass
        except TypeError:
            self.keras_model.test_step = self.custom_test_step

        return None