使用fuzz testing模块测试模型安全性

Linux Ascend GPU CPU 数据准备 模型开发 模型训练 模型调优 企业 高级

使用fuzz testing模块测试模型安全性 - 图1

概述

传统软件的决策逻辑由代码逻辑决定,传统软件通过代码行覆盖率来判断当前测试是否充分,理想情况下覆盖率越高,代码测试越充分。然而,对于深度神经网络而言,程序的决策逻辑由训练数据、网络模型结构和参数通过某种黑盒机制决定,代码行覆盖率已不足以评估测试的充分性。需要根据深度网络的特点选择更为适合的测试评价准则,指导神经网络进行更为充分的测试,发现更多的边缘错误用例,从而确保模型的通用性、鲁棒性。

MindArmour的fuzz_testing模块以神经元覆盖率作为测试评价准则。神经元覆盖率,是指通过一组输入观察到的、激活的神经元数量和神经元输出值的范围。我们通过神经元覆盖率来指导输入变异,让输入能够激活更多的神经元,神经元值的分布范围更广,从而探索不同类型的模型输出结果、错误行为。

这里以LeNet模型,MNIST数据集为例,说明如何使用Fuzzer。

本例面向CPU、GPU、Ascend 910 AI处理器,你可以在这里下载完整的样例代码:https://gitee.com/mindspore/mindarmour/blob/r1.0/examples/ai_fuzzer/lenet5_mnist_fuzzing.py

实现阶段

导入需要的库文件

下列是我们需要的公共模块、MindSpore相关模块和fuzz_testing特性模块,以及配置日志标签和日志等级。

  1. import numpy as np
  2. from mindspore import Model
  3. from mindspore import context
  4. from mindspore.train.serialization import load_checkpoint, load_param_into_net
  5. from mindarmour.fuzz_testing import Fuzzer
  6. from mindarmour.fuzz_testing import ModelCoverageMetrics
  7. from mindarmour.utils.logger import LogUtil
  8. from examples.common.dataset.data_processing import generate_mnist_dataset
  9. from examples.common.networks.lenet5.lenet5_net import LeNet5
  10. LOGGER = LogUtil.get_instance()
  11. TAG = 'Fuzz_testing'
  12. LOGGER.set_level('INFO')

参数配置

配置必要的信息,包括环境信息、执行的模式。

  1. context.set_context(mode=context.GRAPH_MODE, device_target="Ascend")

详细的接口配置信息,请参见context.set_context接口说明。

