TadGAN with Tensorflow 2.3 support

Hello everyone,
thank you for this nice module and the good examples for the TadGAN. I wonder if anyone had success so far get the TadGAN model running under Tensorflow 2 instead of 1.15?
I tried a lot so far but had no luck.
Best regards,
Sebastian

Hi @blaskowitz100
Thanks for the comment, right now we only support running on tensorflow>=1.11.0,<2 we’re planning to release a new version soon that supports tensorflow>=2.

Hello @sarahmish ,
thank you for your feedback. If I made some progress on my implementation I will let you know.

Hello @sarahmish ,
thank you for your feedback. If I made some progress on my implementation I will let you know.

Hello @blaskowitz100, can you please share your version for Tensorflow 2.3... Thanks

Hello @sarahmish ,
thank you for your feedback. If I made some progress on my implementation I will let you know.

Hello @blaskowitz100, can you please share your version for Tensorflow 2.3... Thanks

Hello @sarahmish and @A2015Albasir ,
here are my current version I was able to run in TF2.3 and TF2.4. It uses the Subclassing API and can handle multivariate time series data. This means the model can be trained using the fit/predict function like a simple Keras model. The rest of the architecture should be the same as in the TadGAN paper.
import os
from typing import Tuple
import numpy as np
import tensorflow as tf

def _wasserstein_loss(y_true, y_pred):
    return tf.keras.backend.mean(y_true * y_pred)

