模型黑盒水印、白盒水印实现,并提供容器化部署

liyan a419db951e 新增项目说明文档 4 maanden geleden
asserts a419db951e 新增项目说明文档 4 maanden geleden
docker 4eb74e113a 修改docker镜像构建 8 maanden geleden
tests 4144a73f4b 新增基于pytorch框架的图像分类模型黑盒水印嵌入流程集成 5 maanden geleden
watermark_generate 3c7901d4fa 将模型水印嵌入接口按照工标进行修改 4 maanden geleden
.gitignore 1abc52c2f6 添加提交忽略文件 7 maanden geleden
README.md a419db951e 新增项目说明文档 4 maanden geleden
YOLOX.zip 180aba8774 上传待嵌入水印的模型工程文件 5 maanden geleden
classification-models-pytorch.zip 180aba8774 上传待嵌入水印的模型工程文件 5 maanden geleden
classification-models-tensorflow.zip 180aba8774 上传待嵌入水印的模型工程文件 5 maanden geleden
faster-rcnn-pytorch-3.1.zip 180aba8774 上传待嵌入水印的模型工程文件 5 maanden geleden
ssd-pytorch-3.1.zip 180aba8774 上传待嵌入水印的模型工程文件 5 maanden geleden

README.md

模型水印嵌入工具

提供修改模型工程文件来集成白盒水印、黑盒水印的功能

分支说明

  • master分支修改模型工程文件,使模型文件集成黑盒水印嵌入和白盒水印嵌入功能

水印嵌入流程

  1. 调用提供的HTTP接口,传输模型工程文件压缩包二进制流和标签信息
  2. 对收到的模型工程文件压缩包解压至指定目录,并使用指定标签信息生成密码标签
  3. 使用deals目录中各种模型、各种模型水印嵌入方式的处理文件进行处理
  4. 将处理完成的模型工程文件重新压缩,响应压缩文件二进制流

支持模型

  • 图像分类模型:AlexNet(pytorch/Keras)、VGGNet(pytorch/Tensorflow)、GoogleNet(pytorch)、ResNet101(pytorch)
  • 目标检测模型:YOLOX(pytorch)、Faster-RCNN(pytorch)、SSD(pytorch)

代码说明

model_watermark_generate
    ├── README.md  # 项目说明文档
    ├── YOLOX.zip  # YOLOX工程文件
    ├── classification-models-pytorch.zip  # 基于Pytorch框架图像分类模型工程文件
    ├── classification-models-tensorflow.zip  # 基于Tensorflow、Keras框架图像分类模型工程文件
    ├── tests  # 测试脚本
    ├── docker  # docker部署
    │   ├── Dockerfile
    │   ├── build.sh  # docker部署所需命令
    │   └── debian.sources
    ├── faster-rcnn-pytorch-3.1.zip  # Faster-RCNN工程文件
    ├── ssd-pytorch-3.1.zip  # SSD工程文件
    └── watermark_generate  # 模型水印嵌入工具
        ├── __init__.py
        ├── app.py
        ├── controller  # API接口定义
        │   ├── __init__.py
        │   ├── function_test.py
        │   └── watermark_generate_controller.py
        ├── data  # 模拟签名验签接口所需数据
        │   ├── extract
        │   ├── sm2_1.key
        │   ├── sm2_1.pub
        │   ├── sm2_2.key
        │   └── sm2_2.pub
        ├── deals  # 所有支持模型工程文件处理流程
        │   ├── classfication_tensorflow_black_embed.py
        │   ├── classfication_tensorflow_white_embed.py
        │   ├── classification_pytorch_black_embed.py
        │   ├── classification_pytorch_white_embed.py
        │   ├── faster_rcnn_pytorch_black_embed.py
        │   ├── faster_rcnn_pytorch_white_embed.py
        │   ├── googlenet_pytorch_white_embed.py
        │   ├── ssd_pytorch_black_embed.py
        │   ├── ssd_pytorch_white_embed.py
        │   ├── yolox_pytorch_black_embed.py
        │   └── yolox_pytorch_white_embed.py
        ├── exceptions.py  # 自定义异常信息
        ├── requirements.txt  # 项目依赖
        ├── run.py  # 程序运行入口
        └── tools  # 所需工具脚本
            ├── __init__.py
            ├── general_tool.py
            ├── modify_file.py
            ├── secret_label_func.py
            └── sign_verify.py

