mindarmour

MindArmour是MindSpore的工具箱,用于增强模型可信,实现隐私保护机器学习。

class mindarmour.Attack[源代码]

所有通过创建对抗样本的攻击类的抽象基类。

对抗样本是通过向原始样本添加对抗噪声来生成的。

batch_generate(inputs, labels, batch_size=64)[源代码]

根据输入样本及其标签来批量生成对抗样本。

参数:
  • inputs (Union[numpy.ndarray, tuple]) - 生成对抗样本的原始样本。

  • labels (Union[numpy.ndarray, tuple]) - 原始/目标标签。若每个输入有多个标签,将它包装在元组中。

  • batch_size (int) - 一个批次中的样本数。默认值:64。

返回:
  • numpy.ndarray - 生成的对抗样本。

generate(inputs, labels)[源代码]

根据正常样本及其标签生成对抗样本。

参数:
  • inputs (Union[numpy.ndarray, tuple]) - 生成对抗样本的原始样本。

  • labels (Union[numpy.ndarray, tuple]) - 原始/目标标签。若每个输入有多个标签,将它包装在元组中。

异常:
  • NotImplementedError - 此为抽象方法。

class mindarmour.BlackModel[源代码]

将目标模型视为黑盒的抽象类。模型应由用户定义。

is_adversarial(data, label, is_targeted)[源代码]

检查输入样本是否为对抗样本。

参数:
  • data (numpy.ndarray) - 要检查的输入样本,通常是一些恶意干扰的样本。

  • label (numpy.ndarray) - 对于目标攻击,标签是受扰动样本的预期标签。对于无目标攻击,标签是相应未扰动样本的原始标签。

  • is_targeted (bool) - 对于有目标/无目标攻击,请选择True/False。

返回:
  • bool - 如果为True,则输入样本是对抗性的。如果为False,则输入样本不是对抗性的。

predict(inputs)[源代码]

使用用户指定的模型进行预测。预测结果的shape应该是(m,n),其中n表示此模型分类的类数。

参数:
  • inputs (numpy.ndarray) - 要预测的输入样本。

异常:
  • NotImplementedError - 抽象方法未实现。

class mindarmour.Detector[源代码]

所有对抗样本检测器的抽象基类。

detect(inputs)[源代码]

从输入样本中检测对抗样本。

参数:
  • inputs (Union[numpy.ndarray, list, tuple]) - 要检测的输入样本。

异常:
  • NotImplementedError - 抽象方法未实现。

detect_diff(inputs)[源代码]

计算输入样本和去噪样本之间的差值。

参数:
  • inputs (Union[numpy.ndarray, list, tuple]) - 要检测的输入样本。

异常:
  • NotImplementedError - 抽象方法未实现。

fit(inputs, labels=None)[源代码]

拟合阈值,拒绝与去噪样本差异大于阈值的对抗样本。当应用于正常样本时,阈值由假正率决定。

参数:
  • inputs (numpy.ndarray) - 用于计算阈值的输入样本。

  • labels (numpy.ndarray) - 训练数据的标签。默认值:None。

异常:
  • NotImplementedError - 抽象方法未实现。

transform(inputs)[源代码]

过滤输入样本中的对抗性噪声。

参数:
  • inputs (Union[numpy.ndarray, list, tuple]) - 要转换的输入样本。

异常:
  • NotImplementedError - 抽象方法未实现。

class mindarmour.Defense(network)[源代码]

所有防御类的抽象基类,用于防御对抗样本。

参数:
  • network (Cell) - 要防御的MindSpore风格的深度学习模型。

batch_defense(inputs, labels, batch_size=32, epochs=5)[源代码]

对输入进行批量防御操作。

参数:
  • inputs (numpy.ndarray) - 生成对抗样本的原始样本。

  • labels (numpy.ndarray) - 输入样本的标签。

  • batch_size (int) - 一个批次中的样本数。默认值:32。

  • epochs (int) - epochs的数量。默认值:5。

返回:
  • numpy.ndarray - batch_defense 操作的损失。

异常:
  • ValueError - batch_size 为0。

defense(inputs, labels)[源代码]

对输入进行防御操作。

参数:
  • inputs (numpy.ndarray) - 生成对抗样本的原始样本。

  • labels (numpy.ndarray) - 输入样本的标签。

异常:
  • NotImplementedError - 抽象方法未实现。

class mindarmour.Fuzzer(target_model)[源代码]

深度神经网络的模糊测试框架。

参考文献: DeepHunter: A Coverage-Guided Fuzz Testing Framework for Deep Neural Networks

