一、前言
智慧交通行业主要是对交通场景内的行人,机动车,非机动车进行识别分析。然而,就在这些复合任务的流程中,由于特别制作的数据、复杂的黑盒模型、数据偏见、数据滥用等,可能会导致安全性、可解释性、公平性以及隐私等相关AI安全风险。例如在安全性方面,对抗攻击能够让AI模型产生误判,从而可能引发严重的安全风险,此时就需要设计对抗防御的监测模块来降低安全风险。
本文主要以智慧交通中对抗防御监测应用为例,对基于AidLux平台实现的“车辆检测和检测框提取+使用对抗样本+AI安全监测与告警功能”业务应用进行评测。
二、AidLux环境配置
Aidlux是基于ARM架构的跨生态(Android/鸿蒙+Linux)一站式AIOT应用开发平台。将装有Aidlux应用的安卓手机或边缘设备与PC连接,之后就可以进行代码的移植和调试,进而实现应用测试。
如果使用安卓手机,可以从手机应用商店下载相应的Aidlux软件。下载后进行安装、初始化、注册登录,就可进入其图形界面。在图形界面中,可以进入examples中,尝试一系列的 AI 案例。此外,还可以将手机与同一个局域网下的PC连接。首先通过点击图形界面中的Cloud_ip获取其IP地址,然后将电脑的浏览器打开,并输入IP地址和密码aidlux,就可以看到手机上该软件的图形界面在PC端的投影了,随后就可以进入文件管理中,完成文件的上传、下载、修改等操作了。
当需要调试代码时,手机界面的操作不太方便,可以通过电脑端的vscode连接手机进行调试。主要思路是将手机当作一个远程服务器,在PC端通过SSH协议与其进行连接,具体流程参见相关文章:厉害了我的哥:基于AidLux平台的人流统计应用评测、《智慧安防AI实战训练营:边缘端实现越界识别》Lesson2 (qq.com)。
三、车辆检测模型的训练和部署
3.1,下载并整理数据集。使用Kaggle开源的车辆数据集,其网址是: Car Object Detection | Kaggle。将数据标签转换成YOLOv5可以训练的格式,而数据集划分按照9:1的方式进行,即90%是训练集, 10%是验证集。
3.2,使用服务器训练检测模型。下载YOLOv5算法代码,新建car.yaml,修改train.py参数,使用yolov5n的模型权重,修改models/yolov5n.yaml,选用YOLOv5环境镜像。
3.3,PC端车辆检测模型推理测试。Pytorch核心库安装,其他依赖库安装;打开detect_image.py文件,这里主要修改代码中的模型、图片路径、yaml文件。
3.4,Aidlux端模型推理测试。pt模型转换成tflite模型,Aidlux端推理代码编写,代码上传到Aidlux中,远程连接Aidlux软件,推理测试Aidlux端代码。注意,要修改utils.py中标签的类别,coco_class=['car']。
3.5,据增强技术扩展性。为了对训练数据进行增强,优化模型的检测效果和鲁棒性,可以使用数据增强技术进行优化训练。以imgaug为例,包含了color,blur,blend,weather,contrast等数据增强的方式。网址:https://github.com/aleju/imgaug。生成图像如下:
四、对抗攻击和对抗防御测试
4.1,对抗攻击
对抗攻击(adversarial attack)是AI安全方向的重要分支,其核心逻辑是在数据中增加一些微小扰动,在人类视觉系统无法察觉的情况下,使得算法模型对这些数据产生误判。其中被增加扰动的数据也称为对抗样本,可以理解为生成噪声的艺术,其攻击价值的底层依托是算法模型的过拟合问题。
对抗攻击算法可被攻击者和防御者从多个方面应用。目前主流对抗攻击算法包括白盒攻击和黑盒攻击。白盒攻击主要分为基于梯度的攻击,基于优化的攻击以及基于GAN的攻击。黑盒攻击主要分为基于迁移的攻击和基于查询的攻击两大类。
更多攻击算法的介绍可以查阅:Rocky Ding:【CV算法兵器】“晓风残月” ->对抗攻击“兵器”大放送(综述篇)。
4.2,对抗防御
在对抗攻击技术出现之后,对抗防御技术也孕育而生。对抗防御一般针对对抗攻击技术而展开,有针对特定攻击的特定防御,也有一般性防御策略。与对抗攻击结合的形式包括:AI业务的鲁棒性与安全性检查工具;研究对抗攻击,来增强对实际场景中受到的攻击情形的判断力;使用对抗攻击对敏感信息进行隐藏;使用对抗样本在模型训练过程中进行对抗训练。一般性的防御策略有:算法解决方案中加入防御预处理,设计鲁棒模型结构,加入对抗攻击检测模型等方法。
例如,训练轻量级的对抗攻击检测模型,作为算法解决方案的安全模块,在受到攻击风险时,启动防御算法功能。具体原理如下,生成一些对抗样本,并将其和干净样本一同作为训练集,训练一个能够捕捉对抗扰动的二分类模型,并将其作为实际AI项目中的一个前置防御模块。
目前主流对抗防御方法主要有如下几种。1对抗训练是指在训练过程中加入对抗样本,通过不断的学习对抗样本的特征,从而提升模型的鲁棒性。2监测识别对抗样本顾名思义,在项目关键节点处,设置一些能够识别对抗样本的特种模型,从而提前预警对抗攻击风险。3模型鲁棒结构设计是指在模型中设计特定的滤波结构能够一定程度上增强模型鲁棒性,抵御对抗噪声。4对抗扰动结构破坏主要在数据流处理的时候使用,通过一些滤波算法,噪声结构破坏算法,噪声覆盖算法等策略,减弱对抗噪声的影响,使其不能对模型造成攻击。5梯度掩膜则是在白盒对抗防御中非常高效的一种算法,因为其能掩盖真实梯度,从而能够使得白盒攻击算法失效。
4.3,对抗攻击算法效果验证
安装skimage库:
pip install scikit-image -i https://pypi.tuna.tsinghua.edu.cn/simple some-package
pip install torch==1.8.1 -i https://pypi.tuna.tsinghua.edu.cn/simple some-package
pip install torchvision==0.9.1 -i https://pypi.tuna.tsinghua.edu.cn/simple some-package
PC端代码示例:(Lesson4_code\adv_code\attack_code.py)
import os
import torch
import torch.nn as nn
from torchvision.models import mobilenet_v2
from advertorch.utils import predict_from_logits
from advertorch.utils import NormalizeByChannelMeanStd
from advertorch.attacks import LinfPGDAttack
from advertorch_examples.utils import ImageNetClassNameLookup
from advertorch_examples.utils import bhwc2bchw
from advertorch_examples.utils import bchw2bhwc
device = "cuda" if torch.cuda.is_available() else "cpu"
### 读取图片
def get_image():
img_path = os.path.join("./Lesson4_code/adv_code/images", "mountain_bike.png")
img_url = "https://farm1.static.flickr.com/230/524562325_fb0a11d1e1.jpg"
def _load_image():
from skimage.io import imread
return imread(img_path) / 255.
if os.path.exists(img_path):
return _load_image()
else:
import urllib
urllib.request.urlretrieve(img_url, img_path)
return _load_image()
def tensor2npimg(tensor):
return bchw2bhwc(tensor[0].cpu().numpy())
### 展示攻击结果
def show_images(model, img, advimg, enhance=127):
np_advimg = tensor2npimg(advimg)
np_perturb = tensor2npimg(advimg - img)
pred = imagenet_label2classname(predict_from_logits(model(img)))
advpred = imagenet_label2classname(predict_from_logits(model(advimg)))
import matplotlib.pyplot as plt
plt.figure(figsize=(10, 5))
plt.subplot(1, 3, 1)
plt.imshow(np_img)
plt.axis("off")
plt.title("original image\n prediction: {}".format(pred))
plt.subplot(1, 3, 2)
plt.imshow(np_perturb * enhance + 0.5)
plt.axis("off")
plt.title("the perturbation,\n enhanced {} times".format(enhance))
plt.subplot(1, 3, 3)
plt.imshow(np_advimg)
plt.axis("off")
plt.title("perturbed image\n prediction: {}".format(advpred))
plt.show()
normalize = NormalizeByChannelMeanStd(
mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
### 常规模型加载
model = mobilenet_v2(pretrained=True)
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)
如下测试结果,右图中加入对抗扰动,模型把山地车错误判断成三轮车:
4.4,对抗防御算法效果验证
PC端关键代码示例:(Lesson4_code\adv_code\defense_code.py)(在4.3代码中修改替换以下内容)
### GCM模块
robust_mode = GradientConcealment()
### 常规模型+GCM模块
class Model(nn.Module):
def __init__(self, l=290):
super(Model, self).__init__()
self.l = l
self.gcm = GradientConcealment()
# model = resnet18(pretrained=True)
model = mobilenet_v2(pretrained=True)
# pth_path = "/Users/rocky/Desktop/训练营/model/mobilenet_v2-b0353104.pth"
# print(f'Loading pth from {pth_path}')
# state_dict = torch.load(pth_path, map_location='cpu')
# is_strict = False
# if 'model' in state_dict.keys():
# model.load_state_dict(state_dict['model'], strict=is_strict)
# else:
# model.load_state_dict(state_dict, strict=is_strict)
normalize = NormalizeByChannelMeanStd(
mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
self.model = nn.Sequential(normalize, model)
def load_params(self):
pass
def forward(self, x):
x = self.gcm(x)
# x = ResizedPaddingLayer(self.l)(x)
out = self.model(x)
return out
### 常规模型+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)
### 输出原label
pre_label = predict_from_logits(model_defense(img))
如下测试结果,右图中加入对抗扰动,模型判断正确:
4.5,Aidlux端分类模型的部署与效果验证
代码上传。(Lesson4_code/adv_code/aidlux.py)
依赖库安装。
路径修改。
需要注意的是: 由于我们是进行Pytorch原生模型在aidlux部署,运行代码时可能会遇到 OpenBLAS Warning : Detect OpenMP Loop and this application may hang. Please rebuild the library with USE_OPENMP=1 option 这时需要在命令行输入
export OMP_NUM_THREADS=1
五、整体业务功能实现
本节首先介绍了车辆检测和车辆区域提取、黑盒攻击、攻击检测和报警的功能实现方式,最后提供了“车辆检测+对抗攻击+攻击检测+对抗防御+分类模型”整体业务功能的实现代码和效果。其中,本文将攻击与防御注入到检测任务与分类任务的级联点中,完成AI项目的对抗攻防安全功能。
5.1.车俩检测和检测框提取
代码上传。(Lesson5_code/yolov5_code/aidlux/yolov5_extract.py)
我们使用一个函数来提取车辆目标区域,并将其保存至 yolov5_code/aidlux/extract_results文件夹中。函数代码在yolov5_code/aidlux/utils.py中。
运行yolov5_extract.py,得到所有车辆目标的提取图片。
原图和提取图片如下:
5.2.对抗样本的生成和替换
为了模拟“对抗防御监测”的业务应用,同时考虑到代码运行的实时性,本文通过线下方式制造对抗样本,并将车辆检测提取的目标直接用对应的对抗样本替换。
实际中,攻击者一般难以获得算法模型的参数,白盒攻击难以展开。因此,很多攻击者会在使用白盒攻击的基础上,进行迁移攻击,形成基于迁移的黑盒攻击。本文中,假设知道系统方进行车辆分类,但是不知道用的什么分类模型(实际上系统方用的Mobilenetv2),这时攻击者使用一个已有的分类模型 (ResNet18)作为替身模型。使用攻击算法对替身模型进行攻击,这样生成的车辆目标区域对抗样本一定程度上也会使得业务模型产生错误的输出。
PC端代码示例:(Lesson5_code\adv_code\black_attack.py)(在4.3代码中修改替换以下内容)
### 常规模型加载
model = mobilenet_v2(pretrained=True)
model.eval()
model = nn.Sequential(normalize, model)
model = model.to(device)
### 替身模型加载
model_su = resnet18(pretrained=True)
model_su.eval()
model_su = nn.Sequential(normalize, model_su)
model_su = model_su.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_su(img))
### 对抗攻击:PGD攻击算法
adversary = LinfPGDAttack(
model_su, eps=8/255, eps_iter=2/255, nb_iter=80,
rand_init=True, targeted=False)
### 完成攻击,输出对抗样本
advimg = adversary.perturb(img, pred_label)
### 展示源图片,对抗扰动,对抗样本以及模型的输出结果
a_type = 'PGD'
show_images(a_type, model, img, advimg)
### 迁移攻击样本保存
save_path = "./Lesson5_code/adv_code/adv_results/" + img_path.split("/")[-1]
# save_path = r"D:\code\aidlux_Rocky\Lesson5_code\adv_code\adv_results"
torchvision.utils.save_image(advimg.cpu().data, save_path + "_adv_image_"+a_type+".png")
如下测试结果,右图中加入对抗扰动,模型将出租车错误识别为黑天鹅:
5.3. 安全监测和系统告警
黑盒防御策略主要有数据预处理,设计鲁棒性模型结构,使用对抗样本监测模型等方法。本文中使用对抗样本监测模型的形式。对抗攻击监测模型是一个能够捕捉对抗扰动的二分类模型,监测模型的 输入是一张图片,输出则是两个类别,0表示图片是正常图片,1表示图片是具有安全风险的图片。 本文使用了一个已经训练好的基于ResNet50的模型,作为本次训练营的监测模型。
关键代码示例:(Lesson5_code\adv_code\detect_adv_code.py)
### 对抗攻击监测模型
class Detect_Model(nn.Module):
def __init__(self, num_classes=2):
super(Detect_Model, self).__init__()
self.num_classes = num_classes
#model = create_model('mobilenetv3_large_075', pretrained=False, num_classes=num_classes)
model = create_model('resnet50', pretrained=False, num_classes=num_classes)
# self.multi_PreProcess = multi_PreProcess()
pth_path = os.path.join("./Lesson5_code/model", 'track2_resnet50_ANT_best_albation1_64_checkpoint.pth')
#pth_path = os.path.join("./Lesson5_code/model/", "track2_tf_mobilenetv3_large_075_64_checkpoint.pth")
state_dict = torch.load(pth_path, map_location='cpu')
is_strict = False
if 'model' in state_dict.keys():
model.load_state_dict(state_dict['model'], strict=is_strict)
else:
model.load_state_dict(state_dict, strict=is_strict)
normalize = NormalizeByChannelMeanStd(
mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
# self.model = nn.Sequential(normalize, self.multi_PreProcess, model)
self.model = nn.Sequential(normalize, model)
def load_params(self):
pass
def forward(self, x):
# x = x[:,:,32:193,32:193]
# x = F.interpolate(x, size=(224,224), mode="bilinear", align_corners=True)
# x = self.multi_PreProcess.forward(x)
out = self.model(x)
if self.num_classes == 2:
out = out.softmax(1)
#return out[:,1:]
return out[:,1:]
detect_model = Detect_Model().eval().to(device)
### 对抗攻击监测
detect_pred = detect_model(img)
print(detect_pred)
在实际应用中,当检测到AI安全风险时,需要返回告警信息和告警图片。由于没有业务系统,为了更加贴近实际,本文通过微信“喵提醒”的方式实现告警功能。具体步骤为,新建“喵提醒公众号”的账号,修改喵提醒代码测试,设计“对抗攻击监测 + 喵提醒”告警逻辑脚本。
最终实现的功能为,如果被识别为对抗样本,那么使用喵提醒逻辑进行告警,如果被识别为干净样本,则开启后续级联任务的正常流程。
关键代码示例:(Lesson5_code\adv_code\detect_adv_code.py)
if detect_pred > 0.5:
print("出现可疑对抗样本。")
效果验证如下:
5.4. 生成对抗样本的算法扩展和效果展示
第一步,我们先模拟攻击者,生成可以使得业务系统中,车辆分类识别会出现问题的对抗样本。
为了通过不同对抗攻击算法生成对抗样本,PC端关键代码如下:(Lesson5_code\adv_code\black_attack.py)(在5.2代码中修改替换以下内容)
### 对抗攻击:PGD攻击算法
adversary = LinfPGDAttack(
model_su, eps=8/255, eps_iter=2/255, nb_iter=80,
rand_init=True, targeted=False)
# ### 对抗攻击:FGSM攻击算法 (eps = 0.5/255, 2/255, 8/255)S
# adversary = FGSM(
# model_su, eps=8/255,
# targeted=False)
# ### 对抗攻击:L1PGD攻击算法 (eps = 100, 400, 1600)
# adversary = L1PGDAttack(
# model_su, eps=1600, eps_iter=2/255, nb_iter=80,
# rand_init=True, targeted=False)
# ### 对抗攻击:L2PGD攻击算法 (eps = 0.5, 2, 8)
# adversary = L2PGDAttack(
# model_su, eps=8, eps_iter=2/255, nb_iter=80,
# rand_init=True, targeted=False)
# ### 对抗攻击:LinfMomentumIterativeAttack攻击算法 (eps = 0.5/255, 2/255, 8/255)
# adversary = LinfMomentumIterativeAttack(
# model_su, eps=8/255
这里用到的数据,可以从Lesson5_code/adv_code/orig_images中选择。
img_path = "Lesson5_code/adv_code/orig_images/vid_5_27620.jpg_0.jpg"
# img_path = "./Lesson5_code/adv_code/orig_images/vid_5_31560.jpg_0.jpg"
生成图像展示:
第二步,那么如何评判对抗样本的生成是有效果的呢? 这时就需要用到前面4.1中的监督模型ResNet50的模型,针对一张图片,会输出两个类别,正常图片 0,有风险的图片1,从而判断我们生成的对抗样本是否有效果。
比如左面的车辆小图,原本是cab出租车,经过对抗攻击,生成右面的图片后,再输入ResNet50模型 后,如果输出0,则表示对抗样本输出的不成功,没有生成具有安全风险的图片。 如果输出1,则表示对抗样本的制作是成功的,因为生成了具有安全风险的图片了。
对抗检测结果展示:
5.5. 整体业务功能串联
将“车辆检测+检测框提取+使用对抗样本+AI安全监测与告警功能”业务逻辑串联,判断每一个图片中的每一个车辆是正常图片还是有安全风险的图片。 如果是正常图片,就进入后面的车辆分类的判断,如果是有安全风险的图片,则通过喵提醒来进行告警。
首先,我们不进行任何攻击,我们使用Lesson5_code/adv_code/test_images中的 vid_5_31560.jpg,经过YOLOv5输出了图中车辆目标区域,并直接将其输入到后续的监测模型模块和级联分类任务中。
然后,我们在尝试进行对抗攻击,将这些车辆目标图进行对抗攻击,生成相应的对抗样本,由于对抗攻击耗时较久,我们这里不进行在线的攻击,我们直接使用Rocky本地已经生成好的对抗样本将原始的车辆目标图进行替换,对抗样本路径为Lesson5_code/adv_code/adv_results。
相应的脚本如下:(Lesson5_code/main_lxj/main_app.py)
#%%
## 1.车辆检测+检测框小图提取。
# aidlux相关
from cvs import *
import aidlite_gpu
from utils import detect_postprocess, preprocess_img, draw_detect_res, extract_detect_res
import time
import cv2
# AidLite初始化:调用AidLite进行AI模型的加载与推理,需导入aidlite
aidlite = aidlite_gpu.aidlite()
# Aidlite模型路径
model_path = '/home/Lesson5_code/yolov5_code/models/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)
# 读取图片进行推理
# 设置测试集路径
source = "/home/Lesson5_code/yolov5_code/data/images/test1"
images_list = os.listdir(source)
print(images_list)
frame_id = 0
# 读取数据集
for image_name in images_list:
frame_id += 1
print("frame_id:", frame_id)
image_path = os.path.join(source, image_name)
frame = cvs.imread(image_path)
# 预处理
img = preprocess_img(frame, target_shape=(640, 640), div_num=255, means=None, stds=None)
# 数据转换:因为setTensor_Fp32()需要的是float32类型的数据,所以送入的input的数据需为float32,大多数的开发者都会忘记将图像的数据类型转换为float32
aidlite.setInput_Float32(img, 640, 640)
# 模型推理API
aidlite.invoke()
# 读取返回的结果
pred = aidlite.getOutput_Float32(0)
# 数据维度转换
pred = pred.reshape(1, 25200, 6)[0]
# 模型推理后处理
pred = detect_postprocess(pred, frame.shape, [640, 640, 3], conf_thres=0.25, iou_thres=0.45)
# 绘制推理结果
res_img = draw_detect_res(frame, pred)
# cvs.imshow(res_img)
# 测试结果展示停顿
#time.sleep(5)
# 图片裁剪,提取车辆目标区域
extract_detect_res(frame, pred, image_name)
# cvs.imshow(cut_img)
# cap.release()
# cv2.destroyAllWindows()
#%%
# ## 2.使用对抗样本
# from cvs import os
# rec_path = "/home/Lesson5_code/yolov5_code/aidlux/extract_results/"
# recs_list = os.listdir(rec_path)
# print(recs_list)
# ## 使用原样本
# img_path = os.path.join(rec_path, recs_list[1])
# ## 替换对抗样本
# rec_su_path = "/home/Lesson5_code/yolov5_code/aidlux/extract_results_su/"
# recs_su_list = []
# for rec_su in recs_list:
# recs_su_list.append(rec_su.split('.jpg_0.jpg')[0]+'.jpg_0.png')
# img_path = os.path.join(rec_su_path, recs_su_list[1])
#%%
## 3.AI安全监测与告警功能
##
import os
import torch
import requests
import time
import torch.nn as nn
from torchvision.models import mobilenet_v2,resnet18
from advertorch.utils import predict_from_logits
from advertorch.utils import NormalizeByChannelMeanStd
from robust_layer import GradientConcealment, ResizedPaddingLayer
from timm.models import create_model
from advertorch.attacks import LinfPGDAttack
from advertorch_examples.utils import ImageNetClassNameLookup
from advertorch_examples.utils import bhwc2bchw
from advertorch_examples.utils import bchw2bhwc
device = "cuda" if torch.cuda.is_available() else "cpu"
### 读取图片
def get_image(img_path):
# img_path = os.path.join("/home/Lesson5_code/adv_code/adv_results/", "adv_image.png") ## Cars28.png
print('img_path',img_path)
img_url = "https://farm1.static.flickr.com/230/524562325_fb0a11d1e1.jpg"
def _load_image():
from skimage.io import imread
return imread(img_path) / 255.
if os.path.exists(img_path):
return _load_image()
else:
import urllib
urllib.request.urlretrieve(img_url, img_path)
return _load_image()
def tensor2npimg(tensor):
return bchw2bhwc(tensor[0].cpu().numpy())
normalize = NormalizeByChannelMeanStd(
mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
### 常规模型加载
class Model(nn.Module):
def __init__(self, l=290):
super(Model, self).__init__()
self.l = l
self.gcm = GradientConcealment()
#model = resnet18(pretrained=True)
model = mobilenet_v2(pretrained=True)
# pth_path = "/home/Lesson5_code/model/mobilenet_v2-b0353104.pth"
# print(f'Loading pth from {pth_path}')
# state_dict = torch.load(pth_path, map_location='cpu')
# is_strict = False
# if 'model' in state_dict.keys():
# model.load_state_dict(state_dict['model'], strict=is_strict)
# else:
# model.load_state_dict(state_dict, strict=is_strict)
normalize = NormalizeByChannelMeanStd(
mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
self.model = nn.Sequential(normalize, model)
def load_params(self):
pass
def forward(self, x):
#x = self.gcm(x)
#x = ResizedPaddingLayer(self.l)(x)
out = self.model(x)
return out
### 对抗攻击监测模型
class Detect_Model(nn.Module):
def __init__(self, num_classes=2):
super(Detect_Model, self).__init__()
self.num_classes = num_classes
#model = create_model('mobilenetv3_large_075', pretrained=False, num_classes=num_classes)
model = create_model('resnet50', pretrained=False, num_classes=num_classes)
# self.multi_PreProcess = multi_PreProcess()
pth_path = os.path.join("/home/Lesson5_code/model", 'track2_resnet50_ANT_best_albation1_64_checkpoint.pth')
#pth_path = os.path.join("/home/Lesson5_code/model", "track2_tf_mobilenetv3_large_075_64_checkpoint.pth")
state_dict = torch.load(pth_path, map_location='cpu')
is_strict = False
if 'model' in state_dict.keys():
model.load_state_dict(state_dict['model'], strict=is_strict)
else:
model.load_state_dict(state_dict, strict=is_strict)
normalize = NormalizeByChannelMeanStd(
mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
# self.model = nn.Sequential(normalize, self.multi_PreProcess, model)
self.model = nn.Sequential(normalize, model)
def load_params(self):
pass
def forward(self, x):
# x = x[:,:,32:193,32:193]
# x = F.interpolate(x, size=(224,224), mode="bilinear", align_corners=True)
# x = self.multi_PreProcess.forward(x)
out = self.model(x)
if self.num_classes == 2:
out = out.softmax(1)
#return out[:,1:]
return out[:,1:]
def main(img_path):
np_img = get_image(img_path)
img = torch.tensor(bhwc2bchw(np_img))[None, :, :, :].float().to(device)
imagenet_label2classname = ImageNetClassNameLookup()
model = Model().eval().to(device)
detect_model = Detect_Model().eval().to(device)
### 对抗攻击监测
detect_pred = detect_model(img)
print(detect_pred)
if detect_pred > 0.5:
print("出现可疑对抗样本。")
pred = imagenet_label2classname(predict_from_logits(model(img)))
print(pred)
id = 't5Su94C'
# 填写喵提醒中,发送的消息,这里放上前面提到的图片外链
text = "出现可疑对抗样本!!" +str(img_path)
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)
else:
print("图片正常。")
pred = imagenet_label2classname(predict_from_logits(model(img)))
print(pred)
# %%
if __name__ == '__main__':
## 使用原样本
img_path_ = "Lesson5_code/adv_code/orig_images/vid_5_26660.jpg_0.jpg"
main(img_path_)
## 替换对抗样本
img_path_ = "Lesson5_code/adv_code/adv_results/vid_5_26660.jpg_0.png"
main(img_path_)
测试视频如下:
六、本文小结和学习心得
本文是在Rocky以及Aidlux团队的训练营中学习而来,详细代码可关注Aidlux公众号并回复关键词"2211lesson3,2211lesson4,2211lesson5"获得,其它同学的分享文章和心得也可参考附录中的链接。
附录
参考链接
基于Aidlux的智慧交通AI安全车辆检测训练实战 - 知乎 (zhihu.com)