Exemple #1
0
    def create_model(self):

        X_input = Input(self.state_space)
        X = X_input

        #Input Layer of state size and Hidden Layer with 512 nodes
        X = Dense(512, input_shape=self.state_space, activation="relu", kernel_initializer='he_uniform')(X)

        # Hidden layer with 256 nodes
        X = Dense(256, activation="relu", kernel_initializer='he_uniform')(X)

        # Hidden layer with 64 nodes
        X = Dense(64, activation="relu", kernel_initializer='he_uniform')(X)

        if self.Dueling:
            state_value = Dense(1, kernel_initializer='he_uniform')(X)
            state_value = Lambda(lambda s: K.expand_dims(s[:, 0], -1), output_shape=(self.action_space,))(state_value)

            action_advantage = Dense(self.action_space, kernel_initializer='he_uniform')(X)
            action_advantage = Lambda(lambda a: a[:, :] - K.mean(a[:, :], keepdims=True), output_shape=(self.action_space,))(action_advantage)

            X = Add()([state_value, action_advantage])
        else:
            X = Dense(self.action_space, activation="linear", kernel_initializer='he_uniform')(X)

        model = Model(inputs = X_input, outputs = X)
        model.compile(loss="mean_squared_error", optimizer=adam_v2.Adam(learning_rate = self.Learning_Rate), metrics=["accuracy"])

        model.summary()
        return model
Exemple #2
0
def build_GAN(discriminator, generator):
    discriminator.trainable = False
    GAN_input = Input(shape=(100, ))
    x = generator(GAN_input)
    GAN_output = discriminator(x)
    GAN = Model(inputs=GAN_input, outputs=GAN_output)
    GAN.compile(loss='binary_crossentropy',
                optimizer=adam_v2.Adam(0.0002, 0.5))
    return GAN
Exemple #3
0
def buildmodel():
    print("Now we build the model")
    model = Sequential()
    model.add(Dense(64, input_shape=(BOARDX, BOARDY, BOARDZ, 1)))
    model.add(Activation('relu'))
    model.add(Dense(512))
    model.add(Activation('relu'))
    model.add(Dense(ACTIONS))

    adam = adam_v2.Adam(lr=LEARNING_RATE)
    model.compile(loss='mse', optimizer=adam)
    print("We finished building the model")
    return model
Exemple #4
0
def createDiscriminator():
    discriminator = Sequential()
    discriminator.add(Dense(units=512, input_dim=784))
    discriminator.add(LeakyReLU(2.0))
    discriminator.add(Dense(units=256))
    discriminator.add(LeakyReLU(2.0))
    discriminator.add(Dense(units=1, activation='sigmoid'))

    discriminator.compile(loss='binary_crossentropy',
                          optimizer=adam_v2.Adam(learning_rate=0.0002,
                                                 beta_1=0.5))

    return discriminator
Exemple #5
0
def build_generator():
    model = Sequential()

    model.add(Dense(units=256, input_dim=100))
    model.add(LeakyReLU(alpha=0.2))

    model.add(Dense(units=512))
    model.add(LeakyReLU(alpha=0.2))

    model.add(Dense(units=1024))
    model.add(LeakyReLU(alpha=0.2))

    model.add(Dense(units=784, activation='tanh'))

    model.compile(loss='binary_crossentropy',
                  optimizer=adam_v2.Adam(0.0002, 0.5))
    return model
