【AI安全初探】卷积神经网络的攻击与防御实战(附代码)—— 一名学生的实践笔记

📅 2026/6/20 7:05:48
【AI安全初探】卷积神经网络的攻击与防御实战(附代码)—— 一名学生的实践笔记
学生党好容易才接触到了网络安全和AI原理我接触这个领域有一段时间了最近在学习卷积神经网络CNN的攻防技术感觉很有意思也踩了不少坑。趁着端午假期我把自己的实践过程整理成了这篇文章。我知道在座的大佬很多文章里肯定有错误或理解不到位的地方恳请大家不吝赐教、斧正。这篇文章算是我的学习笔记如果能给同样刚起步的朋友一点参考那就更好了。免责声明本文所有内容仅用于在受控环境下的安全研究与学习请勿用于任何未经授权的攻击行为。所有操作均在本地实验环境进行。一、先看城墙CNN的底层结构在理解如何攻击之前我首先尝试搞清楚CNN的内部结构。卷积神经网络的核心无非是三部分1. 卷积层可以理解为用一个个小方块卷积核在图像上滑动提取边缘、纹理等特征。就像用不同的滤镜扫描图片滤镜不同提取的特征也不同。2. 池化层这一层会主动丢弃部分细节信息例如最大池化只保留区域内的最强信号。从安全角度看丢弃的信息可能成为潜在的攻击面。3. 全连接层最后所有特征被展平通过全连接层给出最终判断。我的一个粗浅理解是CNN的决策过程是一个从原始像素到抽象概念的连续“压缩”过程压缩必然带来信息丢失这些丢失的信息就可能成为攻击的突破口。二、攻击者的视角尝试让CNN“失明”我的实验目标是给输入数据添加人眼难以察觉的微小扰动让模型输出完全错误的结果。我使用的经典方法是基于梯度的对抗样本攻击——FGSM快速梯度符号法。它的核心公式是adv_x x ε * sign(∇x J(θ, x, y))沿着损失函数对输入图像的梯度方向走一小步ε让损失变大模型预测就可能会出错。实验环境与设备情况下面的代码是在一台普通笔记本上运行的配置不高没有独立显卡。为了节省时间我只训练了3个epoch模型精度有限但足够演示攻击效果。原本想截取训练过程中的loss曲线图但运行时为了截图导致系统卡死图片没保存下来所以文中只放了最终结果的截图——这也算是一个小插曲吧。攻击代码实战TensorFlow/Keras我使用MNIST手写数字数据集先训练一个简单的CNN然后生成对抗样本进行攻击。import tensorflow as tf import numpy as np import matplotlib.pyplot as plt # 1. 加载并预处理数据 (x_train, y_train), (x_test, y_test) tf.keras.datasets.mnist.load_data() x_train, x_test x_train / 255.0, x_test / 255.0 x_train x_train[..., tf.newaxis] x_test x_test[..., tf.newaxis] # 2. 训练一个简单的CNN靶机 model tf.keras.models.Sequential([ tf.keras.layers.Conv2D(32, (3,3), activationrelu, input_shape(28,28,1)), tf.keras.layers.MaxPooling2D((2,2)), tf.keras.layers.Conv2D(64, (3,3), activationrelu), tf.keras.layers.MaxPooling2D((2,2)), tf.keras.layers.Flatten(), tf.keras.layers.Dense(64, activationrelu), tf.keras.layers.Dense(10, activationsoftmax) ]) model.compile(optimizeradam, losssparse_categorical_crossentropy, metrics[accuracy]) model.fit(x_train, y_train, epochs3, batch_size64) # 3. FGSM攻击函数 def fgsm_attack(image, epsilon, gradient): signed_grad tf.sign(gradient) perturbed_image image epsilon * signed_grad perturbed_image tf.clip_by_value(perturbed_image, 0, 1) return perturbed_image # 4. 生成对抗样本 def generate_adversarial(model, image, label, epsilon): image tf.convert_to_tensor(image.reshape((1,28,28,1))) with tf.GradientTape() as tape: tape.watch(image) prediction model(image) loss tf.keras.losses.sparse_categorical_crossentropy(label, prediction) gradient tape.gradient(loss, image) adversarial_image fgsm_attack(image, epsilon, gradient) return adversarial_image.numpy().squeeze() # 5. 取一张测试图片进行攻击 test_idx 1 original_img x_test[test_idx] true_label y_test[test_idx] pred_orig model.predict(original_img.reshape(1,28,28,1)).argmax() print(f原始预测: {pred_orig}, 真实标签: {true_label}) epsilon 0.1 adv_img generate_adversarial(model, original_img, true_label, epsilon) pred_adv model.predict(adv_img.reshape(1,28,28,1)).argmax() print(f对抗样本预测: {pred_adv}, 真实标签: {true_label}) plt.figure(figsize(8,3)) plt.subplot(1,2,1) plt.title(fOriginal (pred:{pred_orig})) plt.imshow(original_img.squeeze(), cmapgray) plt.subplot(1,2,2) plt.title(fAdversarial (pred:{pred_adv})) plt.imshow(adv_img.squeeze(), cmapgray) plt.show()实验结果人眼几乎看不出两张图片的区别但CNN已经将对抗样本识别成了完全不同的数字。这个结果让我挺意外的原来AI的视觉系统并没有想象中那么可靠。一些进一步的思考不完全抛砖引玉· 如果拿不到梯度黑盒场景还能攻击吗我了解到的有迁移攻击、查询攻击等方式但还没深入实践。· 扰动能更隐蔽吗应该有CW攻击、DeepFool等更精细的方法。· 物理世界攻击把生成的扰动打印出来贴在路牌上自动驾驶的CNN会犯错吗——这可能是更接近现实的威胁场景。这些我暂时只停留在理论层面欢迎大佬指点。三、从攻击到防御如何提高CNN的鲁棒性既然知道了攻击的原理自然就想尝试一下如何防御。以下是我尝试过的几种方法效果不一。1. 对抗训练Adversarial Training把生成的对抗样本混入训练集让模型学习识别它们提高鲁棒性。这是目前工业界常用的手段但缺点是可能会降低模型在干净样本上的精度。2. 梯度掩蔽Gradient Masking通过不可微的操作如JPEG压缩让梯度无法准确计算增加攻击难度。不过高级攻击者可能通过BPDA等技术绕过所以不是万能的。3. 输入预处理与检测在模型前加一个检测层判断输入是否带有对抗扰动实时拦截。这些防御手段我还在学习中目前只是跑通了基本流程效果还有待验证。四、后续学习方向这篇文章只是我的一个起点。在未来我希望能把CNN攻防的思想延伸到更广泛的AI安全领域· 多模态模型攻击对视觉语言大模型注入伪装指令· 联邦学习投毒在分布式训练中注入恶意数据使模型产生后门· AI驱动的免杀用生成模型实时改变恶意代码特征学习资源推荐我自己也在看· 书籍《对抗机器学习》中文译本、《AI安全之对抗样本入门》· 实战平台Kaggle上的对抗样本竞赛、阿里云天池AI安全赛道· 学术会议USENIX Security、IEEE SP上最新的AI安全论文结语通过这次实践我深刻体会到只有亲手攻破过模型才知道如何更好地防御它。每一次攻击实验都加深了我对防御策略的理解。这篇文章是我的学习笔记代码虽然经过了测试但因为个人水平有限肯定存在不少疏漏。欢迎各位在评论区指正也希望能和更多对这个方向感兴趣的朋友交流。---作者注本文所有技术内容仅供在受控环境下的授权安全研究与学习使用任何未授权的攻击行为均属违法。