class TadGAN(tf.keras.Model):
    """
    TadGAN based on the idea of https://arxiv.org/pdf/2009.07769.pdf

    The model can be used for anomaly detection in univariate & multivariate time series based on a GAN network architecture.

    This GAN architecture uses a encoder-generator network in combination with two discriminator networks (critics).
    One for the encoding of the incoming time series and the other to discriminate the learned embedding.

    This implementation uses the new TensorFlow 2 / Keras Subclassing API instead of a simple Python class.
    """
    def __init__(
        self,
        # Time series hyper parameters
        ts_input_shape: Tuple[int] = (100, 1),
        latent_dim: int = 20,
        gradient_penelty_weight: int = 10,
        n_iterations_critic: int = 5,

        # sub network hyper parameters
        encoder_lstm_units: int = 100,
        generator_lstm_units: int = 100,
        generator_output_activation: str = "tanh",
        critic_x_cnn_blocks: int = 4,
        critic_x_cnn_filters: int = 64,
        critic_z_dense_units: int = 100,

        log_all_losses: bool = True,
        print_model_summaries: bool = False
    ):
        super(TadGAN, self).__init__()

        # Parse default variables
        self.latent_dim = latent_dim
        self.ts_input_shape = ts_input_shape
        self.signal_length = ts_input_shape[0]
        self.n_channels = ts_input_shape[1]
        self.gradient_penelty_weight = gradient_penelty_weight
        self.n_iterations_critic = n_iterations_critic
        self.log_all_losses = log_all_losses

        # TadGAN encoder
        self.encoder_lstm_units = encoder_lstm_units
        self.encoder = self._build_encoder(lstm_units=self.encoder_lstm_units)

        # TadGAN generator
        self.generator_lstm_units = generator_lstm_units
        self.generator_act_fn = generator_output_activation
        self.generator = self._build_generator(generator_lstm_units=self.generator_lstm_units, output_activation=generator_output_activation)

        # TadGAN critic x
        self.critic_x_cnn_filters = critic_x_cnn_filters
        self.critic_x_cnn_blocks = critic_x_cnn_blocks
        self.critic_x = self._build_critic_x(n_cnn_filters=self.critic_x_cnn_filters, n_cnn_blocks=self.critic_x_cnn_blocks)

        # TadGAN critic z
        self.critic_z_dense_units = critic_z_dense_units
        self.critic_z = self._build_critic_z(critic_z_dense_units=self.critic_z_dense_units)

        if print_model_summaries:
            print(self.encoder.summary())
            print(self.generator.summary())
            print(self.critic_x.summary())
            print(self.critic_z.summary())

        self.build(input_shape=(None, ts_input_shape[0], ts_input_shape[1]))

    def get_config(self) -> dict:
        """
        Build a config dict for the custom attributes of this subclassing Keras model

        :return: Config as Python dict
        """
        return dict(
            ts_input_shape=self.ts_input_shape,
            latent_dim=self.latent_dim,
            gradient_penelty_weight=self.gradient_penelty_weight,
            n_iterations_critic=self.n_iterations_critic,
            log_all_losses=self.log_all_losses,

            # Hyperparameters
            encoder_lstm_units=self.encoder_lstm_units,
            generator_lstm_units=self.generator_lstm_units,
            critic_x_cnn_filters=self.critic_x_cnn_filters,
            critic_x_cnn_blocks=self.critic_x_cnn_blocks,
            critic_z_dense_units=self.critic_z_dense_units
        )

    def compile(
        self,
        critic_x_optimizer,
        critic_z_optimizer,
        encoder_generator_optimizer,
        critic_x_loss_fn,
        critic_z_loss_fn,
        encoder_generator_loss_fn,
        **kwargs
    ):
        """
        Customized Keras model compilation based on the idea of https://keras.io/examples/generative/wgan_gp/

        :param critic_x_optimizer: Keras optimizer for the critic x model
        :param critic_z_optimizer: Keras optimizer for the critic z model
        :param encoder_generator_optimizer: Keras optimizer for the encoder & generator model
        :param critic_x_loss_fn: Loss function for the critic x model
        :param critic_z_loss_fn: Loss function for the critic z model
        :param encoder_generator_loss_fn: Loss function for the generator & encoder model

        :param kwargs: Additional kwargs forwarded to the super class

        :return: None
        """
        super(TadGAN, self).compile(**kwargs)

        self.critic_x_optimizer = critic_x_optimizer
        self.critic_z_optimizer = critic_z_optimizer
        self.encoder_generator_optimizer = encoder_generator_optimizer

        self.critic_x_loss_fn = critic_x_loss_fn
        self.critic_z_loss_fn = critic_z_loss_fn
        self.encoder_generator_loss_fn = encoder_generator_loss_fn

    def _build_encoder(self, lstm_units: int = 100):
        """
        Build the Encoder subnetwork for the GAN. This model learns the compressed representation of the input
        time series.
        The encoder uses a single layer BI-LSTM network to learn the compressed representation.
        The number of LSTM units can be adjusted.

        :param lstm_units: Number of LSTM units that could be used for the time series encoding

        :return: Encoder model
        """
        x = tf.keras.layers.Input(shape=self.ts_input_shape, name="encoder_input")

        # Encode the sequence and extend its dimensions
        encoded = tf.keras.layers.Bidirectional(tf.keras.layers.LSTM(units=lstm_units, return_sequences=True))(x)
        encoded = tf.keras.layers.Flatten()(encoded)
        encoded = tf.keras.layers.Dense(units=self.latent_dim, name="latent_encoding")(encoded)
        encoded = tf.keras.layers.Reshape(target_shape=(self.latent_dim, 1), name='output_encoder')(encoded)

        model = tf.keras.Model(inputs=x, outputs=encoded, name="encoder_model")

        return model

    def _build_generator(self, generator_lstm_units: int = 100, output_activation: str = "tanh") -> tf.keras.Model:
        """
        Build the Generator model for the GAN. This model uses the compressed representation of the encoder and
        tries to reconstruct the original time series from it.
        At the moment a two-layer Bi-LSTM network is used for the reconstruction.

        :param generator_lstm_units: Number of LSTM units that should be used for the reconstruction.
        :param output_activation: The final activation of the generator. Choose with respect to the preprocesssing (scaling/normalizing)
                       of the input time series

        :return: Generator model
        """
        x = tf.keras.layers.Input(shape=(self.latent_dim, 1), name="generator_input")

        # Remove additional dimensions from the latent embedding
        decoded = tf.keras.layers.Flatten()(x)

        # Check if the sequence length is a even number (this is required for this model architecture)
        if self.signal_length % 2 == 1:
            raise ValueError(f"The signal length needs to be even (current signal length: {self.signal_length})")

        # Build the first layer of the generator that should be half the size of the sequence length
        half_seq_length = self.signal_length // 2
        decoded = tf.keras.layers.Dense(units=half_seq_length)(decoded)
        decoded = tf.keras.layers.Reshape(target_shape=(half_seq_length, 1))(decoded)

        # Generation of a new time series using LSTM in combination with up sampling
        decoded = tf.keras.layers.Bidirectional(
            tf.keras.layers.LSTM(units=generator_lstm_units, return_sequences=True, dropout=0.2, recurrent_dropout=0.2),
            merge_mode='concat'
        )(decoded)
        decoded = tf.keras.layers.UpSampling1D(2)(decoded)
        decoded = tf.keras.layers.Bidirectional(
            tf.keras.layers.LSTM(units=generator_lstm_units, return_sequences=True, dropout=0.2, recurrent_dropout=0.2),
            merge_mode='concat'
        )(decoded)

        # Rebuild the original time series signal for all channels
        decoded = tf.keras.layers.TimeDistributed(tf.keras.layers.Dense(self.n_channels))(decoded)
        decoded = tf.keras.layers.Activation(activation=output_activation)(decoded)

        model = tf.keras.Model(inputs=x, outputs=decoded, name="generator_model")

        return model

    def _build_critic_x(self, n_cnn_filters: int = 64, n_cnn_blocks: int = 4) -> tf.keras.Model:
        """
        Build the critic x network that learns to differ between a fake and real input sequence. The classifier uses a
        stack of 1D CNN block (CNN + leaky relu + dropout) and a final fully connected classifier network.

        :return: Critic x model
        """

        x = tf.keras.layers.Input(shape=self.ts_input_shape, name="critic_x_input")

        if n_cnn_blocks < 1:
            raise ValueError(f"The number of CNN blocks needs to be greater than 1 (current value: {n_cnn_blocks})")

        y = tf.keras.layers.Conv1D(filters=n_cnn_filters, kernel_size=5)(x)
        y = tf.keras.layers.LeakyReLU(alpha=0.2)(y)
        y = tf.keras.layers.Dropout(rate=0.25)(y)

        if n_cnn_blocks > 1:
            for i in range(n_cnn_blocks - 1):
                y = tf.keras.layers.Conv1D(filters=n_cnn_filters, kernel_size=5)(y)
                y = tf.keras.layers.LeakyReLU(alpha=0.2)(y)
                y = tf.keras.layers.Dropout(rate=0.25)(y)

        y = tf.keras.layers.Flatten()(y)
        y = tf.keras.layers.Dense(1)(y)

        model = tf.keras.Model(inputs=x, outputs=y, name="critic_x_model")

        return model

    def _build_critic_z(self, critic_z_dense_units: int = 100) -> tf.keras.Model:
        """
        Build the critic z model that learns to differ between a real and a fake encoding coming from the encoder.
        The network works with a two-layer fully connected network in combination with a leaky RELU activation
        and dropout regularization.

        :param critic_z_dense_units: Number of units for each of the fully connected layers

        :return: Critic z model
        """

        x = tf.keras.layers.Input(shape=(self.latent_dim, 1), name="critic_z_input")
        y = tf.keras.layers.Flatten()(x)

        y = tf.keras.layers.Dense(units=critic_z_dense_units)(y)
        y = tf.keras.layers.LeakyReLU(alpha=0.2)(y)
        y = tf.keras.layers.Dropout(rate=0.2)(y)

        y = tf.keras.layers.Dense(units=critic_z_dense_units)(y)
        y = tf.keras.layers.LeakyReLU(alpha=0.2)(y)
        y = tf.keras.layers.Dropout(rate=0.2)(y)

        y = tf.keras.layers.Dense(1)(y)

        model = tf.keras.Model(inputs=x, outputs=y, name="critic_z_model")

        return model

    @tf.function
    def critic_x_gradient_penalty(self, batch_size, y_true, y_pred):
        """
        Calculates the gradient penalty.
        """
        alpha = tf.keras.backend.random_uniform((batch_size, 1, 1))
        interpolated = (alpha * y_true) + ((1 - alpha) * y_pred)

        with tf.GradientTape() as gp_tape:
            gp_tape.watch(interpolated)
            # 1. Get the discriminator output for this interpolated image.
            pred = self.critic_x(interpolated)

        grads = gp_tape.gradient(pred, [interpolated])[0]
        norm = tf.sqrt(tf.reduce_sum(tf.square(grads), axis=[1, 2]))
        gp = tf.reduce_mean((norm - 1.0) ** 2)

        return gp

    @tf.function
    def critic_z_gradient_penalty(self, batch_size, y_true, y_pred):
        """
        Calculates the gradient penalty.
        """
        alpha = tf.keras.backend.random_uniform((batch_size, 1, 1))
        interpolated = (alpha * y_true) + ((1 - alpha) * y_pred)

        with tf.GradientTape() as gp_tape:
            gp_tape.watch(interpolated)
            # 1. Get the discriminator output for this interpolated image.
            pred = self.critic_z(interpolated)

        # 2. Calculate the gradients w.r.t to this interpolated image.
        grads = gp_tape.gradient(pred, [interpolated])[0]
        norm = tf.sqrt(tf.reduce_sum(tf.square(grads), axis=[1, 2]))
        gp = tf.reduce_mean((1.0 - norm) ** 2)

        return gp

    @tf.function
    def _critic_x_loss(self, x_mb, z, valid, fake, mini_batch_size):
        """
        Do a step forward and calculate the loss on the critic x model

        :param x_mb: Minibatch of input data
        :param z: Minibatch of random noise
        :param valid: Ground truth vector for valid samples
        :param fake: Ground truth vector for fake samples
        :param mini_batch_size:

        :return: A tuple containing the total loss and the three single losses
        """
        # Do a step forward on critic x model and collect gradients
        x_ = self.generator(z)
        fake_x = self.critic_x(x_)
        valid_x = self.critic_x(x_mb)

        # Calculate critic x loss
        critic_x_valid_cost = self.critic_x_loss_fn(y_true=valid, y_pred=valid_x)
        critic_x_fake_cost = self.critic_x_loss_fn(y_true=fake, y_pred=fake_x)
        # TODO: [SMe] Is the mini_batch size still required?
        critic_x_gradient_penalty = self.critic_x_gradient_penalty(mini_batch_size, x_mb, x_)
        critic_x_total_loss = critic_x_valid_cost + critic_x_fake_cost + (critic_x_gradient_penalty * self.gradient_penelty_weight)

        return critic_x_total_loss, critic_x_valid_cost, critic_x_fake_cost, critic_x_gradient_penalty

    @tf.function
    def _critic_z_loss(self, x_mb, z, valid, fake, mini_batch_size):
        """
        Do a step forward and calculate the loss on the critic z model

        :param x_mb: Minibatch of input data
        :param z: Minibatch of random noise
        :param valid: Ground truth vector for valid samples
        :param fake: Ground truth vector for fake samples
        :param mini_batch_size:

        :return: A tuple containing the total loss and the three single losses
        """
        # Do a step forward on critic z model and collect gradients
        z_ = self.encoder(x_mb)
        fake_z = self.critic_z(z_)
        valid_z = self.critic_z(z)

        # Calculate critic z loss
        critic_z_valid_cost = self.critic_z_loss_fn(y_true=valid, y_pred=valid_z)
        critic_z_fake_cost = self.critic_z_loss_fn(y_true=fake, y_pred=fake_z)
        critic_z_gradient_penalty = self.critic_z_gradient_penalty(mini_batch_size, z, z_)
        critic_z_total_loss = critic_z_valid_cost + critic_z_fake_cost + (critic_z_gradient_penalty * self.gradient_penelty_weight)

        return critic_z_total_loss, critic_z_valid_cost, critic_z_fake_cost, critic_z_gradient_penalty

    @tf.function
    def _encoder_generator_loss(self, x_mb, z, valid):
        """
        Do a step forward and calculate the loss on the encoder-generator model

        :param x_mb: Minibatch of input data
        :param z: Minibatch of random noise
        :param valid: Ground truth vector for valid samples

        :return: A tuple containing the total loss and the three single losses
        """
        # Do a step forward on the encoder generator model
        x_gen_ = self.generator(z)
        fake_gen_x = self.critic_x(x_gen_)

        z_gen_ = self.encoder(x_mb)
        x_gen_rec = self.generator(z_gen_)
        fake_gen_z = self.critic_z(z_gen_)

        # Calculate encoder generator loss
        encoder_generator_fake_gen_x_cost = self.encoder_generator_loss_fn(y_true=valid, y_pred=fake_gen_x)
        encoder_generator_fake_gen_z_cost = self.encoder_generator_loss_fn(y_true=valid, y_pred=fake_gen_z)

        # Use simple MSE as reconstruction error
        general_reconstruction_cost = tf.reduce_mean(tf.square((x_mb - x_gen_rec)))
        encoder_generator_total_loss = encoder_generator_fake_gen_x_cost + encoder_generator_fake_gen_z_cost + (10.0 * general_reconstruction_cost)

        return encoder_generator_total_loss, encoder_generator_fake_gen_x_cost, encoder_generator_fake_gen_z_cost, general_reconstruction_cost

    @tf.function
    def train_step(self, X) -> dict:
        """
        Custom training step for this Subclassing API Keras model.
        The shape should be (n_iterations_critic * batch size, n_channels) because the critic networks are trained
        multiple times over the encoder-generator network.

        :param X: Group of mini batches that are used to train the critics and the encoder-generator network
                  Shape: (batch_size, signal_length, n_channels)

        :return: Sub-model losses as los dict
        """
        if isinstance(X, tuple):
            X = X[0]

        batch_size = X.shape[0]
        mini_batch_size = batch_size // self.n_iterations_critic

        # Prepare the ground truth data
        fake = tf.ones((mini_batch_size, 1))
        valid = -tf.ones((mini_batch_size, 1))

        critic_x_loss_steps = []
        critic_z_loss_steps = []

        # Train the critics multiple steps more then the encoder-generator model
        for critic_train_step in range(self.n_iterations_critic):
            z = tf.random.normal(shape=(mini_batch_size, self.latent_dim, 1))
            x_mb = X[critic_train_step * mini_batch_size: (critic_train_step + 1) * mini_batch_size]

            # Optimize step on critic x
            with tf.GradientTape() as tape:
                # Do a step forward on critic x model and collect gradients
                _critic_x_losses = self._critic_x_loss(x_mb, z, valid, fake, mini_batch_size)

            # Backward step with updating critic x weights
            critic_x_gradient = tape.gradient(_critic_x_losses[0], self.critic_x.trainable_variables)
            self.critic_x_optimizer.apply_gradients(zip(critic_x_gradient, self.critic_x.trainable_variables))

            # Collect summaries for logging
            _critic_x_losses = np.array(_critic_x_losses)
            critic_x_loss_steps.append(_critic_x_losses)

            # Optimize step on critic z
            with tf.GradientTape() as tape:
                # Do a step forward on critic z model and collect gradients
                _critic_z_losses = self._critic_z_loss(x_mb, z, valid, fake, mini_batch_size)

            # Backward step with updating critic z weights
            critic_z_gradient = tape.gradient(_critic_z_losses[0], self.critic_z.trainable_variables)
            self.critic_z_optimizer.apply_gradients(zip(critic_z_gradient, self.critic_z.trainable_variables))

            # Collect summaries for logging
            _critic_z_losses = np.array(_critic_z_losses)
            critic_z_loss_steps.append(_critic_z_losses)

        # Optimize step on encoder & generator and collect gradients
        with tf.GradientTape() as tape:
            # Do a step forward on the encoder generator model
            _encoder_generator_losses = self._encoder_generator_loss(x_mb, z, valid)

        # Backward step with updating encoder generator weights
        encoder_generator_gradient = tape.gradient(_encoder_generator_losses, self.encoder.trainable_variables + self.generator.trainable_variables)
        self.encoder_generator_optimizer.apply_gradients(zip(encoder_generator_gradient, self.encoder.trainable_variables + self.generator.trainable_variables))

        # Collect summaries for logging
        critic_x_losses = np.mean(np.array(critic_x_loss_steps), axis=0)
        critic_z_losses = np.mean(np.array(critic_z_loss_steps), axis=0)
        encoder_generator_losses = np.array(_encoder_generator_losses)

        if self.log_all_losses:
            loss_dict = {
                "Cx_total": critic_x_losses[0],
                "Cx_valid": critic_x_losses[1],
                "Cx_fake": critic_x_losses[2],
                "Cx_gp_penalty": critic_x_losses[3],

                "Cz_total": critic_z_losses[0],
                "Cz_valid": critic_z_losses[1],
                "Cz_fake": critic_z_losses[2],
                "Cz_gp_penalty": critic_z_losses[3],

                "EG_total": encoder_generator_losses[0],
                "EG_fake_gen_x": encoder_generator_losses[1],
                "EG_fake_gen_z": encoder_generator_losses[2],
                "G_rec": encoder_generator_losses[3],
            }
        else:
            loss_dict = {
                "Cx_total": critic_x_losses[0],
                "Cz_total": critic_z_losses[0],
                "EG_total": encoder_generator_losses[0]
            }

        return loss_dict

    @tf.function
    def test_step(self, X):
        """
        Custom test step for this Subclassing API Keras model.
        This overrides the default behavior of the model.evaluate() function.

        :param X: Minibatch of time series signals (batch_size, signal_length, n_channels)

        :return: Sub-model losses as los dict
        """

        if isinstance(X, tuple):
            X = X[0]

        batch_size = X.shape[0]

        # Prepare the ground truth data
        fake = tf.ones((batch_size, 1))
        valid = -tf.ones((batch_size, 1))

        z = tf.random.normal(shape=(batch_size, self.latent_dim, 1))

        critic_x_losses = self._critic_x_loss(X, z, valid, fake, batch_size)
        critic_z_losses = self._critic_z_loss(X, z, valid, fake, batch_size)
        encoder_generator_losses = self._encoder_generator_loss(X, z, valid)

        if self.log_all_losses:
            loss_dict = {
                "Cx_total": critic_x_losses[0],
                "Cx_valid": critic_x_losses[1],
                "Cx_fake": critic_x_losses[2],
                "Cx_gp_penalty": critic_x_losses[3],

                "Cz_total": critic_z_losses[0],
                "Cz_valid": critic_z_losses[1],
                "Cz_fake": critic_z_losses[2],
                "Cz_gp_penalty": critic_z_losses[3],

                "EG_total": encoder_generator_losses[0],
                "EG_fake_gen_x": encoder_generator_losses[1],
                "EG_fake_gen_z": encoder_generator_losses[2],
                "G_rec": encoder_generator_losses[3],
            }
        else:
            loss_dict = {
                "Cx_total": critic_x_losses[0],
                "Cz_total": critic_z_losses[0],
                "EG_total": encoder_generator_losses[0]
            }

        return loss_dict

    @tf.function
    def call(self, X, **kwargs) -> Tuple[np.array, np.array, np.array, np.array]:
        """
        Default forward step during the inference step of the model (for training and evaluation see train_step() and test_step()).
        This function will be called in the model.predict() function to use the trained sub networks for anomaly detection.

        :param X: Batch of signals that should be analyzed by the model (batch_size, signal_length, n_channels)

        :param kwargs: Additional kwargs forwarded to the super class fit method

        :return: Tuple containing the outputs of the sub networks as numpy arrays:
                 - The reconstructed signals from the generator
                 - The compressed embedding of the time series (latent_dim, 1) from the encoder
                 - The fake/real classification result for the reconstructed time series from the critic x network
                 - The fake/real classification result for the learned embedding from the critic z network
        """
        latent_encoding = self.encoder(X)
        y_hat = self.generator(latent_encoding)
        critic_x = self.critic_x(X)
        critic_z = self.critic_z(latent_encoding)
        return y_hat, latent_encoding, critic_x, critic_z

    def fit(
        self,
        x=None, y=None, batch_size=None, epochs=1, verbose=1, callbacks=None,
        validation_split=0., validation_data=None, shuffle=True,
        class_weight=None, sample_weight=None,
        initial_epoch=0, steps_per_epoch=None, validation_steps=None, validation_batch_size=None, validation_freq=1,
        max_queue_size=10, workers=1, use_multiprocessing=False
    ):
        """
        Extends the orignal fit method of the keras.Model API with some checks for the train_step batch size requirements.
        See for https://www.tensorflow.org/api_docs/python/tf/keras/Model#fit more details

        :return: Keras model training history dict
        """
        # Adjust batch size to support multiple training steps on the critics
        if not isinstance(validation_data, tf.data.Dataset):
            if (validation_data is not None) and (validation_batch_size is None):
                validation_batch_size = batch_size

        if not isinstance(x, tf.data.Dataset):
            batch_size = batch_size * self.n_iterations_critic

        return super().fit(x, y, batch_size, epochs, verbose, callbacks, validation_split, validation_data, shuffle,
                           class_weight, sample_weight, initial_epoch, steps_per_epoch, validation_steps,
                           validation_batch_size, validation_freq, max_queue_size, workers, use_multiprocessing)

    @staticmethod
    def export_as_keras_model(tadgan_model, export_path: str):
        # Rebuild model graph
        x = tf.keras.layers.Input(shape=tadgan_model.ts_input_shape, name="ts_input")
        latent_encoding = tadgan_model.encoder(x)
        y_hat = tadgan_model.generator(latent_encoding)
        critic_x = tadgan_model.critic_x(x)
        critic_z = tadgan_model.critic_z(latent_encoding)

        # Export model
        standalone_model = tf.keras.models.Model(inputs=x, outputs=[y_hat, latent_encoding, critic_x, critic_z])
        standalone_model.save(export_path)

