基于Aidlux平台的智慧交通AI安全算法实战

一、

通常来说,智慧交通行业主要是对交通场景内的行人,机动车,非机动车进行识别分析。

行人识别分析包括对行人的姿态,方向,外观,以及基于行人的交通事件识别分析,(行人闯红灯等)。

机动车识别分析包括对机动车的外型,颜色,车灯,车窗,驾驶员安全事件分析(是否在打电话,是否系安全带等),车牌,车辆方向以及基于机动车的交通事件识别分析(超速检测,违停判定等)。

非机动车识别分析包括对非机动车的细分类别识别,运动状态识别,驾驶员安全事件分析(是否戴头盔等),以及基于非机动车的交通事件识别分析(非机动车闯红灯等)。

基于Aidlux平台的智慧交通AI安全算法实战_第1张图片

智慧交通的场景主要划分为:十字路口,交通卡口,交通出入口,停车场等场景。不同公司的业务领域、覆盖范围都不一样。有些会做交通场景的整体解决方案,有些会做算法提供商,还有一些会做交通细分领域的解决方案或者算法提供商。

在智慧交通的的场景中,每个场景都对应了不同的算法业务功能,每个算法业务功能则是由不同应用技术如目标检测,图像分割,图像分类,目标追踪,OCR识别等组合而成。

基于Aidlux平台的智慧交通AI安全算法实战_第2张图片

 应用场景,AI算法功能,Ai算法模型这三者有机结合,形成了面对不同需求的整体算法解决方案。在上图里的AI算法功能中:车辆识别功能其底层的算法技术主要是车辆检测+车牌检测+车牌字符识别+业务功能判断等组成。这里的业务功能,包括车辆框矫正,车牌框矫正,车牌字符后处理等逻辑;行人识别算法功能,其底层的算法技术主要是行人检测+人脸识别+行人重识别等组成;车辆属性识别算法功能,其底层主要是车辆检测+车标识别+车系识别+驾驶员行为识别等组成。交通事件检测算法功能则更为复杂,其需要大量的交通规则作为约束,并且在检测机动车,行人以及非机动车的同时,要准确感知当前的背景环境条件。比如检测交通指示牌,检测交通道路指示线等来对交通事件的判定进行支持。行人闯红灯,车辆闯红灯,机动车超速,超时停车,机动车违停等都属于上述所说的交通事件中的典型细分功能。

二、

