mindarmour
MindArmour是MindSpore的工具箱,用于增强模型可信,实现隐私保护机器学习。
- class mindarmour.Attack[源代码]
所有通过创建对抗样本的攻击类的抽象基类。
对抗样本是通过向原始样本添加对抗噪声来生成的。
- class mindarmour.BlackModel[源代码]
将目标模型视为黑盒的抽象类。模型应由用户定义。
- class mindarmour.Detector[源代码]
所有对抗样本检测器的抽象基类。
- detect(inputs)[源代码]
从输入样本中检测对抗样本。
参数:
inputs (Union[numpy.ndarray, list, tuple]) - 要检测的输入样本。
异常:
NotImplementedError - 抽象方法未实现。
- detect_diff(inputs)[源代码]
计算输入样本和去噪样本之间的差值。
参数:
inputs (Union[numpy.ndarray, list, tuple]) - 要检测的输入样本。
异常:
NotImplementedError - 抽象方法未实现。
- class mindarmour.Defense(network)[源代码]
所有防御类的抽象基类,用于防御对抗样本。
参数:
network (Cell) - 要防御的MindSpore风格的深度学习模型。
- 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, **kwargs)[源代码]
DPModel用于构建差分隐私训练的模型。
这个类就是重载Mindpore.train.model.Model。
详情请查看: 应用差分隐私机制保护用户隐私。
参数:
micro_batches (int) - 从原始批次拆分的小批次数。默认值:2。
norm_bound (float) - 用于剪裁绑定,如果设置为1,将返回原始数据。默认值:1.0。
noise_mech (float) - 对象可以生成不同类型的噪音。默认值:None。
clip_mech (Mechanisms) - 该对象用于更新自适应剪裁。默认值:None。
异常:
ValueError - DPOptimizer和noise_mech都为None或非None。
ValueError - noise_mech或DPOtimizer的mech方法是自适应的,而clip_mech不是None。
- class mindarmour.MembershipInference(model, n_jobs=- 1)[源代码]
成员推理是由Shokri、Stronati、Song和Shmatikov提出的一种用于推测用户隐私数据的灰盒攻击。它需要训练样本的loss或logits结果。(隐私是指单个用户的一些敏感属性)。
有关详细信息,请参见:使用成员推理测试模型安全性。
参数:
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 (minspore.dataset) - 目标模型的训练数据集。
dataset_test (minspore.dataset) - 目标模型的测试数据集。
metrics (Union[list, tuple]) - 评估指标。指标的值必须在[“precision”, “accuracy”, “recall”]中。默认值:[“precision”]。
返回:
list - 每个元素都包含攻击模型的评估指标。
- train(dataset_train, dataset_test, attack_config)[源代码]
根据配置,使用输入数据集训练攻击模型。
将攻击模型保存至self._attack_list。
参数:
dataset_train (minspore.dataset) - 目标模型的训练数据集。
dataset_test (minspore.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)}}]
异常:
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))[源代码]
一种用于通过还原图像的深层表达来重建图像的攻击方法。
参数:
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的值都不是正int。
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所有部分的网络。_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的值都不是正int.Z
- 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)