Hello @sarahmish and @A2015Albasir ,
here are my current version I was able to run in TF2.3 and TF2.4. It uses the Subclassing API and can handle multivariate time series data. This means the model can be trained using the fit/predict function like a simple Keras model. The rest of the architecture should be the same as in the TadGAN paper.
import os
from typing import Tuple
import numpy as np
import tensorflow as tf

def _wasserstein_loss(y_true, y_pred):
    return tf.keras.backend.mean(y_true * y_pred)

class TadGAN(tf.keras.Model):
    """
    TadGAN based on the idea of https://arxiv.org/pdf/2009.07769.pdf

    The model can be used for anomaly detection in univariate & multivariate time series based on a GAN network architecture.

    This GAN architecture uses a encoder-generator network in combination with two discriminator networks (critics).
    One for the encoding of the incoming time series and the other to discriminate the learned embedding.

    This implementation uses the new TensorFlow 2 / Keras Subclassing API instead of a simple Python class.
    """
    def __init__(
        self,
        # Time series hyper parameters
        ts_input_shape: Tuple[int] = (100, 1),
        latent_dim: int = 20,
        gradient_penelty_weight: int = 10,
        n_iterations_critic: int = 5,

        # sub network hyper parameters
        encoder_lstm_units: int = 100,
        generator_lstm_units: int = 100,
        generator_output_activation: str = "tanh",
        critic_x_cnn_blocks: int = 4,
        critic_x_cnn_filters: int = 64,
        critic_z_dense_units: int = 100,

        log_all_losses: bool = True,
        print_model_summaries: bool = False
    ):
        super(TadGAN, self).__init__()

        # Parse default variables
        self.latent_dim = latent_dim
        self.ts_input_shape = ts_input_shape
        self.signal_length = ts_input_shape[0]
        self.n_channels = ts_input_shape[1]
        self.gradient_penelty_weight = gradient_penelty_weight
        self.n_iterations_critic = n_iterations_critic
        self.log_all_losses = log_all_losses

        # TadGAN encoder
        self.encoder_lstm_units = encoder_lstm_units
        self.encoder = self._build_encoder(lstm_units=self.encoder_lstm_units)

        # TadGAN generator
        self.generator_lstm_units = generator_lstm_units
        self.generator_act_fn = generator_output_activation
        self.generator = self._build_generator(generator_lstm_units=self.generator_lstm_units, output_activation=generator_output_activation)

        # TadGAN critic x
        self.critic_x_cnn_filters = critic_x_cnn_filters
        self.critic_x_cnn_blocks = critic_x_cnn_blocks
        self.critic_x = self._build_critic_x(n_cnn_filters=self.critic_x_cnn_filters, n_cnn_blocks=self.critic_x_cnn_blocks)

        # TadGAN critic z
        self.critic_z_dense_units = critic_z_dense_units
        self.critic_z = self._build_critic_z(critic_z_dense_units=self.critic_z_dense_units)

        if print_model_summaries:
            print(self.encoder.summary())
            print(self.generator.summary())
            print(self.critic_x.summary())
            print(self.critic_z.summary())

        self.build(input_shape=(None, ts_input_shape[0], ts_input_shape[1]))

    def get_config(self) -> dict:
        """
        Build a config dict for the custom attributes of this subclassing Keras model

        :return: Config as Python dict
        """
        return dict(
            ts_input_shape=self.ts_input_shape,
            latent_dim=self.latent_dim,
            gradient_penelty_weight=self.gradient_penelty_weight,
            n_iterations_critic=self.n_iterations_critic,
            log_all_losses=self.log_all_losses,

            # Hyperparameters
            encoder_lstm_units=self.encoder_lstm_units,
            generator_lstm_units=self.generator_lstm_units,
            critic_x_cnn_filters=self.critic_x_cnn_filters,
            critic_x_cnn_blocks=self.critic_x_cnn_blocks,
            critic_z_dense_units=self.critic_z_dense_units
        )

    def compile(
        self,
        critic_x_optimizer,
        critic_z_optimizer,
        encoder_generator_optimizer,
        critic_x_loss_fn,
        critic_z_loss_fn,
        encoder_generator_loss_fn,
        **kwargs
    ):
        """
        Customized Keras model compilation based on the idea of https://keras.io/examples/generative/wgan_gp/

        :param critic_x_optimizer: Keras optimizer for the critic x model
        :param critic_z_optimizer: Keras optimizer for the critic z model
        :param encoder_generator_optimizer: Keras optimizer for the encoder & generator model
        :param critic_x_loss_fn: Loss function for the critic x model
        :param critic_z_loss_fn: Loss function for the critic z model
        :param encoder_generator_loss_fn: Loss function for the generator & encoder model

        :param kwargs: Additional kwargs forwarded to the super class

        :return: None
        """
        super(TadGAN, self).compile(**kwargs)

        self.critic_x_optimizer = critic_x_optimizer
        self.critic_z_optimizer = critic_z_optimizer
        self.encoder_generator_optimizer = encoder_generator_optimizer

        self.critic_x_loss_fn = critic_x_loss_fn
        self.critic_z_loss_fn = critic_z_loss_fn
        self.encoder_generator_loss_fn = encoder_generator_loss_fn

    def _build_encoder(self, lstm_units: int = 100):
        """
        Build the Encoder subnetwork for the GAN. This model learns the compressed representation of the input
        time series.
        The encoder uses a single layer BI-LSTM network to learn the compressed representation.
        The number of LSTM units can be adjusted.

        :param lstm_units: Number of LSTM units that could be used for the time series encoding

        :return: Encoder model
        """
        x = tf.keras.layers.Input(shape=self.ts_input_shape, name="encoder_input")

        # Encode the sequence and extend its dimensions
        encoded = tf.keras.layers.Bidirectional(tf.keras.layers.LSTM(units=lstm_units, return_sequences=True))(x)
        encoded = tf.keras.layers.Flatten()(encoded)
        encoded = tf.keras.layers.Dense(units=self.latent_dim, name="latent_encoding")(encoded)
        encoded = tf.keras.layers.Reshape(target_shape=(self.latent_dim, 1), name='output_encoder')(encoded)

        model = tf.keras.Model(inputs=x, outputs=encoded, name="encoder_model")

        return model

    def _build_generator(self, generator_lstm_units: int = 100, output_activation: str = "tanh") -> tf.keras.Model:
        """
        Build the Generator model for the GAN. This model uses the compressed representation of the encoder and
        tries to reconstruct the original time series from it.
        At the moment a two-layer Bi-LSTM network is used for the reconstruction.

        :param generator_lstm_units: Number of LSTM units that should be used for the reconstruction.
        :param output_activation: The final activation of the generator. Choose with respect to the preprocesssing (scaling/normalizing)
                       of the input time series

        :return: Generator model
        """
        x = tf.keras.layers.Input(shape=(self.latent_dim, 1), name="generator_input")

        # Remove additional dimensions from the latent embedding
        decoded = tf.keras.layers.Flatten()(x)

        # Check if the sequence length is a even number (this is required for this model architecture)
        if self.signal_length % 2 == 1:
            raise ValueError(f"The signal length needs to be even (current signal length: {self.signal_length})")

        # Build the first layer of the generator that should be half the size of the sequence length
        half_seq_length = self.signal_length // 2
        decoded = tf.keras.layers.Dense(units=half_seq_length)(decoded)
        decoded = tf.keras.layers.Reshape(target_shape=(half_seq_length, 1))(decoded)

        # Generation of a new time series using LSTM in combination with up sampling
        decoded = tf.keras.layers.Bidirectional(
            tf.keras.layers.LSTM(units=generator_lstm_units, return_sequences=True, dropout=0.2, recurrent_dropout=0.2),
            merge_mode='concat'
        )(decoded)
        decoded = tf.keras.layers.UpSampling1D(2)(decoded)
        decoded = tf.keras.layers.Bidirectional(
            tf.keras.layers.LSTM(units=generator_lstm_units, return_sequences=True, dropout=0.2, recurrent_dropout=0.2),
            merge_mode='concat'
        )(decoded)

        # Rebuild the original time series signal for all channels
        decoded = tf.keras.layers.TimeDistributed(tf.keras.layers.Dense(self.n_channels))(decoded)
        decoded = tf.keras.layers.Activation(activation=output_activation)(decoded)

        model = tf.keras.Model(inputs=x, outputs=decoded, name="generator_model")

        return model

    def _build_critic_x(self, n_cnn_filters: int = 64, n_cnn_blocks: int = 4) -> tf.keras.Model:
        """
        Build the critic x network that learns to differ between a fake and real input sequence. The classifier uses a
        stack of 1D CNN block (CNN + leaky relu + dropout) and a final fully connected classifier network.

        :return: Critic x model
        """

        x = tf.keras.layers.Input(shape=self.ts_input_shape, name="critic_x_input")

        if n_cnn_blocks < 1:
            raise ValueError(f"The number of CNN blocks needs to be greater than 1 (current value: {n_cnn_blocks})")

        y = tf.keras.layers.Conv1D(filters=n_cnn_filters, kernel_size=5)(x)
        y = tf.keras.layers.LeakyReLU(alpha=0.2)(y)
        y = tf.keras.layers.Dropout(rate=0.25)(y)

        if n_cnn_blocks > 1:
            for i in range(n_cnn_blocks - 1):
                y = tf.keras.layers.Conv1D(filters=n_cnn_filters, kernel_size=5)(y)
                y = tf.keras.layers.LeakyReLU(alpha=0.2)(y)
                y = tf.keras.layers.Dropout(rate=0.25)(y)

        y = tf.keras.layers.Flatten()(y)
        y = tf.keras.layers.Dense(1)(y)

        model = tf.keras.Model(inputs=x, outputs=y, name="critic_x_model")

        return model

    def _build_critic_z(self, critic_z_dense_units: int = 100) -> tf.keras.Model:
        """
        Build the critic z model that learns to differ between a real and a fake encoding coming from the encoder.
        The network works with a two-layer fully connected network in combination with a leaky RELU activation
        and dropout regularization.

        :param critic_z_dense_units: Number of units for each of the fully connected layers

        :return: Critic z model
        """

        x = tf.keras.layers.Input(shape=(self.latent_dim, 1), name="critic_z_input")
        y = tf.keras.layers.Flatten()(x)

        y = tf.keras.layers.Dense(units=critic_z_dense_units)(y)
        y = tf.keras.layers.LeakyReLU(alpha=0.2)(y)
        y = tf.keras.layers.Dropout(rate=0.2)(y)

        y = tf.keras.layers.Dense(units=critic_z_dense_units)(y)
        y = tf.keras.layers.LeakyReLU(alpha=0.2)(y)
        y = tf.keras.layers.Dropout(rate=0.2)(y)

        y = tf.keras.layers.Dense(1)(y)

        model = tf.keras.Model(inputs=x, outputs=y, name="critic_z_model")

        return model

    @tf.function
    def critic_x_gradient_penalty(self, batch_size, y_true, y_pred):
        """
        Calculates the gradient penalty.
        """
        alpha = tf.keras.backend.random_uniform((batch_size, 1, 1))
        interpolated = (alpha * y_true) + ((1 - alpha) * y_pred)

        with tf.GradientTape() as gp_tape:
            gp_tape.watch(interpolated)
            # 1. Get the discriminator output for this interpolated image.
            pred = self.critic_x(interpolated)

        grads = gp_tape.gradient(pred, [interpolated])[0]
        norm = tf.sqrt(tf.reduce_sum(tf.square(grads), axis=[1, 2]))
        gp = tf.reduce_mean((norm - 1.0) ** 2)

        return gp

    @tf.function
    def critic_z_gradient_penalty(self, batch_size, y_true, y_pred):
        """
        Calculates the gradient penalty.
        """
        alpha = tf.keras.backend.random_uniform((batch_size, 1, 1))
        interpolated = (alpha * y_true) + ((1 - alpha) * y_pred)

        with tf.GradientTape() as gp_tape:
            gp_tape.watch(interpolated)
            # 1. Get the discriminator output for this interpolated image.
            pred = self.critic_z(interpolated)

        # 2. Calculate the gradients w.r.t to this interpolated image.
        grads = gp_tape.gradient(pred, [interpolated])[0]
        norm = tf.sqrt(tf.reduce_sum(tf.square(grads), axis=[1, 2]))
        gp = tf.reduce_mean((1.0 - norm) ** 2)

        return gp

    @tf.function
    def _critic_x_loss(self, x_mb, z, valid, fake, mini_batch_size):
        """
        Do a step forward and calculate the loss on the critic x model

        :param x_mb: Minibatch of input data
        :param z: Minibatch of random noise
        :param valid: Ground truth vector for valid samples
        :param fake: Ground truth vector for fake samples
        :param mini_batch_size:

        :return: A tuple containing the total loss and the three single losses
        """
        # Do a step forward on critic x model and collect gradients
        x_ = self.generator(z)
        fake_x = self.critic_x(x_)
        valid_x = self.critic_x(x_mb)

        # Calculate critic x loss
        critic_x_valid_cost = self.critic_x_loss_fn(y_true=valid, y_pred=valid_x)
        critic_x_fake_cost = self.critic_x_loss_fn(y_true=fake, y_pred=fake_x)
        # TODO: [SMe] Is the mini_batch size still required?
        critic_x_gradient_penalty = self.critic_x_gradient_penalty(mini_batch_size, x_mb, x_)
        critic_x_total_loss = critic_x_valid_cost + critic_x_fake_cost + (critic_x_gradient_penalty * self.gradient_penelty_weight)

        return critic_x_total_loss, critic_x_valid_cost, critic_x_fake_cost, critic_x_gradient_penalty

    @tf.function
    def _critic_z_loss(self, x_mb, z, valid, fake, mini_batch_size):
        """
        Do a step forward and calculate the loss on the critic z model

        :param x_mb: Minibatch of input data
        :param z: Minibatch of random noise
        :param valid: Ground truth vector for valid samples
        :param fake: Ground truth vector for fake samples
        :param mini_batch_size:

        :return: A tuple containing the total loss and the three single losses
        """
        # Do a step forward on critic z model and collect gradients
        z_ = self.encoder(x_mb)
        fake_z = self.critic_z(z_)
        valid_z = self.critic_z(z)

        # Calculate critic z loss
        critic_z_valid_cost = self.critic_z_loss_fn(y_true=valid, y_pred=valid_z)
        critic_z_fake_cost = self.critic_z_loss_fn(y_true=fake, y_pred=fake_z)
        critic_z_gradient_penalty = self.critic_z_gradient_penalty(mini_batch_size, z, z_)
        critic_z_total_loss = critic_z_valid_cost + critic_z_fake_cost + (critic_z_gradient_penalty * self.gradient_penelty_weight)

        return critic_z_total_loss, critic_z_valid_cost, critic_z_fake_cost, critic_z_gradient_penalty

    @tf.function
    def _encoder_generator_loss(self, x_mb, z, valid):
        """
        Do a step forward and calculate the loss on the encoder-generator model

        :param x_mb: Minibatch of input data
        :param z: Minibatch of random noise
        :param valid: Ground truth vector for valid samples

        :return: A tuple containing the total loss and the three single losses
        """
        # Do a step forward on the encoder generator model
        x_gen_ = self.generator(z)
        fake_gen_x = self.critic_x(x_gen_)

        z_gen_ = self.encoder(x_mb)
        x_gen_rec = self.generator(z_gen_)
        fake_gen_z = self.critic_z(z_gen_)

        # Calculate encoder generator loss
        encoder_generator_fake_gen_x_cost = self.encoder_generator_loss_fn(y_true=valid, y_pred=fake_gen_x)
        encoder_generator_fake_gen_z_cost = self.encoder_generator_loss_fn(y_true=valid, y_pred=fake_gen_z)

        # Use simple MSE as reconstruction error
        general_reconstruction_cost = tf.reduce_mean(tf.square((x_mb - x_gen_rec)))
        encoder_generator_total_loss = encoder_generator_fake_gen_x_cost + encoder_generator_fake_gen_z_cost + (10.0 * general_reconstruction_cost)

        return encoder_generator_total_loss, encoder_generator_fake_gen_x_cost, encoder_generator_fake_gen_z_cost, general_reconstruction_cost

    @tf.function
    def train_step(self, X) -> dict:
        """
        Custom training step for this Subclassing API Keras model.
        The shape should be (n_iterations_critic * batch size, n_channels) because the critic networks are trained
        multiple times over the encoder-generator network.

        :param X: Group of mini batches that are used to train the critics and the encoder-generator network
                  Shape: (batch_size, signal_length, n_channels)

        :return: Sub-model losses as los dict
        """
        if isinstance(X, tuple):
            X = X[0]

        batch_size = X.shape[0]
        mini_batch_size = batch_size // self.n_iterations_critic

        # Prepare the ground truth data
        fake = tf.ones((mini_batch_size, 1))
        valid = -tf.ones((mini_batch_size, 1))

        critic_x_loss_steps = []
        critic_z_loss_steps = []

        # Train the critics multiple steps more then the encoder-generator model
        for critic_train_step in range(self.n_iterations_critic):
            z = tf.random.normal(shape=(mini_batch_size, self.latent_dim, 1))
            x_mb = X[critic_train_step * mini_batch_size: (critic_train_step + 1) * mini_batch_size]

            # Optimize step on critic x
            with tf.GradientTape() as tape:
                # Do a step forward on critic x model and collect gradients
                _critic_x_losses = self._critic_x_loss(x_mb, z, valid, fake, mini_batch_size)

            # Backward step with updating critic x weights
            critic_x_gradient = tape.gradient(_critic_x_losses[0], self.critic_x.trainable_variables)
            self.critic_x_optimizer.apply_gradients(zip(critic_x_gradient, self.critic_x.trainable_variables))

            # Collect summaries for logging
            _critic_x_losses = np.array(_critic_x_losses)
            critic_x_loss_steps.append(_critic_x_losses)

            # Optimize step on critic z
            with tf.GradientTape() as tape:
                # Do a step forward on critic z model and collect gradients
                _critic_z_losses = self._critic_z_loss(x_mb, z, valid, fake, mini_batch_size)

            # Backward step with updating critic z weights
            critic_z_gradient = tape.gradient(_critic_z_losses[0], self.critic_z.trainable_variables)
            self.critic_z_optimizer.apply_gradients(zip(critic_z_gradient, self.critic_z.trainable_variables))

            # Collect summaries for logging
            _critic_z_losses = np.array(_critic_z_losses)
            critic_z_loss_steps.append(_critic_z_losses)

        # Optimize step on encoder & generator and collect gradients
        with tf.GradientTape() as tape:
            # Do a step forward on the encoder generator model
            _encoder_generator_losses = self._encoder_generator_loss(x_mb, z, valid)

        # Backward step with updating encoder generator weights
        encoder_generator_gradient = tape.gradient(_encoder_generator_losses, self.encoder.trainable_variables + self.generator.trainable_variables)
        self.encoder_generator_optimizer.apply_gradients(zip(encoder_generator_gradient, self.encoder.trainable_variables + self.generator.trainable_variables))

        # Collect summaries for logging
        critic_x_losses = np.mean(np.array(critic_x_loss_steps), axis=0)
        critic_z_losses = np.mean(np.array(critic_z_loss_steps), axis=0)
        encoder_generator_losses = np.array(_encoder_generator_losses)

        if self.log_all_losses:
            loss_dict = {
                "Cx_total": critic_x_losses[0],
                "Cx_valid": critic_x_losses[1],
                "Cx_fake": critic_x_losses[2],
                "Cx_gp_penalty": critic_x_losses[3],

                "Cz_total": critic_z_losses[0],
                "Cz_valid": critic_z_losses[1],
                "Cz_fake": critic_z_losses[2],
                "Cz_gp_penalty": critic_z_losses[3],

                "EG_total": encoder_generator_losses[0],
                "EG_fake_gen_x": encoder_generator_losses[1],
                "EG_fake_gen_z": encoder_generator_losses[2],
                "G_rec": encoder_generator_losses[3],
            }
        else:
            loss_dict = {
                "Cx_total": critic_x_losses[0],
                "Cz_total": critic_z_losses[0],
                "EG_total": encoder_generator_losses[0]
            }

        return loss_dict

    @tf.function
    def test_step(self, X):
        """
        Custom test step for this Subclassing API Keras model.
        This overrides the default behavior of the model.evaluate() function.

        :param X: Minibatch of time series signals (batch_size, signal_length, n_channels)

        :return: Sub-model losses as los dict
        """

        if isinstance(X, tuple):
            X = X[0]

        batch_size = X.shape[0]

        # Prepare the ground truth data
        fake = tf.ones((batch_size, 1))
        valid = -tf.ones((batch_size, 1))

        z = tf.random.normal(shape=(batch_size, self.latent_dim, 1))

        critic_x_losses = self._critic_x_loss(X, z, valid, fake, batch_size)
        critic_z_losses = self._critic_z_loss(X, z, valid, fake, batch_size)
        encoder_generator_losses = self._encoder_generator_loss(X, z, valid)

        if self.log_all_losses:
            loss_dict = {
                "Cx_total": critic_x_losses[0],
                "Cx_valid": critic_x_losses[1],
                "Cx_fake": critic_x_losses[2],
                "Cx_gp_penalty": critic_x_losses[3],

                "Cz_total": critic_z_losses[0],
                "Cz_valid": critic_z_losses[1],
                "Cz_fake": critic_z_losses[2],
                "Cz_gp_penalty": critic_z_losses[3],

                "EG_total": encoder_generator_losses[0],
                "EG_fake_gen_x": encoder_generator_losses[1],
                "EG_fake_gen_z": encoder_generator_losses[2],
                "G_rec": encoder_generator_losses[3],
            }
        else:
            loss_dict = {
                "Cx_total": critic_x_losses[0],
                "Cz_total": critic_z_losses[0],
                "EG_total": encoder_generator_losses[0]
            }

        return loss_dict

    @tf.function
    def call(self, X, **kwargs) -> Tuple[np.array, np.array, np.array, np.array]:
        """
        Default forward step during the inference step of the model (for training and evaluation see train_step() and test_step()).
        This function will be called in the model.predict() function to use the trained sub networks for anomaly detection.

        :param X: Batch of signals that should be analyzed by the model (batch_size, signal_length, n_channels)

        :param kwargs: Additional kwargs forwarded to the super class fit method

        :return: Tuple containing the outputs of the sub networks as numpy arrays:
                 - The reconstructed signals from the generator
                 - The compressed embedding of the time series (latent_dim, 1) from the encoder
                 - The fake/real classification result for the reconstructed time series from the critic x network
                 - The fake/real classification result for the learned embedding from the critic z network
        """
        latent_encoding = self.encoder(X)
        y_hat = self.generator(latent_encoding)
        critic_x = self.critic_x(X)
        critic_z = self.critic_z(latent_encoding)
        return y_hat, latent_encoding, critic_x, critic_z

    def fit(
        self,
        x=None, y=None, batch_size=None, epochs=1, verbose=1, callbacks=None,
        validation_split=0., validation_data=None, shuffle=True,
        class_weight=None, sample_weight=None,
        initial_epoch=0, steps_per_epoch=None, validation_steps=None, validation_batch_size=None, validation_freq=1,
        max_queue_size=10, workers=1, use_multiprocessing=False
    ):
        """
        Extends the orignal fit method of the keras.Model API with some checks for the train_step batch size requirements.
        See for https://www.tensorflow.org/api_docs/python/tf/keras/Model#fit more details

        :return: Keras model training history dict
        """
        # Adjust batch size to support multiple training steps on the critics
        if not isinstance(validation_data, tf.data.Dataset):
            if (validation_data is not None) and (validation_batch_size is None):
                validation_batch_size = batch_size

        if not isinstance(x, tf.data.Dataset):
            batch_size = batch_size * self.n_iterations_critic

        return super().fit(x, y, batch_size, epochs, verbose, callbacks, validation_split, validation_data, shuffle,
                           class_weight, sample_weight, initial_epoch, steps_per_epoch, validation_steps,
                           validation_batch_size, validation_freq, max_queue_size, workers, use_multiprocessing)

    @staticmethod
    def export_as_keras_model(tadgan_model, export_path: str):
        # Rebuild model graph
        x = tf.keras.layers.Input(shape=tadgan_model.ts_input_shape, name="ts_input")
        latent_encoding = tadgan_model.encoder(x)
        y_hat = tadgan_model.generator(latent_encoding)
        critic_x = tadgan_model.critic_x(x)
        critic_z = tadgan_model.critic_z(latent_encoding)

        # Export model
        standalone_model = tf.keras.models.Model(inputs=x, outputs=[y_hat, latent_encoding, critic_x, critic_z])
        standalone_model.save(export_path)

