【隐私计算篇】利用多方安全计算MPC实现VGG16人脸识别隐私推理

1. 背景介绍

        本文主要介绍一种利用多方安全计算MPC技术,实现VGG16的人脸识别模型,侧重于模型推理阶段,目前已经公开专利,因此以下内容的分享都是基于公开材料。该分享涉及到最小化多方安全计算(MPC)以及明密文混合计算的思想,仅供参考。

        人脸识别是一种基于生物特征识别技术的身份验证和识别方法,在多种场景中广泛应用,比如安防、银行、终端设备等,更贴近生活的还有支付宝的扫脸支付。人脸识别在各领域的广泛应用带来了便利,但也引发了隐私和数据安全方面的讨论以及担忧,传统的人脸识别系统在数据采集、存储和处理过程中很可能会存在隐私泄露的风险。

        比如传统人脸识别系统通常需要将用户的面部数据上传到中央服务器进行处理,如果这些数据被黑客入侵、内部人员滥用或系统漏洞利用,可能会导致用户敏感信息泄露。此外,某些公司或机构可能会将收集到的人脸数据用于未经用户同意的商业或其他用途,侵犯个人隐私。

        鉴于上述原因,很有必要采用隐私保护技术。隐私计算技术(如联邦学习、差分隐私、多方安全计算等)允许在不直接共享原始数据的前提下进行人脸识别模型的训练和推理,从而防止数据滥用和泄露。实现隐私计算的人脸识别是为了在保证人脸识别技术有效性的同时,最大程度地保护用户的个人隐私。     

2. 算法介绍

        本文主要介绍利用安全多方计算(MPC)实现VGG16人脸识别模型的推理预测。在介绍具体算法之前,需要对MPC有一定的了解,有助于理解后续的深度学习算法隐私计算化改造。安全多方计算(MPC)是一种密码学技术,它允许多个参与方在不泄露各自私有数据的前提下,协同计算一个共同的函数结果。关于MPC的介绍,这里不做详细展开,有兴趣的话可以看下冯登国院士关于MPC的基础知识分享,包括 基于秘密分享方法的MPC以及基于混淆电路方法的MPC,另外关于混淆电路的知识也可以参考我们之前的文章《混淆电路深入浅出》,涉及的密码原语不经意传输可以参考我们的系列文章《OT&OT扩展(不经意传输扩展)深入浅出》、《不经意传输协议(OT/OTE)的进一步补充》。

2.1 具体算法介绍

        整体算法介绍会涉及采集端分片处理、分布式存储、分布式推理、模型本身的MPC化等工作。

2.1.1 人脸分布式存储

        在人脸图像采集、识别环节都采用分片形式的分布式存储。采用MPC加性碎片形式,将原始人脸图像数据分成多个小碎片,每个碎片单独存储在不同的存储节点上,不同的存储点可以分布在物理独立的地区,即使某个库被攻破,也无法窃取到具体的人脸明文数据。

2.1.2 VGG模型介绍

        在进行VGG模型的改造之前,也调研了相应的其他模型,比如AlexNet模型,总体来看,结构类似,但vgg的层数更深、参数更多。

        AlexNet: 共有 8 层,其中 5 层是卷积层,3 层是全连接层。

 VGG16: 共有 16 层,其中包括 13 层卷积层和 3 层全连接层【1,2】。

        

        VGG16由13个卷积层、5个最大池化层和3个全连接层组成。因此,具有可调参数的层数为16(13个卷积层和3个全连接层)。这也是该模型被命名为VGG16的原因。第一组卷积层中的滤波器数量为64,之后每个卷积模块中的滤波器数量逐步加倍,直到达到512个。该模型最后由两个全连接隐藏层和一个输出层构成。两个全连接隐藏层的神经元数量相同,均为4096。

        因此从模型的结构、复杂度、参数量来看,vgg会比alexnet更强大,因此我们选择vgg16作为mpc化改造的基座模型。

2.1.3 VGG模型MPC化

        对于VGG模型的mpc化方案,同样也适合AlexNet网络结构,可以迁移使用。该面向的多方计算场景为两方,当然也可以平滑扩展到N方,但考虑到推理的耗时问题,两方、三方会比较合适。因为随着参与方的增多,进行矩阵乘法的时候,彼此之间的通信量会显著增加。另外,场景面向的是1对N的人脸识别任务。

方案描述

        对人脸特征提取算法MPC化,将人脸特征提取算法进行拆分,拆分成若干层,每层都是基本的CNN中的处理层,包括卷积层、激活层、池化层、全连接层等。对每个层次进行MPC化改造,在保证
安全性的情况下进行特定的优化。首先对单层MPC改造的优化,包括卷积层的MPC化、激活层的MPC化、池化层的MPC化、全连接层的MPC化,其次对多个层次的组合优化。