参数:
  • target_model (Model) - 目标模糊模型。

样例:

>>> from mindspore.common.initializer import TruncatedNormal
>>> from mindspore.ops import operations as P
>>> from mindspore.train import Model
>>> from mindspore.ops import TensorSummary
>>> from mindarmour.fuzz_testing import Fuzzer
>>> from mindarmour.fuzz_testing import KMultisectionNeuronCoverage
>>> class Net(nn.Cell):
...     def __init__(self):
...         super(Net, self).__init__()
...         self.conv1 = nn.Conv2d(1, 6, 5, padding=0, weight_init=TruncatedNormal(0.02), pad_mode="valid")
...         self.conv2 = nn.Conv2d(6, 16, 5, padding=0, weight_init=TruncatedNormal(0.02), pad_mode="valid")
...         self.fc1 = nn.Dense(16 * 5 * 5, 120, TruncatedNormal(0.02), TruncatedNormal(0.02))
...         self.fc2 = nn.Dense(120, 84, TruncatedNormal(0.02), TruncatedNormal(0.02))
...         self.fc3 = nn.Dense(84, 10, TruncatedNormal(0.02), TruncatedNormal(0.02))
...         self.relu = nn.ReLU()
...         self.max_pool2d = nn.MaxPool2d(kernel_size=2, stride=2)
...         self.reshape = P.Reshape()
...         self.summary = TensorSummary()
...
...     def construct(self, x):
...         x = self.conv1(x)
...         x = self.relu(x)
...         self.summary('conv1', x)
...         x = self.max_pool2d(x)
...         x = self.conv2(x)
...         x = self.relu(x)
...         self.summary('conv2', x)
...         x = self.max_pool2d(x)
...         x = self.reshape(x, (-1, 16 * 5 * 5))
...         x = self.fc1(x)
...         x = self.relu(x)
...         self.summary('fc1', x)
...         x = self.fc2(x)
...         x = self.relu(x)
...         self.summary('fc2', x)
...         x = self.fc3(x)
...         self.summary('fc3', x)
...         return x
>>> net = Net()
>>> model = Model(net)
>>> mutate_config = [{'method': 'GaussianBlur',
...                   'params': {'ksize': [1, 2, 3, 5], 'auto_param': [True, False]}},
...                  {'method': 'MotionBlur',
...                   'params': {'degree': [1, 2, 5], 'angle': [45, 10, 100, 140, 210, 270, 300],
...                   'auto_param': [True]}},
...                  {'method': 'UniformNoise',
...                   'params': {'factor': [0.1, 0.2, 0.3], 'auto_param': [False, True]}},
...                  {'method': 'GaussianNoise',
...                   'params': {'factor': [0.1, 0.2, 0.3], 'auto_param': [False, True]}},
...                  {'method': 'Contrast',
...                   'params': {'alpha': [0.5, 1, 1.5], 'beta': [-10, 0, 10], 'auto_param': [False, True]}},
...                  {'method': 'Rotate',
...                   'params': {'angle': [20, 90], 'auto_param': [False, True]}},
...                  {'method': 'FGSM',
...                   'params': {'eps': [0.3, 0.2, 0.4], 'alpha': [0.1], 'bounds': [(0, 1)]}}]
>>> batch_size = 8
>>> num_classe = 10
>>> train_images = np.random.rand(32, 1, 32, 32).astype(np.float32)
>>> test_images = np.random.rand(batch_size, 1, 32, 32).astype(np.float32)
>>> test_labels = np.random.randint(num_classe, size=batch_size).astype(np.int32)
>>> test_labels = (np.eye(num_classe)[test_labels]).astype(np.float32)
>>> initial_seeds = []
>>> # make initial seeds
>>> for img, label in zip(test_images, test_labels):
...     initial_seeds.append([img, label])
>>> initial_seeds = initial_seeds[:10]
>>> nc = KMultisectionNeuronCoverage(model, train_images, segmented_num=100, incremental=True)
>>> model_fuzz_test = Fuzzer(model)
>>> samples, gt_labels, preds, strategies, metrics = model_fuzz_test.fuzzing(mutate_config, initial_seeds,
...                                                                          nc, max_iters=100)
fuzzing(mutate_config, initial_seeds, coverage, evaluate=True, max_iters=10000, mutate_num_per_seed=20)[源代码]

深度神经网络的模糊测试。