以深度学习为核心的人工智能存在 易受攻击的缺陷 ,攻击者通过精心制作的3D人脸面具以及相应的合
成图片,破解了多个公司的人脸识别系统,说明人工智 能的可靠性仍需加强。
目前AI算法模型 以黑盒为主 ,具备 高度复杂性和不确定性 ,很多决策原理无法直观理解。这种 黑盒特性也大大限制了深度学习理论的进一步发展。
AI项目的输出结果受到训练数据的影响,如果数据中存在偏见歧视,AI项目很可能形成偏见的智能决策。
比如上图中表示美国芝加哥法院使用的犯罪风险评估系统被证明,对黑人会做出 偏见决策
而且AI系统的智能决策也会受到 复杂因素影响 ,导致责任事故主体的界定存在困难。
目前最为业界所关注的是自动驾驶与智能机器人等应用出现安全事故时,其 责任界定逻辑 还需进一步探讨。
随着大数据时代的到来, 数据滥用可能会导致隐私泄漏的风险 ,从而影响人们正常的生活社交安全。
在智慧交通场景中,面对复杂的交通应用场景,AI算法也很容易受到一些 人为的对抗样本攻击,以及复杂自然环境中引入的不确定噪声影响
比如车辆,行人人脸,车牌,交通指示牌等都可能成为受攻击的目标。加上智慧交通AI项目一般都是ToB或者ToG的,客户对项目底层技术的可解释性与数据安全有一定的要求。黑盒系统容易引发不确定性风险,很多交通事件以及交通违规判定仍需专业人员进行二次验证。
此外, 数据偏见在交通场景中尤为常见。 比如在高速场景中,AI算法往往将卡车,货车等大型车辆作为重点目标,并进行超速检测,安全性分析,交通违规检测等项目功能。相对来说,不够重视小轿车,面包车等小型车辆。可能造成对于小轿车,面包车超速违规的 漏检,安全事件的漏判等情况 ,甚至造成与车辆相级联的相关驾驶员事件功能的偏见决策。
再比如卡口场景,一般来说都是机动车,非机动车等车辆目标,可能会存在对行人相关项目功能的偏见决策与结果输出(行人漏检,机动车虚检,非机动车虚检等) 在非机动车项目中,外卖小哥每天在外风驰电掣,其流量与行动范围远远大于其他例如自行车,三轮车,家用电动车等非机动车。
这些场景中采集的数据必然会存在数据偏见的情况,对模型后续的智能决策会产生影响(比如非机动车驾驶员违规识别偏见决策,非机动车礼让行人偏见决策等)
当然,AI项目一般会持续优化迭代。如果新增的训练数据中一直存在偏见,那么在不断的迭代训练
中,算法会进一步受到影响,固化数据中存在的歧视偏见,并形成更加偏见的智能决策。
三、
本次的智慧交通实战中选用了Kaggle开源的车辆数据集,其网址是: https://www.kaggle.com/datasets/sshika
maru/car-object-detection
数据集中总共包含了三个方面的内容:1001张的训练数据集,175张的测试数据集,以及一个标签csv 文件。这个数据集是一个典型的小量级数据,这在实际项目中非常常见,后续我们将用“以数据为中心”的思想对数据集进行优化。
训练过程可见: 基于Aidlux平台的街道人流量统计开发与测试_qq_42950407的博客-CSDN博客
只需修改类别数量和类别名称'person'->'car'即可,训练后得到best.pt。在模型推理测试文件 detect_image.py中修改修改代码中的模型、图片路径、yaml文件、权重。运行后可以得到一张张推理的图片效果。最后在将pt模型转化为tfilte模型,复制到Aidlux中(进行SSH远程链接后)运行,便可以在Aidlux端进行模型推理测试。
模型转化代码如下:
# 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/lesson3_codes/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/yolov5_code/data/tests"
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)

    # 图片裁剪,裁剪区域[Ly:Ry,Lx:Rx]
    # cut_img = extract_detect_res(frame, pred)
    # cvs.imshow(cut_img)
    # cap.release()
    # cv2.destroyAllWindows()


基于Aidlux平台的智慧交通AI安全算法实战_第3张图片
四、
对抗攻击(adversarial attack)是AI安全方向的重要分支,其核心逻辑是在数据中增加一些微小扰
动,在人类视觉系统无法察觉的情况下,使得算法模型对这些数据产生误判。其中被增加扰动的数据 也称为对抗样本。
下面是一些直观的通过增加对抗噪声来让算法模型误判的例子:
基于Aidlux平台的智慧交通AI安全算法实战_第4张图片
在智慧交通场景中,由于通常来说场景多样复杂(卡口,出入口,十字路口,停车场等),环境多样
复杂(白天,夜晚,雨天,大雾天,反光等),场景目标复杂多样(机动车种类多,非机动车种类
多,行人流量大,交通事件种类繁杂等),让对抗攻击有了很广泛的应用价值。
对于攻击者来说,上述 场景,环境,场景目标都可能是其攻击对象 ,这些在前三节课中都已经涉及,
这里就不再展开。
对于防御者来说,对抗攻击作为AI安全方向中的一个分支,其能让算法解决方案提供方对攻击者知己知彼,促进算法模型去提升其鲁棒性与防御性。
接下来,我们讲讲对于防御者,该如何应用对抗攻击技术。
对抗攻击技术可以作为智慧交通AI业务的鲁棒性与安全性检查工具,用于算法解决方案的测试短,对 算法解决方案可能存在的安全风险,早发现,早解决,早完善。
通过研究对抗攻击,来增强对实际场景中受到的攻击种类与情形的判断力,从而能够更好的设计相应的对抗防御方法。
使用对抗攻击对敏感信息进行隐藏,比如在交通场景的敏感数据进行对抗攻击,防止数据被非法分子破解和利用。
再比如对抗攻击与验证码相结合,对原始验证码有针对性的加入干扰,使得人眼识别不受影响,但会显著降低人工智能模型的识别率,从而防范打码平台的破解,同时保持用户体验。