@blaskowitz100 thanks man!

@blaskowitz100 thanks man!

@AKJHK2021
You can fit the model with a numpy array that has a shape of (n_samples, subsequence_length, features) or a similar prepared tf.data.Dataset. One thing is very important. The n_samples needs to be a multiple of the class attribute "n_iterations_critic".
Here is a small example for a tf.data.Dataset:
x_train_normal = ... # Numpy array with training data
x_val_normal = ... # Numpy array with validation data
batch_size = 32 # Model batch size that should be used to fit the model
predict_batch_size = 1024 # Bigger batch size to speed up model predictions

train_normal_ds = tf.data.Dataset.from_tensor_slices(x_train_normal).shuffle(x_train_normal.shape[0])
train_normal_ds = train_normal_ds.batch(batch_size * n_critic_train_iter, drop_remainder=True)

val_normal_ds = tf.data.Dataset.from_tensor_slices(x_val_normal).shuffle(x_val_normal.shape[0])
val_normal_ds = val_normal_ds.batch(predict_batch_size, drop_remainder=True)

You can then use this in the fit() function:
...
model.fit(
   train_normal_ds,
   epochs=100,
   validation_data=val_normal_ds
)
...

The prediction later on is very similar.

@AKJHK2021
You can fit the model with a numpy array that has a shape of (n_samples, subsequence_length, features) or a similar prepared tf.data.Dataset. One thing is very important. The n_samples needs to be a multiple of the class attribute "n_iterations_critic".
Here is a small example for a tf.data.Dataset:
x_train_normal = ... # Numpy array with training data
x_val_normal = ... # Numpy array with validation data
batch_size = 32 # Model batch size that should be used to fit the model
predict_batch_size = 1024 # Bigger batch size to speed up model predictions

