本文进行了AI安全对抗攻防实践,并在安卓手机上利用Aidlux软件进行部署测试。
总结于:https://mp.weixin.qq.com/s/a_xLMPyi7ST-ZTKC3Vxksg
AI项目开发与部署
开发流程
通常来说AI项目开发的流程主要分为一下几个部分:
- 明确场景,用户需求,获取数据
这是算法解决方案的起始,也是最关键的部分。业务场景定义机器学习问题,数据侧不断逼近这个机器学习问题的真实分布,而用户需求则指明了切入点和优化方向。
在车辆属性识别项目中,首先需要确定场景,是十字路口,卡口,出入口还是停车场,在确定场景后,再沟通需求,比如哪些车辆属性是用户的核心需求,场景中的亮度,数据源(摄像头)获取的图像的清晰程度,是否存在大角度的目标,场景中的流量复杂程度等。完成需求定义与评估后,接着现场采集数据、数据标注、数据清洗校验等工作。
- 算法训练&部署
有了数据,再选用合适的算法模型,进行训练和优化。
在车辆属性识别项目中,其底层主要是车辆检测、AI安全模块、车系识别、车牌识别、驾驶员行为识别等一系列AI算法功能组成。
完成模型训练后进行部署,包括模型转换,模型量化,模型与平台适配等工作。
- 部门协作&多模块集成
最后开展协同工作,将多模块的算法功能与配套功能结合,形成完整的解决方案。
部署方式
模型部署方面,主要有三种形式:线上部署,嵌入式部署,docker交付
对于智慧交通场景,一般都是通过端侧设备的算力来支持AI算法的运行分析,所以这里主要对嵌入式部署进行介绍
- 嵌入式部署
嵌入式部署也叫端侧部署,主要分为硬件/芯片部署与离线APP两种形式。其硬件由ARM架构的CPU + GPU/TPU/NPU等协处理器 + 整体功耗 + 外围接口 + 工具链等部分组成。可能接触到的硬件侧知识有:硬件性能评估,模型转换,硬件侧验证,视频编解码,模型推理加速,Opencv,FFmpeg,Tensor RT等。
- 硬件/芯片部署
算法模型的嵌入式部署路径为:算法模型训练、图片量化校准、转换模型、精度测试
嵌入式部署一般需要对模型量化操作来优化模型,训练出来的模型是FP32(32位浮点,单精度)的;而低精度主要有两种:FP16(半精度浮点)和INT8(8位定点整数)。目前主流模型部署框架量化后的低精度一般是INT8,保证网络精度的基础上,大幅减少功耗,内存,传输延迟,大幅提高模型推理速度。通常,使用Caffe框架训练模型并进行部署,是硬件/芯片端部署的最友好的方式。Caffe有原生C环境,与硬件平台的兼容性很好,而其他框架则需要使用特定的转换工具进行模型转换才能在特定的平台上运行。
实际场景中,在高性能端侧设备上能直接使用FP32的模型进行部署,而在低性能端侧设备上使用低精度FP8的模型进行部署。精度转换后肯能存在进度变差的情况,所以要将转换后的低精度模型重新测试验证性能。
图片量化校准是指,在校准数据集上进行FP32推理,每个网络层都寻找INT8精度下的最优参数,最后从量化工具中输出INT8模型。
- 离线APP
与硬件/芯片部署主要不同在于载体,离线APP主要在手机端应用,即使用相应的手机部署框架来进行模型转换。手机端CPU芯片一般是基于ARM架构的,最基础和可靠的方案就是基于CPU完成神经网络推理任务。也可以用AI处理器进行网络推理,功耗得到保证的同时计算速度也会比CPU快很多。
而在带GPU的嵌入式端,也就是GPU盒子,使用可以CUDA加速的框架就能较好的部署,这也是最为方便的一种硬件部署方式。手机端,则需要使用专门的轻量级框架。
总的来说,端侧设备的选型与性能评估也很重要,在业务中,比如需要考虑:
- 算法模型与端侧设备的适配性兼容性,端侧设备是否兼容一些特殊的网络结构?
- 模型转换部署后的精度是否下降?功耗与耗时是否达标?
Aidlux
Aidlux是基于ARM架构的跨生态(Android/鸿蒙+Linux)一站式AIOT应用开发平台。
通常来说编写训练模型,测试模型的时候,用的是 Linux/window系统。而实际现场应用的时候是嵌入式设备(比如Android手机、人脸识别闸机,摄像头等)、边缘设备。Android 嵌入式设备的底层芯片,通常是ARM架构。而Linux底层也是ARM架构,并且Android又是基于Linux内核开发的操作系统,两者可以共享Linux内核。因此基于ARM芯片开发的Aidlux平台,就带来了原生Android和原生Linux的使用体验。即使用Aidlux平台后,Linux上开发的Python代码,可以在安卓手机、边缘设备上转换后无缝使用。
本文就使用平板/手机 + Aidlux软件 + 电脑的形式来开展实践。Aidlux软件可以在各大安卓应用商店中找到并下载,它提供了一个可以在安卓手机/平板上开发和部署的环境,并且内置了各种AI案例参考,这个环境和现实中的边缘计算设备基本一致。
智慧交通概述
业务场景
- 行人识别
行人姿态、方向、外观,以及基于行人的交通事件识别分析,如闯红灯等。
- 机动车识别
对机动车外形,颜色,车灯,车窗驾驶员安全事件分析,比如是否在打电话,是否系安全带;车牌,车辆方向以及基于机动车的交通事件识别分析,如超速,违停等。
- 非机动车识别
对非机动车的运动状态识别,驾驶员安全事件分析,如是否带头盔等;基于非机动车的交通事件识别分析,比如非机动车闯红灯等。
智慧交通场景划分主要有:十字路口,交通卡口,交通出入口,停车场等
算法划分
不同的场景有不同的业务功能,对应了不同的算法技术,比如目标检测,图像分割,图像分类,目标追踪,OCR识别等。针对不同的需求,将引用场景、AI算法功能、AI算法模型三者进行有机结合构成解决方法。
- 车辆识别
对于车辆识别功能,其底层的算法技术主要是车辆检测+车牌检测+车牌字符识别+业务功能判断等组成。这里的业务功能包括车辆框矫正、车牌框矫正、车牌字符后处理等逻辑。
- 行人识别
行人识别的底层算法功能主要是行人检测+人脸检测+行人重识别等组成。
- 车辆属性识别
车辆属性识别的底层算法主要是车辆检测+车标识别+车系识别+驾驶员行为识别等组成。
- 交通事件检测
交通事件检测功能更为复杂,需要大量的交通规则作为约束,并且在检测机动车,行人以及非机动车的同时,要准确的感知当前的背景环境条件。比如交通指示牌,道路指示线等对交通事件的判定进行支持。其细分功能包含行人闯红灯、车辆闯红灯、机动车超速、超时停车、机动车违停等。
AI安全
安全风险
在智慧交通场景中,目标检测是AI项目的前置任务。车辆识别,车辆属性识别,交通事件判定,交通执法判定,行人识别等智慧交通中的复合任务都需要对感兴趣目标区域进行检测提取后才能接着进行后续算法流程,而在这些复合任务流程中,对抗攻击能够让AI模型产生误判,可能引发严重的安全风险。
- 交通指示牌对抗攻击
对指示牌进行类似风格迁移的攻击,可以使得自动驾驶系统对STOP交通指示牌出现误判,从而引发出严重的交通风险。
- 人体检测对抗攻击
在人体前放置一个对抗攻击算法特定生成的图画,便能对人体检测模型的性能产生较大的影响,从而无法对人体做出准确的检测。
智慧交通中的摄像头设备,也会接收到类似的对抗样本并将其作为后续算法功能的输入,从而导致算法解决方案中某一环失效。
- 图像分类对抗
图像分类算法是AI项目最基础的基石,然而攻击算法生成的对抗样本会让目前主流的分类器出现明显的误分类。
针对这些安全风险,需要设计使用一些安全防御策略,比如对抗样本监测,黑盒攻击防御,白盒攻击防御等,尽可能来防范可能存在的安全风险。
- 数据偏见
除了对抗算法生成的样本,若数据中存在偏见歧视,AI项目很可能形成偏见的智能决策。
比如卡口场景,一般都是机动车,非机动车等车辆目标,可能会在行人相关的项目功能出现偏见决策(行人漏检);而在非机动车项目中,外卖骑手的流量远远大于其他自行车,三轮车,家用电动车等非机动车,这样的场景采集的数据必然会存在偏见。
AI安全技术
AI安全技术主要包含了安全性,可解释性,公平性以及隐私保护等方面
- 安全性
AI系统面临着很多特有的干扰,主要是针对数据和系统的攻击,比如中毒攻击,对抗攻击,后门攻击等。
中毒攻击是通过向训练数据投入干扰数据,从而影响AI模型的指标。其多发生在新数据并入训练集的阶段,扰乱数据分布,往往难以察觉。比如交通卡口场景下的交通事件识别,随着交通事件类别的不断丰富,数据量不断增加,AI功能效果也会不断提升。而在这个过程中,如果有攻击者将特意制作的干扰样本持续注入新数据流中(例如行人特征混淆,机动车细分类别混淆等),在模型侧进行训练的时候就会存在中毒的风险。
对抗攻击主要是通过制造对抗样本,让AI模型产生错判,从而导致严重的后果。在上一栏安全风险中已经介绍了对抗攻击的几种案例,这里再举一个案例。比如下图中,攻击者使用一个精心制作的对抗眼镜,就能使得人脸系统对人脸ID出现误判。
后门攻击,具有很强的隐蔽性,主要是通过AI模型植入后门,进而对AI系统进行操控,在一些安全要求很高的任务上比如自动驾驶,可能会带来严重的后果。植入后门模型通常和干净模型表现一样正常,无法仅通过验证测试样本的准确性来区分是否植入后门,当秘密触发器Trigger(只有攻击者知道)出现在输入中时,后门模型就会被错误引导去执行攻击者的子任务,比如输出分类为攻击者指定的目标类别。
针对这些攻击,很多工作提出了各种不同的方法,比如设计异常数据检测方法来检测并清除中毒样本,对抗样本,后门样本等攻击性样本;再比如,设计对抗攻击检测技术来避免在线的对抗攻击;或者使用对抗训练,预处理后处理等技术防御对抗样本;通过模型结构鲁棒性设计,模型剪枝,门后检测等技术抵御后门攻击。
- 可解释性
针对AI模型可解释弱的问题,一种方法是建立可视化机制和解释模型的中间态来缓解。比如Grad-CAM分析模型的注意力机制
- 隐私保护
针对隐私保护的问题,最常用的是基于差分隐私和基于联邦学习的隐私保护策略,甚至将联邦学习和差分隐私相结合,来构建隐私保护能力更强的AI系统。
差分隐私主要通过随机算法对数据加上一些扰动,避免攻击者分辨出任何具体的隐私或者敏感信息。联邦学习的目标是在保证数据隐私安全及合法合规的基础上,实现数据本地保存,模型线上联合训练,提升AI模型的效果,并一定程度上解决了数据孤岛问题。
联邦学习概念的漫画图解: https://rockyding.blog.csdn.net/article/details/103162649
- 公平性
公平性问题,主要是受类别不均衡的数据集影响,训练出的模型出现偏见决策。解决办法就是构建完整的异构数据集,并对数据集进行定期检查与维护,设计删除敏感信息或者不同采样方法等预处理手段来降低数据的偏差。
数据策略
上一小结介绍了一些AI安全技术的应用,提升AI项目安全的途径有很多,可以出数据、预处理、模型本身、后处理等方面入手。从AI算法的角度来说,数据是非常关键的因素。这里将介绍用“以数据为中心”的鲁棒机器学习策略来提升模型的准确性与安全性。
在许多AI场景中,模型及训练不会是业务业务中的难点,实际瓶颈往往在与如何获取、开发所需要的数据。而高价值数据采集获取的成本非常高,难度非常大,如何在拥有一定量高质量数据的情况下,通过科学的方法让网络学习到我们想让它学习的东西。
可以考虑的策略包括,数据标注纠偏纠错,对数据子集进行优化,合成特定的数据,特定数据增强,标签细化,多模态融合等。比如通过GAN生成模型合成一些长尾数据,包括特种车辆,稀有车牌,稀有车型等数据来支持细分领域的算法功能优化。在数据量级不大的情况下,不断优化数据,生成高质量数据,提供能支持模型优化bad case的数据。
攻防对抗
对抗攻击
对抗攻击的核心逻辑是在数据中增加一些微小的扰动,在人类视觉系统无法察觉的情况下,使得算法模型对这些数据产生误判,而这种被增加扰动的数据就称为对抗样本。下图就是在熊猫图片中加入微小的对抗噪声,就让模型将其误判为长臂猿。对抗样本可以理解为作为噪声的艺术,其攻击的底层依托是算法模型的过拟合问题。
而对于防御者来说,最直接的防御方式就是对抗训练,在训练集中加入对抗样本一起训练,可以在扩充训练集的同时,使得数据集逼近想要的数据分布,训练后的模型鲁棒性和泛化性也大大增强。
对抗攻击算法
- 白盒攻击
当算法模型和训练数据等信息被攻击者掌握,并在此基础上进行针对性的攻击,称为白盒攻击。
- FGSM算法
FGSM是第一个使用模型梯度信息来对抗攻击的算法。原理是增大模型对输入数据的loss,通过原图+梯度信息->更新图像的步骤来实现:
- PGD算法
PGD算法是FGSM算法的一个优化版本。在FGSM的基础上引入了迭代攻击的思想,将多次攻击后的数据作为最终的对抗样本。
- Deepfool算法
Deepfool攻击算法是基于超平面分类的攻击方法,其通过迭代计算的方法生成最小规范对抗扰动,将位于分类边界的图像逐步推到边界外,直到出现错误预测。
- 基于GAN的攻击
AdyGAN将GAN思想引入对抗,通过生成器生成对抗扰动,添加到干净样本中。而判别器主要负责判别输入的是对抗样本还是干净样本,将整个对抗训练过程转化为GAN经典博弈过程。
- 黑盒攻击
在对算法模型的结构和参数一无所知甚至相关训练数据也一无所知的情况下,进行攻击的过程,称为黑盒攻击。
- 基于迁移的攻击
主要由白盒攻击扩展,通过对白盒攻击生成的对抗样本,一般对不同的算法模型具备一定的迁移攻击性。
- 基于查询的攻击
基于查询的对抗攻击首先设定一个搜索空间,并通过不断的查询模型的输出来优化对抗扰动。
更多攻击算法的介绍可以查阅以下的相关材料:
https://zhuanlan.zhihu.com/p/493333024
AI对抗防御算法
目前主流的对抗防御有:
- 对抗训练是指在训练过程中加入对抗样本,通过不断的学习对抗样本的特征,从而提高模型的鲁棒性。
- 检测识别,顾名思义就是在项目关键节点设置一些能够识别对抗样本的特征模型,从而提前预警对抗攻击风险。
- 模型鲁棒结构设计是指在模型中设计制定的滤波结构能够一定程度上增强模型的鲁棒性,抵御对抗噪声。
- 对抗扰动结构破坏,主要是在数据处理的时候使用,通过一些滤波算法,噪声结构破坏算法,噪声覆盖算法等策略,减弱对抗噪声的影响。
比如在输入图像中添加微小的白噪声,使得对抗样本中本身就十分微小的对抗扰动结构破坏,从而一定程度上消除对抗噪声的影响。
- 梯度掩膜则是在白盒对抗防御中非常高效的一种算法,因为其能掩盖真实梯度,从而能够使得白盒攻击算法失效。
上图就是基于梯度掩膜的GCM模块应用示意图,它通过改造输入,使模型在前向测试时并不影响原来的结果,但是在进行梯度反向传播时,能隐藏原来的梯度,使得白盒攻击无所适从。加入GCM模块后的模型梯度反向传播:
实践
这里使用基于迁移的攻击算法,替身模型为ResNet18,使用PGD攻击算法在替身模型上生成对抗样本,来攻击常规模型MobileNetv2。
- 攻击样本生成
在替身模型ResNet18中,原图被识别为limousineh豪华轿车,而生成的对抗样本被错误识别为joystick操纵杆
- 迁移攻击
在攻击模型MobileNetv2中原图被识别为cab出租车,而该对抗样本同样被误识别为joystick操纵杆
基于替身模型ResNet18进行白盒攻击生成的对抗样本成功在目标模型MobileNetv2上实现攻击效果
- 防御策略
这里采用检测识别的防御策略,在数据流进入AI项目时,前置一个检测模型,这里的监测模型为一个训练好的ResNet50模,判断输入数据是否存在安全风险,如果发现对抗样本,则及时告警并切断后续算法功能。
测试视频演示
这里使用Pytorch原生模型在aidlux部署
结果视频演示【bilibili】
代码部分
from cvs import *
import time
import cv2
import torch
import requests
import aidlite_gpu
import torch.nn as nn
from yolov5_code.aidlux.utils import detect_postprocess, preprocess_img, draw_detect_res, extract_detect_res
from detect_adv_code import Model, Detect_Model
from torchvision.models import mobilenet_v2, resnet18
from advertorch.utils import predict_from_logits
from advertorch_examples.utils import ImageNetClassNameLookup
from advertorch.utils import NormalizeByChannelMeanStd
from advertorch_examples.utils import bhwc2bchw
device = "cuda" if torch.cuda.is_available() else "cpu"
normalize = NormalizeByChannelMeanStd(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
imagenet_label2classname = ImageNetClassNameLookup()
### 分类模型
model = mobilenet_v2(pretrained=True)
model.eval()
model = nn.Sequential(normalize, model)
model = model.to(device)
# 攻击样本监测模型
detect_attack = Detect_Model().eval().to(device)
def miaotx(text):
# 喵提醒id
id = 'tKWj98S'
text = "出现对抗攻击风险!!"
ts = str(time.time())
type = 'json'
request_url = "http://miaotixing.com/trigger?"
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.67 Safari/537.36 Edg/87.0.664.47'}
requests.post(request_url + "id=" + id + "&text=" + text + "&ts=" + ts + "&type=" + type,
headers=headers)
'''获取视频流'''
cap = cvs.VideoCapture("/home/2022.12/Lesson5_code/adv_code/data/test.mp4")
frame_id = 0
while True:
### 获取图像
print('='*50)
print(f'next frame_id:{frame_id}')
frame = cap.read()
if frame is None:
continue
frame_id += 1
### 数据预处理
np_img = preprocess_img(frame, target_shape=(640, 640), div_num=255, means=None, stds=None)
img = torch.tensor(bhwc2bchw(np_img)).float().to(device)
###对抗攻击检测
detect_pred =detect_attack(img).item()
print(f"对抗样本监测:{detect_pred :.2f}")
if detect_pred > 0.5:
txt = "监测到对抗攻击风险!!"
print(txt)
cv2.putText(frame, f'Attack Detected!! {detect_pred :.2f}', (100, 100), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 255), 2)
cvs.imshow(frame)
miaotx(txt)
print('已发送告警信息')
else:
print("数据正常")
cv2.putText(frame, f'Normal', (100, 100), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255, 0, 0), 2)
cvs.imshow(frame)
pred = model(img)
class_name = imagenet_label2classname(predict_from_logits(pred))
print('分类:', class_name)