2.1.3.1 对单层MPC改造的优化

        将人脸特征提取算法进行拆分,拆分成若干层,每层都是基本的CNN中的处理层,包括卷积层、激活层、池化层、全连接层等,对每个层次进行MPC化改造,在保证安全性的情况下进行特定的优
化。

        (1)卷积层的MPC化

        方式一: 执行纯碎片态的卷积操作,其中生物信息输入是以碎片态,而卷积核采用明文态。

    步骤:
        各个参与方用本方碎片化的输入与明文态的卷积核进行向量内积计算,得到碎片态的卷积输入结果。卷积层的MPC化改造不涉及到交互,仅在各个参与方内部进行本地化碎片态的计算。

        此外,在某些场景下,也可以选择完全碎片态的卷积核执行分布式MPC计算。更加安全。

        方式二: 随机部分恢复后卷积,我们也称之为随机掩码态。

        这种模式下,各参与方在本地会进行随机恢复某些信息,但不足以用于判别,并且每一次使用都会用户重分片处理,重新随机。各个参与方随机恢复出明文,非明文位置用0填充,在本地进行
明文卷积运算,得到碎片态输出。这里有个注意点,需要设计一种新的随机化策略,避免恢复对于卷积贡献度较大的随机块。此外,应用该方法,对于输入的矩阵块大小有一定的要求,因为size过小容易造成信息的暴露,所以对于矩阵块的大小以及随机化策略需要重点考虑。

        (2)激活层的MPC化   

     参与方之间需要根据某种机制形成互补的索引集合,标注各个参与方在此步中需要恢复处明文的索引,根据索引各方相互交互,恢复部分明文。各方根据自己恢复出的明文,进行本地明文下的激活函数计算。各方对持有的激活函数计算出来的明文结果进行重分片。由于后续需要对激活层的记过进行进一步的卷积、池化等层操作,参与方在本层恢复出来的明文,在后续的层操作中需要与其他
自己不掌握数据的索引位置进行相应计算,所以随机部分明文化激活操作,不会泄露隐私数据。

        这里给出一种数值处理示例:

        (3)池化层的MPC化 

        参与方之间形成互补的池子索引集合,双方恢复各自掌握的池子里的明文信息。对自己恢复的池子里的数据进行本地明文池化。参与方对自己掌握的池化结果进行重分片。

       (4)全连接层的MPC化

        各个参与方根据公开的权重参数,进行向量内积计算,获得全连接的输出结果,这里采用的是纯MPC乘法计算方式。

2.1.3.2 对多层的组合优化       

        由于大多数特征提取算法中的单个层次之间的组合模式较为通用。例如"卷积->池化->激活"的操作,可以作如下的进一步优化。对于较为常用的层次组合,可定制化开发优化的算子。


2.1.3.3 MPC化推理模块组成

        以下展示整体模型的MPC化推理示例:


2.2 MPC人脸识别系统的整体架构

        模型训练参数的生成,可以采用完全MPC的方式直接生成碎片态参数,也可以采用明文训练后对模型参数进行碎片化处理。具体的方式根据实际业务需求进行选择。

       (1)一种模型训练参数的碎片化处理方式

        (2)人脸识别推理的处理流程

        (3)代码示例

        使用mpc化的模型,其使用方式和普通的明文模型其实很类似,只不过内部的底层算子是MPC的基本算子,其中的Conv2D、MaxPooling2D、Flatten、activation都是MPC化的算子。

        代码使用示例:

def VGG16(x):# Block 1kernel, bias = get_kernel_bias_by_name('conv1_1')x = Conv2D(64, (3, 3), activation='relu', padding='same', name='conv1_1')(x, kernel, bias)kernel, bias = get_kernel_bias_by_name('conv1_2')x = Conv2D(64, (3, 3), activation='relu', padding='same', name='conv1_2')(x, kernel, bias)x = MaxPooling2D((2, 2), strides=(2, 2), name='pool1')(x)# Block 2kernel, bias = get_kernel_bias_by_name('conv2_1')x = Conv2D(128, (3, 3), activation='relu', padding='same', name='conv2_1')(x, kernel, bias)kernel, bias = get_kernel_bias_by_name('conv2_2')x = Conv2D(128, (3, 3), activation='relu', padding='same', name='conv2_2')(x, kernel, bias)x = MaxPooling2D((2, 2), strides=(2, 2), name='pool2')(x)# Block 3kernel, bias = get_kernel_bias_by_name('conv3_1')x = Conv2D(256, (3, 3), activation='relu', padding='same', name='conv3_1')(x, kernel, bias)kernel, bias = get_kernel_bias_by_name('conv3_2')x = Conv2D(256, (3, 3), activation='relu', padding='same', name='conv3_2')(x, kernel, bias)kernel, bias = get_kernel_bias_by_name('conv3_3')x = Conv2D(256, (3, 3), activation='relu', padding='same', name='conv3_3')(x, kernel, bias)x = MaxPooling2D((2, 2), strides=(2, 2), name='pool3')(x)# Block 4kernel, bias = get_kernel_bias_by_name('conv4_1')x = Conv2D(512, (3, 3), activation='relu', padding='same', name='conv4_1')(x, kernel, bias)kernel, bias = get_kernel_bias_by_name('conv4_2')x = Conv2D(512, (3, 3), activation='relu', padding='same', name='conv4_2')(x, kernel, bias)kernel, bias = get_kernel_bias_by_name('conv4_3')x = Conv2D(512, (3, 3), activation='relu', padding='same', name='conv4_3')(x, kernel, bias)x = MaxPooling2D((2, 2), strides=(2, 2), name='pool4')(x)# Block 5kernel, bias = get_kernel_bias_by_name('conv5_1')x = Conv2D(512, (3, 3), activation='relu', padding='same', name='conv5_1')(x, kernel, bias)kernel, bias = get_kernel_bias_by_name('conv5_2')x = Conv2D(512, (3, 3), activation='relu', padding='same', name='conv5_2')(x, kernel, bias)kernel, bias = get_kernel_bias_by_name('conv5_3')x = Conv2D(512, (3, 3), activation='relu', padding='same', name='conv5_3')(x, kernel, bias)x = MaxPooling2D((2, 2), strides=(2, 2), name='pool5')(x)# Block 6kernel, bias = get_kernel_bias_by_name('fc6')x = Conv2D(4096, (7, 7), activation='relu', name='fc6')(x, kernel, bias)# x = Dropout(0.5, name='fc6/dropout')(x)kernel, bias = get_kernel_bias_by_name('fc7')x = Conv2D(4096, (1, 1), activation='relu', name='fc7')(x, kernel, bias)# x = Dropout(0.5, name='fc7/dropout')(x)kernel, bias = get_kernel_bias_by_name('fc8')x_fc = Conv2D(1024, (1, 1), name='fc8')(x, kernel, bias)x_flatten = Flatten(name='flatten')(x_fc)return x_flattendef deepface(random_idx, output_path, img):# y: [5947, 1024]  图像特征碎片化数据库y = mpc.read(ff_db_5947, 5947, 1024, ss_img_feature_db)# x: [1, 224, 224, 3] 图像数据碎片x = mpc.read_img(random_idx, 1, [224, 224, 3], ss_img)# 模型推理得到的输出x = VGG16(x)  # -> [1, 1024]

3. 参考材料

【1】An overview of VGG16 and NiN models

【2】Difference between AlexNet, VGGNet, ResNet, and Inception

【3】GitHub - rcmalli/keras-vggface: VGGFace implementation with Keras Framework

        

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/432695.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

签署《AI安全国际对话威尼斯共识》 智源持续推动人工智能安全发展

近日,由AI安全国际论坛(Safe AI Forum)和博古睿研究院(Berggruen Institute) 共同举办的第三届国际AI安全对话(International Dialogues on AI Safety)在威尼斯举办。图灵奖得主Yoshua Bengio、姚期智教授&…

UBUNTU20.04安装CH384串口卡驱动

继续上文:统信UOS安装CH384串口卡驱动-CSDN博客 统信UOS系统成功安装CH384串口驱动后,继续在ubuntu20.04下安装驱动,发现一直报错,原因是内核驱动不一致。 解决办法: 1. 下载最新的驱动。CH35XCH384驱动源文件资源-C…

Java语言程序设计基础篇_编程练习题**18.30 (找出单词)

题目:**18.30 (找出单词) 编写一个程序,递归地找出某个目录下的所有文件中某个单词出现的次数。从命令行如下传递参数: java Exercise18_30 dirName word 习题思路 (读取路径方法)和18.28题差不多,把找…

Structure-Aware Transformer for Graph Representation Learning

Structure-Aware Transformer for Graph Representation Learning(ICML22) 摘要 Transformer 架构最近在图表示学习中受到越来越多的关注,因为它通过避免严格的结构归纳偏差而仅通过位置编码对图结构进行编码,自然地克服了图神经…

分享课程:VUE数据可视化教程

在当今这个数据驱动的世界中,数据可视化已经成为了一种至关重要的工具,它帮助我们理解复杂的数据集,发现模式、趋势和异常。数据可视化不仅仅是将数字转换成图表,它是一种将数据转化为洞察力的艺术。 1.什么是数据可视化&#xf…

C语言指针系列1——初识指针