train_normal_ds = tf.data.Dataset.from_tensor_slices(x_train_normal).shuffle(x_train_normal.shape[0])
train_normal_ds = train_normal_ds.batch(batch_size * n_critic_train_iter, drop_remainder=True)

val_normal_ds = tf.data.Dataset.from_tensor_slices(x_val_normal).shuffle(x_val_normal.shape[0])
val_normal_ds = val_normal_ds.batch(predict_batch_size, drop_remainder=True)

You can then use this in the fit() function:
...
model.fit(
   train_normal_ds,
   epochs=100,
   validation_data=val_normal_ds
)
...

The prediction later on is very similar.

@blaskowitz100
The source code for this issue has not yet been merged, can I use it as an MIT license like any other Orion source code?
Thanks

@halkkuma
For me it is not a problem and you can use the code in the same way like the other sources of this repository.
@GiacomoSintoni
To run the code snippet from above it is important that the input numpy arrays have the shape [n_samples, n_features, n_timesteps] otherwise the training will fail. If you have still problems more information/details about the failure would be helpful.

I love this model, and greatly admire your work here. Can you comment on the compile step, in particular the loss functions for the critics and encoder/generators, but also suggestions for best optimisers, to go with Adam or some of the the others? Thanks

@blaskowitz100 Thank you for sharing your code.
I have one question. I imported TadGAN class and set my custom data(4200000,20,1).
and I tried to fit the model.
But It doesn't work caues "name 'model' is not defined"
how can I make model using TadGAN class?

Hi @My-MacE, do you have some more details on how you set up your model? Usally there is no need to define a separate model, because TadGAN is a subclass of a Keras model:
model = TadGAN(ts_input_shape=(20,1), ...)

@blaskowitz100 Thank you for your replying. Could you write more details when fit the model?
Here is my code

I imported TadGAN class that you written in commented [on Jan 28, 2021]
I made traning data set(x_train) using my custom data: Training input shape:  (4749410, 20, 1))
After making traning set, I typed your code to fit the model

x_train_normal = x_train[0:4274460] # Numpy array with training data
x_val_normal = x_train[4274460:4749400] # Numpy array with validation data
batch_size = 128 # Model batch size that should be used to fit the model
predict_batch_size = 1024 # Bigger batch size to speed up model predictions
train_normal_ds = tf.data.Dataset.from_tensor_slices(x_train_normal).shuffle(x_train_normal.shape[0])
train_normal_ds = train_normal_ds.batch(batch_size * 33395, drop_remainder=True).  # I replaced n_critic_train_iter with 33395 cause I think my tranning size is  4274460(128*33395) Am I right?
val_normal_ds = tf.data.Dataset.from_tensor_slices(x_val_normal).shuffle(x_val_normal.shape[0])
val_normal_ds = val_normal_ds.batch(predict_batch_size, drop_remainder=True)
and I ran this code
model.fit(
train_normal_ds,
epochs=1,
validation_data=val_normal_ds
)
I think I didn't make 'model' so I want to know how can I train my own data(Making model code using subclass)
Thank you!

Hi @blaskowitz100 I tried to used NewYork taxi data

Hi  @blaskowitz100 , I tried to use this model NewYork Taxi Data,
I found error
model.fit(x_train,batch_size=256,epochs=1)

TypeError                                 Traceback (most recent call last)
Cell In[49], line 1
----> 1 model.fit(x_train,batch_size=256,epochs=1)

Cell In[44], line 567, in TadGAN.fit(self, x, y, batch_size, epochs, verbose, callbacks, validation_split, validation_data, shuffle, class_weight, sample_weight, initial_epoch, steps_per_epoch, validation_steps, validation_batch_size, validation_freq, max_queue_size, workers, use_multiprocessing)
    564 if not isinstance(x, tf.data.Dataset):
    565     batch_size = batch_size * self.n_iterations_critic
--> 567 return super().fit(x, y, batch_size, epochs, verbose, callbacks, validation_split, validation_data, shuffle,
    568                    class_weight, sample_weight, initial_epoch, steps_per_epoch, validation_steps,
    569                    validation_batch_size, validation_freq, max_queue_size, workers, use_multiprocessing)

TypeError: fit() takes from 1 to 19 positional arguments but 20 were given

I don't know why fit error happen. My data is (Number of sample(8060), Time_step(100), Feature(1))

Hello @My-MacE,
what version of TensorFlow are you using to train the model?
I see that I only used positional arguments to call the parent fit function. Maybe the order or the number of arguments has changed between the different Tensorflow versions. To check this, we have to take a look at the standard fit function of the Temsorflow version that you are using in your environment.
The last time I trained the model, I used TF2.3.

@blaskowitz100
I used TF2.3. But It didn't work
my data type is numpy.ndarray.
Does it have difference?

Hi @blaskowitz100,
I ran the code provided by you in comment 'https://github.com/sintel-dev/Orion/issues/143#issuecomment-768640950'.
The code runs fine after rectifying few errors as per my data. But I have 2 questions:

I want to know the significance of 'n_iterations_critic'
Where in the code of train step have we used epoch to train the model for the specified number of epochs?
I capture history while fitting the model, the history results are as below, whereas I was expecting all the loss values in each n_iterations_critic step, instead of one:
history.history.keys()
dict_keys(['Cx_total', 'Cx_valid', 'Cx_fake', 'Cx_gp_penalty', 'Cz_total', 'Cz_valid', 'Cz_fake', 'Cz_gp_penalty', 'EG_total', 'EG_fake_gen_x', 'EG_fake_gen_z', 'G_rec'])
[0.02138495445251465]
[4.742159366607666]
[-4.880722522735596]
[0.015994776040315628]
[-3.5925278663635254]
[-2.8535757064819336]
[-1.146549105644226]
[0.040759697556495667]
[2.1441867351531982]
[-0.054472602903842926]
[1.587338924407959]
[0.061132051050662994]
Also. I don't know whether above vlues are satisfactoy, what values to improve and what to expect in each loss (I did refer issue 441 but I am still not able to comprehend)