参数:
  • mutate_config (list) - 变异方法配置。格式为:
    mutate_config =
        [{'method': 'GaussianBlur',
          'params': {'ksize': [1, 2, 3, 5], 'auto_param': [True, False]}},
         {'method': 'UniformNoise',
          'params': {'factor': [0.1, 0.2, 0.3], 'auto_param': [False, True]}},
         {'method': 'GaussianNoise',
          'params': {'factor': [0.1, 0.2, 0.3], 'auto_param': [False, True]}},
         {'method': 'Contrast',
          'params': {'alpha': [0.5, 1, 1.5], 'beta': [-10, 0, 10], 'auto_param': [False, True]}},
         {'method': 'Rotate',
          'params': {'angle': [20, 90], 'auto_param': [False, True]}},
         {'method': 'FGSM',
          'params': {'eps': [0.3, 0.2, 0.4], 'alpha': [0.1], 'bounds': [(0, 1)]}}]
        ...]
    
    • 支持的方法在列表 self._strategies 中,每个方法的参数必须在可选参数的范围内。支持的方法分为两种类型:

    • 首先,自然鲁棒性方法包括:’Translate’, ‘Scale’、’Shear’、’Rotate’、’Perspective’、’Curve’、’GaussianBlur’、’MotionBlur’、’GradientBlur’、’Contrast’、’GradientLuminance’、’UniformNoise’、’GaussianNoise’、’SaltAndPepperNoise’、’NaturalNoise’。

    • 其次,对抗样本攻击方式包括:’FGSM’、’PGD’和’MDIM’。’FGSM’、’PGD’和’MDIM’分别是 FastGradientSignMethod、ProjectedGradientDent和MomentumDiverseInputIterativeMethod的缩写。 mutate_config 必须包含在[‘Contrast’, ‘GradientLuminance’, ‘GaussianBlur’, ‘MotionBlur’, ‘GradientBlur’, ‘UniformNoise’, ‘GaussianNoise’, ‘SaltAndPepperNoise’, ‘NaturalNoise’]中的方法。

    • 第一类方法的参数设置方式可以在 mindarmour/natural_robustness/transform/image 中看到。第二类方法参数配置参考 self._attack_param_checklists

  • initial_seeds (list[list]) - 用于生成变异样本的初始种子队列。初始种子队列的格式为[[image_data, label], […], …],且标签必须为one-hot。

  • coverage (CoverageMetrics) - 神经元覆盖率指标类。

  • evaluate (bool) - 是否返回评估报告。默认值:True。

  • max_iters (int) - 选择要变异的种子的最大数量。默认值:10000。

  • mutate_num_per_seed (int) - 每个种子的最大变异次数。默认值:20。

返回:
  • list - 模糊测试生成的变异样本。

  • list - 变异样本的ground truth标签。

  • list - 预测结果。

  • list - 变异策略。

  • dict - Fuzzer的指标报告。

异常:
  • ValueError - 参数’Coverage’必须是CoverageMetrics的子类。

  • ValueError - 初始种子队列为空。

  • ValueError - 初始种子队列中的种子不是包含两个元素。

class mindarmour.DPModel(micro_batches=2, norm_bound=1.0, noise_mech=None, clip_mech=None, optimizer=nn.Momentum, **kwargs)[源代码]

DPModel用于构建差分隐私训练的模型。

此类重载 mindspore.Model

详情请查看: 应用差分隐私机制保护用户隐私

参数:
  • micro_batches (int) - 从原始批次拆分的小批次数。默认值:2。

  • norm_bound (float) - 用于裁剪的约束,如果设置为1,将返回原始数据。默认值:1.0。

  • noise_mech (Mechanisms) - 用于生成不同类型的噪音。默认值:None。

  • clip_mech (Mechanisms) - 用于更新自适应剪裁。默认值:None。

  • optimizer (Cell) - 用于更新差分隐私训练过程中的模型权重值。默认值:nn.Momentum。

异常:
  • ValueError - optimizer 值为None。

  • ValueError - optimizer 不是DPOptimizer,且 noise_mech 为None。

  • ValueError - optimizer 是DPOptimizer,且 noise_mech 非None。

  • ValueError - noise_mech 或DPOptimizer的mech方法是自适应的,而 clip_mech 不是None。

class mindarmour.MembershipInference(model, n_jobs=- 1)[源代码]

成员推理是由Shokri、Stronati、Song和Shmatikov提出的一种用于推测用户隐私数据的灰盒攻击。它需要训练样本的loss或logits结果,隐私是指单个用户的一些敏感属性。

有关详细信息,请参见:使用成员推理测试模型安全性

参考文献:Reza Shokri, Marco Stronati, Congzheng Song, Vitaly Shmatikov. Membership Inference Attacks against Machine Learning Models. 2017.

