tf-encrypted介绍
TF Encrypted是TensorFlow中一个用于加密机器学习的框架,它看起来和感觉上都很像TensorFlow,利用了Keras API 的易用性,同时通过安全多方计算和同态加密实现了对加密数据的训练和预测。TF Encrypted的目标是使保护隐私的机器学习变得可用,而不需要密码学、分布式系统或高性能计算方面的专业知识。
同时,现在TF Encrypted已经完全支持tensorflow2,使代码更加清晰明了。
tf-encrypted隐私计算库的安装
tf-encrypted最直接的安装方式:
pip install tf-encrypted
但是这个方式已经不能用了,会出现报错,比如:
'NoneType' object has no attribute 'secure_seed'
取而代之的方式是直接git clone这个仓库,流程如下:
安装python版本为3.8的conda环境
conda create -n tfe python=3.8
激活环境
conda activate tfe
下载tf-encrypted仓库
git clone https://github.com/tf-encrypted/tf-encrypted.git
进入tf-encrypted仓库
cd tf-encrypted
安装所需依赖包
pip install -e .
需要注意:tensorflow版本必须>=2.9.1,否则可能出现如下报错:
ImportError: cannot import name 'glob_stateful_parallelism' from 'tensorflow.python.ops.while_v2'
编译tf-encrypted仓库
make build
执行后会先下载一个压缩包,如果执行太慢,可以尝试手动执行下载:
curl -ol https://github.com/jedisct1/libsodium/archive/1.0.17.tar.gz
编译到最后可能出现如下问题:
原因就是系统中g++的版本过低,需要升级,以至少支持g++14版本。
tf-encrypted使用示例
加载tf-encrypted库
由于此时我们没有在Python环境中安装tf-encrypted,因此需要手动载入这个库:
sys.path.append('/home/zwx/tf-encrypted')
import tf_encrypted as tfe
官网提供的矩阵乘法示例
import tensorflow as tf
import sys
sys.path.append('/home/zwx/tf-encrypted')
import tf_encrypted as tfe
@tfe.local_computation('input-provider')
def provide_input():
# normal TensorFlow operations can be run locally
# as part of defining a private input, in this
# case on the machine of the input provider
return tf.ones(shape=(2, 5))
# provide inputs
w = tfe.define_private_variable(tf.ones(shape=(5, 3)))
print('w:', w)
print('w_plaintext:', w.reveal(), '\n', w.reveal().to_native())
x = provide_input()
print('x:', x)
print('x_plaintext:', x.reveal(), '\n', x.reveal().to_native())
# eager execution
y = tfe.matmul(x, w)
res = y.reveal().to_native()
# build graph and run graph
@tfe.function
def matmul_func(x, w):
y = tfe.matmul(x, w)
print('y_ciphertext:', y)
return y.reveal().to_native()
res = matmul_func(x, w)
print('res:\n', res)
代码重点:
- 使用修饰器@tfe.local_computation(‘input-provider’)将输入封装成private类型
- 使用tfe.define_private_variable()定义private类型的变量
- 对于private类型的x,使用x.reveal()将其解密得到public类型数据,使用x.reveal().to_native()可以提取具体的明文值
- 当直接打印private类型的数据时,share_type中显示了秘密分享的类型,比如上图中的arithmetic,即算术秘密分享
- 现在tf-encrypted均基于tensorflow2,无需考虑和tensorflow1不兼容的问题
官网提供的简单神经网络示例
import tensorflow as tf
import sys
sys.path.append('/home/zwx/tf-encrypted')
import tf_encrypted as tfe
@tfe.local_computation('prediction-client')
def provide_input():
# normal TensorFlow operations can be run locally
# as part of defining a private input, in this
# case on the machine of the input provider
return tf.ones(shape=(5, 10))
x = provide_input()
model = tfe.keras.Sequential([
tfe.keras.layers.Dense(512, batch_input_shape=x.shape),
tfe.keras.layers.Activation('relu'),
tfe.keras.layers.Dense(10),
])
# get prediction input from client
logits = model(x)
result = logits.reveal()
print('result:', result, '\n', result.to_native())
神经网络推理
在/examples/benchmark/inference文件中给出了隐私推理的示例。
首先进入tf-encrypted的根目录下(因为跑推理的脚本里需要tf_encrypted.player
):
cd /tf-encrypted
然后执行命令跑基于协议的模型推理:
./examples/benchmark/inference/run-remote.sh resnet50 --protocol ABY3 --config ./examples/benchmark/inference/config.json
注意路径要正确,不然是跑不通的!
参数选择:
model_name: resnet50, densenet121, vgg19
protocol: ABY3, Pond, SecureNN
precision: 64-bit by default (可以改成high使用128-bit)
config: IP的配置(感觉暂时不用管)
执行命令,可以得到这6个文件:
不过,可能会遇到如下的报错:
attr {
key: "explicit_paddings"
value {
list {
}
}
}
raise ValueError(
ValueError: Could not infer attribute explicit_paddings type from empty iterator
不用着急,这个问题是框架在转tf模型时出现的onnx库错误,通过查阅tensorflow-onnx官方文档,知道了这个问题的原因是onnx版本过高的问题。
解决方案:将onnx版本降级到1.14.1即可:pip install onnx==1.14.1
再次执行推理命令,可以在log_master.txt中看到如下的输出日志信息:
从这个日志文件中能得到什么信息?
- Plain model predcited和predicted中各个类别的概率分布是接近的
- 应该能分别看出构建graph和推理的时间(暂时还不太清楚怎么看)