mxnet FGSM 对抗样本生成

感慨:初学mxnet 和 python  ,写出来一个FGSM真的坑太多了。

FGSM的原理很简单,利用输入层的梯度作为扰动,改变输入图像,从而达到肉眼看不到区别的前提下能够使得神经网络错分。

原理博客:

https://blog.csdn.net/u014038273/article/details/78773515

mxnet example版本,不定向生成。(ps:这个我觉得是有点问题的。就产生一次扰动就能确保错分了???)

我自己的未成熟的版本:(还有一些问题待解决,现放出来看看有么有大神指点)

if __name__ == '__main__':
    # load an image
    batchSize = 1
    datashape = (1, 144, 128)
    ctx = mx.gpu(device_id=2)
    data_iter = mx.io.ImageRecordIter(path_imgrec='./webface/train_webface_train.rec',data_shape=datashape, batch_size=batchSize)
    data_iter.reset()
    batch = data_iter.next()

    # load model
    modelPrefix = '/netname' # model name
    modelEpoch = 20
    # net = import_module('symbols.' + model)
    sym1, arg_params, aux_params = mx.model.load_checkpoint(modelPrefix, modelEpoch)
    mod = mx.mod.Module(sym1,context=ctx)
    mod.bind(data_shapes=[('data', (1, 1, 144, 128))], for_training=True, inputs_need_grad=True)
    mod.set_params(arg_params=arg_params, aux_params=aux_params)
    # 备份
    mod_copy = mx.mod.Module(sym1,context=ctx)
    mod_copy.bind(data_shapes=[('data', (1, 1, 144, 128))], for_training=True, inputs_need_grad=True)
    mod_copy.set_params(arg_params=arg_params, aux_params=aux_params)
   
    # 开始利用FGSM生成样本
    examples=210000 #生成样本数
    for index in range(examples):
        print("the %d pic \n"%(index))

        # first bp 利用当前网络做一次预测,做为比照
        mod.forward(batch, is_train=True)
        out = mod.get_outputs()[0].asnumpy()
        # print("ouput: ", mod.get_outputs()[0].asnumpy().shape)
        maxValue = 0
        maxIndex = 0
        for i in range(len(out[0])):
            # print(out[0][i])
            if out[0][i] > maxValue:
                maxValue = out[0][i]
                maxIndex = i
        trueLabel = maxIndex
        print("the true label is %s"%(trueLabel))

        ## --------------------FGSM-------
        ratio = 0.75
        iterNum=200
        
        originalData = copy.deepcopy(batch.data) #必须用深复制,list的浅复制是引用
        image = batch.data[0]
        originalBatch = mx.io.DataBatch(data=originalData, label=batch.label)
        image = image[0].asnumpy()
        plt.subplot(1, 3, 1)
        plt.imshow(image[0].astype(np.uint8),cmap='gray')
        
        # 定向的生成 选择一个错误的label
        batch.label[0][0] = 10575 - batch.label[0][0]

        for iter in range(iterNum):

            # get the grad for input layer
            mod.backward()
            grad = mod.get_input_grads()[0].asnumpy()

            # add the noise to raw pic
            noise = np.sign(grad)
            raw_batch = mx.io.DataBatch(data=copy.deepcopy(batch.data), label=batch.label)
            raw_output = raw_batch.data[0].asnumpy() + ratio * noise
            raw_batch.data[0][:] = raw_output

            # predict the new pic deepcopy
            mod_copy.forward(raw_batch, is_train=False)
            out = mod_copy.get_outputs()[0].asnumpy()
            maxValue = 0
            maxIndex = 0

            for i in range(len(out[0])):
                # print(out[0][i])
                if out[0][i] > maxValue:
                    maxValue = out[0][i]
                    maxIndex = i

            batch = raw_batch
            mod.forward(batch, is_train=True)

            if iter == 10 & trueLabel == maxIndex:
                ratio=1.5

            if iter == 20 & trueLabel == maxIndex:
                ratio = 2

            if trueLabel != maxIndex:
                print("the %d iteration is %f \n" % (iter, maxValue))
                print("the true label is \t", trueLabel)
                print("the predict label is ", maxIndex)
                print("\n")

                image2 = raw_batch.data[0]
                image2 = image2[0].asnumpy()
                image_deta = image - image2
                plt.subplot(1, 3, 2)
                plt.imshow(image2[0].astype(np.uint8),cmap='gray')
                plt.subplot(1, 3, 3)
                plt.imshow(image_deta[0].astype(np.uint8),cmap='gray')

                cv2.imwrite("./fgsm/original_"+str(trueLabel)+".jpg",image[0])
                cv2.imwrite("./fgsm/"+str(trueLabel)+"_"+str(maxIndex)+".jpg",image2[0])
                # plt.show()
                break

        data_iter.iter_next()
        batch = data_iter.next()