运用Fuzz Testing

  1. 建立LeNet模型,加载MNIST数据集,操作同模型安全

    1. ...
    2. # Lenet model
    3. model = Model(net)
    4. # get training data
    5. data_list = "../common/dataset/MNIST/train"
    6. batch_size = 32
    7. ds = generate_mnist_dataset(data_list, batch_size, sparse=False)
    8. train_images = []
    9. for data in ds.create_tuple_iterator():
    10. images = data[0].asnumpy().astype(np.float32)
    11. train_images.append(images)
    12. train_images = np.concatenate(train_images, axis=0)
    13. # get test data
    14. data_list = "../common/dataset/MNIST/test"
    15. batch_size = 32
    16. ds = generate_mnist_dataset(data_list, batch_size, sparse=False)
    17. test_images = []
    18. test_labels = []
    19. for data in ds.create_tuple_iterator():
    20. images = data[0].asnumpy().astype(np.float32)
    21. labels = data[1].asnumpy()
    22. test_images.append(images)
    23. test_labels.append(labels)
    24. test_images = np.concatenate(test_images, axis=0)
    25. test_labels = np.concatenate(test_labels, axis=0)
  2. Fuzzer参数配置。

    设置数据变异方法及参数。支持同时配置多种方法,目前支持的数据变异方法包含三类:

    • 图像仿射变换方法:Translate、Scale、Shear、Rotate。

    • 基于图像像素值变化的方法: Contrast、Brightness、Blur、Noise。

    • 基于对抗攻击的白盒、黑盒对抗样本生成方法:FGSM、PGD、MDIIM。

    数据变异方法中一定要包含基于图像像素值变化的方法。

    前两种类型的图像变化方法,支持用户自定义配置参数,也支持算法随机选择参数。用于自定义参数配置范围请参考:https://gitee.com/mindspore/mindarmour/blob/r1.0/mindarmour/fuzz_testing/image_transform.py 中对应的类方法。算法随机选择参数,则params设置为'auto_param': [True],参数将在推荐范围内随机生成。

    基于对抗攻击方法的参数配置请参考对应的攻击方法类。

    下面时变异方法及其参数配置的一个例子:

    1. mutate_config = [{'method': 'Blur',
    2. 'params': {'radius': [0.1, 0.2, 0.3],
    3. 'auto_param': [True, False]}},
    4. {'method': 'Contrast',
    5. 'params': {'auto_param': [True]}},
    6. {'method': 'Translate',
    7. 'params': {'auto_param': [True]}},
    8. {'method': 'Brightness',
    9. 'params': {'auto_param': [True]}},
    10. {'method': 'Noise',
    11. 'params': {'auto_param': [True]}},
    12. {'method': 'Scale',
    13. 'params': {'auto_param': [True]}},
    14. {'method': 'Shear',
    15. 'params': {'auto_param': [True]}},
    16. {'method': 'FGSM',
    17. 'params': {'eps': [0.3, 0.2, 0.4], 'alpha': [0.1]}}
    18. ]

    设置评价指标,目前支持5种评价指标,包括:

    • 通用评价指标:accuracy。

    • 神经元覆盖率指标:kmnc, nbc,snac。

    • 对抗攻击评价指标:attack_success_rate。 也可以设置为‘auto’,默认使用所有评价指标。

    1. eval_metrics =['accuracy', 'kmnc', 'attack_success_rate']
  3. 初始化种子队列,种子队列中的每个种子,包含2个值:原始图片、图片标签。这里取100个样本作为初始种子队列。

    1. # make initial seeds
    2. initial_seeds = []
    3. for img, label in zip(test_images, test_labels):
    4. initial_seeds.append([img, label])
    5. initial_seeds = initial_seeds[:100]
  4. 测试Fuzz测试前的神经元覆盖率。

    1. segmented_num=1000
    2. neuron_num=10
    3. model_coverage_test = ModelCoverageMetrics(model, segmented_num, neuron_num, train_images)
    4. model_coverage_test.calculate_coverage(np.array(test_images[:100]).astype(np.float32))
    5. LOGGER.info(TAG, 'KMNC of this test is : %s', model_coverage_test.get_kmnc())

    结果:

    1. KMNC of this test is : 0.0851
  5. Fuzz测试。

    1. eval_metrics = 'auto'
    2. model_fuzz_test = Fuzzer(model, train_images, neuron_num, segmented_num)
    3. _, _, _, _, metrics = model_fuzz_test.fuzzing(mutate_config, initial_seeds, eval_metrics=eval_metrics)
  6. 实验结果。

    fuzzing的返回结果中包含了5个数据:fuzz生成的样本fuzz_samples、生成样本的真实标签true_labels、被测模型对于生成样本的预测值fuzz_preds、 生成样本使用的变异方法fuzz_strategies、fuzz testing的评估报告metrics_report。用户可使用这些返回结果进一步的分析模型的鲁棒性。这里只展开metrics_report,查看fuzz testing后的各个评估指标。

    1. if metrics:
    2. for key in metrics:
    3. LOGGER.info(TAG, key + ': %s', metrics[key])

    Fuzz测试后结果如下:

    1. Accuracy: 0.7929
    2. Attack_success_rate: 0.3939
    3. Neural_coverage_KMNC: 0.4797

    Fuzz测试前种子的KMNC神经元覆盖率为8.5%,Fuzz后,KMNC神经元覆盖率为47.97%,神经元覆盖率提升,样本的多样性提升。Fuzz后,模型对于Fuzz生成样本的准确率为79.29%,使用了对抗攻击方法的样本,攻击成功率为39.39%。由于初始化种子、变异方法和相应的参数均为随机选择的,结果有一定的浮动是正常的。

    原始图片:

    fuzz_seed

​ Fuzz生成的变异图片:

fuzz_res