利用Keras实现FGSM算法

最近项目中需要使用FGSM攻击方法,使用主流的foolboxcleverhans中的攻击方法时,发现模型不匹配,所以不能继续使用,网上找到的代码也不能使用,需要自己实现一个。

根据论文 Explaining and Harnessing Adversarial Examples,FGSM的原理是损失函数对图像x求梯度,所以先求得损失函数,之后再对图像x求导,获得梯度,代码如下。

FGSM算法原理
其中噪声的计算方法如下所示,ε 表示扰动的大小,L 表示损失函数。

通过查找资料和讨论,得出了如下的代码。

from keras import backend, losses

def fgsm(model, image, y_true, eps=0.1):
   
    y_pred = model.output 
    
    # y_true: 目标真实值的张量。
    # y_pred: 目标预测值的张量。
    loss = losses.categorical_crossentropy(y_true, y_pred)

    gradient = backend.gradients(loss, model.input)
    gradient = gradient[0] 

    adv = image + backend.sign(gradient) * eps #fgsm算法
    
    sess = backend.get_session() 
    adv = sess.run(adv, feed_dict={ model.input : image}) #注意这里传递参数的情况
    adv = np.clip(adv, 0, 255) #有的像素点会超过255,需要处理

    return adv

# fgsm攻击 函数调用
# 下面部分代码(图像处理)需要根据自己的攻击图像的实际情况进行修改
def fgsm_attack(img, epsilons = 1000):
    image = cv2.imread(img)
    if image is None:
        print(img, end=' ')
        print("图像读取失败")
        return False

    # 加载准备攻击的模型,对要攻击的图形进行转换
    lpr_model = xxx 
    img_convert = cv2.resize(image, (x,y)) # 这里的x/y根据要求进行修改
    ret_predict = lpr_model.predict(np.array([img_convert])) #进行预测

    # 获取预测结果的one-hot编码,在攻击时需要用到
    label = np.zeros([1, 10, 1, 10]) #根据自己的情况进行修改
    for i in range(ret_predict.shape[0]):
        pos = res[i]
        label[0][i][0][pos] = 1

    # 计算eps的值
    epsilons = np.linspace(0,1,num=epsilons+1)[1:]

    print("开始使用fgsm进行攻击")
    for eps in epsilons:
        img_attack = fgsm(lpr_model, img_convert, label, eps=eps)
        attack = lpr_model.predict(img_attack)

        # 当识别的结果不等时,表示攻击成功
        if attack != ret_predict:
            print('攻击成功,攻击后的结果为:', attack)
            cv2.imwrite("attack_result.jpg", img_ret)

            return True
    return False

if __name__ == "__main__":
    fgsm_attack("./images/1.jpg")

参考:

  1. stackoverflow问答 https://stackoverflow.com/questions/39561560/getting-gradient-of-model-output-w-r-t-weights-using-keras
  2. keras的官方issue https://github.com/keras-team/keras/issues/2226
  3. stackoverflow问答 https://stackoverflow.com/questions/54480208/get-gradient-values-in-a-cnn-with-keras-tf
评论 27
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值