コード例 #1
0
ファイル: RLT3.py プロジェクト: zuraSherl/defense_test
    def defense(self, train_loader=None, validation_loader=None):
        # train_loader:训练集
        # validation_loader:验证集
        # best_val_acc:验证集上的最佳分类精度
        best_val_acc = None
        # 进行epoch次训练
        for epoch in range(self.num_epochs):
            self.train_one_epoch_with_adv_and_nat(train_loader=train_loader,
                                                  epoch=epoch)
            # 计算每一次训练后在验证集上的分类精度
            val_acc = validation_evaluation(
                model=self.model,
                validation_loader=validation_loader,
                device=self.device)
            # 如果是CIFAR10数据集,则调整模型参数
            if self.Dataset == 'CIFAR10':
                adjust_learning_rate(epoch=epoch, optimizer=self.optimizer)

            # 将最佳模型参数保存到DefenseEnhancedModels/NAT/CIFAR10_NAT_enhanced.pt中或MNIST
            assert os.path.exists('../DefenseEnhancedModels/{}'.format(
                self.defense_name))
            defense_enhanced_saver = '../DefenseEnhancedModels/{}/{}_{}_enhanced.pt'.format(
                self.defense_name, self.Dataset, self.defense_name)
            if not best_val_acc or round(val_acc, 4) >= round(best_val_acc, 4):
                if best_val_acc is not None:
                    os.remove(defense_enhanced_saver)
                best_val_acc = val_acc
                self.model.save(name=defense_enhanced_saver)
            else:
                print(
                    'Train Epoch{:>3}: validation dataset accuracy did not improve from {:.4f}\n'
                    .format(epoch, best_val_acc))
コード例 #2
0
ファイル: NEW_MART.py プロジェクト: zuraSherl/defense_test
 def defense(self, train_loader=None, validation_loader=None):
     # train_loader:训练集
     # validation_loader:验证集
     # best_val_acc:验证集最佳分类精度
     best_val_acc = None
     # 进行num_epochs次PGD对抗训练
     for epoch in range(self.num_epochs):
         # 进行一次完整PGD对抗训练
         self.train_one_epoch_with_pgd_and_nat(train_loader=train_loader, epoch=epoch)
         # val_acc:对验证集进行评估的分类精度
         val_acc = validation_evaluation(model=self.model, validation_loader=validation_loader, device=self.device)
         # 进行学习率调整
         if self.Dataset == 'CIFAR10':
             adjust_CIFAR10_learning_rate(epoch=epoch, optimizer=self.optimizer)
         else:
             adjust_MNIST_learning_rate(epoch=epoch, optimizer=self.optimizer)
         assert os.path.exists('../DefenseEnhancedModels/{}'.format(self.defense_name))
         # defense_enhanced_saver:对抗训练网络参数的存放位置为DefenseEnhancedModels/PAT/CIFAR10_PAT_enhanced.pt中
         defense_enhanced_saver = '../DefenseEnhancedModels/{}/{}_{}_enhanced.pt'.format(self.defense_name, self.Dataset, self.defense_name)
         # 选取对验证集分类精度最高的模型参数进行保存
         if not best_val_acc or round(val_acc, 4) >= round(best_val_acc, 4):
             if best_val_acc is not None:
                 os.remove(defense_enhanced_saver)
             best_val_acc = val_acc
             self.model.save(name=defense_enhanced_saver)
         else:
             print('Train Epoch{:>3}: validation dataset accuracy did not improve from {:.4f}\n'.format(epoch, best_val_acc))
コード例 #3
0
 def defense(self, pre_trained_models=None, train_loader=None, validation_loader=None):
     # pre_trained_models:预训练模型
     # train_loader:训练集
     # validation_loader:验证集
     # best_val_acc:最佳测试集分类精度
     best_val_acc = None
     # 进行num_epochs次集成对抗训练
     for epoch in range(self.num_epochs):
         # training the model with natural examples and corresponding adversarial examples from external models
         # 一次完整的集成对抗训练
         self.train_one_epoch_with_adv_from_external_models(pre_trained_models=pre_trained_models, train_loader=train_loader, epoch=epoch)
         # 计算训练后的模型对验证集的分类精度
         val_acc = validation_evaluation(model=self.model, validation_loader=validation_loader, device=self.device)
         # 如果数据集为CIFAR10则进行学习率的调整
         if self.Dataset == 'CIFAR10':
             adjust_learning_rate(epoch=epoch, optimizer=self.optimizer_adv)
         assert os.path.exists('../DefenseEnhancedModels/{}'.format(self.defense_name))
         # defense_enhanced_saver:集成对抗训练防御模型参数的保存位置在DefenseEnhancedModels/NEAT/MNIST_NEAT_enhanced.pt中或者CIFAR10
         defense_enhanced_saver = '../DefenseEnhancedModels/{}/{}_{}_enhanced.pt'.format(self.defense_name, self.Dataset, self.defense_name)
         # 选择验证集上分类精度最高的模型进行保存
         if not best_val_acc or round(val_acc, 4) >= round(best_val_acc, 4):
             if best_val_acc is not None:
                 os.remove(defense_enhanced_saver)
             best_val_acc = val_acc
             self.model.save(name=defense_enhanced_saver)
         else:
             print('Train Epoch {:>3}: validation dataset accuracy did not improve from {:.4f}\n'.format(epoch, best_val_acc))