参数:
  • model (Model) - 目标模型。

  • n_jobs (int) - 并行运行的任务数量。-1表示使用所有处理器,否则n_jobs的值必须为正整数。

异常:
  • TypeError - 模型的类型不是Mindspore.Model。

  • TypeError - n_jobs 的类型不是int。

  • ValueError - n_jobs 的值既不是-1,也不是正整数。

样例:

>>> import mindspore.ops.operations as P
>>> from mindspore.nn import Cell
>>> from mindspore import Model
>>> from mindarmour.privacy.evaluation import MembershipInference
>>> def dataset_generator():
...     batch_size = 16
...     batches = 1
...     data =  np.random.randn(batches * batch_size,1,10).astype(np.float32)
...     label =  np.random.randint(0,10, batches * batch_size).astype(np.int32)
...     for i in range(batches):
...         yield data[i*batch_size:(i+1)*batch_size], label[i*batch_size:(i+1)*batch_size]
>>> class Net(Cell):
...     def __init__(self):
...         super(Net, self).__init__()
...         self._softmax = P.Softmax()
...         self._Dense = nn.Dense(10,10)
...         self._squeeze = P.Squeeze(1)
...     def construct(self, inputs):
...         out = self._softmax(inputs)
...         out = self._Dense(out)
...         return self._squeeze(out)
>>> net = Net()
>>> loss = nn.SoftmaxCrossEntropyWithLogits(sparse=True)
>>> opt = nn.Momentum(params=net.trainable_params(), learning_rate=0.1, momentum=0.9)
>>> model = Model(network=net, loss_fn=loss, optimizer=opt)
>>> inference_model = MembershipInference(model, 2)
>>> config = [{
...     "method": "KNN",
...     "params": {"n_neighbors": [3, 5, 7],}
...     }]
>>> ds_train = ds.GeneratorDataset(dataset_generator, ["image", "label"])
>>> ds_test = ds.GeneratorDataset(dataset_generator, ["image", "label"])
>>> inference_model.train(ds_train, ds_test, config)
>>> metrics = ["precision", "accuracy", "recall"]
>>> eval_train = ds.GeneratorDataset(dataset_generator, ["image", "label"])
>>> eval_test = ds.GeneratorDataset(dataset_generator, ["image", "label"])
>>> result = inference_model.eval(eval_train. eval_test, metrics)
>>> print(result)
eval(dataset_train, dataset_test, metrics)[源代码]

评估目标模型的不同隐私。 评估指标应由metrics规定。

参数:
  • dataset_train (mindspore.dataset) - 目标模型的训练数据集。

  • dataset_test (mindspore.dataset) - 目标模型的测试数据集。

  • metrics (Union[list, tuple]) - 评估指标。指标的值必须在[“precision”, “accuracy”, “recall”]中。默认值:[“precision”]。

返回:
  • list - 每个元素都包含攻击模型的评估指标。

train(dataset_train, dataset_test, attack_config)[源代码]

根据配置,使用输入数据集训练攻击模型。

参数:
  • dataset_train (mindspore.dataset) - 目标模型的训练数据集。

  • dataset_test (mindspore.dataset) - 目标模型的测试集。

  • attack_config (Union[list, tuple]) - 攻击模型的参数设置。格式为:

    attack_config = [
        {"method": "knn", "params": {"n_neighbors": [3, 5, 7]}},
         {"method": "lr", "params": {"C": np.logspace(-4, 2, 10)}}]
    
    • 支持的方法有knn、lr、mlp和rf,每个方法的参数必须在可变参数的范围内。参数实现的提示可在下面找到:

异常:
  • KeyError - attack_config 中的配置没有键{“method”, “params”}。

  • NameError - attack_config 中的方法(不区分大小写)不在[“lr”, “knn”, “rf”, “mlp”]中。

class mindarmour.ImageInversionAttack(network, input_shape, input_bound, loss_weights=(1, 0.2, 5))[源代码]

一种通过还原图像的深层表达来重建图像的攻击方法。

参考文献:Aravindh Mahendran, Andrea Vedaldi. Understanding Deep Image Representations by Inverting Them. 2014.

参数:
  • network (Cell) - 网络,用于推断图像的深层特征。

  • input_shape (tuple) - 单个网络输入的数据形状,应与给定网络一致。形状的格式应为(channel, image_width, image_height)。

  • input_bound (Union[tuple, list]) - 原始图像的像素范围,应该像[minimum_pixel, maximum_pixel]或(minimum_pixel, maximum_pixel)。

  • loss_weights (Union[list, tuple]) - InversionLoss中三个子损失的权重,可以调整以获得更好的结果。默认值:(1, 0.2, 5)。