祛魅:其实指针这块儿并不难,有人说难只是因为基础到进阶没有处理好,大家要好好跟着一步一步学习,今天我们先来认识一下指针 指针定义:指针就是内存地址,指针变量是用来存放内存地址的变量,在同一…

Java.动态代理

1.创建一个接口 package Mydynamicproxy1;public interface Star {public abstract String sing(String str);public abstract void dance(String str); }2.创建一个BigStar类,要实现Star这个接口 package Mydynamicproxy1;public class BigStar implements Star{…

webpack4 target:“electron-renderer“ 打包加速配置

背景 昨天写得一篇Electron-vue asar 局部打包优化处理方案——绕开每次npm run build 超级慢的打包问题-CSDN博客文章浏览阅读754次,点赞19次,收藏11次。因为组员对于 Electron 打包过程存在比较迷糊的状态,且自己也没主动探索 Electron-vu…

tcp、udp通信调试工具Socket Tool

tcp、udp通信调试工具Socket Tool ]

线程池的执行流程和配置参数总结

一、线程池的执行流程总结 提交线程任务;如果线程池中存在空闲线程,则分配一个空闲线程给任务,执行线程任务;线程池中不存在空闲线程,则线程池会判断当前线程数是否超过核心线程数(corePoolSize&#xff09…

LeaferJS 动画、状态、过渡、游戏框架

LeaferJS 现阶段依然专注于绘图、交互和图形编辑场景。我们引入游戏场景,只是希望让 LeaferJS 被更多有需要的人看到,以充分发挥它的价值 LeaferJS 为你带来了全新的游戏、动画、状态和过渡功能,助你实现那些年少时的游戏梦想。我们引入了丰富…

【后端开发】JavaEE初阶——计算机是如何工作的???

前言: 🌟🌟本期讲解计算机工作原理,希望能帮到屏幕前的你。 🌈上期博客在这里:【MySQL】MySQL中JDBC编程——MySQL驱动包安装——(超详解) 🌈感兴趣的小伙伴看一看小编主…

Dependency Check:一款针对应用程序依赖组件的安全检测工具

关于Dependency Check Dependency-Check 是一款软件组合分析 (SCA) 工具,可尝试检测项目依赖项中包含的公开披露的漏洞。它通过确定给定依赖项是否存在通用平台枚举 (CPE) 标识符来实现此目的。如果找到,它…

Java线程的三大特性

原子性: 线程任务不可再分。 int i 1; i; 原子类 AtomicXXX 可见性: 线程之间的操作是互相不可见的。 volatile //线程A如果,flag为true,就运行打印语句 A: trueThread t1 new Thread(() -> {while (true) {if (flag) {System.out.println(&q…

【数据结构】AVL树相关知识详细梳理

1. AVL树的概念 AVL的全称是Adelson-Velsky-Landis,其名称来源于其发明者Adelson、Velsky和Landis, 是平衡二叉树搜索树。 它的出现是由于二叉搜索树虽可以缩短查找的效率,但如果数据有序或接近有序二叉搜索树将退化为单支树,查找…

【数据结构】栈和队列(Stack Queue)

引言 在对顺序表,链表有了充分的理解之后,现在让我们学习栈和队列!!! 【链表】 👈链表 【顺序表】👈顺序表 目录 💯栈 1.栈的概念及结构 2.栈的实现 ⭐初始化栈 ⭐入栈 ⭐…

Vue引入js脚本问题记录(附解决办法)

目录 一、需求 二、import引入问题记录 三、解决方式 一、需求 我想在我的Vue项目中引入jquery.js和bootstrap.js这种脚本文件,但发现不能单纯的import引入,问题如下。 二、import引入问题记录 我直接这么引入,发现控制台报错TypeError: …

POI操作EXCEL增加下拉框

文章目录 POI操作EXCEL增加下拉框 POI操作EXCEL增加下拉框 有时候通过excel将数据批量导入到系统,而业务操作人员对于一些列不想手动输入,而是采用下拉框的方式来进行选择 采用隐藏sheet页的方式来进行操作 String sheetName "supplier_hidden_s…

MedPrompt:基于提示工程的医学诊断准确率优化方法

Medprompt:基于提示工程的医学诊断准确率优化方法 秒懂大纲解法拆解MedPrompt 提示词全流程分析总结创意视角 论文:Can Generalist Foundation Models Outcompete Special-Purpose Tuning? Case Study in Medicine 秒懂大纲 ├── 1 研究背景【描述背…

vue.js——“微商城”后台管理系统

1. 需求背景: 先创建运行环境,“微商城”后台管理系统是一种后台管理系统平台,旨在提供一个便捷、安全和高效的管 理和操作各类数据的平台。系统将涵盖用户登录、商品管理、分类管理、新增分类和个人中 心等功能,以满足用户高效数据管理的各…