Exemple #6
0
    def test_keras_classifier(self):
        """
        Second test with the KerasClassifier.
        :return:
        """
        # Build KerasClassifier
        victim_krc = get_image_classifier_kr()

        # Create simple CNN
        model = Sequential()
        model.add(Conv2D(1, kernel_size=(7, 7), activation="relu", input_shape=(28, 28, 1)))
        model.add(MaxPooling2D(pool_size=(4, 4)))
        model.add(Flatten())
        model.add(Dense(10, activation="softmax"))
        loss = keras.losses.categorical_crossentropy
        try:
            from keras.optimizers import Adam

            optimizer = Adam(lr=0.001)
        except ImportError:
            from keras.optimizers import adam_v2

            optimizer = adam_v2.Adam(lr=0.001)
        model.compile(loss=loss, optimizer=optimizer, metrics=["accuracy"])

        # Get classifier
        thieved_krc = KerasClassifier(model, clip_values=(0, 1), use_logits=False)

        # Create attack
        copycat_cnn = CopycatCNN(
            classifier=victim_krc,
            batch_size_fit=self.batch_size,
            batch_size_query=self.batch_size,
            nb_epochs=NB_EPOCHS,
            nb_stolen=NB_STOLEN,
        )
        thieved_krc = copycat_cnn.extract(x=self.x_train_mnist, thieved_classifier=thieved_krc)

        victim_preds = np.argmax(victim_krc.predict(x=self.x_train_mnist[:100]), axis=1)
        thieved_preds = np.argmax(thieved_krc.predict(x=self.x_train_mnist[:100]), axis=1)
        acc = np.sum(victim_preds == thieved_preds) / len(victim_preds)

        self.assertGreater(acc, 0.3)

        # Clean-up
        k.clear_session()
Exemple #7
0
    def test_keras_iris(self):
        """
        Second test for Keras.
        :return:
        """
        # Build KerasClassifier
        victim_krc = get_tabular_classifier_kr()

        # Create simple CNN
        model = Sequential()
        model.add(Dense(10, input_shape=(4,), activation="relu"))
        model.add(Dense(10, activation="relu"))
        model.add(Dense(3, activation="softmax"))
        try:
            from keras.optimizers import Adam

            optimizer = Adam(lr=0.001)
        except ImportError:
            from keras.optimizers import adam_v2

            optimizer = adam_v2.Adam(lr=0.001)
        model.compile(loss="categorical_crossentropy", optimizer=optimizer, metrics=["accuracy"])

        # Get classifier
        thieved_krc = KerasClassifier(model, clip_values=(0, 1), use_logits=False, channels_first=True)

        # Create attack
        copycat_cnn = CopycatCNN(
            classifier=victim_krc,
            batch_size_fit=self.batch_size,
            batch_size_query=self.batch_size,
            nb_epochs=NB_EPOCHS,
            nb_stolen=NB_STOLEN,
        )
        thieved_krc = copycat_cnn.extract(x=self.x_train_iris, thieved_classifier=thieved_krc)

        victim_preds = np.argmax(victim_krc.predict(x=self.x_train_iris[:100]), axis=1)
        thieved_preds = np.argmax(thieved_krc.predict(x=self.x_train_iris[:100]), axis=1)
        acc = np.sum(victim_preds == thieved_preds) / len(victim_preds)

        self.assertGreater(acc, 0.3)

        # Clean-up
        k.clear_session()
Exemple #8
0
def build_discriminator():
    model = Sequential()

    model.add(Dense(units=1024, input_dim=784))
    model.add(LeakyReLU(alpha=0.2))
    model.add(Dropout(0.3))

    model.add(Dense(units=512))
    model.add(LeakyReLU(alpha=0.2))
    model.add(Dropout(0.3))

    model.add(Dense(units=256))
    model.add(LeakyReLU(alpha=0.2))
    model.add(Dropout(0.3))

    model.add(Dense(units=1, activation='sigmoid'))

    model.compile(loss='binary_crossentropy',
                  optimizer=adam_v2.Adam(0.0002, 0.5))
    return model
Exemple #9
0
def make_model():

    num_4x1 = 32
    num_4x4 = 64

    inputs = Input(shape=(4, 4, 4, 3))
    t = inputs

    t144 = Flatten()(Conv3D(num_4x1, (4, 1, 1), padding='valid')(t))
    t414 = Flatten()(Conv3D(num_4x1, (1, 4, 1), padding='valid')(t))
    t441 = Flatten()(Conv3D(num_4x1, (1, 1, 4), padding='valid')(t))

    t114 = Flatten()(Conv3D(num_4x4, (4, 4, 1), padding='valid')(t))
    t141 = Flatten()(Conv3D(num_4x4, (4, 1, 4), padding='valid')(t))
    t411 = Flatten()(Conv3D(num_4x4, (1, 4, 4), padding='valid')(t))

    t = Concatenate()([t144, t414, t441, t114, t141, t411, Flatten()(t)])
    t = BatchNormalization()(t)
    t = Activation('relu')(t)

    t = Dense(2048)(t)
    t = BatchNormalization()(t)
    t = Activation('relu')(t)

    t = Dense(512)(t)
    t = BatchNormalization()(t)
    t = Activation('relu')(t)

    t = Dense(1)(t)
    t = Activation('tanh')(t)

    model = Model(inputs, t)
    #model.load_weights("models/model50.h5")
    adam = adam_v2.Adam(learning_rate=LEARNING_RATE)
    model.compile(loss='mse', optimizer=adam)
    return model