这里面的几个问题需要记录一下:

1.生成步骤

step 1:加载网络,加载原始样本

step 2 :对样本做前向预测,作为baseline用。

step 3 :得到输入的梯度,加上sign函数最大化扰动,产生噪声。

step 4 :在原始图像上加上噪声。

step 5 :对新图像在原始网络中,前向运算预测类别。

step 6 :错分则保留,否则继续迭代,直到达到迭代上限。

2.几个问题

第一个,生成样本速度。

在实现的过程中,我发现有的图片通过一次迭代就能产生对抗样本。而有的图片通过无数次迭代都是无法产生的。

这个问题我觉跟样本本身有关,本来就易错分的样本容易受干扰影响。

第二个,生成样本质量。

在图片上,有的对抗样本确实和原始样本差异较小,肉眼无法区分。而有的却比较大,感觉到了图片发生了改变。

第三个,对抗样本的意义。

一般为了增强某个网络的鲁棒性,生成对抗样本加入到原始训练集中一起训练,可以增强对某些扰动的鲁棒性。但是,我觉得这种效果是微小的乃至无效的。一来是对抗样本的质量无法控制,二来是对抗样本的生成依旧是训练集的一种扩充,提升的效果可以看为数据集扩充带来的效果。

第四个,再FGSM的过程中,mxnet的backward函数需要先进行一次forward,那么此时的网络是否更新了。

第五个,如何量化这个生成质量,如何提高速度,控制迭代,如何选择扰动系数。

————————————————————————————————————update-------------------------------

几个小体会。

1、mxnet api:

forward 设置 is_train 为true和false 的时候,计算结果不一样。

forward 将is_train 设置为false 时的结果和用predict的计算结果是一致的。

这个看不到源码,也不知道为什么,可能需要找找。

2、深浅复制

list的深复制要用,copy.deepcopy()

ndarray的深复制,要用.copy()

 

----------------------------------------------------------------------update---------------------------------------------------------------------

感谢lq大神,嗯终于找到了问题。

问题复述:

之前不论是定向生成还是不定向生成,都存在一个问题。无法收敛,难以生成对抗样本。

解决:

加入噪声的过程该是减去的过程,而不是加的过程。这个原理如果利用方向传播,减小loss,就是减去梯度来想其实是类似的。但是在论文中是+,包括部分复现的代码都是+。我觉得也是有道理的,假如从不定向的角度来想,我们需要最大化这个正确分类的loss,所以是加上扰动。从定向的角度来想,应该是最小化错误分类的loss,所以是减去扰动。

但是,在代码复现的过程中,发现用减去是无法收敛的。所以还需要多想想为什么。

更新代码:

if __name__ == '__main__':
    # load an image
    batchSize = 1
    datashape = (1, 144, 128)
    ctx = mx.gpu(device_id=2)
    data_iter = mx.io.ImageRecordIter(path_imgrec='./webface/train_webface_train.rec',data_shape=datashape, batch_size=batchSize)
    data_iter.reset()
    batch = data_iter.next()

    # load model
    modelPrefix = '/netname' # model name
    modelEpoch = 20
    # net = import_module('symbols.' + model)
    sym1, arg_params, aux_params = mx.model.load_checkpoint(modelPrefix, modelEpoch)
    mod = mx.mod.Module(sym1,context=ctx)
    mod.bind(data_shapes=[('data', (1, 1, 144, 128))], for_training=True, inputs_need_grad=True)
    mod.set_params(arg_params=arg_params, aux_params=aux_params)
    # 备份
    mod_copy = mx.mod.Module(sym1,context=ctx)
    mod_copy.bind(data_shapes=[('data', (1, 1, 144, 128))], for_training=True, inputs_need_grad=True)
    mod_copy.set_params(arg_params=arg_params, aux_params=aux_params)
   
    # 开始利用FGSM生成样本
    examples=210000 #生成样本数
    for index in range(examples):
        print("the %d pic \n"%(index))

        # first bp 利用当前网络做一次预测,做为比照
        mod.forward(batch, is_train=True)
        out = mod.get_outputs()[0].asnumpy()
        # print("ouput: ", mod.get_outputs()[0].asnumpy().shape)
        maxValue = 0
        maxIndex = 0
        for i in range(len(out[0])):
            # print(out[0][i])
            if out[0][i] > maxValue:
                maxValue = out[0][i]
                maxIndex = i
        trueLabel = maxIndex
        print("the true label is %s"%(trueLabel))

        ## --------------------FGSM-------
        ratio = 0.75
        iterNum=30
        
        originalData = copy.deepcopy(batch.data) #必须用深复制,list的浅复制是引用
        image = batch.data[0]
        originalBatch = mx.io.DataBatch(data=originalData, label=batch.label)
        image = image[0].asnumpy()
        plt.subplot(1, 3, 1)
        plt.imshow(image[0].astype(np.uint8),cmap='gray')
        
        # 定向的生成 选择一个错误的label
        batch.label[0][0] = 10575 - batch.label[0][0]

        for iter in range(iterNum):

            # get the grad for input layer
            mod.backward()
            grad = mod.get_input_grads()[0].asnumpy()

            # add the noise to raw pic
            noise = np.sign(grad)
            raw_batch = mx.io.DataBatch(data=copy.deepcopy(batch.data), label=batch.label)
            raw_output = raw_batch.data[0].asnumpy() -ratio * noise
            raw_batch.data[0][:] = raw_output

            # predict the new pic deepcopy
            mod_copy.forward(raw_batch, is_train=False)
            out = mod_copy.get_outputs()[0].asnumpy()
            maxValue = 0
            maxIndex = 0

            for i in range(len(out[0])):
                # print(out[0][i])
                if out[0][i] > maxValue:
                    maxValue = out[0][i]
                    maxIndex = i

            batch = raw_batch
            mod.forward(batch, is_train=True)

            if iter == 10 & trueLabel == maxIndex:
                ratio=1.5

            if iter == 20 & trueLabel == maxIndex:
                ratio = 2

            if trueLabel != maxIndex:
                print("the %d iteration is %f \n" % (iter, maxValue))
                print("the true label is \t", trueLabel)
                print("the predict label is ", maxIndex)
                print("\n")

                image2 = raw_batch.data[0]
                image2 = image2[0].asnumpy()
                image_deta = image - image2
                plt.subplot(1, 3, 2)
                plt.imshow(image2[0].astype(np.uint8),cmap='gray')
                plt.subplot(1, 3, 3)
                plt.imshow(image_deta[0].astype(np.uint8),cmap='gray')

                cv2.imwrite("./fgsm/original_"+str(trueLabel)+".jpg",image[0])
                cv2.imwrite("./fgsm/"+str(trueLabel)+"_"+str(maxIndex)+".jpg",image2[0])
                # plt.show()
                break

        data_iter.iter_next()
        batch = data_iter.next()

主要的更新:

raw_output = raw_batch.data[0].asnumpy() -ratio * noise

还有些小的代码优化,就不需要放出了。

 

 

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 13
    评论
生成MXNet训练集的步骤如下: 1. 下载数据集:可以使用MXNet提供的数据集,例如MNIST数据集。 2. 加载数据集:使用MXNet提供的`mxnet.gluon.data.vision.datasets`模块来加载数据集。 3. 对数据集进行预处理:对每张图像进行归一化处理,将像素值缩放到0到1之间。对于标签数据,使用独热编码方式进行处理。 4. 定义输入和标签:将图像数据和标签数据分别存储在MXNet提供的`mxnet.ndarray`类型的数组中。输入数据的数组应该为4维,即(N, C, H, W),其中N表示图像数量,C表示通道数(对于灰度图像为1),H表示图像高度,W表示图像宽度。标签数据的数组应该为1维,即(N,)。 以下是一个示例代码,用于生成MXNet的训练集: ```python import mxnet as mx from mxnet.gluon.data.vision import MNIST from mxnet.ndarray import one_hot # 下载MNIST数据集 train_set = MNIST(train=True) # 对数据进行预处理 X_train = train_set._data.astype('float32') / 255.0 y_train = train_set._label.astype('int32') y_train = one_hot(y_train, 10) # 定义输入和标签 X_train = mx.nd.array(X_train).reshape((-1, 1, 28, 28)) y_train = mx.nd.array(y_train).argmax(axis=1) ``` 在上面的代码中,我们使用了`MNIST`函数来加载MNIST数据集,并将图像数据和标签数据分别存储在MXNet的`ndarray`类型的数组中。对于标签数据,我们使用了`one_hot`函数进行独热编码,并将结果转换为MXNet的`ndarray`类型的数组。最后,我们将图像数据和标签数据分别存储在MXNet的`ndarray`类型的数组中,并对输入数据的维度进行了调整,以适应LeNet模型的输入尺寸。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值