コード例 #4
0
def main(args):
    os.environ['CUDA_VISIBLE_DEVICES'] = args.gpu_index
    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
    torch.backends.cudnn.deterministic = True
    torch.backends.cudnn.benchmark = False
    torch.manual_seed(args.seed)
    if torch.cuda.is_available():
        torch.cuda.manual_seed(args.seed)
    np.random.seed(args.seed)
    random.seed(args.seed)

    # 下载mnist训练集,划分为训练集和测试集(然后进行分组),保存到MNIST文件夹下面
    train_loader, valid_loader = get_mnist_train_validate_loader(dir_name='../data/MNIST', batch_size=MNIST_Training_Parameters['batch_size'],valid_size=0.1, shuffle=True)
    # 下载minst测试集(然后进行分组),保存到MNIST文件夹下面
    test_loader = get_mnist_test_loader(dir_name='../data/MNIST', batch_size=MNIST_Training_Parameters['batch_size'])
    # 设置模型
    # **************引入的模型名称**************
    mnist_model = MNIST_CNN().to(device)
    # 设置优化器
    optimizer = optim.SGD(mnist_model.parameters(), lr=MNIST_Training_Parameters['learning_rate'],
                          momentum=MNIST_Training_Parameters['momentum'], weight_decay=MNIST_Training_Parameters['decay'], nesterov=True)
    # 训练
    # 最好的验证集精度
    best_val_acc = None
    # 训练模型参数保存路径:/MNIST/model/MNIST_raw.pt
    # **************不同模型需要修改名称**************
    model_saver = '../data/MNIST/model/MART_MNIST_' + 'raw' + '.pt'
    # 进行epoch次循环训练
    for epoch in range(MNIST_Training_Parameters['num_epochs']):
        # 一次epoch训练
        train_one_epoch(model=mnist_model, train_loader=train_loader, optimizer=optimizer, epoch=epoch, device=device)
        # 验证集的精度
        val_acc = validation_evaluation(model=mnist_model, validation_loader=valid_loader, device=device)
        adjust_MNIST_learning_rate(optimizer=optimizer, epoch=epoch)
        # 每一次epoch后验证集的精度大于最好的精度时(移除模型保存路径),或者best_val_acc为None时,更新最佳精度,然后将模型参数重新写入保存路径中
        if not best_val_acc or round(val_acc, 4) >= round(best_val_acc, 4):
            if best_val_acc is not None:
                os.remove(model_saver)
            best_val_acc = val_acc
            mnist_model.save(name=model_saver)
        # 否则提示精度未发生提高
        else:
            print('Train Epoch{:>3}: validation dataset accuracy did not improve from {:.4f}\n'.format(epoch, best_val_acc))
    # 测试
    # 复制mnist_model
    final_model = copy.deepcopy(mnist_model)
    # 加载final_model
    final_model.load(path=model_saver, device=device)
    # 计算模型在测试集上面的精度并输出
    accuracy = testing_evaluation(model=final_model, test_loader=test_loader, device=device)
    # 打印模型在测试集上的精度
    print('Finally, the ACCURACY of saved model [{}] on testing dataset is {:.2f}%\n'.format(final_model.model_name, accuracy * 100.0))