from keras.layers import Conv2D, Dense, Dropout, Flatten, MaxPooling2D, BatchNormalization
from keras.models import Sequential, save_model
from keras.optimizers import adam_v2

input_dims = (100, 100, 1)
n_classes = 27
learning_rate = 0.001
adam = adam_v2.Adam(learning_rate=0.001)
classifier = Sequential()

classifier.add(Conv2D(64, (5, 5), padding='same',
               input_shape=input_dims, activation='relu'))
classifier.add(MaxPooling2D(pool_size=(4, 4)))

classifier.add(Conv2D(128, (5, 5), padding='same',
               input_shape=input_dims, activation='relu'))
classifier.add(MaxPooling2D(pool_size=(4, 4)))

classifier.add(Conv2D(256, (5, 5), padding='same',
               input_shape=input_dims, activation='relu'))
classifier.add(MaxPooling2D(pool_size=(4, 4)))

classifier.add(BatchNormalization())

classifier.add(Flatten())
classifier.add(Dropout(0.5))
classifier.add(Dense(1024, activation='sigmoid'))
classifier.add(Dense(n_classes, activation='softmax'))

classifier.compile(
    optimizer='adam', loss='categorical_crossentropy', metrics=["accuracy"])
Exemple #11
0
def trainNetwork(model, args):
    # open up a game state to communicate with emulator
    game_state = game.GameState()

    # store the previous observations in replay memory
    D = deque()

    # get the first state by doing nothing and preprocess the image to 80x80x4
    do_nothing = np.zeros(ACTIONS)
    do_nothing[0] = 1
    x_t, r_0, terminal = game_state.frame_step(do_nothing)

    s_t = np.stack((x_t, x_t, x_t, x_t), axis=2)
    #print (s_t.shape)

    #In Keras, need to reshape
    s_t = s_t.reshape(1, s_t.shape[0], s_t.shape[1], s_t.shape[2])  #1*80*80*4

    if args['mode'] == 'Run':
        OBSERVE = 999999999  #We keep observe, never train
        epsilon = FINAL_EPSILON
        print("Now we load weight")
        model.load_weights("model.h5")
        adam = adam_v2.Adam(lr=LEARNING_RATE)
        model.compile(loss='mse', optimizer=adam)
        print("Weight load successfully")
    else:  #We go to training mode
        OBSERVE = OBSERVATION
        epsilon = INITIAL_EPSILON

    t = 0
    while (True):
        loss = 0
        Q_sa = 0
        action_index = 0
        r_t = 0
        a_t = np.zeros([ACTIONS])
        #choose an action epsilon greedy
        if t % FRAME_PER_ACTION == 0:
            if random.random() <= epsilon:
                print("----------Random Action----------")
                action_index = random.randrange(ACTIONS)
                a_t[action_index] = 1
            else:
                q = model.predict(
                    s_t)  #input a stack of 4 images, get the prediction
                max_Q = np.argmax(q)
                action_index = max_Q
                a_t[max_Q] = 1

        #We reduced the epsilon gradually
        if epsilon > FINAL_EPSILON and t > OBSERVE:
            epsilon -= (INITIAL_EPSILON - FINAL_EPSILON) / EXPLORE

        #run the selected action and observed next state and reward
        x_t1_colored, r_t, terminal = game_state.frame_step(a_t)

        x_t1 = x_t1.reshape(1, x_t1.shape[0], x_t1.shape[1], 1)  #1x80x80x1
        s_t1 = np.append(x_t1, s_t[:, :, :, :3], axis=3)

        # store the transition in D
        D.append((s_t, action_index, r_t, s_t1, terminal))
        if len(D) > REPLAY_MEMORY:
            D.popleft()

        #only train if done observing
        if t > OBSERVE:
            #sample a minibatch to train on
            minibatch = random.sample(D, BATCH)

            inputs = np.zeros((BATCH, s_t.shape[1], s_t.shape[2],
                               s_t.shape[3]))  #32, 80, 80, 4
            print(inputs.shape)
            targets = np.zeros((inputs.shape[0], ACTIONS))  #32, 2

            #Now we do the experience replay
            for i in range(0, len(minibatch)):
                state_t = minibatch[i][0]
                action_t = minibatch[i][1]  #This is action index
                reward_t = minibatch[i][2]
                state_t1 = minibatch[i][3]
                terminal = minibatch[i][4]
                # if terminated, only equals reward

                inputs[i:i + 1] = state_t  #I saved down s_t

                targets[i] = model.predict(
                    state_t)  # Hitting each buttom probability
                Q_sa = model.predict(state_t1)

                if terminal:
                    targets[i, action_t] = reward_t
                else:
                    targets[i, action_t] = reward_t + GAMMA * np.max(Q_sa)

            # targets2 = normalize(targets)
            loss += model.train_on_batch(inputs, targets)

        s_t = s_t1
        t = t + 1

        # save progress every 10000 iterations
        if t % 1000 == 0:
            print("Now we save model")
            model.save_weights("model.h5", overwrite=True)
            with open("model.json", "w") as outfile:
                json.dump(model.to_json(), outfile)

        # print info
        state = ""
        if t <= OBSERVE:
            state = "observe"
        elif t > OBSERVE and t <= OBSERVE + EXPLORE:
            state = "explore"
        else:
            state = "train"

        print("TIMESTEP", t, "/ STATE", state, \
            "/ EPSILON", epsilon, "/ ACTION", action_index, "/ REWARD", r_t, \
            "/ Q_MAX " , np.max(Q_sa), "/ Loss ", loss)

    print("Episode finished!")
    print("************************")