而防御者最直接了当的使用对抗攻击的形式是对抗训练。 使用对抗样本在模型训练过程中进行对抗训练,我们在训练时将对抗样本加入训练集一起训练,即为对抗训练。 进行对抗训练能扩充训练集的可能性,使得数据集逼近我们想要的数据分布,训练后的模型鲁棒性和泛化性能也大大增强。

目前主流对抗攻击算法的总体分支与逻辑:
基于Aidlux平台的智慧交通AI安全算法实战_第5张图片

其中,当算法模型参数和训练数据等信息被攻击者所掌握,并且攻击者在此基础上进行的针对性攻击
称为白盒攻击。白盒攻击主要分为基于梯度的攻击,基于优化的攻击以及基于GAN的攻击。而在对算 法模型的结构和参数一无所知,甚至相关训练数据也一无所知的情况下,进行攻击的过程称为黑盒攻 击。
黑盒攻击主要分为基于迁移的攻击和基于查询的攻击两大类。
基于迁移的攻击逻辑由白盒攻击延伸而来,一般会有一个白盒模型作为替身模型(surrogate)进行攻击,而生成的对抗样本一般也会对其他模型有一定的迁移攻击性。
基于查询的攻击其主要是通过查询黑盒模型的输出信息,对黑盒模型进行直接的攻击,但完成整个攻击流程往往需要大量的查询,容易被模型所有者检测到异常。
再者,基于此我们再介绍两个有趣的攻击策略:
有目标攻击(targeted attack):通过攻击使得模型将特定数据错误输出到指定的label上。
无目标攻击:通过攻击使得模型将特定数据错误输出到除真实label外的其他任何label上。
类模型,针对有目标攻击,我们通过生成对抗样本,想让分类模型将猫的类别错判成狗。而无目标攻击,并不限定特定类别,只要模型发生错判即可。
模型配置加载:
完成了数据读取部分的修改,我们现在就可以加载模型了,这次实验我们选择了Pytorch已经训练好的 预训练模型Mobilenet_v2,或者替身模型Resnet50,运行代码时,会将相应的预训练权重下载下来。 如果出现下载有问题的情况,dont’t worry 我们也可以选择本地已经下载好的模型权重,都在代码中。
基于Aidlux平台的智慧交通AI安全算法实战_第6张图片

 使用对抗攻击算法:

使用PGD攻击算法进行白盒攻击,将原模型model作为受攻击模型,eps代表对抗扰动的范围,eps_iter代表一次攻击的步长,nb_iter代表攻击次数,rand_init代表是否在一开始生成一个随机的对抗扰动。

基于Aidlux平台的智慧交通AI安全算法实战_第7张图片

 等待一段时间,攻击就完成了,此时会输出对抗样本advimg。

 对抗攻击效果验证:

测试集中总共有6张图片,分别是不同的交通工具图片。
我们可以看到经过攻击后,模型将山地自行车错判成三轮车。
基于Aidlux平台的智慧交通AI安全算法实战_第8张图片
将敞篷车错判成小巴士:
基于Aidlux平台的智慧交通AI安全算法实战_第9张图片
将出租车错判成美洲驼:

基于Aidlux平台的智慧交通AI安全算法实战_第10张图片 了解了上面的实验结果,可以看到,PGD对抗攻击的效果还是非常好的,只是添加了人眼系统一时无 法分辨的微小对抗扰动,就可以使得AI模型出现严重的误判,这在智慧交通场景中,可能会引起很多 不确定风险。

对抗攻击代码如下:

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 robust_layer import GradientConcealment, ResizedPaddingLayer

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("E:/AidLux2/Lesson4_code/adv_code/images", "cab.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])

### 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)

pre_label = predict_from_logits(model_defense(img))


### 对抗攻击:PGD攻击算法
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)

 五、