コード例 #5
0
 def search_best_radius(self,
                        validation_loader=None,
                        radius_min=0.0,
                        radius_max=1.0,
                        radius_step=0.01):
     # validation_loader:验证集
     # radius_min:半径最小值为0.0
     # radius_max:半径最大值为1.0
     # radius_step:半径迭代的步长为0.001
     self.model.eval()
     with torch.no_grad():
         # val_acc:原始验证集的分类精度
         val_acc = validation_evaluation(
             model=self.model,
             validation_loader=validation_loader,
             device=self.device)
         print(
             '<--- original classification accuracy on validation dataset is {:.4f} --->'
             .format(val_acc))
         # total_step:总的迭代次数
         total_step = int((radius_max - radius_min) / radius_step)
         # 循环进行迭代
         for index in range(total_step):
             # tmp_radius:每一次的半径都加上一个步长
             tmp_radius = radius_min + radius_step * (index + 1)
             total = 0.0
             correct = 0.0
             for images, labels in validation_loader:
                 # rc_preds:返回RC预测的标签
                 # rc_labels:将RC预测标签转化为tensor
                 rc_preds = self.region_based_classification(
                     samples=images, radius=tmp_radius)
                 rc_labels = torch.from_numpy(rc_preds)
                 # 如果预测的标签和真实标签一致,正确个数加1
                 correct += (rc_labels == labels).sum().item()
                 # total:为总的验证集数目
                 total += labels.size(0)
             # rc_acc:RC预测标签的准确率
             rc_acc = correct / total
             print(
                 '\tcurrent radius is {:.2f}, validation accuracy is {:.1f}/{:.1f}={:.5f}'
                 .format(tmp_radius, correct, total, rc_acc))
             # 如果原始验证集的分类精度与RC模型的分类精度之差大于0.01时(RC的精度开始降低),则返回上一个迭代的半径
             if (val_acc - rc_acc) > 1e-2:
                 return round(tmp_radius - radius_step, 2)
         # 否则返回最大迭代半径1.0
         return radius_max
コード例 #6
0
    def train_external_model_group(self, train_loader=None, validation_loader=None):
        # train_loader:训练集
        # validation_loader:验证集
        # model_group:MNIST/CIFAR10的网络,各有4个
        if self.Dataset == 'MNIST':
            model_group = [MNIST_A(), MNIST_B(), MNIST_C(), MNIST_D()]
        else:
            model_group = [CIFAR10_A(), CIFAR10_B(), CIFAR10_C(), CIFAR10_D()]
        model_group = [model.to(self.device) for model in model_group]

        # 一个一个训练MNIST/CIFAR10的网络
        for i in range(len(model_group)):
            # 为MNIST/CIFAR10准备优化器,MNIST网络的优化器都为SGD,CIFAR10的最后一个网络优化器为Adam,其余的都为SGD优化器
            if self.Dataset == "MNIST":
                optimizer_external = optim.SGD(model_group[i].parameters(), lr=self.training_parameters['learning_rate'],
                                               momentum=self.training_parameters['momentum'], weight_decay=self.training_parameters['decay'],
                                               nesterov=True)
            else:
                # 可进行调整
                if i == 3:
                    optimizer_external = optim.SGD(model_group[i].parameters(), lr=0.001, momentum=0.9, weight_decay=1e-6)
                else:
                    optimizer_external = optim.Adam(model_group[i].parameters(), lr=self.training_parameters['lr'])
            print('\nwe are training the {}-th static external model ......'.format(i))
            # best_val_acc:验证集上的最佳分类精度
            best_val_acc = None
            # 对网络训练num_epochs次
            for index_epoch in range(self.num_epochs):
                # 一次完整的训练
                train_one_epoch(model=model_group[i], train_loader=train_loader, optimizer=optimizer_external, epoch=index_epoch,
                                device=self.device)
                # val_acc:每一次训练结束后,对验证集的分类精度
                val_acc = validation_evaluation(model=model_group[i], validation_loader=validation_loader, device=self.device)
                # 如果数据集为CIFAR10进行学习率调整
                if self.Dataset == 'CIFAR10':
                    adjust_learning_rate(epoch=index_epoch, optimizer=optimizer_external)
                assert os.path.exists('../DefenseEnhancedModels/{}'.format(self.defense_name))
                # defense_external_saver:最佳模型参数保存位置为DefenseEnhancedModels/NEAT/MNIST_NEAT_0.pt中,或者为CIFAR10
                defense_external_saver = '../DefenseEnhancedModels/{}/{}_NEAT_{}.pt'.format(self.defense_name, self.Dataset, str(i))
                # 计算每次训练对验证集的分类精度,将最佳的验证精度对应的模型参数进行保存
                if not best_val_acc or round(val_acc, 4) >= round(best_val_acc, 4):
                    if best_val_acc is not None:
                        os.remove(defense_external_saver)
                    best_val_acc = val_acc
                    model_group[i].save(name=defense_external_saver)
                else:
                    print('Train Epoch {:>3}: validation dataset accuracy did not improve from {:.4f}\n'.format(index_epoch, best_val_acc))