Exemple #12
0
    def test_binary_input_detector(self):
        """
        Test the binary input detector end-to-end.
        :return:
        """
        # Get MNIST
        nb_train, nb_test = 1000, 10
        (x_train, y_train), (x_test, y_test), _, _ = load_mnist()
        x_train, y_train = x_train[:NB_TRAIN], y_train[:NB_TRAIN]
        x_test, y_test = x_test[:NB_TEST], y_test[:NB_TEST]

        # Keras classifier
        classifier = get_image_classifier_kr()

        # Generate adversarial samples:
        attacker = FastGradientMethod(classifier, eps=0.1)
        x_train_adv = attacker.generate(x_train[:nb_train])
        x_test_adv = attacker.generate(x_test[:nb_test])

        # Compile training data for detector:
        x_train_detector = np.concatenate((x_train[:nb_train], x_train_adv),
                                          axis=0)
        y_train_detector = np.concatenate(
            (np.array([[1, 0]] * nb_train), np.array([[0, 1]] * nb_train)),
            axis=0)

        # Create a simple CNN for the detector
        input_shape = x_train.shape[1:]
        try:
            from keras.optimizers import Adam

            optimizer = Adam(lr=0.01)
        except ImportError:
            from keras.optimizers import adam_v2

            optimizer = adam_v2.Adam(lr=0.01)
        model = Sequential()
        model.add(
            Conv2D(4,
                   kernel_size=(5, 5),
                   activation="relu",
                   input_shape=input_shape))
        model.add(MaxPooling2D(pool_size=(2, 2)))
        model.add(Flatten())
        model.add(Dense(2, activation="softmax"))
        model.compile(loss=keras.losses.categorical_crossentropy,
                      optimizer=optimizer,
                      metrics=["accuracy"])

        # Create detector and train it:
        detector = BinaryInputDetector(
            KerasClassifier(model=model, clip_values=(0, 1), use_logits=False))
        detector.fit(x_train_detector,
                     y_train_detector,
                     nb_epochs=2,
                     batch_size=128)

        # Apply detector on clean and adversarial test data:
        test_detection = np.argmax(detector.predict(x_test), axis=1)
        test_adv_detection = np.argmax(detector.predict(x_test_adv), axis=1)

        # Assert there is at least one true positive and negative:
        nb_true_positives = len(np.where(test_adv_detection == 1)[0])
        nb_true_negatives = len(np.where(test_detection == 0)[0])
        logger.debug("Number of true positives detected: %i",
                     nb_true_positives)
        logger.debug("Number of true negatives detected: %i",
                     nb_true_negatives)
        self.assertGreater(nb_true_positives, 0)
        self.assertGreater(nb_true_negatives, 0)
    def __init__(
        self,
        model: KERAS_MODEL_TYPE,
        use_logits: bool = False,
        channels_first: bool = False,
        clip_values: Optional["CLIP_VALUES_TYPE"] = None,
        preprocessing_defences: Union["Preprocessor", List["Preprocessor"], None] = None,
        postprocessing_defences: Union["Postprocessor", List["Postprocessor"], None] = None,
        preprocessing: "PREPROCESSING_TYPE" = (0.0, 1.0),
        input_layer: int = 0,
        output_layer: int = 0,
        steps: int = 1000,
        init_cost: float = 1e-3,
        norm: Union[int, float] = 2,
        learning_rate: float = 0.1,
        attack_success_threshold: float = 0.99,
        patience: int = 5,
        early_stop: bool = True,
        early_stop_threshold: float = 0.99,
        early_stop_patience: int = 10,
        cost_multiplier: float = 1.5,
        batch_size: int = 32,
    ):
        """
        Create a Neural Cleanse classifier.

        :param model: Keras model, neural network or other.
        :param use_logits: True if the output of the model are logits; false for probabilities or any other type of
               outputs. Logits output should be favored when possible to ensure attack efficiency.
        :param channels_first: Set channels first or last.
        :param clip_values: Tuple of the form `(min, max)` of floats or `np.ndarray` representing the minimum and
               maximum values allowed for features. If floats are provided, these will be used as the range of all
               features. If arrays are provided, each value will be considered the bound for a feature, thus
               the shape of clip values needs to match the total number of features.
        :param preprocessing_defences: Preprocessing defence(s) to be applied by the classifier.
        :param postprocessing_defences: Postprocessing defence(s) to be applied by the classifier.
        :param preprocessing: Tuple of the form `(subtrahend, divisor)` of floats or `np.ndarray` of values to be
               used for data preprocessing. The first value will be subtracted from the input. The input will then
               be divided by the second one.
        :param input_layer: The index of the layer to consider as input for models with multiple input layers. The layer
                            with this index will be considered for computing gradients. For models with only one input
                            layer this values is not required.
        :param output_layer: Which layer to consider as the output when the models has multiple output layers. The layer
                             with this index will be considered for computing gradients. For models with only one output
                             layer this values is not required.
        :param steps: The maximum number of steps to run the Neural Cleanse optimization
        :param init_cost: The initial value for the cost tensor in the Neural Cleanse optimization
        :param norm: The norm to use for the Neural Cleanse optimization, can be 1, 2, or np.inf
        :param learning_rate: The learning rate for the Neural Cleanse optimization
        :param attack_success_threshold: The threshold at which the generated backdoor is successful enough to stop the
                                         Neural Cleanse optimization
        :param patience: How long to wait for changing the cost multiplier in the Neural Cleanse optimization
        :param early_stop: Whether or not to allow early stopping in the Neural Cleanse optimization
        :param early_stop_threshold: How close values need to come to max value to start counting early stop
        :param early_stop_patience: How long to wait to determine early stopping in the Neural Cleanse optimization
        :param cost_multiplier: How much to change the cost in the Neural Cleanse optimization
        :param batch_size: The batch size for optimizations in the Neural Cleanse optimization
        """
        import keras.backend as K
        from keras.losses import categorical_crossentropy
        from keras.metrics import categorical_accuracy

        super().__init__(
            model=model,
            use_logits=use_logits,
            channels_first=channels_first,
            clip_values=clip_values,
            preprocessing_defences=preprocessing_defences,
            postprocessing_defences=postprocessing_defences,
            preprocessing=preprocessing,
            input_layer=input_layer,
            output_layer=output_layer,
            steps=steps,
            init_cost=init_cost,
            norm=norm,
            learning_rate=learning_rate,
            attack_success_threshold=attack_success_threshold,
            early_stop=early_stop,
            early_stop_threshold=early_stop_threshold,
            early_stop_patience=early_stop_patience,
            patience=patience,
            cost_multiplier=cost_multiplier,
            batch_size=batch_size,
        )
        mask = np.random.uniform(size=super().input_shape)
        pattern = np.random.uniform(size=super().input_shape)
        self.epsilon = K.epsilon()

        # Normalize mask between [0, 1]
        self.mask_tensor_raw = K.variable(mask)
        # self.mask_tensor = K.expand_dims(K.tanh(self.mask_tensor_raw) / (2 - self.epsilon) + 0.5, axis=0)
        self.mask_tensor = K.tanh(self.mask_tensor_raw) / (2 - self.epsilon) + 0.5

        # Normalize pattern between [0, 1]
        self.pattern_tensor_raw = K.variable(pattern)
        self.pattern_tensor = K.expand_dims(K.tanh(self.pattern_tensor_raw) / (2 - self.epsilon) + 0.5, axis=0)

        reverse_mask_tensor = K.ones_like(self.mask_tensor) - self.mask_tensor
        input_tensor = K.placeholder(model.input_shape)
        x_adv_tensor = reverse_mask_tensor * input_tensor + self.mask_tensor * self.pattern_tensor

        output_tensor = self.model(x_adv_tensor)
        y_true_tensor = K.placeholder(model.outputs[0].shape.as_list())

        self.loss_acc = categorical_accuracy(output_tensor, y_true_tensor)
        self.loss_ce = categorical_crossentropy(output_tensor, y_true_tensor)

        if self.norm == 1:
            # TODO: change 3 to dynamically set img_color
            self.loss_reg = K.sum(K.abs(self.mask_tensor)) / 3
        elif self.norm == 2:
            self.loss_reg = K.sqrt(K.sum(K.square(self.mask_tensor)) / 3)

        self.cost = self.init_cost
        self.cost_tensor = K.variable(self.cost)
        self.loss_combined = self.loss_ce + self.loss_reg * self.cost_tensor

        try:
            from keras.optimizers import Adam

            self.opt = Adam(lr=self.learning_rate, beta_1=0.5, beta_2=0.9)
        except ImportError:
            from keras.optimizers import adam_v2

            self.opt = adam_v2.Adam(lr=self.learning_rate, beta_1=0.5, beta_2=0.9)
        self.updates = self.opt.get_updates(
            params=[self.pattern_tensor_raw, self.mask_tensor_raw], loss=self.loss_combined
        )
        self.train = K.function(
            [input_tensor, y_true_tensor],
            [self.loss_ce, self.loss_reg, self.loss_combined, self.loss_acc],
            updates=self.updates,
        )