水印嵌入方式

  • 黑盒水印:将密码标签分为3份(图像分类模型为2份),选择训练集5%图片添加密码标签二维码并替换其标签为指定分类
    • 基于pytorch框架实现的图像分类的模型工程文件,通过创建自定义Dataset来替换原始工程文件训练集的Dataset来实现黑盒模型水印嵌入
    • 基于pytorch框架实现的目标检测类型的模型工程文件,通过修改原始模型工程文件Dataset实现黑盒模型水印嵌入
    • 基于Tensorflow、Keras框架实现的图像分类模型工程文件,通过将修改后图片保存至额外的文件夹,替换原始工程文件的训练集的水印图片文件路径来实现黑盒模型水印的嵌入
  • 白盒水印:选择模型指定位置的卷积层列表,根据密码标签长度和卷积层长度随机生成投影矩阵,训练卷积层列表和投影矩阵的矩阵乘积为密码标签
    • 基于Tensorflow、Keras框架实现的模型工程文件,通过自定义损失函数实现白盒水印嵌入
    • 基于pytorch框架实现的模型工程文件,通过修改原始损失函数实现白盒水印嵌入

黑盒水印嵌入原理

  • 图像分类模型: 通过在训练开始前,从训练集中取出一部分图片,将密码标签转换为二维码,将二维码粘贴至选中的图片上,并修改这张图片所属的标签为指定的标签,通过不断训练,使模型记住水印特征。达到图片没有添加水印二维码,模型推理结果为原始分类,图片添加水印二维码,模型推理结果为水印指定分类
  • 目标检测模型: 通过在训练开始前,从训练集中取出一部分图片,将密码标签转换为二维码,将二维码粘贴至选中的图片上,在选中图片的标注文件中添加二维码的标注信息(二维码的位置信息+二维码所属分类,注意加载进模型的标注文件格式:xyxy还是xywh格式)。通过不断训练,使模型记住水印特征。达到图片没有添加水印二维码,模型推理结果为正常圈选,图片添加水印二维码,模型推理结果为会增加对水印二维码的圈选,并指定其分类为指定分类。 004256.jpg

白盒水印嵌入原理

将密码标签转换为二进制字符串,在模型工程文件选择指定模型的特定的一些卷积层(根据测试得出效果好的),将卷积层按照outputs维度进行取平均,然后进行取平均再拉直的操作,根据处理后卷积层的长度和密码标签二进制字符串的长度随机生成投影矩阵,编写水印损失函数,达到处理后的卷积层与投影矩阵的矩阵乘积为密码标签二进制串,将水印损失函数与原始训练任务的损失相加。经过模型不断训练,水印损失不断减少,达到提取密码标签的目的。

  • 注意事项:Tensorflow、Keras与Pytorch的卷积核排布方式不一致,对卷积核取平均时,Pytorch框架需要重新对卷积核进行排布,使其形状与Tensorflow框架卷积核形状一致。 python def flatten_parameters(self, weights): flattened = [tf.reduce_mean(layer, axis=3) for layer in weights] return tf.concat([tf.reshape(layer, [-1]) for layer in flattened], axis=0) python def flatten_parameters(self, weights): weights = [weight.permute(2, 3, 1, 0) for weight in weights] # 注意这行代码,对卷积核形状进行了重新排布 return torch.cat([torch.mean(x, dim=3).reshape(-1) for x in weights])