コード例 #7
0
def main(args):
    os.environ['CUDA_VISIBLE_DEVICES'] = args.gpu_index
    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
    # Set the random seed manually for reproducibility.
    torch.backends.cudnn.deterministic = True
    torch.backends.cudnn.benchmark = False
    torch.manual_seed(args.seed)
    if torch.cuda.is_available():
        torch.cuda.manual_seed(args.seed)
    np.random.seed(args.seed)
    random.seed(args.seed)

    # 下载CIFAR10训练集,划分为训练集和测试集(然后进行分组),保存到CIFAR10文件夹下面
    train_loader, valid_loader = get_cifar10_train_validate_loader(
        dir_name='../data/CIFAR10/',
        batch_size=CIFAR10_Training_Parameters['batch_size'],
        valid_size=0.1,
        shuffle=True)
    # 下载CIFAR10测试集(然后进行分组),保存到CIFAR10文件夹下面
    test_loader = get_cifar10_test_loader(
        dir_name='../data/CIFAR10/',
        batch_size=CIFAR10_Training_Parameters['batch_size'])
    # 设置模型
    # **************引入的模型名称**************
    resnet_model = ResNet18().to(device)
    # 设置优化器
    optimizer = optim.Adam(resnet_model.parameters(),
                           lr=CIFAR10_Training_Parameters['lr'])
    # 训练
    # 最好的验证集精度
    best_val_acc = None
    # 训练模型参数保存路径:/CIFAR10/model/CIFAR10_raw.pt
    # **************不同模型需要修改名称**************
    model_saver = './CIFAR10/model/ResNet18_' + 'raw' + '.pt'
    # 进行epoch次循环训练
    for epoch in range(CIFAR10_Training_Parameters['num_epochs']):
        # 一次epoch训练
        train_one_epoch(model=resnet_model,
                        train_loader=train_loader,
                        optimizer=optimizer,
                        epoch=epoch,
                        device=device)
        # 验证集的精度
        val_acc = validation_evaluation(model=resnet_model,
                                        validation_loader=valid_loader,
                                        device=device)
        # 学习率调整
        adjust_learning_rate(optimizer=optimizer, epoch=epoch)
        # 每一次epoch后验证集的精度大于最好的精度时(移除模型保存路径),或者best_val_acc为None时,更新最佳精度,然后将模型参数重新写入保存路径中
        if not best_val_acc or round(val_acc, 4) >= round(best_val_acc, 4):
            if best_val_acc is not None:
                os.remove(model_saver)
            best_val_acc = val_acc
            resnet_model.save(name=model_saver)
        # 否则提示精度未发生提高
        else:
            print(
                'Train Epoch{:>3}: validation dataset accuracy did not improve from {:.4f}\n'
                .format(epoch, best_val_acc))
    # 测试
    # 复制resnet_model
    final_model = copy.deepcopy(resnet_model)
    # 加载final_model
    final_model.load(path=model_saver, device=device)
    # 计算模型在测试集上面的精度并输出
    accuracy = testing_evaluation(model=final_model,
                                  test_loader=test_loader,
                                  device=device)
    # 打印模型在测试集上的精度
    print(
        'Finally, the ACCURACY of saved model [{}] on testing dataset is {:.2f}%\n'
        .format(final_model.model_name, accuracy * 100.0))