convert GetHashCode to expression bodied member

Just a quick demo of a PR for my audience. Sent uncompiled, YOLO.

thanks Adam 😉

🎉 https://twitter.com/adamralph/status/873559514179661826


Support llvm 7.0.1

It looks like the bug in llvm 7 that broke the llvm backend was fixed in llvm 7.0.1, which, while not available on Ubuntu 18.04, is available in Debian Buster, whereas llvm 8 is not. So I'm going to add support for it here.

It looks like the bug in llvm 7 that broke the llvm backend was fixed in llvm 7.0.1, which, while not available on Ubuntu 18.04, is available in Debian Buster, whereas llvm 8 is not. So I'm going to add support for it here.

LLVM 8 is available on debian buster:
deb http://apt.llvm.org/buster/ llvm-toolchain-buster-8 main
deb-src http://apt.llvm.org/buster/ llvm-toolchain-buster-8 main

add the key: wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key|sudo apt-key add -
see https://apt.llvm.org/

Sure, of course you can always add a third party package repository, but we should not be asking our users to do this if we can avoid it because it adds an extra step to the installation process.

Well yes, but this is the official release. Maybe the benefits outweigh the
cost in this case.
On Tue, Jul 23, 2019 at 19:52 dwightguth<EMAIL_ADDRESS>wrote:

Sure, of course you can always add a third party package repository, but
we should not be asking our users to do this if we can avoid it because it
adds an extra step to the installation process.
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
https://github.com/kframework/llvm-backend/pull/192?email_source=notifications&email_token=ACJYIFHYSPO5MDZJFJDSLRTQA6RUPA5CNFSM4IGLBE72YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD2U2WPY#issuecomment-514435903,
or mute the thread
https://github.com/notifications/unsubscribe-auth/ACJYIFDZWMPRYX2J6SAJLCLQA6RUPANCNFSM4IGLBE7Q
.

We didn't use llvm 7 because it made the backend segfault. It looks like this was fixed in 7.0.1, so we might as well just use 7.0.1, since it's the version in buster by default.


💖 Add new contributors to the list 💖

@all-contributors please add @ujwalkumar1995 for code. They helped fix a code smell reported by Sonar.

@all-contributors please add @shivam-Purohit for code. They helped fix a code smell reported by Sonar.

@all-contributors please add @NyorJa for maintenance and review. Lately he has helped me checking and reviewing new code by recent volunteers and it's been really nice. Thank you so much!

@all-contributors please add @mepox for review. He's trying hard to improve his expertise and now helps reviewing new code as well. He's quite dedicated. Thank you!!!

@all-contributors please add @Angel-M-R for code. They helped with a plethora of Sonar issues 😄

@all-contributors please @Prashriya for code. They helped fix an issue reported by Sonar 👌

@all-contributors please add @Prashriya for code. They helped fix an issue reported by Sonar 👌

@all-contributors please add @logesr for code. They helped fix an issue reported by Sonar 👌


Use forever to run scripts overnight

Hi
I'm interested in scheduling a script to run every ingot at a specific time and stop when it's done executing until the next day.
I was wondering if forever can be used for that. I understand that forever was not designed for that but there is a reason behind my question. I already use forever to run another script FOREVER (no pun intended) so it would be ideal to not have to install anything else and just use forever for scheduled script run
Thanks in advance

This is not the purpose of forever. I suggest using cron


User Interaction Design

Description

As a user, I want to have a complete end-to-end user experience of the system
We need to create a low-fidelity mock-up to show the whole system flow that includes all desire features we have created stories for.

Scope of Work
Create low-fid mock-up met the following requirements:

Chat Interface

The conversation between bot and the end user must be interactive and not as a simple chat window.
Must show EULA at the beginning of the conversation as part of the conversation. The EULA may include a hyperlink that directs to complete EULA and shows only the essential outline of it.
BOT should be able to prompt upload option inside the chat bubble. This option should include 1) upload button that user can select local files, 2) drag and drop local files, 3)  a camera button to open camera
BOT should give pre-selected answers set and show them as buttons. These buttons should be inside the chat bubble or above text input. The option "an input is missing" should be given if the pre-selected answers don't include user's desired option.
BOT should regularly show a recap to make sure the user's previous inputs are desired. This is more on functionality side but we should show this flow in mock-up as well. Following the recap, there should be a way the users can re-enter their answers if they want to.
BOT should be able to generate a report. The report should 1) show graph and diagram, 2) show proper data, 3) show download/email transcript, demand letter generation, 4) should follow with lawyer contact, email, website
User text input, along with voice input button
Should show legal definition as a tooltip.

Side Bar Interface

Should show user basic profile
Should show account options (login, logout)
Should show a list of existing conversation (case) and previous ones
When toggling down the case, there should be 1) a progress bar (i.e. how far is the user to final report), 2) a list of uploaded files

Landing Page

Should have a button to start the process

Acceptance Criteria

Create low-fid to show all the features listed above in scope of work

Story Points

13

Priority

Medium

Risk

Low

This story does not represent a benefit to the user. We need to discuss before it is included in an iteration

Closed the story since it does not represent a benefit to the user.


Producer drops messages under heavy workload with batch_send=True

The SimpleProducer dropped about 2/3 messages in my test when using producer sent to broker on another machine with Kafka 0.8.1.
I set batch size to 100, each message in my test is about 800 bytes.
buffer.size is default (100KB).
Test code:
from kafka.client import KafkaClient
from kafka.producer import SimpleProducer

kafka = KafkaClient("host:9092")

producer = SimpleProducer(kafka,
            async=False,
            #req_acks=Producer.ACK_AFTER_LOCAL_WRITE,
            #ack_timeout=Producer.DEFAULT_ACK_TIMEOUT, # 1000ms
            batch_send=True,
            batch_send_every_n=100,
            batch_send_every_t=1000)

data_file = "mylog.log"

count = 0
with open(data_file) as f:
    for line in f:
        producer.send_messages("my-topic", str(count) + line)
        count += 1

There is no problem when the batch_send is disabled.
I also tested the Java client, no messages dropped.

producers now register atexit handlers - #360


support for nodejs v0.6.2

Now that the latest stable release is 0.6.2 can we have the package.json file updated to support the v0.6.x version of node (assuming there aren't any issues)

We will update the package.json when we have tested on 0.6.x thoroughly.
Feel free to clone the repo locally and modify the package.json to test.

In the next week we should bump Haibu and Haibu-Carapace to support 0.6.x,
currently there are 0.6.x branches that have not been merged in yet.
On Thu, Nov 24, 2011 at 5:38 PM, Sugendran Ganess <
<EMAIL_ADDRESS>
wrote:

Now that the latest stable release is 0.6.2 can we have the package.json
file updated to support the v0.6.x version of node (assuming there aren't
any issues)

Reply to this email directly or view it on GitHub:
https://github.com/nodejitsu/haibu/issues/84


Upgrade maven-failsafe-plugin.version to the latest

My question is very trivial, but I fail to understand why.
How come, for example, the version for maven-failsafe-plugin.version is 2.22.2 while spring-boot-dependencies brings a much higher version. This means that all dependent projects (like spring-cloud-kubernetes) will use that lower version.
Thank you!

We don't inherit versions of plugins from spring boot

PRs welcome


Roslyn?

Cool project. :)
Looks like the code generation is based on the older CodeCom model.  Are there plans to leverage/utilize the new Roslyn engine in VS2015?

Thanks. Maybe, tho there is only 1-2 things, which I couldn't properly generate so not sure if it's worth it (as standalone generator). Would be cool to have Roslyn based generator for generating code from XAML in runtime tho.

That's sort of what I am aiming for. :)  To be sure... when you say UI Generator... this is the generator that takes a Xaml file and creates the .cs file, correct?
Also, from what what I understand, Roslyn is much faster than CodeDom/previous code-walking APIs.

Yes, that's correct.
Yeah, sure that Roslyn is much faster and on top of that it's actually compiler too. You could use this "old" generator in runtime too. I used that kind of tech in the past, but Roslyn would be better. So maybe in future... :)

Yeah I have used CodeCom before and it was not very pleasant.  I wouldn't mind possibly looking into helping move this project to Roslyn. :D

Sure, you can check it out how much work it would be. I knew that one day I might move from old CodeDom so 99% of the methods generating code are in CodeComHelper class. Would be interesting to know if there is anything, which would be problematic with Roslyn gen.

cooooool... i'll check it out!


xarray depends on seaborn-base not seaborn

See https://github.com/conda-forge/xarray-feedstock/pull/118
Checklist

[x] Used a static YAML file for the patch if possible (instructions).
[x] Only wrote code directly into generate_patch_json.py if absolutely necessary.
[x] Ran pre-commit run -a and ensured all files pass the linting checks.
[x] Ran python show_diff.py and posted the output as part of the PR.
[x] Modifications won't affect packages built in the future.

Hi! This is the friendly automated conda-forge-linting service.
I just wanted to let you know that I linted all conda-recipes in your PR (recipe/meta.yaml) and found it was in an excellent condition.

Draft while feedstock PR is not yet merged.

Fixes https://github.com/conda-forge/xarray-feedstock/issues/117


How do I set the spacing between Y-axis coordinates in LineChart

Lack of information. Please explain more. There is no description provided.


Remove dependency on ipfs-api

[x] changes nodew3c-xmlhttprequest library to be xmlhttprequest
the same as web3 (also less broken)
[x] implements format internally
[x] uses GET for get requests

ipfs-mini
Thank you for contributing! Please take a moment to review our contributing guidelines
to make the process easy and effective for everyone involved.
Please open an issue before embarking on any significant pull request, especially those that
add a new library or change existing tests, otherwise you risk spending a lot of time working
on something that might not end up being merged into the project.
Before opening a pull request, please ensure:

[x] You have followed our contributing guidelines
[x] Pull request has tests (we are going for 100% coverage!)
[x] Code is well-commented, linted and follows project conventions
[x] Documentation is updated (if necessary)
[x] Internal code generators and templates are updated (if necessary)
[x] Description explains the issue/use-case resolved and auto-closes related issues

Be kind to code reviewers, please try to keep pull requests as small and focused as possible :)
IMPORTANT: By submitting a patch, you agree to allow the project
owners to license your work under the terms of the MIT License.

Coverage decreased (-1.6%) to 98.413% when pulling b4dc7e3d90b1704889642619681a11ab7c2da5b1 on pelle:bye-bye-streams into 362c5acb41632a29782be02d7832bbb5ef0aec9a on SilentCicero:master.


Colored Mesh

Hi @stachnis @YuePanEdward @jbehley,
Thanks for your great work. I have already tested out Kiss-ICP several times, and now I experimented with SHINE, which seems to work better for 3D reconstruction of outdoor scenes. May I ask, if there is a way to generate a colored MC mesh? I'm using point clouds from a stereo cam (colored PCDs), not lidar.
Kind regards

Hi, @DimitrisKatsatos, thanks for your interest in our work.
It's possible to generate a colored mesh but it's currently not implemented in SHINE-Mapping.
One possible solution is to use another MLP decoder to regress the color value using the same interpolated feature vector (similar to what we did for the semantic mapping).
You are welcome to send a PR to add the feature of colorized mesh reconstruction to SHINE-Mapping.

@YuePanEdward @ddkats  Hi,I have implemented the colored mesh method based on the SHINE-MAPPING repository.Hope it can help you. click this

