def test_squeezing_data(self):
        x_range = get_range(self.mc.data_container.x_train)
        x_train = np.copy(self.mc.data_container.x_train)

        squeezer = FeatureSqueezing(
            self.mc,
            clip_values=x_range,
            smoothing_methods=['normal', 'binary'],
            bit_depth=8,
            sigma=0.1,
            kernel_size=2,
            pretrained=False,
        )

        # Expecting difference between input data and squeezed data
        mc_normal = squeezer.get_def_model_container('normal')
        mc_binary = squeezer.get_def_model_container('binary')

        self.assertFalse((x_train == mc_normal.data_container.x_train).all())
        self.assertFalse((x_train == mc_binary.data_container.x_train).all())

        # average perturbation
        l2 = np.mean(get_l2_norm(x_train, mc_normal.data_container.x_train))
        logger.info('L2 norm of normal squeezer:%f', l2)
        self.assertLessEqual(l2, 0.2)

        # maximum perturbation
        l2 = np.max(get_l2_norm(x_train, mc_binary.data_container.x_train))
        logger.info('L2 norm of binary squeezer:%f', l2)
        self.assertLessEqual(l2, 0.2)
    def test_load(self):
        x_range = get_range(self.mc.data_container.x_train)
        # Do not load pretrained parameters
        squeezer = FeatureSqueezing(
            self.mc,
            clip_values=x_range,
            smoothing_methods=['normal', 'binary'],
            bit_depth=8,
            sigma=0.1,
            kernel_size=2,
            pretrained=False,
        )
        squeezer.load(os.path.join('save', SQUEEZER_FILE))

        mc_normal = squeezer.get_def_model_container('normal')
        mc_binary = squeezer.get_def_model_container('binary')

        x_test = squeezer.model_container.data_container.x_test
        y_test = squeezer.model_container.data_container.y_test
        acc_nor_after = mc_normal.evaluate(x_test, y_test)
        logger.info('For normal squeezer, accuracy after load parameters: %f',
                    acc_nor_after)
        self.assertGreater(acc_nor_after, 0.90)
        acc_bin_after = mc_binary.evaluate(x_test, y_test)
        logger.info('For binary squeezer, accuracy after load parameters: %f',
                    acc_bin_after)
        self.assertGreater(acc_bin_after, 0.90)
    def test_data(self):
        x_train = np.copy(self.mc.data_container.x_train)
        y_train = np.copy(self.mc.data_container.y_train)
        x_range = get_range(self.mc.data_container.x_train)
        squeezer = FeatureSqueezing(
            self.mc,
            clip_values=x_range,
            smoothing_methods=SQUEEZING_METHODS,
            bit_depth=8,
            sigma=0.1,
            kernel_size=3,
            pretrained=True,
        )

        # expecting test set and train set have not been altered.
        res = np.all(
            squeezer.model_container.data_container.x_train == x_train)
        self.assertTrue(res)
        res = np.all(
            squeezer.model_container.data_container.y_train == y_train)
        self.assertTrue(res)

        x_test = np.copy(squeezer.model_container.data_container.x_test)
        y_test = np.copy(squeezer.model_container.data_container.y_test)
        x_train = np.copy(squeezer.model_container.data_container.x_train)
        y_train = np.copy(squeezer.model_container.data_container.y_train)

        squeezer.fit(max_epochs=2, batch_size=128)

        # expecting test set and train set have not been altered.
        res = np.all(squeezer.model_container.data_container.x_test == x_test)
        self.assertTrue(res)
        res = np.all(squeezer.model_container.data_container.y_test == y_test)
        self.assertTrue(res)
        res = np.all(
            squeezer.model_container.data_container.x_train == x_train)
        self.assertTrue(res)
        res = np.all(
            squeezer.model_container.data_container.y_train == y_train)
        self.assertTrue(res)
    def test_squeezing_data(self):
        x_range = get_range(self.mc.data_container.x_train)
        x_train = np.copy(self.mc.data_container.x_train)

        squeezer = FeatureSqueezing(
            self.mc,
            clip_values=x_range,
            smoothing_methods=SQUEEZING_METHODS,
            bit_depth=8,
            sigma=0.1,
            kernel_size=3,
            pretrained=False,
        )

        # Expecting difference between input data and squeezed data
        mc_binary = squeezer.get_def_model_container(SQUEEZING_METHODS[0])
        mc_median = squeezer.get_def_model_container(SQUEEZING_METHODS[1])
        mc_normal = squeezer.get_def_model_container(SQUEEZING_METHODS[2])

        self.assertFalse((x_train == mc_binary.data_container.x_train).all())
        self.assertFalse((x_train == mc_median.data_container.x_train).all())
        self.assertFalse((x_train == mc_normal.data_container.x_train).all())

        # maximum perturbation
        l2 = np.max(get_l2_norm(x_train, mc_binary.data_container.x_train))
        logger.info('L2 norm of binary squeezer:%f', l2)
        self.assertLessEqual(l2, 0.5)

        # average perturbation
        # No upper bound on median filter
        l2 = np.mean(get_l2_norm(x_train, mc_median.data_container.x_train))
        logger.info('L2 norm of median squeezer:%f', l2)
        self.assertLessEqual(l2, 2.0)

        # average perturbation
        l2 = np.mean(get_l2_norm(x_train, mc_normal.data_container.x_train))
        logger.info('L2 norm of normal squeezer:%f', l2)
        self.assertLessEqual(l2, 2.0)
    def test_load(self):
        x_range = get_range(self.mc.data_container.x_train)
        # Do not load pretrained parameters
        squeezer = FeatureSqueezing(
            self.mc,
            clip_values=x_range,
            smoothing_methods=SQUEEZING_METHODS,
            bit_depth=8,
            sigma=0.1,
            kernel_size=3,
            pretrained=False,
        )
        squeezer.load(os.path.join('save', SQUEEZER_FILE))

        mc_median = squeezer.get_def_model_container(SQUEEZING_METHODS[0])

        x_test = squeezer.model_container.data_container.x_test
        y_test = squeezer.model_container.data_container.y_test

        acc_med_after = mc_median.evaluate(x_test, y_test)
        logger.info('For median squeezer, accuracy after load parameters: %f',
                    acc_med_after)
        self.assertGreater(acc_med_after, 0.90)
    def test_detect(self):
        dc = self.mc.data_container
        x_range = get_range(dc.x_train)
        # Do not load pretrained parameters
        squeezer = FeatureSqueezing(
            self.mc,
            clip_values=x_range,
            smoothing_methods=['normal', 'binary'],
            bit_depth=8,
            sigma=0.1,
            kernel_size=2,
            pretrained=False,
        )
        squeezer.load(os.path.join('save', SQUEEZER_FILE))

        # testing clean set
        x_test = dc.x_test
        pred = self.mc.predict(x_test)
        blocked_indices, passed_x = squeezer.detect(x_test,
                                                    pred,
                                                    return_passed_x=True)
        logger.info('blocked clean samples: %d', len(blocked_indices))
        self.assertLessEqual(len(blocked_indices), len(x_test) * 0.1)
        self.assertEqual(len(blocked_indices) + len(passed_x), len(x_test))

        # the prediction parameter should not alter the result.
        blocked_indices_2, passed_x = squeezer.detect(x_test,
                                                      return_passed_x=True)
        self.assertEqual(len(blocked_indices_2) + len(passed_x), len(x_test))

        # NOTE: due to the randomness of the method. The blocked indices are not guaranteed to be the same!
        # self.assertEquals(len(blocked_indices_2), len(blocked_indices))

        # test detector using FGSM attack
        # NOTE: the block rate is almost 0.
        attack = FGSMContainer(self.mc,
                               norm=2,
                               eps=0.2,
                               eps_step=0.1,
                               targeted=False,
                               batch_size=128)
        adv, y_adv, x, y = attack.generate(count=1000, use_testset=True)
        blocked_indices, adv_passed = squeezer.detect(adv,
                                                      y_adv,
                                                      return_passed_x=True)
        logger.info('blocked adversarial: %d', len(blocked_indices))

        passed_indices = np.where(
            np.isin(np.arange(len(adv)), blocked_indices) == False)[0]
        acc_adv = self.mc.evaluate(adv_passed, y[passed_indices])
        logger.info('Accuracy on passed adv. examples: %f', acc_adv)
    def test_fit_save(self):
        x_range = get_range(self.mc.data_container.x_train)
        squeezer = FeatureSqueezing(
            self.mc,
            clip_values=x_range,
            smoothing_methods=['normal', 'binary'],
            bit_depth=8,
            sigma=0.1,
            kernel_size=2,
            pretrained=False,
        )
        x_test = np.copy(squeezer.model_container.data_container.x_test)
        y_test = np.copy(squeezer.model_container.data_container.y_test)
        mc_normal = squeezer.get_def_model_container('normal')
        mc_binary = squeezer.get_def_model_container('binary')

        # predictions before fit
        # without pre-trained parameter, expecting low accuracy
        acc_nor_before = mc_normal.evaluate(x_test, y_test)
        logger.info('[Before fit] Accuracy of normal squeezer: %f',
                    acc_nor_before)
        self.assertLessEqual(acc_nor_before, 0.60)
        acc_bin_before = mc_binary.evaluate(x_test, y_test)
        logger.info('[Before fit] Accuracy of binary squeezer: %f',
                    acc_bin_before)
        self.assertLessEqual(acc_bin_before, 0.60)

        squeezer.fit(max_epochs=MAX_EPOCHS, batch_size=128)

        # predictions after fit
        acc_nor_after = mc_normal.evaluate(x_test, y_test)
        logger.info('[After fit] Accuracy of normal squeezer: %f',
                    acc_nor_after)
        self.assertGreater(acc_nor_after, acc_nor_before)
        acc_bin_after = mc_binary.evaluate(x_test, y_test)
        logger.info('[After fit] Accuracy of binary squeezer: %f',
                    acc_bin_after)
        self.assertGreater(acc_bin_after, acc_bin_before)

        # save parameters and check the existence of the files
        squeezer.save(SQUEEZER_FILE, True)
        self.assertTrue(
            os.path.exists(
                os.path.join('save', 'test', 'IrisNN_Iris_e200_normal.pt')))
        self.assertTrue(
            os.path.exists(
                os.path.join('save', 'test', 'IrisNN_Iris_e200_binary.pt')))
    def test_detect(self):
        dc = self.mc.data_container
        x_range = get_range(dc.x_train)
        # Do not load pretrained parameters
        squeezer = FeatureSqueezing(
            self.mc,
            clip_values=x_range,
            smoothing_methods=SQUEEZING_METHODS,
            bit_depth=8,
            sigma=0.1,
            kernel_size=3,
            pretrained=False,
        )
        squeezer.load(os.path.join('save', SQUEEZER_FILE))

        # testing clean set
        x_test = dc.x_test
        pred = self.mc.predict(x_test)
        blocked_indices, passed_x = squeezer.detect(x_test,
                                                    pred,
                                                    return_passed_x=True)
        logger.info('blocked clean samples: %d', len(blocked_indices))
        self.assertLessEqual(len(blocked_indices), len(x_test) * 0.1)
        self.assertEqual(len(blocked_indices) + len(passed_x), len(x_test))

        # the prediction parameter should not alter the result.
        blocked_indices_2 = squeezer.detect(x_test, return_passed_x=False)
        self.assertTrue((blocked_indices_2 == blocked_indices).all())

        # test detector using FGSM attack
        # NOTE: the block rate is almost 0.
        attack = FGSMContainer(self.mc,
                               norm=np.inf,
                               eps=0.3,
                               eps_step=0.1,
                               targeted=False,
                               batch_size=128)
        adv, y_adv, x, y = attack.generate(count=1000, use_testset=True)
        blocked_indices = squeezer.detect(adv, y_adv, return_passed_x=False)
        logger.info('blocked adversarial: %d', len(blocked_indices))
        self.assertGreater(len(blocked_indices), 500)
    def test_fit_save(self):
        x_range = get_range(self.mc.data_container.x_train)
        squeezer = FeatureSqueezing(
            self.mc,
            clip_values=x_range,
            smoothing_methods=SQUEEZING_METHODS,
            bit_depth=8,
            sigma=0.1,
            kernel_size=3,
            pretrained=False,
        )

        squeezer.fit(max_epochs=MAX_EPOCHS, batch_size=128)

        # save parameters and check the existence of the files
        squeezer.save(SQUEEZER_FILE, True)
        self.assertTrue(
            os.path.exists(
                os.path.join('save', 'test',
                             'MnistCnnV2_MNIST_e50_median.pt')))
    def test_fit_save(self):
        x_range = get_range(self.mc.data_container.x_train)
        squeezer = FeatureSqueezing(
            self.mc,
            clip_values=x_range,
            smoothing_methods=SQUEEZING_METHODS,
            bit_depth=8,
            sigma=0.1,
            kernel_size=3,
            pretrained=False,
        )
        x_test = np.copy(squeezer.model_container.data_container.x_test)
        y_test = np.copy(squeezer.model_container.data_container.y_test)

        mc_binary = squeezer.get_def_model_container(SQUEEZING_METHODS[0])
        mc_median = squeezer.get_def_model_container(SQUEEZING_METHODS[1])
        mc_normal = squeezer.get_def_model_container(SQUEEZING_METHODS[2])

        # predictions before fit
        # without pre-trained parameter, expecting lower accuracy
        acc_bin_before = mc_binary.evaluate(
            squeezer.apply_binary_transform(x_test), y_test)
        logger.info('[Before fit] Accuracy of binary squeezer: %f',
                    acc_bin_before)
        self.assertLessEqual(acc_bin_before, 0.80)

        acc_med_before = mc_median.evaluate(
            squeezer.apply_median_transform(x_test), y_test)
        logger.info('[Before fit] Accuracy of median squeezer: %f',
                    acc_bin_before)
        self.assertLessEqual(acc_med_before, 0.80)

        acc_nor_before = mc_normal.evaluate(
            squeezer.apply_normal_transform(x_test), y_test)
        logger.info('[Before fit] Accuracy of normal squeezer: %f',
                    acc_nor_before)
        self.assertLessEqual(acc_nor_before, 0.80)

        squeezer.fit(max_epochs=MAX_EPOCHS, batch_size=128)

        # predictions after fit
        acc_bin_after = mc_binary.evaluate(
            squeezer.apply_binary_transform(x_test), y_test)
        logger.info('[After fit] Accuracy of binary squeezer: %f',
                    acc_bin_after)
        self.assertGreater(acc_bin_after, acc_bin_before)

        acc_med_after = mc_median.evaluate(
            squeezer.apply_median_transform(x_test), y_test)
        logger.info('[After fit] Accuracy of median squeezer: %f',
                    acc_bin_after)
        self.assertGreater(acc_med_after, acc_med_before)

        acc_nor_after = mc_normal.evaluate(
            squeezer.apply_normal_transform(x_test), y_test)
        logger.info('[After fit] Accuracy of normal squeezer: %f',
                    acc_nor_after)
        self.assertGreater(acc_nor_after, acc_nor_before)

        # save parameters and check the existence of the files
        squeezer.save(SQUEEZER_FILE, True)
        self.assertTrue(
            os.path.exists(
                os.path.join('save', 'test',
                             'MnistCnnV2_MNIST_e50_binary.pt')))
        self.assertTrue(
            os.path.exists(
                os.path.join('save', 'test',
                             'MnistCnnV2_MNIST_e50_median.pt')))
        self.assertTrue(
            os.path.exists(
                os.path.join('save', 'test',
                             'MnistCnnV2_MNIST_e50_normal.pt')))