Exemple #14
0
    def __init__(
        self,
        classifier: "CLASSIFIER_TYPE",
        backdoor: PoisoningAttackBackdoor,
        feature_layer: Union[int, str],
        target: Union[np.ndarray, List[Tuple[np.ndarray, np.ndarray]]],
        pp_poison: Union[float, List[float]] = 0.05,
        discriminator_layer_1: int = 256,
        discriminator_layer_2: int = 128,
        regularization: float = 10,
        learning_rate: float = 1e-4,
        clone=True,
    ):
        """
        Initialize an Feature Collision Clean-Label poisoning attack

        :param classifier: A neural network classifier.
        :param backdoor: The backdoor attack used to poison samples
        :param feature_layer: The layer of the original network to extract features from
        :param target: The target label to poison
        :param pp_poison: The percentage of training data to poison
        :param discriminator_layer_1: The size of the first discriminator layer
        :param discriminator_layer_2: The size of the second discriminator layer
        :param regularization: The regularization constant for the backdoor recognition part of the loss function
        :param learning_rate: The learning rate of clean-label attack optimization.
        :param clone: Whether or not to clone the model or apply the attack on the original model
        """
        super().__init__(classifier=classifier)
        self.backdoor = backdoor
        self.feature_layer = feature_layer
        self.target = target
        if isinstance(pp_poison, float):
            self.pp_poison = [pp_poison]
        else:
            self.pp_poison = pp_poison
        self.discriminator_layer_1 = discriminator_layer_1
        self.discriminator_layer_2 = discriminator_layer_2
        self.regularization = regularization
        self.train_data: Optional[np.ndarray] = None
        self.train_labels: Optional[np.ndarray] = None
        self.is_backdoor: Optional[np.ndarray] = None
        self.learning_rate = learning_rate
        self._check_params()

        if isinstance(self.estimator, KerasClassifier):
            using_tf_keras = "tensorflow.python.keras" in str(
                type(self.estimator.model))
            if using_tf_keras:  # pragma: no cover
                from tensorflow.keras.models import Model, clone_model  # pylint: disable=E0611
                from tensorflow.keras.layers import (  # pylint: disable=E0611
                    GaussianNoise, Dense, BatchNormalization, LeakyReLU,
                )
                from tensorflow.keras.optimizers import Adam  # pylint: disable=E0611

                opt = Adam(lr=self.learning_rate)

            else:
                from keras import Model
                from keras.models import clone_model
                from keras.layers import GaussianNoise, Dense, BatchNormalization, LeakyReLU

                try:
                    from keras.optimizers import Adam

                    opt = Adam(lr=self.learning_rate)
                except ImportError:
                    from keras.optimizers import adam_v2

                    opt = adam_v2.Adam(lr=self.learning_rate)

            if clone:
                self.orig_model = clone_model(
                    self.estimator.model,
                    input_tensors=self.estimator.model.inputs)
            else:
                self.orig_model = self.estimator.model
            model_input = self.orig_model.input
            init_model_output = self.orig_model(model_input)

            # Extracting feature tensor
            if isinstance(self.feature_layer, int):
                feature_layer_tensor = self.orig_model.layers[
                    self.feature_layer].output
            else:
                feature_layer_tensor = self.orig_model.get_layer(
                    name=feature_layer).output
            feature_layer_output = Model(inputs=[model_input],
                                         outputs=[feature_layer_tensor])

            # Architecture for discriminator
            discriminator_input = feature_layer_output(model_input)
            discriminator_input = GaussianNoise(stddev=1)(discriminator_input)
            dense_layer_1 = Dense(
                self.discriminator_layer_1)(discriminator_input)
            norm_1_layer = BatchNormalization()(dense_layer_1)
            leaky_layer_1 = LeakyReLU(alpha=0.2)(norm_1_layer)
            dense_layer_2 = Dense(self.discriminator_layer_2)(leaky_layer_1)
            norm_2_layer = BatchNormalization()(dense_layer_2)
            leaky_layer_2 = LeakyReLU(alpha=0.2)(norm_2_layer)
            backdoor_detect = Dense(2,
                                    activation="softmax",
                                    name="backdoor_detect")(leaky_layer_2)

            # Creating embedded model
            self.embed_model = Model(
                inputs=self.orig_model.inputs,
                outputs=[init_model_output, backdoor_detect])

            # Add backdoor detection loss
            model_name = self.orig_model.name
            model_loss = self.estimator.model.loss
            loss_name = "backdoor_detect"
            loss_type = "binary_crossentropy"
            if isinstance(model_loss, str):
                losses = {model_name: model_loss, loss_name: loss_type}
                loss_weights = {
                    model_name: 1.0,
                    loss_name: -self.regularization
                }
            elif isinstance(model_loss, dict):
                losses = model_loss
                losses[loss_name] = loss_type
                loss_weights = self.orig_model.loss_weights
                loss_weights[loss_name] = -self.regularization
            else:
                raise TypeError(
                    f"Cannot read model loss value of type {type(model_loss)}")

            self.embed_model.compile(optimizer=opt,
                                     loss=losses,
                                     loss_weights=loss_weights,
                                     metrics=["accuracy"])
        else:
            raise NotImplementedError(
                "This attack currently only supports Keras.")