@ZorAttC Thank you very much for your contribution. I will mark this issue as closed.


Added Xcode project. Generated libNUI.a to make use in projects easier.

I think it's a hassle to import all .m/.h files in my Xcode projects, I'd rather import a subproject into my main project and link against a library.

Added Xcode project generating libNUI.a so it can be easily imported in another Xcode project.
Added Xcode related files to .gitignore.
Created NUI.h to import in one place all files a user may need when using NUI.

Can we close this issue since it seems that cocoapods could have solve @mittsh  problems?
@timbodeit


Bluetooth: suspend private address (RPA) rotating

Is your feature request related to a problem? Please describe.
When Bluetooth privacy is enabled, address is changed every BT_RPA_TIMEOUT seconds.
However, for Microsoft Swift Pair feature it is needed to pause changing the address:

If LE Privacy is supported, the peripheral should suspend rotating the Bluetooth LE Address during the Swift Pair session. The rotated address would be received as a new device request by Windows and would show two notifications for a single peripheral.

https://docs.microsoft.com/en-us/windows-hardware/design/component-guidelines/bluetooth-swift-pair
Describe the solution you'd like
There could be API to stop/start the RPA change timer, which will be used by application to suspend the address change when Swift Pair advertising is used.

@jhedberg I think it would be better to force an RPA timeout instead of suspending it, that way we don't risk accidentally disabling privacy.
I think it is possible to do this with bt_le_oob_get_local

@Qbicz Does using bt_le_oob_get_local to generate a fresh address and reset the timer work for the swift pairing use-case?

@joerchan this looks like a good idea, I will give it a try this week.

Currently privacy does not work in our configuration because we use multiple identities. @MarekPieta will you be able to check it once problem with privacy/multiple identities is resolved?

@MarekPieta @Qbicz As far as I know the privacy issues have been fixed. Can you please check if the suggestion solves the problem?

I checked and I think we can close the issue. Thanks for all the help.


Go one level deeper when converting to an array.

Resolves #3.
I encountered what I believe to be the same issue as described in #3—I'd convert to an array and get an array of the first value repeated for each element rather than the correct non-first values.  In poking at the code, there's something about children.map that yields elements that behave like they're at the parent level.  Inserting the .children in the if let resolved the issue.

Thanks


Fixes gradle error: 'Could not find lint-gradle-api.jar' (#23095)

Fixes gradle error:
Could not resolve all files for configuration 'classpath'.
Could not find lint-gradle-api.jar (com.android.tools.lint:lint-gradle-api:26.1.2).
Searched in the following locations:
https://jcenter.bintray.com/com/android/tools/lint/lint-gradle-api/26.1.2/lint-gradle-api-26.1.2.jar

I signed it!

Hi,
I've added google() inside the buildScript and also updated the gradle-wrapper properties distributionUrl to distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip.
change the buildScript from $flutterRoot/packages/flutter_tools/gradle/flutter.gradle file to
buildscript {
    repositories {
        google()
        jcenter()
        maven {
            url 'https://dl.google.com/dl/android/maven2'
        }
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.2.1'
    }
}

and the issue disappeared for me . try these if any one is facing the same issue.

any ideas on how I can get travis to use this fix too ? ^^

it will be noticed that the google() should be joined in :
**flutter/packages/flutter_tools/gradle/flutter.gradle**
it spends me almost 1 day to solve......

Pinging @Hixie @tvolkert @gspencergoog
This is an isuse that is breaking lots of people CI + local build systems
Any chance this fix can be merged sooner than rather + backported to the latest beta version?

Looks like we forgot got re-land https://github.com/flutter/flutter/pull/13565 after the bots had accepted the new license. @dnfield, do you feel Gradle-aware enough to land that?

Just have one comment on this one and then I'm comfortable with landing it.
Do we need to update the device lab templates in the same PR?

I think it would be good to keep them in sync, and obviously Mikkel did too, so I'd say yes, but if you want to split them out, that might make it easier to revert if needed.

duplicate of https://github.com/flutter/flutter/pull/23467

For everyone having trouble with travis: I used this "hack" to get travis working again.
before_script:
  - git clone https://github.com/flutter/flutter.git -b beta --depth 1
  - export PATH=./flutter/bin:$PATH
  - cd ./flutte
  - git fetch origin pull/23397/head:pull_23397
  - git checkout pull_23397
  - cd ..

It's just checking out this pull request and using that code to run.

Apparently, PRs to flutter/plugins are not passing exactly because of this problem.
The last 3 PRs (867, 868, flutter/plugins#869) are stuck with this error.

Total newb here. I'm having this issue. How do I solve it?
Can I add Google() to my project? Do I have to wait for an update?
Any help appreciated.

For everyone having trouble with travis: I used this "hack" to get travis working again.
before_script:
  - git clone https://github.com/flutter/flutter.git -b beta --depth 1
  - export PATH=./flutter/bin:$PATH
  - cd ./flutter
  - git fetch origin pull/23397/head:pull_23397
  - git checkout pull_23397
  - cd ..

It's just checking out this pull request and using that code to run.

where do I execute that?

LGTM, made the change myself since this is getting a lot of requests.

Will land on green.

Hi,
I've added google() inside the buildScript and also updated the gradle-wrapper properties distributionUrl to distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip.
change the buildScript from $flutterRoot/packages/flutter_tools/gradle/flutter.gradle file to
buildscript {
    repositories {
        google()
        jcenter()
        maven {
            url 'https://dl.google.com/dl/android/maven2'
        }
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.2.1'
    }
}

and the issue disappeared for me . try these if any one is facing the same issue.

The solution above worked for me I have
[✓] Flutter (Channel beta, v0.9.4, on Mac OS X 10.13.4 17E202, locale en-KR)
[✓] Android toolchain - develop for Android devices (Android SDK 27.0.3)
[✓] iOS toolchain - develop for iOS devices (Xcode 9.4.1)
[✓] Android Studio (version 3.1)
[✓] VS Code (version 1.28.2)
[✓] Connected devices (1 available)
This error will go after this https://github.com/flutter/flutter/pull/23397 merge
but for now, just use instruction above.
Thanks @Mahi-K

可以了,谢谢.

how resolve?

Thanks for your pull request. It looks like this may be your first contribution to a Google open source project (if not, look below for help). Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).
📝 Please visit https://cla.developers.google.com/ to sign.
Once you've signed (or fixed any issues), please reply here (e.g. I signed it!) and we'll verify it.
What to do if you already signed the CLA
Individual signers

It's possible we don't have your GitHub username or you're using a different email address on your commit. Check your existing CLA data and verify that your email is set on your git commits.

Corporate signers

Your company has a Point of Contact who decides which employees are authorized to participate. Ask your POC to be added to the group of authorized contributors. If you don't know who your Point of Contact is, direct the Google project maintainer to go/cla#troubleshoot (Public version).
The email used to register you as an authorized contributor must be the email used for the Git commit. Check your existing CLA data and verify that your email is set on your git commits.
The email used to register you as an authorized contributor must also be attached to your GitHub account.

I followed of those steps and still doesn't work with me.
Any other solution ??

This solution is not working for me too

Hi,
I've added google() inside the buildScript and also updated the gradle-wrapper properties distributionUrl to distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip.
change the buildScript from $flutterRoot/packages/flutter_tools/gradle/flutter.gradle file to
buildscript {
    repositories {
        google()
        jcenter()
        maven {
            url 'https://dl.google.com/dl/android/maven2'
        }
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.2.1'
    }
}

and the issue disappeared for me . try these if any one is facing the same issue.

Thank you, this solved! Besides those changes i did this:

I just solve the issue thinks to Allah then to then to the 24 contributors who solved this issue
At first I don't know if the first step is necessary to solve this issue or not, but I did it.
first step :-

I  visited this link https://cla.developers.google.com/ to sign as I understood from googlebot ,with adding my github user name.
thin I followed the steps in this link ( https://help.github.com/articles/setting-your-commit-email-address-in-git/ )to link my github account with the git command, to be honest I didn't understand why am doing this think but I just tried follow what googlebot said to fix this problem.

second step :-
-Go the fluuter.gradle from the flutter that you have already downloaded it.
In my cause I downloaded it in C:\src
C:\src\flutter\packages\flutter_tools\gradle\fluuter.gradle

Copy the codes from this link  and replace it with exist code in this file (fluuter.gradle).

https://github.com/mrmitew/flutter/blob/6369f5481c08714b8a724a92dea2328d23d7bba3/packages/flutter_tools/gradle/flutter.gradle
one day and half to solve the problem :(

Thanks for the merge. Lost at least 4 hours trying to figure this when trying to test out flutter.

I'd like to say thanks to those who have been working to resolve this. However, I can't see in this thread  any identification of the root cause. My CI builder was able to build my project last week on the same version of flutter and without any local code changes. Did the external dependency move? If so, it would seem wise to see if we could get it put back where it was until this lands in Beta. Does anyone know what happened to cause this?

I have the following version:
$ flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel beta, v0.9.4, on Linux, locale en_US.UTF-8)
[✓] Android toolchain - develop for Android devices (Android SDK 27.0.3)
[✓] Android Studio (version 3.2)
[✓] VS Code (version 1.28.2)
[✓] Connected devices (1 available)

Looking in build.gradle shows the change from the referenced PR applied, but I am still getting the same error.  Seems like it doesn't even check the google repository.

I have the following version:
$ flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel beta, v0.9.4, on Linux, locale en_US.UTF-8)
[✓] Android toolchain - develop for Android devices (Android SDK 27.0.3)
[✓] Android Studio (version 3.2)
[✓] VS Code (version 1.28.2)
[✓] Connected devices (1 available)

Looking in build.gradle shows the change from the referenced PR applied, but I am still getting the same error. Seems like it doesn't even check the google repository.

I think it's not the build.gradle file, the name of the file is flutter.gradle inside this directory :
  $flutterRoot/packages/flutter_tools/gradle/

I believe that's the root of the flutter project, and that is what creates the app build.gradle for an application when using flutter create @diegoveloper

then I have the same issue :/

@diegoveloper Are you also on Linux?  Could you share the output of flutter doctor?

Actually I don't have any issues in my local machine (I'm using Mac and Flutter v0.10.1)
		[✓] Flutter (Channel dev, v0.10.1, on Mac OS X 10.14 18A391, locale en-PE)
		[✓] Android toolchain - develop for Android devices (Android SDK 28.0.0)
		[✓] iOS toolchain - develop for iOS devices (Xcode 10.0)
		[✓] Android Studio (version 3.1)
		    ✗ Flutter plugin not installed; this adds Flutter specific functionality.
		    ✗ Dart plugin not installed; this adds Dart specific functionality.
		[✓] VS Code (version 1.28.2)

The problem I have is on CI environment, It's on Linux
		[✓] Flutter (Channel dev, v0.10.1, on Linux, locale en_US)
		    • Flutter version 0.10.1 at /opt/flutter
		    • Framework revision 6a3ff018b1 (8 days ago), 2018-10-18 18:38:26 -0400
		    • Engine revision 3860a43379
		    • Dart version 2.1.0-dev.7.1.flutter-b99bcfd309

I know the PR was merge into master channel, but I'm using dev channel

Interesting.  Well I've tried everything I can think of for tonight.  I'm just going to write some Dart, and hope I can figure it out soon