def experiment(index, data_container, max_epochs, adv_file, res_file):
    # STEP 1: select data and model
    dname = data_container.name
    num_classes = data_container.num_classes
    num_features = data_container.dim_data[0]
    model = IrisNN(num_features=num_features,
                   hidden_nodes=num_features * 4,
                   num_classes=num_classes)
    distill_model = IrisNN(num_features=num_features,
                           hidden_nodes=num_features * 4,
                           num_classes=num_classes)

    # STEP 2: train models
    mc = ModelContainerPT(model, data_container)
    mc.fit(max_epochs=max_epochs, batch_size=BATCH_SIZE)
    accuracy = mc.evaluate(data_container.x_test, data_container.y_test)
    logger.info('Accuracy on test set: %f', accuracy)
    adv_res = [accuracy]

    # STEP 3: generate adversarial examples
    # no more than 1000 samples are required
    x = data_container.x_test
    y = data_container.y_test
    # The test set has fixed size, 1000.
    if len(x) > 1000:
        x = x[:1000]
        y = y[:1000]
    accuracy = mc.evaluate(x, y)
    adv_res.append(accuracy)

    advs = np.zeros((len(ATTACK_LIST), x.shape[0], x.shape[1]),
                    dtype=np.float32)
    pred_advs = -np.ones((len(ATTACK_LIST), len(y)),
                         dtype=np.int32)  # assign -1 as initial value
    pred_clean = mc.predict(x)

    advs[0] = x
    pred_advs[0] = pred_clean

    att_param_json = open(os.path.join(DIR_PATH, 'AttackParams.json'))
    att_params = json.load(att_param_json)

    for i, att_name in enumerate(ATTACK_LIST):
        # Clean set is only used in evaluation phase.
        if att_name == 'Clean':
            continue

        logger.debug('[%d]Running %s attack...', i, att_name)
        kwargs = att_params[att_name]
        logger.debug('%s params: %s', att_name, str(kwargs))
        Attack = get_attack(att_name)
        attack = Attack(mc, **kwargs)
        adv, pred_adv, x_clean, pred_clean_ = attack.generate(
            use_testset=False, x=x)
        assert np.all(pred_clean == pred_clean_)
        assert np.all(x == x_clean)
        logger.info('created %d adv examples using %s from %s', len(advs[i]),
                    att_name, dname)
        not_match = pred_adv != pred_clean
        success_rate = len(not_match[not_match == True]) / len(pred_clean)
        accuracy = mc.evaluate(adv, y)
        advs[i] = adv
        pred_advs[i] = pred_adv
        logger.info('Success rate of %s: %f', att_name, success_rate)
        logger.info('Accuracy on %s: %f', att_name, accuracy)
        adv_res.append(accuracy)
    adv_file.write(','.join([str(r) for r in adv_res]) + '\n')

    # STEP 4: train defences
    blocked_res = np.zeros(len(TITLE_RESULTS), dtype=np.int32)
    blocked_res[0] = index
    for def_name in DEFENCE_LIST:
        logger.debug('Running %s...', def_name)
        if def_name == 'AdvTraining':
            attack = BIMContainer(mc,
                                  eps=0.3,
                                  eps_step=0.1,
                                  max_iter=100,
                                  targeted=False)
            defence = AdversarialTraining(mc, [attack])
            defence.fit(max_epochs=max_epochs,
                        batch_size=BATCH_SIZE,
                        ratio=ADV_TRAIN_RATIO)
            block_attack(0, advs, defence, def_name, blocked_res)
        elif def_name == 'Destillation':
            # A single temperature is used for all sets
            temp = 20
            defence = DistillationContainer(mc,
                                            distill_model,
                                            temperature=temp,
                                            pretrained=False)
            defence.fit(max_epochs=max_epochs, batch_size=BATCH_SIZE)
            block_attack(1, advs, defence, def_name, blocked_res)
        elif def_name == 'Squeezing':
            defence = FeatureSqueezing(
                mc,
                SQUEEZER_FILTER_LIST,
                bit_depth=SQUEEZER_DEPTH,
                sigma=SQUEEZER_SIGMA,
                pretrained=True,
            )
            defence.fit(max_epochs=max_epochs, batch_size=BATCH_SIZE)
            block_attack(2, advs, defence, def_name, blocked_res)
        elif def_name == 'AD':
            ad_param_file = open(AD_PARAM_FILE)
            # BreastCancer uses a different set of parameters
            if dname == 'BreastCancerWisconsin':
                param_file = os.path.join(DIR_PATH, 'AdParamsBC.json')
                ad_param_file = open(param_file)
            ad_params = json.load(ad_param_file)
            logger.debug('AD params: %s', str(ad_params))
            defence = ApplicabilityDomainContainer(
                mc, hidden_model=model.hidden_model, **ad_params)
            defence.fit()
            block_attack(3, advs, defence, def_name, blocked_res)

    res_file.write(','.join([str(r) for r in blocked_res]) + '\n')