结合车辆检测+AI安全+分类模型的模式,将攻击与防御注入到检测任务与分类任务的级联点
中,完成AI项目的对抗攻防安全功能。
在YOLOv5模型与分类模型中增加一个对抗风险监测模型,当检测到AI安全风险时,返回告警信息
和告警图片。
一般在实际应用的项目业务系统中,会出现一个告警弹窗。
比如某个图片被识别为对抗样本,出现告警信息,便会安排人员进行及时评估。
这时候,数据流会被切断,后续级联任务暂时停止,在评估好安全风险后,我们可以选择对这张图片
进行对抗噪声破坏操作或者直接在算法流程中移除。
不过我们训练营中并没有业务系统,为了更加贴近实际,在本训练营中,我们才用了一种更加简单实
用的方式,即通过微信“喵提醒”的方式。
基于Aidlux平台的智慧交通AI安全算法实战_第11张图片

 我们在使用白盒攻击的基础上,进行迁移攻击,形成基于迁移的黑盒攻击。具体来说,上面我们已经将车辆目标区域提取出来,在实际AI项目中,攻击者一般难以获得算法模型的参数,白盒攻击难以展开。这时,可以选择另外一个模型作为替身模型,比如我们知道他后面会进行车辆分类,但是不知道用的什么分类模型(实际上系统方用的Mobilenetv2),这时我们可以使用一个已有的分类模型(ResNet18)作为替身。使用攻击算法对替身模型进行攻击,这样生成的车辆目标区域对抗样本一定程度上也会使得业务模型产生错误的输出。

基于Aidlux平台的智慧交通AI安全算法实战_第12张图片

import os
import torch
import torch.nn as nn
import torchvision.utils
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

# PGD攻击算法
from advertorch.attacks import LinfPGDAttack
#FGSM攻击算法
from advertorch.attacks import FGSM
#L1PGD攻击算法
from advertorch.attacks import L1PGDAttack
#L2PGD攻击算法
from advertorch.attacks import L2PGDAttack
#LinfMomentumIterative攻击算法
from advertorch.attacks import LinfMomentumIterativeAttack

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("/home/Lesson5_code/adv_code/adv_results", "adv_image.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.show()

    plt.axis("off")
    plt.title("original image\n prediction: {}".format(pred))
    plt.subplot(1, 3, 2)
    plt.imshow(np_perturb * enhance + 0.5)
    plt.show()


    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)


### 替身模型加载
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))


### 对抗攻击:FGSM攻击算法(eps = 0.5 / 255, 2 /255, 8 /255)
# adversary = FGSM(
#     model_su, eps=8/255, eps_iter=2/255, nb_iter=80,
#     rand_init=True, targeted=False)

### 对抗攻击:PGD攻击算法
adversary = LinfPGDAttack(
   model_su, eps=8/255, eps_iter=2/255, nb_iter=80,
   rand_init=True, targeted=False)

# ### 对抗攻击:L1PGD攻击算法
# adversary = L1PGDAttack(
#    model_su, eps=1600, eps_iter=2/255, nb_iter=80,
#    rand_init=True, targeted=False)

# ### 对抗攻击:L2PGD攻击算法
# adversary = L2PGDAttack(
#    model_su, eps=8, eps_iter=2/255, nb_iter=80,
#    rand_init=True, targeted=False)

# ### 对抗攻击:L1PGD攻击算法
# adversary = LinfMomentumIterativeAttack(
#     model_su, eps=8/255, eps_iter=2/255, nb_iter=80,
#    rand_init=True, targeted=False)


### 完成攻击,输出对抗样本
advimg = adversary.perturb(img, pred_label)


### 展示源图片,对抗扰动,对抗样本以及模型的输出结果
show_images(model, img, advimg)


### 迁移攻击样本保存
save_path = "/home/Lesson5_code/adv_code/adv_results/"
torchvision.utils.save_image(advimg.cpu().data, save_path + "adv_image.png")

面对上面讲到的实际场景中可能存在的黑盒攻击,我们就需要提前准备,设计相应的黑盒防御策略。 在业务系统中,可以通过防御策略,比如通过二分类模型(正常图片和扰动图片),告知工作人员, 图像中可能出现安全风险,这样系统就更加安全了。