@nathansamson I'm not sure about merging this into the latest beta, but it is possible to fix this manually by modifying build.gradle. See, for example, this commit: https://github.com/flutter/flutter/pull/23438/files#diff-89970c613560f892af5f6c393a52d2c0R3
(Unless your CI is regenerating that file, which I think should only be happening if you're testing flutter create for some reason.)

I am working on the beta channel and I applied the manual fix but still get the same errors. The cause for me seems to stem from the following line apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" which resides in my android/app/build.gradle. Apply the same manual fix to flutter.gradle then fixes the issue, but that's just the same as me manually back-porting the fix in this PR. Being new to flutter I tried removing the line which applies flutter.gradle thinking it might not be needed for non demo apps, but I just got more errors. Not really sure what to try from here other than just leaving the flutter.gradle modified until this change makes it into the beta channel.

@zoechi I think yes, there is actually no need to merge this, although we need to upgrade the gradle version to 3.2.1 and gradle wrapper to 4.6, update all the firebase plugins to the latest versions so that there are no performance issues (as my app was crashing most of the time because of FirebaseMessaging). Thanks.

there is actually no need to merge this, although we need to upgrade the gradle version to 3.2.1 and gradle wrapper to 4.6, (...)
The file at "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" can be changed as
(...)

There are few things confused here: 3.2.1 is not a version of Gradle but Android Gradle plugin. Secondly, maven { url 'https://dl.google.com/dl/android/maven2'  } has the same effect as google() since Gradle (wrapper) 4.1. https://developer.android.com/studio/build/dependencies#google-maven

Can someone be more explicit on where this buildscript file is supposed to be found? "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" does not exist in a create flutter boiler plate app and changing the buildscript in build.gradle does not fix this issue. A little frustrating that hello world no longer works -_-.

Hi sorry about the experience, you can find this file from your flutter directory which is usually in
C:/Users/name/flutter/packages/flutter_tools/gradle/flutter.gradle  and on mac
/Users/yourname/development/flutter/packages/flutter_tools/gradle/flutter.gradle if you have installed it to development folder or /Users/yourname/flutter... you can simply use IJIDEAEditor to edit the file or any notepad or texteditor will suffice.
Hope this helps thanks.

there is actually no need to merge this, although we need to upgrade the gradle version to 3.2.1 and gradle wrapper to 4.6, (...)
The file at "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" can be changed as
(...)

There are few things confused here: 3.2.1 is not a version of Gradle but Android Gradle plugin. Secondly, maven { url 'https://dl.google.com/dl/android/maven2' } has the same effect as google() since Gradle (wrapper) 4.1. https://developer.android.com/studio/build/dependencies#google-maven

sorry mybad, i meant gradle plugin, yes maven's repository now means google(). Thanks

Thanks Mahi-k - I can confirm your fix works!

Thank you @patientplatypus @gamebox glad that it worked for you. Happy coding 👍

Does #23404 (comment) mean this PR should be undone?

JCenter proxies the central repository and provides additional dependencies. However, proxying seems to be broken quite regularly (there were also long threads in Twitter about it not long time ago). Its better to use google's repository directly for any artifacts that are available there and fallback to jcenter for those that do not exist. Many times in order to fix a gradle build, adding google's repo as a first option, is the way to go.

I am really confused by all the comments above. Can someone please guide me how to resolve this problem. I am trying to resolve this error for past 4 hrs and am unable to do so.

Hi sorry about the experience, you can find this file from your flutter directory which is usually in
C:/Users/name/flutter/packages/flutter_tools/gradle/flutter.gradle and on mac
/Users/yourname/development/flutter/packages/flutter_tools/gradle/flutter.gradle if you have installed it to development folder or /Users/yourname/flutter... you can simply use IJIDEAEditor to edit the file or any notepad or texteditor will suffice.
Hope this helps thanks.

Thank You so much man!

Unfortunately, nothing of all solutions above has solved the problem for me, neither (4.10.2), gradle 3.2.1, nor google() above jcenter().

@elrasool It should be fixed in the flutter beta channel. Ensure you are in there by typing flutter channel, and if in beta, just run flutter upgrade to get latest changes. See https://github.com/flutter/flutter/pull/23397 for further info.

Guys this is a workaround actually working for fixing flutter issues with gradle :

First, important!!, reimport the folder "app" while creating flutter proyect!!

Modify exactly the gradle with the version 3.3.2  and the  .yaml  file not exceed version more than >= 1.0.0

Go to android/build.gradle and copy exactly this:

``
buildscript {
repositories {
google()
jcenter()
mavenCentral()
}
dependencies {
    classpath 'com.android.tools.build:gradle:3.3.2' (This is crucial for work)
    classpath 'com.google.gms:google-services:4.2.0'
}

}
allprojects {
repositories {
google()
jcenter()
mavenCentral()
}
}
rootProject.buildDir = '../build'
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
}
subprojects {
project.evaluationDependsOn(':app')
}
task clean(type: Delete) {
delete rootProject.buildDir
}
subprojects {
project.configurations.all {
resolutionStrategy.eachDependency { details ->
if (details.requested.group == 'com.android.support'
&& !details.requested.name.contains('multidex') ) {
details.useVersion "27.1.0"
}
}
}
}
//resolutionStrategy.eachDependency { details ->
//    if (details.requested.group == 'com.android.support'
//            && !details.requested.name.contains('multidex') ) {
//        details.useVersion "26.1.0"
//    }
//} ``

Ready!!


add date and time conversions

in std.datetime, support DateTime, SysTime, TimeOfDay, and Date.
in python's datetime, support datetime, date, and time

still need to support numpy's datetime64
still need to support timezones in datetime.datetime and datetime64

this is for #21

Thanks!


upgrade GitPython

Try to solve:
https://github.com/CSCfi/csc-user-guide/security/dependabot/2

I just deployed it here:
https://csc-user-guide-csc-user-guide-dev.rahtiapp.fi/

I just deployed it here: https://csc-user-guide-csc-user-guide-dev.rahtiapp.fi/

I'm actually not quite sure what the library in question is used for exactly, but I tested the Git related stuff like "Go to repository", "Edit this page" and the "Last update" date at the bottom of pages and it all seems to work just fine.


cmd/cgo: generates code with inappropriate array copy

The following code behaves as expected under go1.11 and go.1.11.10 but panics under go1.12 and go1.12.6.
Minor changes to the expression passed to the address-of operator "fix" the behaviour.  Debugging and instrumentation show that an "unexpected" pointer is passed to the underlying cgo wrapper and C function; perhaps a heap allocated temporary?  The presence of both IndexExpr appear to be necessary to the reproduction of the problem; with only one or the other, it apparently does not reproduce.
The ast.Print() output appears to match between 1.11 and 1.12, but the liveness/opt analysis (gcflags -m -live),  parse tree (-W), Go asm (-S), and final object code all differ in various ways.  (I currently lack enough experience with Go compiler internals to further interpret the information.)
What did you do?
(Code does not run under Go playground because of Cgo.)
package main

// #include <string.h>
// struct S { unsigned char data[1]; };
import "C"
import "unsafe"

func main() {
	const fill = 0xff
	var s [1]C.struct_S
	C.memset(unsafe.Pointer(&s[0].data[0]), fill, C.size_t(unsafe.Sizeof(s[0].data))) // panic
	// C.memset(unsafe.Pointer(&(s[0].data[0])), fill, C.size_t(unsafe.Sizeof(s[0].data))) // ok
	// C.memset(unsafe.Pointer(&s[0].data), fill, C.size_t(unsafe.Sizeof(s[0].data))) // ok
	if s[0].data[0] != fill {
		panic("oops")
	}
}

What did you expect to see?
No output, exit 0.
With go run -gcflags -r:
# command-line-arguments
MOVE [0xc00038bb30]
.   NAME-main.s a(true) g(1) l(13) x(0) class(PAUTO) ld(1) tc(1) addrtaken used ARRAY-[1]_Ctype_struct_S

What did you see instead?

goroutine 1 [running]:
main.main()
	/home/nschelle/go/src/cgo/cgo.go:15 +0x42
exit status 2

With go run -gcflags -r:
# command-line-arguments
MOVE [0xc0003b73b0]
.   NAME-main._cgoIndex0 a(true) g(2) l(14) x(0) class(PAUTO) ld(1) tc(1) addrtaken used ARRAY-[1]_Ctype_uchar
panic: oops

goroutine 1 [running]:
main.main()
	/home/nschelle/go/src/cgo/cgo.go:15 +0x42
exit status 2

Does this issue reproduce with the latest release (go1.12.6)?
Yes.
System details
go version go1.12.5 linux/amd64
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/nschelle/.cache/go-build"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/home/nschelle/go"
GOPROXY=""
GORACE=""
GOROOT="/usr/local/go"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD=""
GOROOT/bin/go version: go version go1.12.5 linux/amd64
GOROOT/bin/go tool compile -V: compile version go1.12.5
uname -sr: Linux 4.4.0-146-generic
Distributor ID:	Ubuntu
Description:	Ubuntu 16.04.6 LTS
Release:	16.04
Codename:	xenial
/gnu/store/h90vnqw0nwd0hhm1l5dgxsdrigddfmq4-glibc-2.28/lib/libc.so.6: GNU C Library (GNU libc) stable release version 2.28.
gdb --version: GNU gdb (GDB) 8.3

I investigated this issue and realized that @ianlancetaylor understood this issue completely. But, for my curiosity, I report my result.
This behavior is produced after the CL, https://go-review.googlesource.com/c/go/+/142884/ . For example, it rewrites C function call,
C.memset(unsafe.Pointer(&s[0].data[0]), 1, C.size_t(1))

with
func() _cgo_unsafe.Pointer{ _cgoIndex0 := s[0].data; _cgo0 := unsafe.Pointer(&_cgoIndex0[0]); _cgo1 := _Ctype_int(1); _cgo2 := _Ctype_size_t(1); _cgoCheckPointer(_cgo0, _cgoInd  ex0); return ...

, intead of the right one,
func() _cgo_unsafe.Pointer{ _cgoIndex0 := &s[0].data; _cgo0 := unsafe.Pointer(&(*_cgoIndex0)[0]); _cgo1 := _Ctype_int(1); _cgo2 := _Ctype_size_t(1); _cgoCheckPointer(_cgo0, _cgoInd  ex0); return ...

.
This behavior can be patched as follows,
func (p *Package) isVariable(x ast.Expr) bool {
  switch x := x.(type) {
  case *ast.Ident:
    return true
  case *ast.SelectorExpr:
    return p.isVariable(x.X)
  case *ast.IndexExpr:   // new line
    return true          // new line
  }
  return false
}

Is it the expeced patch ?

Yes, at least at first glance that seems like the right general idea.  Would you like to send that in as a GitHub pull request or in Gerrit as described at https://golang.org/doc/contribute.html?  Please also add a test to misc/cgo/test.  Thanks.

Thank you for your checking. I will send my patch and test via Gerrit as soon as possible.

Is it a candidate for a backport?

@gopherbot please open backport to 1.12

1.11 doesn't have the bug but 1.12 does.


Acknowledgement to SNIC

Vi måste skicka en rapport på projektet och noterade att vi bör ha en acknowledgement till SNIC i publikationer och lika bra att ha den på websidan också

The computations/data handling/[SIMILAR] were/was enabled by resources provided by the Swedish National Infrastructure for Computing (SNIC) at [SNIC CENTRE] partially funded by the Swedish Research Council through grant agreement no. 2018-05973.

@donal-mur Where on the homepage should this go?

How about in this blick
The consortium bringing data from space all the way to you
On 1 Apr 2021, at 11:46, Andreas Skyman<EMAIL_ADDRESS>wrote:
@donal-murhttps://github.com/donal-mur Where on the homepage should this go?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHubhttps://github.com/Odin-SMR/odin-api/issues/109#issuecomment-811791517, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AO72MFEKVXSLJBBRK6DYLDDTGQ6HVANCNFSM42GYGXYQ.