def experiment(index, dname, mname, max_epochs, adv_file, res_file):
    # STEP 1: select data
    dc = get_data_container(dname, use_shuffle=True, use_normalize=True)
    Model = get_model(mname)
    model = Model()
    distill_model = Model()
    logger.info('Selected %s model', model.__class__.__name__)

    # STEP 2: train models
    mc = ModelContainerPT(model, dc)
    mc.fit(max_epochs=max_epochs, batch_size=BATCH_SIZE)
    accuracy = mc.evaluate(dc.x_test, dc.y_test)
    logger.info('Accuracy on test set: %f', accuracy)
    adv_res = [accuracy]

    # STEP 3: generate adversarial examples
    # no more than 1000 samples are required
    n = 1000 if len(dc.x_test) >= 1000 else len(dc.x_test)
    # idx = np.random.choice(len(dc.x_test), n, replace=False)
    # x = dc.x_test[idx]
    # y = dc.y_test[idx]
    x = dc.x_test[:n]
    y = dc.y_test[:n]
    accuracy = mc.evaluate(x, y)
    adv_res.append(accuracy)

    advs = np.zeros(
        tuple([len(ATTACK_LIST)] + list(x.shape)),
        dtype=np.float32)
    pred_advs = -np.ones(
        (len(ATTACK_LIST), n),
        dtype=np.int32)  # assign -1 as initial value
    pred_clean = mc.predict(x)

    advs[0] = x
    pred_advs[0] = pred_clean

    att_param_json = open(os.path.join(DIR_PATH, 'AttackParams.json'))
    att_params = json.load(att_param_json)

    for i, att_name in enumerate(ATTACK_LIST):
        # Clean set is only used in evaluation phase.
        if att_name == 'Clean':
            continue

        logger.debug('[%d]Running %s attack...', i, att_name)
        kwargs = att_params[att_name]
        logger.debug('%s params: %s', att_name, str(kwargs))
        Attack = get_attack(att_name)
        attack = Attack(mc, **kwargs)
        adv, pred_adv, x_clean, pred_clean_ = attack.generate(
            use_testset=False,
            x=x)
        assert np.all(pred_clean == pred_clean_)
        assert np.all(x == x_clean)
        logger.info('created %d adv examples using %s from %s',
                    len(advs[i]),
                    att_name,
                    dname)
        not_match = pred_adv != pred_clean
        success_rate = len(not_match[not_match == True]) / len(pred_clean)
        accuracy = mc.evaluate(adv, y)
        advs[i] = adv
        pred_advs[i] = pred_adv
        logger.info('Success rate of %s: %f', att_name, success_rate)
        logger.info('Accuracy on %s: %f', att_name, accuracy)
        adv_res.append(accuracy)
    adv_file.write(','.join([str(r) for r in adv_res]) + '\n')

    # STEP 4: train defences
    blocked_res = np.zeros(len(TITLE_RESULTS), dtype=np.int32)
    blocked_res[0] = index
    for def_name in DEFENCE_LIST:
        logger.debug('Running %s...', def_name)
        if def_name == 'AdvTraining':
            attack = BIMContainer(
                mc,
                eps=0.3,
                eps_step=0.1,
                max_iter=100,
                targeted=False)
            defence = AdversarialTraining(mc, [attack])
            defence.fit(max_epochs=max_epochs,
                        batch_size=BATCH_SIZE,
                        ratio=ADV_TRAIN_RATIO)
            block_attack(0, advs, defence, def_name, blocked_res)
        elif def_name == 'Destillation':
            defence = DistillationContainer(
                mc, distill_model, temperature=DISTILL_TEMP, pretrained=False)
            defence.fit(max_epochs=max_epochs, batch_size=BATCH_SIZE)
            block_attack(1, advs, defence, def_name, blocked_res)
        elif def_name == 'Squeezing':
            defence = FeatureSqueezing(
                mc,
                SQUEEZER_FILTER_LIST,
                bit_depth=SQUEEZER_DEPTH,
                sigma=SQUEEZER_SIGMA,
                kernel_size=SQUEEZER_KERNEL,
                pretrained=True,
            )
            defence.fit(max_epochs=max_epochs, batch_size=BATCH_SIZE)
            block_attack(2, advs, defence, def_name, blocked_res)
        elif def_name == 'AD':
            ad_param_file = open(AD_PARAM_FILE)
            ad_params = json.load(ad_param_file)
            logger.debug('AD params: %s', str(ad_params))
            defence = ApplicabilityDomainContainer(
                mc,
                hidden_model=model.hidden_model,
                **ad_params)
            defence.fit()
            block_attack(3, advs, defence, def_name, blocked_res)

    res_file.write(','.join([str(r) for r in blocked_res]) + '\n')
