来自奥胡斯大学密码学PhD、Datadog机器学习工程师Morten Dahl介绍了如何实现基于加密数据进行训练和预测的卷积神经网络。本文进行概括和总结
工作
使用一个经典CNN模型,使其能够用于基于加密数据进行训练和预测。
动机
CNN目前可以用于很多分析图像的领域。如果能够让实际使用的用户在应用场景下提供更多的数据,那么模型的性能肯定可以提高。但是这涉及很多用户的隐私问题,如果用户可以明确自己提交的数据是确保隐私安全的,那么将可以吸引更多用户使用这些工具,提交更多数据。
基于MPC)我们可以潜在地降低暴露信息的风险,从而增强参与的动机。更具体地说,通过转而在加密数据上训练,我们不仅可以防止任何人查看个人数据,还可以防止泄露学习到的模型参数。
使用简单的CNN模型
用例是经典的MNIST手写数字识别,模型是Keras示例中的CNN模型1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22#keras
feature_layers = [
Conv2D(32, (3, 3), padding='same', input_shape=(28, 28, 1)),
Activation('relu'),
Conv2D(32, (3, 3), padding='same'),
Activation('relu'),
MaxPooling2D(pool_size=(2,2)),
Dropout(.25),
Flatten()
]
classification_layers = [
Dense(128),
Activation('relu'),
Dropout(.50),
Dense(NUM_CLASSES),
Activation('softmax')
]
model = Sequential(feature_layers + classification_layers)
model.compile( loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
model.fit(x_train, y_train, epochs=1, batch_size=32, verbose=1, validation_data=(x_test, y_test))
基本的想法是首先让图像通过一组特征层(feature layer),将输入图像的原始像素转换为和我们的分类任务更相关的抽象属性。接着通过一组分类层(classification layer)组合这些属性,以生成可能数字的概率分布。最终输出通常直接是概率最高的数字。使用Keras的优势是我们可以快速地在未加密数据上进行试验。
基于SPDZ的安全计算
CNN就绪后,我们接着来看MPC。我们将使用当前最先进的SPDZ协议,因为它允许我们只使用两个服务器,也允许我们通过将特定计算转移到离线阶段以改善在线表现。
和其他典型的安全计算协议一样,所有计算在一个域中进行,此处的域由一个质数Q表示。这意味着我们需要编码CNN使用的浮点数为以一个质数为模的整数,这给Q带来一些限制,进而对性能有所影响。
此外,在SPDZ协议这样的交互计算中,在典型的时间复杂度之外,同时还要考虑通讯和回合复杂度。通讯复杂度衡量在网络中发送的字节数,一个相对较慢的过程。回合复杂度衡量两个服务器之间的同步点数目,同步点可能阻塞其中一个服务器,使其无所事事,直到另一个服务器赶上来为止。因而两者均对总执行时间有很大的影响。
然而更重要的是,这些协议的“原生”操作只有加法和乘法。除法、比较等可以完成,但就它们的三项复杂度而言,要更昂贵。之后我们将看下如何缓解这引起的其中一些问题,而这里我们首先讨论基本的SPDZ协议。
张量操作
下面的代码为SPDZ协议实现$PublicTensor$和$PrivateTensor$两个类,分别代表两个服务器知道明文的张量和仅仅知道其秘密分享形式的加密值。
1 | class PrivateTensor: |
以上代码用到的工具函数1
2
3
4
5
6
7
8
9
10
11
12
13
14def share(secrets):
shares0 = sample_random_tensor(secrets.shape)
shares1 = (secrets - shares0) % Q
return shares0, shares1
def reconstruct(shares0, shares1):
secrets = (shares0 + shares1) % Q
return secrets
def generate_mul_triple(x_shape, y_shape):
a = sample_random_tensor(x_shape)
b = sample_random_tensor(y_shape)
c = np.multiply(a, b) % Q
return PrivateTensor(a), PrivateTensor(b), PrivateTensor(c)
适配模型
虽然原则上基于我们现有的模型安全地计算任何函数是可能的,实践中需要做的是先考虑对MPC更友好的模型变体,以及对模型更友好的加密协议。用稍微形象一点的话说,我们经常需要打开两个黑箱,让两个技术更好地适配彼此。
这一做法的根源在于,加密操作下,有一些操作惊人地昂贵。我们之前提到过,加法和乘法相对廉价,而比较和基于私密分母的除法则不然。基于这一原因,我们对模型做了一些改动,以避免这一问题(代价过高)。
优化器
首先涉及的是优化器:尽管许多实现基于Adam的高效而选择了它,Adam涉及对私密值取平方根,以及在除法中使用私密值作分母。尽管理论上安全地进行这些计算是可能的,在实践中它会是性能的显著瓶颈,因此需要避免使用Adam。
一个简单的补救方案是转而使用动量SGD(momentum SGD)优化器,它可能意味着较长的训练时间,但只使用简单的操作。
改为:1
model.compile( loss='categorical_crossentropy', optimizer=SGD(clipnorm=10000, clipvalue=10000), metrics=['accuracy'])
网络层
ReLU和最大池化层有“比较”操作的问题,使用了高阶sigmoid激活函数和平均池化层代替。1
2
3
4
5#Activation('relu')
Activation('sigmoid')
#MaxPooling2D(pool_size=(2,2))
AveragePooling2D(pool_size=(2,2))
另外就是要提高epoch数量,epochs=15。剩下的层很好处理。dropout和平层(flatten)不在乎是加密设定还是非加密设定,密集层和卷积层是矩阵点积,只需要基本操作。> 来自奥胡斯大学密码学PhD、Datadog机器学习工程师Morten Dahl介绍了如何实现基于加密数据进行训练和预测的卷积神经网络。本文进行概括和总结
工作
使用一个经典CNN模型,使其能够用于基于加密数据进行训练和预测。
动机
CNN目前可以用于很多分析图像的领域。如果能够让实际使用的用户在应用场景下提供更多的数据,那么模型的性能肯定可以提高。但是这涉及很多用户的隐私问题,如果用户可以明确自己提交的数据是确保隐私安全的,那么将可以吸引更多用户使用这些工具,提交更多数据。
基于MPC)我们可以潜在地降低暴露信息的风险,从而增强参与的动机。更具体地说,通过转而在加密数据上训练,我们不仅可以防止任何人查看个人数据,还可以防止泄露学习到的模型参数。
使用简单的CNN模型
用例是经典的MNIST手写数字识别,模型是Keras示例中的CNN模型1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22#keras
feature_layers = [
Conv2D(32, (3, 3), padding='same', input_shape=(28, 28, 1)),
Activation('relu'),
Conv2D(32, (3, 3), padding='same'),
Activation('relu'),
MaxPooling2D(pool_size=(2,2)),
Dropout(.25),
Flatten()
]
classification_layers = [
Dense(128),
Activation('relu'),
Dropout(.50),
Dense(NUM_CLASSES),
Activation('softmax')
]
model = Sequential(feature_layers + classification_layers)
model.compile( loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
model.fit(x_train, y_train, epochs=1, batch_size=32, verbose=1, validation_data=(x_test, y_test))
基本的想法是首先让图像通过一组特征层(feature layer),将输入图像的原始像素转换为和我们的分类任务更相关的抽象属性。接着通过一组分类层(classification layer)组合这些属性,以生成可能数字的概率分布。最终输出通常直接是概率最高的数字。使用Keras的优势是我们可以快速地在未加密数据上进行试验。
基于SPDZ的安全计算
CNN就绪后,我们接着来看MPC。我们将使用当前最先进的SPDZ协议,因为它允许我们只使用两个服务器,也允许我们通过将特定计算转移到离线阶段以改善在线表现。
和其他典型的安全计算协议一样,所有计算在一个域中进行,此处的域由一个质数Q表示。这意味着我们需要编码CNN使用的浮点数为以一个质数为模的整数,这给Q带来一些限制,进而对性能有所影响。
此外,在SPDZ协议这样的交互计算中,在典型的时间复杂度之外,同时还要考虑通讯和回合复杂度。通讯复杂度衡量在网络中发送的字节数,一个相对较慢的过程。回合复杂度衡量两个服务器之间的同步点数目,同步点可能阻塞其中一个服务器,使其无所事事,直到另一个服务器赶上来为止。因而两者均对总执行时间有很大的影响。
然而更重要的是,这些协议的“原生”操作只有加法和乘法。除法、比较等可以完成,但就它们的三项复杂度而言,要更昂贵。之后我们将看下如何缓解这引起的其中一些问题,而这里我们首先讨论基本的SPDZ协议。
张量操作
下面的代码为SPDZ协议实现$PublicTensor$和$PrivateTensor$两个类,分别代表两个服务器知道明文的张量和仅仅知道其秘密分享形式的加密值。
1 | class PrivateTensor: |
以上代码用到的工具函数1
2
3
4
5
6
7
8
9
10
11
12
13
14def share(secrets):
shares0 = sample_random_tensor(secrets.shape)
shares1 = (secrets - shares0) % Q
return shares0, shares1
def reconstruct(shares0, shares1):
secrets = (shares0 + shares1) % Q
return secrets
def generate_mul_triple(x_shape, y_shape):
a = sample_random_tensor(x_shape)
b = sample_random_tensor(y_shape)
c = np.multiply(a, b) % Q
return PrivateTensor(a), PrivateTensor(b), PrivateTensor(c)
适配模型
虽然原则上基于我们现有的模型安全地计算任何函数是可能的,实践中需要做的是先考虑对MPC更友好的模型变体,以及对模型更友好的加密协议。用稍微形象一点的话说,我们经常需要打开两个黑箱,让两个技术更好地适配彼此。
这一做法的根源在于,加密操作下,有一些操作惊人地昂贵。我们之前提到过,加法和乘法相对廉价,而比较和基于私密分母的除法则不然。基于这一原因,我们对模型做了一些改动,以避免这一问题(代价过高)。
优化器
首先涉及的是优化器:尽管许多实现基于Adam的高效而选择了它,Adam涉及对私密值取平方根,以及在除法中使用私密值作分母。尽管理论上安全地进行这些计算是可能的,在实践中它会是性能的显著瓶颈,因此需要避免使用Adam。
一个简单的补救方案是转而使用动量SGD(momentum SGD)优化器,它可能意味着较长的训练时间,但只使用简单的操作。
改为:1
model.compile( loss='categorical_crossentropy', optimizer=SGD(clipnorm=10000, clipvalue=10000), metrics=['accuracy'])
网络层
ReLU和最大池化层有“比较”操作的问题,使用了高阶sigmoid激活函数和平均池化层代替。1
2
3
4
5#Activation('relu')
Activation('sigmoid')
#MaxPooling2D(pool_size=(2,2))
AveragePooling2D(pool_size=(2,2))
另外就是要提高epoch数量,epochs=15。剩下的层很好处理。dropout和平层(flatten)不在乎是加密设定还是非加密设定,密集层和卷积层是矩阵点积,只需要基本操作。