奧胡斯大學(xué)密碼學(xué)PhD、Datadog機(jī)器學(xué)習(xí)工程師Morten Dahl介紹了如何實(shí)現(xiàn)基于加密數(shù)據(jù)進(jìn)行訓(xùn)練和預(yù)測(cè)的卷積神經(jīng)網(wǎng)絡(luò)。
TL;DR我們選取了一個(gè)經(jīng)典的CNN深度學(xué)習(xí)模型,經(jīng)過一系列步驟的改造,使其得以基于加密數(shù)據(jù)進(jìn)行訓(xùn)練和預(yù)測(cè)。
通過卷積神經(jīng)網(wǎng)絡(luò)(CNN)分析圖像在最近幾年極為流行,因?yàn)镃NN在圖像相關(guān)任務(wù)上的表現(xiàn)超過了其他許多方法。
最近一個(gè)基于CNN分析圖像的應(yīng)用是檢測(cè)皮膚癌,基于這一應(yīng)用,任何人可以使用手機(jī)應(yīng)用快速地拍攝一張皮膚損傷的照片,并得到“表現(xiàn)與專家相當(dāng)?shù)摹狈治觯梢詤⒖糦ouTube上的視頻demo(youtu.be/toK1OSLep3s))。得以獲取大量的臨床圖像在訓(xùn)練模型上起到了關(guān)鍵作用——可以將這一數(shù)據(jù)集認(rèn)為是敏感信息。
這導(dǎo)向了隱私問題以及安全多方計(jì)算(MPC):現(xiàn)在有多少應(yīng)用因?yàn)槿狈晒┰L問的數(shù)據(jù)而受到限制?在上述案例中,如果允許任何使用手機(jī)應(yīng)用的人貢獻(xiàn)數(shù)據(jù),模型會(huì)不會(huì)得到提升?如果答案是肯定的,有多少人自愿冒暴露與個(gè)人健康相關(guān)的信息呢?
基于MPC我們可以潛在地降低暴露信息的風(fēng)險(xiǎn),從而增強(qiáng)參與的動(dòng)機(jī)。更具體地說,通過轉(zhuǎn)而在加密數(shù)據(jù)上訓(xùn)練,我們不僅可以防止任何人查看個(gè)人數(shù)據(jù),還可以防止泄露學(xué)習(xí)到的模型參數(shù)。差別隱私等其他技術(shù)也可能避免從預(yù)測(cè)中泄露信息,但我們這里暫不討論。
本文將討論一個(gè)簡(jiǎn)化了的圖像分析案例,介紹所有需要用到的技術(shù)。GitHub上有一些和本文配套的notebook(mortendahl/privateml),其中主要的notebook提供了概念證明實(shí)現(xiàn)。
此外,我最近在Paris Machine Learning meetup(巴黎機(jī)器學(xué)習(xí)會(huì)議)上做了關(guān)于本文的報(bào)告,相關(guān)的幻燈片發(fā)布在GitHub倉庫mortendahl/talks下的ParisML17.pdf。
非常感謝Andrew Trask、Nigel Smart、Adrià Gascón、OpenMined社區(qū)對(duì)這一話題的啟發(fā)和討論。
設(shè)定
我們假定訓(xùn)練數(shù)據(jù)集由一些輸入提供者(input provider)共同所有,而數(shù)據(jù)由兩個(gè)不同服務(wù)器(方)進(jìn)行,我們信任兩方不會(huì)在協(xié)議指定的范圍之外協(xié)作。例如,在實(shí)踐中,服務(wù)器可能是共享云環(huán)境下由兩個(gè)不同組織掌握的虛擬實(shí)例。
輸入提供者只需在一開始傳輸他們的(加密)訓(xùn)練數(shù)據(jù);在此之后所有的計(jì)算只涉及兩個(gè)服務(wù)器,這意味著事實(shí)上輸入提供者使用手機(jī)之類的設(shè)備是可行的。訓(xùn)練之后,模型將保持由兩個(gè)服務(wù)器共同所有的加密形式,每個(gè)人都可以使用它做出進(jìn)一步的加密預(yù)測(cè)。
出于技術(shù)原因,我們同時(shí)假設(shè)有一個(gè)不同的加密生產(chǎn)商(crypto producer)生成計(jì)算過程中使用的特定原始材料,以提供效率;存在消除這一額外實(shí)體的方法,不過本文暫不討論這些。
最后,就安全術(shù)語而言,我們追求的是實(shí)踐中常用的典型概念,即誠實(shí)而好奇(或被動(dòng))安全(honest-but-curious (or passive) security),即假定服務(wù)器將遵循協(xié)議,但除此之外會(huì)嘗試了解盡可能多的看到的信息。對(duì)服務(wù)器而言,盡管這個(gè)概念比完全惡意(或主動(dòng))安全(fully malicious (or active) security)要弱一點(diǎn),它仍然針對(duì)任何可能在計(jì)算之后攻破其中一個(gè)服務(wù)器的行為提供強(qiáng)力的保護(hù),不管攻擊者做了什么。注意,本文事實(shí)上允許訓(xùn)練過程中的小部分隱私泄露,詳見后文。
基于CNN進(jìn)行圖像分析
我們的用例是經(jīng)典的MNIST手寫數(shù)字識(shí)別,即學(xué)習(xí)給定圖像中的阿拉伯?dāng)?shù)字,我們將使用Keras示例中的CNN模型作為基礎(chǔ)。
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))
這里不討論這一模型的細(xì)節(jié),因?yàn)榫W(wǎng)上已經(jīng)有很多介紹其原理的資源了。不過基本的想法是首先讓圖像通過一組特征層(feature layer),將輸入圖像的原始像素轉(zhuǎn)換為和我們的分類任務(wù)更相關(guān)的抽象屬性。接著通過一組分類層(classification layer)組合這些屬性,以生成可能數(shù)字的概率分布。最終輸出通常直接是概率最高的數(shù)字。
我們很快將看到,使用Keras的優(yōu)勢(shì)是我們可以快速地在未加密數(shù)據(jù)上進(jìn)行試驗(yàn),看看模型本身的表現(xiàn)如何,同時(shí),Keras提供了一個(gè)簡(jiǎn)單的接口,供我們之后的加密設(shè)定效仿。
基于SPDZ安全計(jì)算
CNN就緒后,我們接著來看MPC。我們將使用當(dāng)前最先進(jìn)的SPDZ協(xié)議,因?yàn)樗试S我們只使用兩個(gè)服務(wù)器,也允許我們通過將特定計(jì)算轉(zhuǎn)移到離線階段以改善在線表現(xiàn)。
和其他典型的安全計(jì)算協(xié)議一樣,所有計(jì)算在一個(gè)域中進(jìn)行,此處的域由一個(gè)質(zhì)數(shù)Q表示。這意味著我們需要編碼CNN使用的浮點(diǎn)數(shù)為以一個(gè)質(zhì)數(shù)為模的整數(shù),這給Q帶來一些限制,進(jìn)而對(duì)性能有所影響。
此外,在SPDZ協(xié)議這樣的交互計(jì)算中,在典型的時(shí)間復(fù)雜度之外,同時(shí)還要考慮通訊和回合復(fù)雜度。通訊復(fù)雜度衡量在網(wǎng)絡(luò)中發(fā)送的字節(jié)數(shù),一個(gè)相對(duì)較慢的過程?;睾蠌?fù)雜度衡量?jī)蓚€(gè)服務(wù)器之間的同步點(diǎn)數(shù)目,同步點(diǎn)可能阻塞其中一個(gè)服務(wù)器,使其無所事事,直到另一個(gè)服務(wù)器趕上來為止。因而兩者均對(duì)總執(zhí)行時(shí)間有很大的影響。
然而更重要的是,這些協(xié)議的“原生”操作只有加法和乘法。除法、比較等可以完成,但就它們的三項(xiàng)復(fù)雜度而言,要更昂貴。之后我們將看下如何緩解這引起的其中一些問題,而這里我們首先討論基本的SPDZ協(xié)議。
張量操作
下面的代碼為SPDZ協(xié)議實(shí)現(xiàn)PublicTensor和PrivateTensor兩個(gè)類,分別代表兩個(gè)服務(wù)器知道明文的張量和僅僅知道其秘密分享形式的加密值。
classPrivateTensor:
def __init__(self, values, shares0=None, shares1=None):
ifnot values isNone:
shares0, shares1 = share(values)
self.shares0 = shares0
self.shares1 = shares1
def reconstruct(self):
returnPublicTensor(reconstruct(self.shares0, self.shares1))
def add(x, y):
if type(y) isPublicTensor:
shares0 = (x.values + y.shares0) % Q
shares1 = y.shares1
returnPrivateTensor(None, shares0, shares1)
if type(y) isPrivateTensor:
shares0 = (x.shares0 + y.shares0) % Q
shares1 = (x.shares1 + y.shares1) % Q
returnPrivateTensor(None, shares0, shares1)
def mul(x, y):
if type(y) isPublicTensor:
shares0 = (x.shares0 * y.values) % Q
shares1 = (x.shares1 * y.values) % Q
returnPrivateTensor(None, shares0, shares1)
if type(y) isPrivateTensor:
a, b, a_mul_b = generate_mul_triple(x.shape, y.shape)
alpha = (x - a).reconstruct()
beta = (y - b).reconstruct()
return alpha.mul(beta) + \
alpha.mul(b) + \
a.mul(beta) + \
a_mul_b
代碼基本上還是直截了當(dāng)?shù)?。?dāng)然,其中有一些技術(shù)上的細(xì)節(jié),詳見和本文配套的notebook。
上面的代碼用到的基本工具函數(shù):
def 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
returnPrivateTensor(a), PrivateTensor(b), PrivateTensor(c)
適配模型
雖然原則上基于我們現(xiàn)有的模型安全地計(jì)算任何函數(shù)是可能的,實(shí)踐中需要做的是先考慮對(duì)MPC更友好的模型變體,以及對(duì)模型更友好的加密協(xié)議。用稍微形象一點(diǎn)的話說,我們經(jīng)常需要打開兩個(gè)黑箱,讓兩個(gè)技術(shù)更好地適配彼此。
這一做法的根源在于,加密操作下,有一些操作驚人地昂貴。我們之前提到過,加法和乘法相對(duì)廉價(jià),而比較和基于私密分母的除法則不然。基于這一原因,我們對(duì)模型做了一些改動(dòng),以避免這一問題。
本節(jié)中涉及的許多改動(dòng)和它們相應(yīng)的性能詳見配套的Python notebook。
優(yōu)化器
首先涉及的是優(yōu)化器:盡管許多實(shí)現(xiàn)基于Adam的高效而選擇了它,Adam涉及對(duì)私密值取平方根,以及在除法中使用私密值作分母。盡管理論上安全地進(jìn)行這些計(jì)算是可能的,在實(shí)踐中它會(huì)是性能的顯著瓶頸,因此需要避免使用Adam。
一個(gè)簡(jiǎn)單的補(bǔ)救方案是轉(zhuǎn)而使用動(dòng)量SGD(momentum SGD)優(yōu)化器,它可能意味著較長(zhǎng)的訓(xùn)練時(shí)間,但只使用簡(jiǎn)單的操作。
model.compile(
loss='categorical_crossentropy',
optimizer=SGD(clipnorm=10000, clipvalue=10000),
metrics=['accuracy'])
還有一個(gè)額外的坑,很多優(yōu)化器使用裁剪(clipping)以避免梯度變得過小或過大。裁剪需要比較私密值,在加密設(shè)定下這又是一個(gè)某種程度上昂貴的操作,因此我們的目標(biāo)是避免使用裁剪(在上面的代碼中,我們?cè)黾恿私缦蓿?/p>
網(wǎng)絡(luò)層
說到比較,ReLU和最大池化層同樣有這個(gè)問題。CryptoNet用一個(gè)平方函數(shù)取代了前者,用平均池化取代了后者,而SecureML實(shí)現(xiàn)了一個(gè)類似ReLU的激活函數(shù)(不過,這增加了復(fù)雜度,為了保持簡(jiǎn)單,本文打算避免這一點(diǎn))。因此,我們這里使用了高階sigmoid激活函數(shù)和平均池化層。注意平均池化同樣用到了除法,不過這回分母是公開值,因而除法不過是對(duì)公開值取倒數(shù),接著進(jìn)行一次乘法。
feature_layers = [
Conv2D(32, (3, 3), padding='same', input_shape=(28, 28, 1)),
Activation('sigmoid'),
Conv2D(32, (3, 3), padding='same'),
Activation('sigmoid'),
AveragePooling2D(pool_size=(2,2)),
Dropout(.25),
Flatten()
]
classification_layers = [
Dense(128),
Activation('sigmoid'),
Dropout(.50),
Dense(NUM_CLASSES),
Activation('softmax')
]
model = Sequential(feature_layers + classification_layers)
模擬表明這一改動(dòng)讓我們需要提高epoch數(shù),相應(yīng)地減慢訓(xùn)練速度。學(xué)習(xí)率或動(dòng)量的其他選擇可能可以改善這一點(diǎn)。
model.fit(
x_train, y_train,
epochs=15,
batch_size=32,
verbose=1,
validation_data=(x_test, y_test))
剩下的層很好處理。dropout和平層(flatten)不在乎是加密設(shè)定還是非加密設(shè)定,密集層和卷積層是矩陣點(diǎn)積,只需要基本操作。
softmax和損失函數(shù)
在加密設(shè)定下,最后的softmax層同樣會(huì)給訓(xùn)練帶來復(fù)雜度,因?yàn)槲覀冃枰M(jìn)行以私密值為指數(shù)的指數(shù)運(yùn)算,以及基于私密分母除法的歸一化。
盡管這兩者都是可能達(dá)成的,我們這里選擇了一個(gè)更簡(jiǎn)單的做法,允許向其中一個(gè)服務(wù)器暴露每個(gè)訓(xùn)練樣本的預(yù)測(cè)分類的似然,該服務(wù)器接著基于暴露值計(jì)算結(jié)果。這當(dāng)然導(dǎo)致了隱私泄露,這樣的泄露可能會(huì),也可能不會(huì)形成可接受的風(fēng)險(xiǎn)。
一個(gè)啟發(fā)式的改進(jìn)方案是在暴露任何值前先變換分類似然的向量,從而隱藏哪個(gè)分類對(duì)應(yīng)哪個(gè)向量。然而,這可能起不到什么效果,比如,“健康”常常意味著收緊的分布,而“患病”常常意味著舒展的分布。
另一個(gè)方案是引入第三個(gè)服務(wù)器,專門進(jìn)行這類小計(jì)算,其他任何訓(xùn)練數(shù)據(jù)的信息對(duì)該服務(wù)器而言都將是不可見的,因而無法將標(biāo)簽和樣本數(shù)據(jù)關(guān)聯(lián)起來。雖然這樣仍有部分信息泄露,但這一數(shù)量難以進(jìn)行推理。
最后,我們可以將這樣的一對(duì)多方法替換為一對(duì)一方法,比如,使用sigmoid。如前所述,這允許我們?cè)诓唤饷艿那闆r下完整地計(jì)算預(yù)測(cè)。不過我們?nèi)匀恍枰?jì)算損失,我們也許可以同樣考慮使用一個(gè)不同的損失函數(shù)。
注意,在之后使用訓(xùn)練過的網(wǎng)絡(luò)進(jìn)行預(yù)測(cè)時(shí),這里提到的問題都不存在,因?yàn)闆]有損失需要計(jì)算,而服務(wù)器可以直接跳過softmax層,讓預(yù)測(cè)的接收方自行計(jì)算相應(yīng)值:對(duì)于接收方而言,這只不過是一個(gè)如何解釋值的問題。
遷移學(xué)習(xí)
到此為止,看起來我們已經(jīng)可以按現(xiàn)狀實(shí)際訓(xùn)練模型并得到不錯(cuò)的結(jié)果了。不過,依照CNN的慣例,我們可以利用遷移學(xué)習(xí)顯著加速訓(xùn)練過程;事實(shí)上,某種程度上而言,“極少有人從頭訓(xùn)練他們自己的卷積網(wǎng)絡(luò),因?yàn)樗麄儾⒉痪邆渥銐虻臄?shù)據(jù)”,,“實(shí)踐中總是推薦使用遷移學(xué)習(xí)”,是眾所周知的事實(shí)。
在我們這里的設(shè)定中,遷移學(xué)習(xí)的特定應(yīng)用可能是訓(xùn)練分為兩階段:使用非敏感的公開數(shù)據(jù)的預(yù)訓(xùn)練階段和使用敏感的隱私數(shù)據(jù)的調(diào)優(yōu)階段。例如,在檢測(cè)皮膚癌的案例中,研究人員可能選擇在公開照片集上進(jìn)行預(yù)訓(xùn)練,之后請(qǐng)求志愿者提供額外的照片以改進(jìn)模型。
除了基數(shù)的不同以外,兩個(gè)數(shù)據(jù)集的主體也可能不同,因?yàn)镃NN具有首先分解主體為有意義的子部分的傾向,識(shí)別哪部分是什么可以被遷移。換句話說,這一技術(shù)足夠強(qiáng)大,預(yù)訓(xùn)練可以在和調(diào)優(yōu)不同類型的圖像上進(jìn)行。
回到我們具體的字符識(shí)別用例中,我們可以讓0-4作為“公開”圖像,而讓5-9作為“私密”圖像。作為替代,讓a-z作為“公開”圖像,0-9作為“私密圖像”看起來也沒什么不合理的。
在公開數(shù)據(jù)集上進(jìn)行預(yù)訓(xùn)練
除了避免在公開數(shù)據(jù)集上進(jìn)行加密數(shù)據(jù)訓(xùn)練的額外開銷之外,在公開數(shù)據(jù)集上進(jìn)行預(yù)訓(xùn)練還讓我們得以使用更高級(jí)的優(yōu)化器。比如,這里我們可以轉(zhuǎn)回去使用Adam優(yōu)化器訓(xùn)練圖像,以加快訓(xùn)練進(jìn)度。特別地,我們可以降低所需的epoch數(shù)。
(x_train, y_train), (x_test, y_test) = public_dataset
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))
一旦我們對(duì)預(yù)訓(xùn)練的結(jié)果滿意,服務(wù)器可以直接共享模型參數(shù),轉(zhuǎn)而開始訓(xùn)練私密數(shù)據(jù)集。
在隱私數(shù)據(jù)集上進(jìn)行調(diào)優(yōu)
我們開始進(jìn)行加密訓(xùn)練時(shí),模型的參數(shù)已經(jīng)“到了中途”,因此我們可以期望,不再需要那么多epoch了。如前所述,遷移學(xué)習(xí)還有一個(gè)優(yōu)勢(shì),識(shí)別子部件傾向于發(fā)生在網(wǎng)絡(luò)的底層,在某些情形下可能可以按現(xiàn)狀使用。因此,我們現(xiàn)在凍結(jié)特征層的參數(shù),集中訓(xùn)練分類層。
for layer in feature_layers:
layer.trainable = False
不過,我們?nèi)匀恍枰屗兴矫苡?xùn)練樣本前向通過這些層;唯一的差別是在反向傳播這一步我們跳過這些層,因此我們需要訓(xùn)練的參數(shù)減少了。
接下來的訓(xùn)練和前面一樣,只不過現(xiàn)在使用較低的學(xué)習(xí)率:
(x_train, y_train), (x_test, y_test) = private_dataset
model.compile(
loss='categorical_crossentropy',
optimizer=SGD(clipnorm=10000, clipvalue=10000, lr=0.1, momentum=0.0),
metrics=['accuracy'])
model.fit(
x_train, y_train,
epochs=5,
batch_size=32,
verbose=1,
validation_data=(x_test, y_test))
最終,我們?cè)谀M中將epoch數(shù)從25降到了5.
預(yù)處理
還有少數(shù)可以應(yīng)用的預(yù)處理優(yōu)化,不過這里我們不再進(jìn)一步優(yōu)化下去了。
第一個(gè)優(yōu)化是將凍結(jié)層的計(jì)算轉(zhuǎn)移到輸入提供者那里,這樣,和服務(wù)器共享的將是平層而不是圖像的像素。在這一情形下,這些層進(jìn)行的是特征提?。╢eature extraction),潛在地讓我們可能使用更強(qiáng)大的層。然而,如果我們想要保持模型專有,那么這會(huì)顯著增加復(fù)雜度,因?yàn)楝F(xiàn)在參數(shù)需要以某種形式分發(fā)到客戶端。
另一個(gè)典型的加快訓(xùn)練的方法是首先應(yīng)用諸如主成分分析之類的降維技術(shù)。BSS+’17的加密設(shè)定使用了這一方法。
適配協(xié)議
查看了模型之后,我們接著來看協(xié)議:同樣,正如我們即將看到的,理解我們需要進(jìn)行的操作有助于提升速度。
特別地,許多計(jì)算可以轉(zhuǎn)移到加密提供者處,加密提供者生成的原始材料獨(dú)立于私密輸入,某種程度上甚至獨(dú)立于模型。因此,它的計(jì)算可以在方便的時(shí)候大批量地實(shí)現(xiàn)完成。
回憶一下先前提到的有必要同時(shí)優(yōu)化回合復(fù)雜度和通訊復(fù)雜度,而這里提議的擴(kuò)展常常旨在優(yōu)化這兩者,不過作為代價(jià),需要額外的本地計(jì)算。因此,需要進(jìn)行實(shí)際的試驗(yàn)以驗(yàn)證它們?cè)诰唧w情形下的益處。
Dropout
從最簡(jiǎn)單的網(wǎng)絡(luò)層類型開始,我們注意到?jīng)]有任何和安全計(jì)算特別相關(guān)的事情發(fā)生在這一層,這一層只是確保兩個(gè)服務(wù)器同意在每次訓(xùn)練迭代中丟棄哪些值。這可以通過直接同意一個(gè)種子值達(dá)成。
平均池化
平均池化的前向傳播只需要一次累加以及隨后的基于公開分母的除法。因此,它可以通過乘以一個(gè)公開值實(shí)現(xiàn):由于分母是公開的,我們可以很容易找到它的倒數(shù),然后直接相乘并截?cái)唷n愃频?,反向傳播不過是縮放,因而兩個(gè)方向的傳播都完全是本地操作。
密集層
密集層的前向傳播和反向傳播都需要進(jìn)行點(diǎn)積操作,該操作當(dāng)然可以通過經(jīng)典的乘法和加法實(shí)現(xiàn)。如果我們想為形狀分別為(m, k)和(k, n)的矩陣x和y計(jì)算點(diǎn)積dot(x, y),那么這將需要m * n * k次乘法,意味著我們需要通訊同等數(shù)量的掩碼后的值。盡管這些可以并發(fā)發(fā)送,所以我們僅僅需要一回合,如果我們可以使用另一種預(yù)處理的三元組,那么我們可以降低一個(gè)數(shù)量級(jí)的通訊成本。
例如,我們的模型的第二個(gè)密集層計(jì)算(32, 128)和(128, 5)這兩個(gè)矩陣的點(diǎn)積。使用典型的方法,每個(gè)batch中需要發(fā)送32 * 5 * 128 == 22400掩碼后的值,但使用下面描述的預(yù)處理的三元組,我們只需發(fā)送32 * 128 + 5 * 128 == 4736掩碼后的值,幾乎有5倍的改善。第一個(gè)密集層的效果還要好,大約有25倍多的改善。
技巧在于確保矩陣中的每個(gè)私密值的掩碼僅發(fā)送一次。為了達(dá)成這一點(diǎn),我們需要三元組(a, b, c),其中,a和b是形狀合適的隨機(jī)矩陣,c滿足c == dot(a, b)。
def generate_dot_triple(x_shape, y_shape):
a = sample_random_tensor(x_shape)
b = sample_random_tensor(y_shape)
c = np.dot(a, b) % Q
returnPrivateTensor(a), PrivateTensor(b), PrivateTensor(c)
給定這樣一個(gè)三元組,我們可以轉(zhuǎn)而通訊alpha = x - a和beta = y - b的值,接著通過本地計(jì)算得到dot(x, y)。
classPrivateTensor:
...
def dot(x, y):
if type(y) isPublicTensor:
shares0 = x.shares0.dot(y.values) % Q
shares1 = x.shares1.dot(y.values) % Q
returnPrivateTensor(None, shares0, shares1)
if type(y) isPrivateTensor:
a, b, a_dot_b = generate_dot_triple(x.shape, y.shape)
alpha = (x - a).reconstruct()
beta = (y - b).reconstruct()
return alpha.dot(beta) + \
alpha.dot(b) + \
a.dot(beta) + \
a_dot_b
使用這一三元組的安全性取決于三元組乘法的安全性:通訊的掩碼后的值完美地隱藏了x和y的值,而c是一個(gè)獨(dú)立的新的共享值,這確保了結(jié)果無法泄露任何有關(guān)其組成的信息。
注意,SecureML使用了這類三元組,SecureML同時(shí)給出了無需加密提供者幫助、由服務(wù)器自行生成三元組的技術(shù)。
卷積
類似密集層,卷積可以被看作一系列標(biāo)量乘法或矩陣乘法,盡管后者首先需要將訓(xùn)練樣本的張量擴(kuò)展為帶有很多冗余的矩陣。一點(diǎn)也不讓人驚訝的是,兩者均導(dǎo)致通訊成本增加,通過引入另一種三元組,可以加以改進(jìn)。
舉個(gè)例子,第一卷積層使用32個(gè)形狀為(3, 3, 1)的核將形狀為(m, 28, 28, 1)的張量映射為(m, 28, 28, 32)的張量(不考慮偏置向量)。對(duì)于batch尺寸m == 32而言,如果我們僅僅使用標(biāo)量乘法,這意味著7,225,344個(gè)通訊元素,如果我們使用矩陣乘法,則是226,080個(gè)通訊元素。然而,由于總共只涉及(32*28*28) + (32*3*3) == 25,376個(gè)私密值(同樣不計(jì)算偏置向量,因?yàn)樗鼈儍H僅需要加法),我們看到這里大概有9倍的額外開銷。換句話說,每個(gè)私密值都被掩碼和發(fā)送了好幾次?;谝环N新的三元組,我們可以消除這一額外開銷,節(jié)省通訊成本:對(duì)64位元素而言,這意味這每batch的成本為200KB,而不是相應(yīng)的1.7MB和55MB。
我們這里需要的三元組(a, b, c)和點(diǎn)積中使用的類似,a和b具有匹配輸入的形狀,即(m, 28, 28, 1)和(32, 3, 3, 1),而c則匹配輸出形狀(m, 28, 28, 32)。
sigmoid激活
如同我們先前做的那樣,我們可以使用9項(xiàng)多項(xiàng)式來逼近sigmoid激活函數(shù)至足夠的精確程度。為私密值x演算這一多項(xiàng)式的值需要計(jì)算一系列x的次方,這些當(dāng)然可以通過一系列乘法來完成——但這意味著許多回合和相應(yīng)數(shù)量的通訊。
作為替代,我們一樣可以使用一種新的三元組,該三元組允許我們?cè)谝粋€(gè)回合中計(jì)算所有需要的次方。這些“三元組”的長(zhǎng)度不是固定的,等于最高的指數(shù),比如對(duì)應(yīng)平方的三元組包含a和a**2的獨(dú)立共享,而對(duì)應(yīng)立方的三元組包含a、a**2、a**3的獨(dú)立共享。
一旦我們具備了這些x的次方值,演算帶有公開系數(shù)的多項(xiàng)式就僅僅是本地的加權(quán)總和了。這一計(jì)算的安全性同樣來自于三元組中的所有次方是獨(dú)立共享的。
def pol_public(x, coeffs, triple):
powers = pows(x, triple)
return sum( xe * ce for xe, ce in zip(powers, coeffs) )
和先前一樣,我們會(huì)遇到關(guān)于定點(diǎn)數(shù)精度的坑,即次方的更高精度要求更多的空間:x**n有n倍x的精度,而我們想要確保它不會(huì)在以Q為模時(shí)溢出以致我們無法正確解碼。我們可以通過引入一個(gè)足夠大的域P,在計(jì)算次方時(shí)臨時(shí)切換過去,代價(jià)是額外的兩回合通訊。
實(shí)踐中的試驗(yàn)將表明到底是保持Q使用更多的乘法回合更好,還是進(jìn)行切換支付大數(shù)轉(zhuǎn)換和算術(shù)的代價(jià)更好。特別地,對(duì)低階多項(xiàng)式而言,前者看起來更好。
概念證明實(shí)現(xiàn)
有一個(gè)不帶網(wǎng)絡(luò)的概念證明實(shí)現(xiàn)可供實(shí)驗(yàn)和重現(xiàn)。該實(shí)現(xiàn)尚未完工,目前代碼支持基于加密特征訓(xùn)練一個(gè)新分類器,但不支持從加密圖像中提取特征。換句話說,它假定輸入提供者自行在特征提取層中運(yùn)行圖像,然后將結(jié)果以加密形式發(fā)送給服務(wù)器;因此,模型相應(yīng)部分的權(quán)重目前而言并未保持私密。以后的版本將處理這一點(diǎn),使特征層可以在加密數(shù)據(jù)上運(yùn)行,從而直接基于圖像訓(xùn)練和預(yù)測(cè)。
from pond.nn importSequential, Dense, Sigmoid, Dropout, Reveal, Softmax, CrossEntropy
from pond.tensor importPrivateEncodedTensor
classifier = Sequential([
Dense(128, 6272),
Sigmoid(),
Dropout(.5),
Dense(5, 128),
Reveal(),
Softmax()
])
classifier.initialize()
classifier.fit(
PrivateEncodedTensor(x_train_features),
PrivateEncodedTensor(y_train),
loss=CrossEntropy(),
epochs=3
)
代碼分成幾個(gè)Python notebook,帶有預(yù)計(jì)算的權(quán)重,所以你也可以跳過某些步驟:
第一個(gè)notebook使用Keras處理公開數(shù)據(jù)上的預(yù)訓(xùn)練,并為特征提取生成模型??梢蕴^這一步,轉(zhuǎn)而使用倉庫中的預(yù)計(jì)算權(quán)重。
第二個(gè)notebook將上面的模型應(yīng)用于私密數(shù)據(jù)上的特征提取,從而生成用于訓(xùn)練新的加密分類器的特征。以后的版本將首先加密數(shù)據(jù)。這一步無法省略,因?yàn)樘崛〉臄?shù)據(jù)太大了。
第三個(gè)notebook接受提取的特征,并訓(xùn)練一個(gè)新的加密分類器。這是目前為止最昂貴的一步,可以通過使用倉庫中的預(yù)計(jì)算權(quán)重跳過。
最后,第四個(gè)notebook使用新的分類器在新圖像上進(jìn)行加密預(yù)測(cè)。同樣,特征提取目前是未加密的。
運(yùn)行以上代碼需要先克隆倉庫
$ git clone https://github.com/mortendahl/privateml.git && \
cd privateml/image-analysis/
安裝依賴
$ pip3 install jupyter numpy tensorflow keras h5py
運(yùn)行notebook
$ jupyter notebook
想法
一如既往,當(dāng)先前的想法和疑問得到解答后,早已有一批新的等在那里了。
推廣三元組
嘗試減少通訊的時(shí)候,有人可能會(huì)好奇通過使用額外的三元組,有多少工作可以轉(zhuǎn)移到預(yù)處理階段完成。
前面已經(jīng)好幾次提到了(同時(shí)也是BCG+’17等論文的主張),我們通常尋求確保每個(gè)私密值只發(fā)送掩碼一次。所以,如果我們,比如說,同時(shí)計(jì)算dot(x, y)和dot(x, z),那么,有一個(gè)三元組(r, s, t, u, v)會(huì)是有意義的,其中,r用于掩碼x,s用于掩碼y,u用于掩碼z,而t和u用于計(jì)算結(jié)果。比如,這一模式在訓(xùn)練時(shí)出現(xiàn),在前向傳播時(shí)計(jì)算的值有時(shí)可以被緩存下來,在反向傳播時(shí)加以復(fù)用。
不過,也許更重要的是我們僅僅基于一個(gè)模型做出預(yù)測(cè)的時(shí)候,即,基于固定的私有權(quán)重進(jìn)行計(jì)算。在這一情形下,我們想要只掩碼權(quán)重一次然后在每次預(yù)測(cè)時(shí)加以復(fù)用。進(jìn)行這樣的操作意味著我們的掩碼和通訊數(shù)量與通過模型的輸入向量成正比,而不是與輸入向量和權(quán)重成正比,JVC’18之類的論文就是這么做的。更一般地,理想情況下,我們想要通訊只與變動(dòng)的值成正比,這可以通過特制的三元組(在分期付款的意義上)達(dá)成。
最后,原則上可以讓三元組執(zhí)行更多的功能,比如在一回合的通訊中同時(shí)演算密集層和它的激活函數(shù),但最大的阻礙看起來是可伸縮性問題,包括三元組的儲(chǔ)存,和重組步驟中需要進(jìn)行的計(jì)算量,特別是處理張量時(shí)。
激活函數(shù)
一個(gè)自然的問題是其他哪些典型的激活函數(shù)在加密配置下比較高效。如前所述,SecureML通過臨時(shí)切換到亂碼電路來使用ReLU,而CryptoDL給出了sigmoid、ReLU、Tanh的低階多項(xiàng)式逼近(通了提高精確度,使用了切比雪夫多項(xiàng)式)。
也許有必要考慮更簡(jiǎn)單的非典型激活函數(shù),比如CryptoNet等使用的平方,如果簡(jiǎn)化計(jì)算和通訊最重要的話。
亂碼電路
前文提到通過使用亂碼電路更安全地演算更高級(jí)的激活函數(shù),實(shí)際上,亂碼電路還可以用于更大的部分,包括作為安全計(jì)算的主要手段,像DeepSecure等所做的那樣。
和SPDZ之類的技術(shù)相比,亂碼電路的優(yōu)勢(shì)是僅使用固定數(shù)目的通訊回合。缺點(diǎn)是操作常常發(fā)生在字節(jié)上,而不是相對(duì)而言較大的域元素上,這意味著涉及更多計(jì)算。
精度
大量圍繞聯(lián)合學(xué)習(xí)(federated learning)的研究涉及梯度壓縮(gradient compression)以便減少通訊成本。接近我們?cè)O(shè)定的是BMMP’17,基于量子化應(yīng)用同態(tài)加密到深度學(xué)習(xí)上,甚至未加密的生產(chǎn)環(huán)境就緒系統(tǒng)也常常考慮這一技術(shù),以提高學(xué)習(xí)的性能。
浮點(diǎn)數(shù)運(yùn)算
上面我們使用定點(diǎn)數(shù)將實(shí)數(shù)編碼為有限域元素,而未加密深度學(xué)習(xí)通常使用浮點(diǎn)數(shù)編碼。如ABZS’12和SPDZ的參考實(shí)現(xiàn)所展示的那樣,在加密設(shè)定下使用浮點(diǎn)數(shù)編碼也是可能的,顯然浮點(diǎn)數(shù)編碼在某些操作上性能更有優(yōu)勢(shì)。
出于性能考慮,今時(shí)今日深度學(xué)習(xí)通常在GPU上進(jìn)行,因此很自然地就想到是否可以應(yīng)用類似的加速手段到MPC計(jì)算上。亂碼電路已經(jīng)有這方面的工作,而SPDZ之類的安全共享設(shè)定中這看起來不是那么流行。
這里面臨的最大問題可能是GPU上的任意精度算術(shù)的成熟度和實(shí)用度(不過,其實(shí)已經(jīng)有一些這方面的研究了),因?yàn)樵谳^大的域元素(比如64位之上)上的計(jì)算需要這個(gè)。不過,這里該記住兩點(diǎn):首先,盡管我們計(jì)算的域元素大于那些原生支持的,它們?nèi)匀皇怯薪绲模?shù));其次,我們可以在環(huán)上(而不是域上)進(jìn)行我們的安全計(jì)算。
-
神經(jīng)網(wǎng)絡(luò)
+關(guān)注
關(guān)注
42文章
4733瀏覽量
100415 -
機(jī)器學(xué)習(xí)
+關(guān)注
關(guān)注
66文章
8349瀏覽量
132312
原文標(biāo)題:基于Keras實(shí)現(xiàn)加密卷積神經(jīng)網(wǎng)絡(luò)
文章出處:【微信號(hào):jqr_AI,微信公眾號(hào):論智】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論