Example #13
0
def main():
    # load dataset and initial model
    model = MnistCnnV2()
    dc = DataContainer(DATASET_LIST[DATASET], get_data_path())
    dc(shuffle=True, normalize=True)
    mc = ModelContainerPT(model, dc)
    mc.load(MODEL_FILE)
    accuracy = mc.evaluate(dc.x_test, dc.y_test)
    print(f'Accuracy on test set: {accuracy}')

    # train or load pretrained parameters
    squeezer = FeatureSqueezing(mc, ['median', 'normal', 'binary'],
                                bit_depth=BIT_DEPTH,
                                sigma=SIGMA,
                                kernel_size=KERNEL_SIZE,
                                pretrained=True)

    x_test = dc.x_test
    y_test = dc.y_test
    mc_binary = squeezer.get_def_model_container('binary')
    mc_median = squeezer.get_def_model_container('median')
    mc_normal = squeezer.get_def_model_container('normal')

    print('before fit')
    acc_bin = mc_binary.evaluate(squeezer.apply_binary_transform(x_test),
                                 y_test)
    print(f'Accuracy of binary squeezer: {acc_bin}')
    acc_med = mc_median.evaluate(squeezer.apply_median_transform(x_test),
                                 y_test)
    print(f'Accuracy of median squeezer: {acc_med}')
    acc_nor = mc_normal.evaluate(squeezer.apply_normal_transform(x_test),
                                 y_test)
    print(f'Accuracy of normal squeezer: {acc_nor}')

    if not squeezer.does_pretrained_exist(MODEL_FILE):
        squeezer.fit(max_epochs=MAX_EPOCHS, batch_size=128)

        print('after fit')
        acc_bin = mc_binary.evaluate(squeezer.apply_binary_transform(x_test),
                                     y_test)
        print(f'Accuracy of binary squeezer: {acc_bin}')
        acc_med = mc_median.evaluate(squeezer.apply_median_transform(x_test),
                                     y_test)
        print(f'Accuracy of median squeezer: {acc_med}')
        acc_nor = mc_normal.evaluate(squeezer.apply_normal_transform(x_test),
                                     y_test)
        print(f'Accuracy of normal squeezer: {acc_nor}')

        squeezer.save(MODEL_FILE, True)

    print('after load')
    squeezer.load(MODEL_FILE)
    acc_bin = mc_binary.evaluate(squeezer.apply_binary_transform(x_test),
                                 y_test)
    print(f'Accuracy of binary squeezer: {acc_bin}')
    acc_med = mc_median.evaluate(squeezer.apply_median_transform(x_test),
                                 y_test)
    print(f'Accuracy of median squeezer: {acc_med}')
    acc_nor = mc_normal.evaluate(squeezer.apply_normal_transform(x_test),
                                 y_test)
    print(f'Accuracy of normal squeezer: {acc_nor}')

    # load adversarial examples
    adv_list = ['FGSM', 'BIM', 'DeepFool', 'Carlini', 'Saliency']
    y_file = os.path.join('save',
                          f'{MODEL_NAME}_{DATASET}_{adv_list[0]}_y.npy')
    x_file = os.path.join('save',
                          f'{MODEL_NAME}_{DATASET}_{adv_list[0]}_x.npy')
    x = np.load(x_file, allow_pickle=False)
    y = np.load(y_file, allow_pickle=False)
    acc_og = mc.evaluate(x, y)
    acc_squeezer = squeezer.evaluate(x, y)
    print(f'Accuracy on clean set - OG: {acc_og}, Squeezer: {acc_squeezer}')

    for adv_name in adv_list:
        adv_file = os.path.join(
            'save', build_adv_filename(MODEL_NAME, DATASET, adv_name))
        adv = np.load(adv_file, allow_pickle=False)
        acc_og = mc.evaluate(adv, y)
        acc_squeezer = squeezer.evaluate(adv, y)
        print(
            f'Accuracy on {adv_name} set - OG: {acc_og}, Squeezer: {acc_squeezer}'
        )