那么有哪些黑盒防御策略呢?
具体来说,黑盒防御策略主要有数据预处理,设计鲁棒性模型结构,使用对抗样本监测模型等方法。 方法有很多,不过为了大家快速掌握,本课程主要使用对抗样本监测模型的形式。
下面,我们就来讲解一下。
在前面的学习中,我们知道,对抗攻击监测模型是一个能够捕捉对抗扰动的二分类模型,监测模型的输入是一张图片,输出则是两个类别,0表示图片是正常图片,1表示图片是具有安全风险的图片。
本次训练营中,Rocky直接使用了一个已经训练好的基于ResNet50的模型,作为本次训练营的监测模 型。
在实际场景中,当数据流中的图片进入AI项目中时,在一些关键节点处,可以前置一个监测模型,用 于判断输入数据是否存在安全风险,如果发现对抗样本,则及时告警,并切断后续的算法功能,避免 不确定风险的产生。
比如在智慧交通场景中,对每一个车辆进行提取,再进入对抗攻击监督模型判断是正常的图片,还是 具有安全风险的图片。
基于Aidlux平台的智慧交通AI安全算法实战_第13张图片
### 对抗攻击监测模型
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("/Users/rocky/Desktop/训练营/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:]


model = Model().eval().to(device)

detect_model = Detect_Model().eval().to(device)

 当对抗攻击监测模型,监测到对抗样本或者对抗攻击后。一般在实际场景的AI项目中,会出现一个告警弹窗,并且会告知安全人员及时进行安全排查。本文通过微信“喵提醒”的方式来实现。

整体的串联代码如下:

# aidlux相关
from cvs import *
import aidlite_gpu
from yolov5_code.aidlux.utils import detect_postprocess, preprocess_img, draw_detect_res, extract_detect_res

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"


import time
import cv2

# AidLite初始化:调用AidLite进行AI模型的加载与推理,需导入aidlite
aidlite = aidlite_gpu.aidlite()
# Aidlite模型路径
model_path = '/home/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/adv_code/test_images"
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)

    #图片裁剪,提取车辆目标区域
    cut_img = extract_detect_res(frame, pred, image_name)
    cvs.imshow(cut_img)
    #cap.release()
    #cv2.destroyAllWindows()
    
    # 图片裁剪,裁剪区域[Ly:Ry,Lx:Rx]
    # cut_img = extract_detect_res(frame, pred)
    # cvs.imshow(cut_img)
    # cap.release()
    # cv2.destroyAllWindows()
    

### 读取图片
def get_image():
    img_path = os.path.join("/home/Lesson5_code/adv_code/adv_results", "adv_image.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())


normalize = NormalizeByChannelMeanStd(
    mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])

np_img = get_image()
img = torch.tensor(bhwc2bchw(np_img))[None, :, :, :].float().to(device)
imagenet_label2classname = ImageNetClassNameLookup()


### 常规模型加载
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


### 对抗攻击监测模型
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("/Users/rocky/Desktop/训练营/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:]


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:
    id = 'tLyPaLG'
    # 填写喵提醒中,发送的消息,这里放上前面提到的图片外链
    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(text)
    print(result)
else:
    pred = imagenet_label2classname(predict_from_logits(model(img)))
    print(pred)



心得体会:在经过江大白老师团队第一次训练营后,本次实战已经有了一定的基础,对于模型训练、测试、推理的过程已经聊熟于胸,但是在不同的场景下,AI仍然有许多我们不懂,不知道的算法,比如本次的对抗攻击算法,在本次的学习中,我清楚的了解了AI安全相关的算法,并运用在智慧交通场景,让我对于深度学习,人工智能的兴趣进一步提升,感谢江大白老师团队的贡献和Aidlux团队的支持。
代码:链接:  https://pan.baidu.com/s/1SL2rhiEN2D_HTX6pGx2xXQ 提取码: 23a3
对抗攻击算法效果视频见: 基于Aidlux的智慧交通对抗攻击算法效果-CSDN直播
整体串联后 车辆检测+检测框提取+使用对抗样本+AI安全监测与告警功能的效果视频见:
基于Aidlux平台的智慧交通车辆检测+AI安全检测效果-CSDN直播

你可能感兴趣的:(人工智能)