通常情况下检测任务是整个算法解决方案的一个前置模型,通过检测车辆,行人,交通指示牌等目标,再对感兴趣的目标区域进行级联任务的后续处理。因此关于此次智慧交通项目,首先是完成一个车辆检测模型的训练与部署测试,作为后续对抗攻击与对抗防御、AI安全业务功能以及告警提示等任务的目标。
具体见项目代码中的Lesson3_code,详细讲解可见训练营笔记:AidLux智慧交通AI安全实战训练营3--车辆检测模型训练及部署教程。
对抗攻击(adversarial attack)是AI安全方向的重要分支,其核心逻辑是在数据中增加一些微小扰动,在人类视觉系统无法察觉的情况下,使得算法模型对这些数据产生误判。其中被增加扰动的数据也称为对抗样本。
下面是训练营笔记中的例子:
下面是一些使用PGD攻击算法得到的例子:
具体的对抗攻击代码在Lesson4_code/attack_code.py中,包括更详细的讲解见笔记:AidLux智慧交通AI安全实战训练营4--AI对抗攻击&防御实践及部署教程。主要代码如下:
### 常规模型加载,mobilenet_v2为正常的图像分类模型
model = mobilenet_v2(weights=None)
model_param = torch.load(
'/intelligent_transportation/Lesson4_code/model/mobilenet_v2-b0353104.pth'
)
model.load_state_dict(model_param) # 预训练图像分类模型加载
model.eval()
model = nn.Sequential(normalize, model)
model = model.to(device)
### 数据预处理
np_img = get_image() # 读取数据
img = torch.tensor(bhwc2bchw(np_img))[None, :, :, :].float().to(device)
imagenet_label2classname = ImageNetClassNameLookup()
### 测试模型输出结果
pred = imagenet_label2classname(predict_from_logits(model(img)))
print("test output:", pred)
### 输出原label
pred_label = predict_from_logits(model(img))
### 对抗攻击:PGD攻击算法
adversary = LinfPGDAttack(
model, eps=8 / 255, eps_iter=2 / 255, nb_iter=80,
rand_init=True)
### 完成攻击,输出对抗样本
advimg = adversary.perturb(img, pred_label)
### 展示源图片,对抗扰动,对抗样本以及模型的输出结果
show_images(model, img, advimg)
上面代码使用的对抗攻击算法为PGD攻击算法。
在对抗攻击技术出现之后,对抗防御技术也孕育而生。对抗防御一般针对对抗攻击技术而展开,有针对特定攻击的特定防御,也有一般性防御策略。详细对抗防御代码见Lesson4_code/defense_code.py,更多的对抗防御方法及展示见笔记。主要代码如下:
### 常规模型+GCM模块 加载
model_defense = Model().eval().to(device)
### 数据预处理
np_img = get_image()
img = torch.tensor(bhwc2bchw(np_img))[None, :, :, :].float().to(device)
imagenet_label2classname = ImageNetClassNameLookup()
### 测试模型输出结果
pred_defense = imagenet_label2classname(predict_from_logits(model_defense(img)))
print("test output:", pred_defense)
pre_label = predict_from_logits(model_defense(img))
### 对抗攻击:PGD攻击算法,使用攻击算法攻击GCM防御模型
adversary = LinfPGDAttack(
model_defense, eps=8 / 255, eps_iter=2 / 255, nb_iter=80,
rand_init=True, targeted=False)
### 完成攻击,输出对抗样本
advimg = adversary.perturb(img, pre_label)
### 展示源图片,对抗扰动,对抗样本以及模型的输出结果
show_images(model_defense, img, advimg)
上面的对抗防御算法使用的是GCM防御算法。
车辆检测任务前面已经讲过,具体的车辆检测模型是YOLOv5,训练和部署过程均在笔记中。在原始图像中完成车辆目标框的开框定后,需要将咱们的感兴趣区域即车辆目标框提取出来,效果如下:
车辆区域提取代码在Lesson5_code/yolov5_extract.py中,具体车辆区域提取功能实现代码如下:
def extract_detect_res(img, all_boxes, image_name, save_folder=None):
'''
检测结果提取
'''
assert save_folder != None, '请输入保存地址!'
img = img.astype(np.uint8)
color_step = int(255/len(all_boxes))
img_name_lst = []
for bi in range(len(all_boxes)):
if len(all_boxes[bi]) == 0:
continue
count = 0
for box in all_boxes[bi]:
x, y, w, h = [int(t) for t in box[:4]]
#cv2.putText(img, f'{coco_class[bi]}', (x, y), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 2)
#cv2.rectangle(img, (x,y), (x+w, y+h),(0, bi*color_step, 255-bi*color_step),thickness = 2)
cut_img = img[y:(y+h), x:(x + w)]
cv2.imwrite(f'{save_folder}' \
+ image_name + "_" + str(count) + ".jpg",cut_img)
img_name_lst.append(image_name + "_" + str(count) + ".jpg")
count += 1
# cvs.imshow(cut_img)
return img_name_lst
有了车辆区域后,就可以模拟真实的场景,模拟外部用户对模型进行攻击,使得模型识别的能力出现错乱。这里使用基于迁移的黑盒攻击,通过攻击算法生成车辆区域对抗样本,最后将对抗样本给到常规的识别模型即可完成攻击,具体的生成车辆区域对抗样本的代码见Lesson5_code/adv_code/black_attack.py,其中主要代码如下:
### 常规模型加载
# model = mobilenet_v2(pretrained=True)
model = mobilenet_v2(pretrained=None)
pretrain_param = torch.load('/home/intelligent_transportation/Lesson5_code/model/mobilenet_v2-b0353104.pth')
model.load_state_dict(pretrain_param)
model.eval()
model = nn.Sequential(normalize, model)
model = model.to(device)
### 替身模型加载
# model_su = resnet18(pretrained=True)
model_su = resnet18(pretrained=False)
resnet18_param = torch.load('/home/intelligent_transportation/Lesson5_code/model/resnet18-5c106cde.pth')
model_su.load_state_dict(resnet18_param)
model_su.eval()
model_su = nn.Sequential(normalize, model_su)
model_su = model_su.to(device)
### 对抗攻击:PGD攻击算法
# adversary = LinfPGDAttack(
# model_su, eps=8/255, eps_iter=2/255, nb_iter=80,
# rand_init=True, targeted=False)
adversary = FGSM(
model_su, eps=8/255, eps_iter=2/255, nb_iter=80,
rand_init=True, targeted=False
)
from pathlib import Path
src_img_path = Path('/home/intelligent_transportation/Lesson5_code/adv_code/orig_images')
img_path_lst = [p for p in src_img_path.rglob('*') if p.name.endswith('.jpg')]
for i, img_path in enumerate(img_path_lst):
print(img_path)
### 数据预处理
np_img = get_image(img_path=img_path)
img = torch.tensor(bhwc2bchw(np_img))[None, :, :, :].float().to(device)
imagenet_label2classname = ImageNetClassNameLookup()
### 测试模型输出结果
pred = imagenet_label2classname(predict_from_logits(model(img)))
print("test output:", pred)
### 输出原label
pred_label = predict_from_logits(model_su(img))
# 使用替身模型的相关信息进行对抗样本的获取
# 这包括替身模型的参数、输出label
### 完成攻击,输出对抗样本
advimg = adversary.perturb(img, pred_label)
### 展示源图片,对抗扰动,对抗样本以及模型的输出结果
show_images(model, img, advimg, img_name=f'show_{int(i)}_{pred}.png')
### 迁移攻击样本保存
save_path = "/home/intelligent_transportation/Lesson5_code/adv_code/adv_results/"
torchvision.utils.save_image(advimg.cpu().data, save_path + f"adv_image_{int(i)}_{pred}.png")
此处的逻辑为:将车辆目标区域输入对抗攻击监测模型,注意,此时的车辆目标区域可能是正常样本也可能是对抗攻击样本,因此需要先一步通过监测模型进行监测。在完成对车辆目标区域的监测后,如果监测模型认为当前车辆区域为正常样本,则将其输入常规识别模型中对其进行识别,将识别出的车辆信息输入后续任务流程,而如果监测模型认为当前车辆区域为对抗攻击模型,则停止当前样本的后续业务流程,并通过喵提醒告警存在对抗风险。
对抗攻击监测+常规识别模型识别+喵提醒的实现代码在Lesson5_code/adv_code/detect_adv_code.py中,主要代码如下:
model = Model().eval().to(device) # 常规识别模型
detect_model = Detect_Model().eval().to(device) # 对抗攻击监测模型
if __name__ == '__main__':
from pathlib import Path
src_img_path = Path('/home/intelligent_transportation/Lesson5_code/adv_code/orig_images/')
# img_path_lst = [p for p in src_img_path.rglob('*') if p.name.split('_')[0] == 'adv']
img_path_lst = [p for p in src_img_path.rglob('*') if p.name.endswith('jpg')]
for img_path in img_path_lst:
print('=' * 60)
print(img_path.name)
np_img = get_image(img_path) # 读取车辆目标区域
img = torch.tensor(bhwc2bchw(np_img))[None, :, :, :].float().to(device) # 数据预处理
imagenet_label2classname = ImageNetClassNameLookup()
### 对抗攻击监测
detect_pred = detect_model(img) # 对车辆目标区域进行监测
print(detect_pred)
if detect_pred > 0.5: # 当监测模型认为其为对抗攻击样本时,通过喵提醒进行告警,并停止后续任务流程
id = 'tHyzzn1'
# 填写喵提醒中,发送的消息,这里放上前面提到的图片外链
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'}
result = requests.post(request_url + "id=" + id + "&text=" + text + "&ts=" + ts + "&type=" + type,
headers=headers)
print('存在对抗攻击风险!')
else: # 若监测模型认为当前样本为正常样本,则通过常规识别模型对其进行车辆识别
pred = imagenet_label2classname(predict_from_logits(model(img)))
print('=' * 60)
print('result: ', pred)
将上述各个部分进行串联,具体串联后的代码见Lesson5_code/app_main.py,其中主要代码如下:
if __name__ == '__main__':
# 车辆检测
# AidLite初始化:调用AidLite进行AI模型的加载与推理,需导入aidlite
aidlite = aidlite_gpu.aidlite()
# Aidlite模型路径
model_path = '/home/intelligent_transportation/Lesson5_code/yolov5_code/aidlux/yolov5_car_best-fp16.tflite'
# 定义输入输出shape
in_shape = [1 * 640 * 640 * 3 * 4]
out_shape = [1 * 25200 * 6 * 4]
# 加载Aidlite检测模型:支持tflite, tnn, mnn, ms, nb格式的模型加载
aidlite.ANNModel(model_path, in_shape, out_shape, 4, 0)
imgs_path = "/home/intelligent_transportation/Lesson5_code/yolov5_code/data/images/tests"
# 设置测试集路径
images_lst = os.listdir(imgs_path)
images_lst = [p for p in images_lst if p.endswith('jpg') or p.endswith('png')]
print(images_lst)
# extract_res: frame_lst, pred_lst, images_lst
extract_res = extract_car_img(imgs_path, images_lst)
# 检测框提取
save_folder = "/home/intelligent_transportation/Lesson5_code/yolov5_code/aidlux/extract_results/"
# 图片裁剪,提取车辆目标区域
car_img_name_lst = []
for frame, pred, img_name in zip(*extract_res):
img_name_lst = extract_detect_res(frame, pred, img_name, save_folder)
car_img_name_lst.extend(img_name_lst)
assert car_img_name_lst != [], '没有提取到车辆框!'
# 使用对抗样本
### 替身模型加载
normalize = NormalizeByChannelMeanStd(
mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
# model_su = resnet18(pretrained=True)
model_su = resnet18(pretrained=False)
resnet18_param = torch.load('/home/intelligent_transportation/Lesson5_code/model/resnet18-5c106cde.pth')
model_su.load_state_dict(resnet18_param)
model_su.eval()
model_su = nn.Sequential(normalize, model_su)
model_su = model_su.to(device)
### 对抗攻击:PGD攻击算法
# adversary = LinfPGDAttack(
# model_su, eps=8/255, eps_iter=2/255, nb_iter=80,
# rand_init=True, targeted=False)
adversary = FGSM(
model_su, eps=8/255, targeted=False
)
use_advimg = False
print(f'是否使用对抗样本: {use_advimg}...')
print('车辆框信息:', car_img_name_lst)
img_res = []
for i, img_name in enumerate(car_img_name_lst):
print(img_name)
img_path = save_folder + img_name
if use_advimg:
advimg, advimg_path = get_advimg(img_path)
img_res.append(advimg)
else:
np_img = get_image(img_path)
img = torch.tensor(bhwc2bchw(np_img))[None, :, :, :].float().to(device)
img_res.append(img)
# AI安全监测与告警
model = Model().eval().to(device)
detect_model = Detect_Model().eval().to(device)
imagenet_label2classname = ImageNetClassNameLookup()
for img in img_res:
### 对抗攻击监测
print(img.size())
detect_pred = detect_model(img)
print(detect_pred)
if detect_pred > 0.5:
id = 'tHyzzn1'
# 填写喵提醒中,发送的消息,这里放上前面提到的图片外链
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'}
result = requests.post(request_url + "id=" + id + "&text=" + text + "&ts=" + ts + "&type=" + type,
headers=headers)
print('存在对抗攻击风险!')
else:
pred = imagenet_label2classname(predict_from_logits(model(img)))
print('=' * 60)
print('result: ', pred)
测试图片在Lesson5_code/yolov5_code/data/images/tests中,对tests中的所有图片进行车辆检测和目标区域提取后,后续通过监测模型对所有车辆目标区域进行监测,若正常则进行车辆识别,若不正常则告警。测试结果如下:
AI训练营测试素材测试结果展示:
测试视频测试结果:
aidlux智慧交通项目测试视频
本次训练营的主题为智慧交通,第一期智慧城市的训练营我也参加了,一如既往的内容丰富,解答翔实。