def main():
    parser = ap.ArgumentParser()
    parser.add_argument(
        '-m',
        '--model',
        type=str,
        required=True,
        help=
        'a file which contains a pretrained model. The filename should in "<model>_<dataset>_e<max epochs>[_<date>].pt" format'
    )
    parser.add_argument('-e',
                        '--epoch',
                        type=int,
                        required=True,
                        help='the number of max epochs for training')
    parser.add_argument(
        '-d',
        '--depth',
        type=int,
        default=0,
        help=
        'The image color depth for input images. Apply Binary-Depth filter when receives a parameter'
    )
    parser.add_argument(
        '--sigma',
        type=float,
        default=0,
        help=
        'The Standard Deviation of Normal distribution. Apply Gaussian Noise filter when receives a parameter'
    )
    parser.add_argument(
        '-k',
        '--kernelsize',
        type=int,
        default=0,
        help=
        'The kernel size for Median filter. Apply median filter when receives a parameter'
    )
    parser.add_argument('-b',
                        '--batchsize',
                        type=int,
                        default=128,
                        help='batch size')
    parser.add_argument(
        '-T',
        '--train',
        action='store_true',
        default=False,
        help=
        'Force the model to retrain without searching existing pretrained file'
    )
    parser.add_argument('-s',
                        '--seed',
                        type=int,
                        default=4096,
                        help='the seed for random number generator')
    parser.add_argument('-v',
                        '--verbose',
                        action='store_true',
                        default=False,
                        help='set logger level to debug')
    parser.add_argument('-l',
                        '--savelog',
                        action='store_true',
                        default=False,
                        help='save logging file')
    parser.add_argument('-B',
                        '--bim',
                        action='store_true',
                        default=False,
                        help='Apply BIM attack')
    parser.add_argument('-C',
                        '--carlini',
                        action='store_true',
                        default=False,
                        help='Apply Carlini L2 attack')
    parser.add_argument('-D',
                        '--deepfool',
                        action='store_true',
                        default=False,
                        help='Apply DeepFool attack')
    parser.add_argument('-F',
                        '--fgsm',
                        action='store_true',
                        default=False,
                        help='Apply FGSM attack')
    parser.add_argument('-S',
                        '--saliency',
                        action='store_true',
                        default=False,
                        help='Apply Saliency Map attack')
    args = parser.parse_args()
    model_file = args.model
    max_epochs = args.epoch
    bit_depth = args.depth
    sigma = args.sigma
    kernel_size = args.kernelsize
    batch_size = args.batchsize
    seed = args.seed
    verbose = args.verbose
    save_log = args.savelog
    need_train = args.train

    model_name, data_name = parse_model_filename(model_file)

    # Which filter should apply?
    filter_list = []
    if bit_depth > 0:
        filter_list.append('binary')
    if sigma > 0:
        filter_list.append('normal')
    if kernel_size > 0:
        filter_list.append('median')

    # Which attack should apply?
    attack_list = []
    if args.fgsm:
        attack_list.append('FGSM')
    if args.bim:
        attack_list.append('BIM')
    if args.deepfool:
        attack_list.append('DeepFool')
    if args.carlini:
        attack_list.append('Carlini')
    if args.saliency:
        attack_list.append('Saliency')

    # Quit, if there is nothing to do.
    if len(filter_list) == 0 or len(attack_list) == 0:
        logger.warning('Neither received any filter nor any attack. Exit')
        sys.exit(0)

    y_file = os.path.join('save',
                          f'{model_name}_{data_name}_{attack_list[0]}_y.npy')
    attack_files = [
        os.path.join('save',
                     f'{model_name}_{data_name}_{attack_list[0]}_x.npy')
    ]
    for attack_name in attack_list:
        attack_files.append(
            os.path.join('save',
                         f'{model_name}_{data_name}_{attack_name}_adv.npy'))
    # the 1st file this the clean inputs
    attack_list = ['clean'] + attack_list

    # Do I need train the distillation network?
    pretrain_files = []
    for fname in filter_list:
        pretrain_file = build_squeezer_filename(model_name, data_name,
                                                max_epochs, fname)
        pretrain_files.append(pretrain_file)
        if not os.path.exists(os.path.join('save', pretrain_file)):
            need_train = True

    # set logging config. Run this before logging anything!
    set_logging(LOG_NAME, data_name, verbose, save_log)

    # show parameters
    print(f'[{LOG_NAME}] Running feature squeezing on {model_name}...')
    logger.info('Start at    : %s', get_time_str())
    logger.info('RECEIVED PARAMETERS:')
    logger.info('model file  :%s', model_file)
    logger.info('model       :%s', model_name)
    logger.info('dataset     :%s', data_name)
    logger.info('max_epochs  :%d', max_epochs)
    logger.info('bit_depth   :%d', bit_depth)
    logger.info('sigma       :%f', sigma)
    logger.info('kernel_size :%d', kernel_size)
    logger.info('batch_size  :%d', batch_size)
    logger.info('seed        :%d', seed)
    logger.info('verbose     :%r', verbose)
    logger.info('save_log    :%r', save_log)
    logger.info('need train  :%r', need_train)
    logger.info('filters     :%s', ', '.join(filter_list))
    logger.info('attacks     :%s', ', '.join(attack_list))
    logger.info('pretrained  :%s', ', '.join(pretrain_files))

    # check files
    for file_name in [model_file, y_file] + attack_files:
        if not os.path.exists(file_name):
            logger.error('%s does not exist!', file_name)
            raise FileNotFoundError('{} does not exist!'.format(file_name))

    # reset seed
    master_seed(seed)

    # select data
    dc = get_data_container(
        data_name,
        use_shuffle=True,
        use_normalize=True,
    )

    # select a model
    Model = get_model(model_name)
    model = Model()
    if data_name in ('BankNote', 'HTRU2', 'Iris', 'WheatSeed'):
        num_classes = dc.num_classes
        num_features = dc.dim_data[0]
        model = IrisNN(num_features=num_features,
                       hidden_nodes=num_features * 4,
                       num_classes=num_classes)
    classifier_mc = ModelContainerPT(model, dc)
    classifier_mc.load(model_file)
    accuracy = classifier_mc.evaluate(dc.x_test, dc.y_test)
    logger.info('Accuracy on test set: %f', accuracy)

    # initialize Squeezer
    squeezer = FeatureSqueezing(
        classifier_mc,
        filter_list,
        bit_depth=bit_depth,
        sigma=sigma,
        kernel_size=kernel_size,
        pretrained=True,
    )

    # train or load parameters for Squeezer
    if need_train:
        squeezer.fit(max_epochs=max_epochs, batch_size=batch_size)
        squeezer.save(model_file, True)
    else:
        squeezer.load(model_file)

    # traverse all attacks
    y = np.load(y_file, allow_pickle=False)
    for i in range(len(attack_list)):
        adv_file = attack_files[i]
        adv_name = attack_list[i]
        logger.debug('Load %s...', adv_file)
        adv = np.load(adv_file, allow_pickle=False)
        acc_og = classifier_mc.evaluate(adv, y)
        acc_squeezer = squeezer.evaluate(adv, y)
        logger.info('Accuracy on %s set - OG: %f, Squeezer: %f', adv_name,
                    acc_og, acc_squeezer)
        blocked_indices = squeezer.detect(adv, return_passed_x=False)
        logger.info('Blocked %d/%d samples on %s', len(blocked_indices),
                    len(adv), adv_name)