コード例 #8
0
ファイル: NewRLFAT1.py プロジェクト: zuraSherl/defense_test
    def defense(self, train_loader=None, validation_loader=None):
        # train_loader:训练集
        # validation_loader:验证集
        # best_val_acc:验证集最佳分类精度
        best_val_acc = None
        # 进行num_epochs次PGD对抗训练
        for epoch in range(self.num_epochs):
            # 进行一次完整的RLFAT对抗训练
            self.train_one_epoch_with_rbs_pgd(train_loader=train_loader,
                                              epoch=epoch)
            # val_acc:对验证集进行评估的分类精度
            val_acc = validation_evaluation(
                model=self.model,
                validation_loader=validation_loader,
                device=self.device)

            assert os.path.exists('../DefenseEnhancedModels/{}'.format(
                self.defense_name))
            # defense_enhanced_saver:对抗训练网络参数的存放位置为DefenseEnhancedModels/PAT/CIFAR10_PAT_enhanced.pt中
            defense_enhanced_saver = '../DefenseEnhancedModels/{}/{}_{}_enhanced.pt'.format(
                self.defense_name, self.Dataset, self.defense_name)
            # 选取对验证集分类精度最高的模型参数进行保存
            if not best_val_acc or round(val_acc, 4) >= round(best_val_acc, 4):
                if best_val_acc is not None:
                    os.remove(defense_enhanced_saver)
                best_val_acc = val_acc
                self.model.save(name=defense_enhanced_saver)
            else:
                print(
                    'Train Epoch{:>3}: validation dataset accuracy did not improve from {:.4f}\n'
                    .format(epoch, best_val_acc))

            pgd_sense_val = 0
            gamma_sense_val = 0
            count = 0
            # 产生白盒攻击的PGD对抗样本
            for index, (images, labels) in enumerate(validation_loader):
                count = index
                nat_images = images.to(self.device)
                nat_labels = labels.to(self.device)
                self.model.eval()
                # natural_images:将干净样本转化为numpy的形式
                natural_images = nat_images.cpu().numpy()
                # copy_images:复制干净样本numpy形式
                copy_images = natural_images.copy()
                # 改变图像的曝光度
                gamma_copy_images = natural_images.copy()
                gamma_images = batch_brightness(gamma_copy_images, c=-0.15)
                gamma_images = torch.from_numpy(gamma_images).to(self.device)
                # 从[-epsilon,epsilon)的均匀分布中随机采样,形成初始的扰动叠加在干净样本上
                copy_images = copy_images + np.random.uniform(
                    -self.epsilon, self.epsilon,
                    copy_images.shape).astype('float32')
                # 进行迭代,求PGD对抗样本
                x_adv = []
                for i in range(self.attack_step_num):
                    # 将初始的扰动样本由numpy形式转化为tensor形式
                    var_copy_images = torch.from_numpy(copy_images).to(
                        self.device)
                    # 可以对其进行求导
                    var_copy_images.requires_grad = True
                    # 将其输入模型进行预测
                    preds = self.model(var_copy_images)
                    # 计算损失值
                    loss = F.cross_entropy(preds, nat_labels)
                    # 对输入求梯度
                    gradient = torch.autograd.grad(loss, var_copy_images)[0]
                    # 对梯度求符号函数并转为numpy形式
                    gradient_sign = torch.sign(gradient).cpu().numpy()
                    # 对样本添加一小步扰动
                    copy_images = copy_images + self.step_size * gradient_sign
                    # 将样本的扰动大小控制在[natural_images-epsilon,natural_images+epsilon]的范围之内
                    copy_images = np.clip(copy_images,
                                          natural_images - self.epsilon,
                                          natural_images + self.epsilon)
                    # 将扰动大小控制在[0.0,1.0]之间
                    copy_images = np.clip(copy_images, 0.0, 1.0)
                # 一组PGD对抗样本
                pgd_adv_images = torch.from_numpy(copy_images).to(self.device)
                # 计算ϵ-邻域损失灵敏度
                self.model.eval()
                pgd_preds = self.model(pgd_adv_images)
                # 计算损失值
                pgd_sense_loss = F.cross_entropy(pgd_preds, nat_labels)
                # 对输入求梯度
                pgd_grad = torch.autograd.grad(pgd_sense_loss,
                                               pgd_adv_images)[0]
                # 计算一个分组ϵ-邻域损失灵敏度
                pgd_sense = torch.sum(pgd_grad.mul(pgd_grad))
                # 计算所有分组的损失灵敏度之和
                pgd_sense_val = pgd_sense_val + pgd_sense
                # 计算gamma损失灵敏度
                self.model.eval()
                gamma_preds = self.model(gamma_images)
                # 计算损失值
                gamma_sense_loss = F.cross_entropy(gamma_preds, nat_labels)
                # 对输入求梯度
                gamma_grad = torch.autograd.grad(gamma_sense_loss,
                                                 gamma_images)[0]
                # 计算一个分组的gamma灵敏度
                gamma_sense = torch.sum(pgd_grad.mul(gamma_grad))
                # 计算所有分组的损失灵敏度之和
                gamma_sense_val = gamma_sense_val + gamma_sense

            # 打印ϵ-邻域损失灵敏度和gamma损失灵敏度
            if not best_val_acc or round(val_acc, 4) >= round(best_val_acc, 4):
                print('ϵ loss sense val:', pgd_sense_val / (count + 1))
                print('gamma loss sense val:', gamma_sense_val / (count + 1))