异常:
  • TypeError - 网络类型不是Cell。

  • ValueError - input_shape 的值有非正整数。

  • ValueError - loss_weights 的值有非正数。

样例:

>>> import mindspore.ops.operations as P
>>> from mindspore.nn import Cell
>>> from mindarmour.privacy.evaluation.inversion_attack import ImageInversionAttack
>>> class Net(Cell):
...     def __init__(self):
...         super(Net, self).__init__()
...         self._softmax = P.Softmax()
...         self._reduce = P.ReduceSum()
...         self._squeeze = P.Squeeze(1)
...     def construct(self, inputs):
...         out = self._softmax(inputs)
...         out = self._reduce(out, 2)
...         return self._squeeze(out)
>>> net = Net()
>>> original_images = np.random.random((2,1,10,10)).astype(np.float32)
>>> target_features =  np.random.random((2,10)).astype(np.float32)
>>> inversion_attack = ImageInversionAttack(net,
...                                         input_shape=(1, 10, 10),
...                                         input_bound=(0, 1),
...                                         loss_weights=[1, 0.2, 5])
>>> inversion_images = inversion_attack.generate(target_features, iters=10)
>>> evaluate_result = inversion_attack.evaluate(original_images, inversion_images)
evaluate(original_images, inversion_images, labels=None, new_network=None)[源代码]

通过三个指标评估还原图像的质量:原始图像和还原图像之间的平均L2距离和SSIM值,以及新模型对还原图像的推理结果在真实标签上的置信度平均值。

参数:
  • original_images (numpy.ndarray) - 原始图像,其形状应为(img_num, channels, img_width, img_height)。

  • inversion_images (numpy.ndarray) - 还原图像,其形状应为(img_num, channels, img_width, img_height)。

  • labels (numpy.ndarray) - 原始图像的ground truth标签。默认值:None。

  • new_network (Cell) - 其结构包含self._network中所有网络,但加载了不同的模型文件。默认值:None。

返回:
  • float - l2距离。

  • float - 平均ssim值。

  • Union [float, None] - 平均置信度。如果labels或new_network为 None,则该值为None。

generate(target_features, iters=100)[源代码]

根据 target_features 重建图像。

参数:
  • target_features (numpy.ndarray) - 原始图像的深度表示。 target_features 的第一个维度应该是img_num。 需要注意的是,如果img_num等于1,则 target_features 的形状应该是(1, dim2, dim3, …)。

  • iters (int) - 逆向攻击的迭代次数,应为正整数。默认值:100。

返回:
  • numpy.ndarray - 重建图像,预计与原始图像相似。

异常:
  • TypeError - target_features的类型不是numpy.ndarray。

  • ValueError - iters 的有非正整数.

class mindarmour.ConceptDriftCheckTimeSeries(window_size=100, rolling_window=10, step=10, threshold_index=1.5, need_label=False)[源代码]

概念漂移检查时间序列(ConceptDriftCheckTimeSeries)用于样本序列分布变化检测。

有关详细信息,请查看: 实现时序数据概念漂移检测应用

参数:
  • window_size (int) - 概念窗口的大小,不小于10。如果给定输入数据,window_size在[10, 1/3*len(input data)]中。如果数据是周期性的,通常window_size等于2-5个周期,例如,对于月/周数据,30/7天的数据量是一个周期。默认值:100。

  • rolling_window (int) - 平滑窗口大小,在[1, window_size]中。默认值:10。

  • step (int) - 滑动窗口的跳跃长度,在[1, window_size]中。默认值:10。

  • threshold_index (float) - 阈值索引,\((-\infty, +\infty)\) 。默认值:1.5。

  • need_label (bool) - False或True。如果need_label=True,则需要概念漂移标签。默认值:False。

样例:

>>> from mindarmour import ConceptDriftCheckTimeSeries
>>> concept = ConceptDriftCheckTimeSeries(window_size=100, rolling_window=10,
...                                       step=10, threshold_index=1.5, need_label=False)
>>> data_example = 5*np.random.rand(1000)
>>> data_example[200: 800] = 20*np.random.rand(600)
>>> score, threshold, concept_drift_location = concept.concept_check(data_example)
concept_check(data)[源代码]

在数据序列中查找概念漂移位置。

参数:
  • data (numpy.ndarray) - 输入数据。数据的shape可以是(n,1)或(n,m)。请注意,每列(m列)是一个数据序列。

返回:
  • numpy.ndarray - 样本序列的概念漂移分数。

  • float - 判断概念漂移的阈值。

  • list - 概念漂移的位置。