RM新时代网站-首页

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

基于Numpy實現(xiàn)同態(tài)加密神經(jīng)網(wǎng)絡(luò)

zhKF_jqr_AI ? 2018-03-27 14:52 ? 次閱讀

在分布式AI環(huán)境下,同態(tài)加密神經(jīng)網(wǎng)絡(luò)有助于保護(hù)商業(yè)公司知識產(chǎn)權(quán)和消費(fèi)者隱私。讓我們和DeepMind數(shù)據(jù)科學(xué)家、Udacity深度學(xué)習(xí)導(dǎo)師Andrew Trask一起,來看看如何基于Numpy實現(xiàn)同態(tài)加密神經(jīng)網(wǎng)絡(luò)吧。

TLDR:在這篇文章中,我們將訓(xùn)練一個在訓(xùn)練階段完全加密的神經(jīng)網(wǎng)絡(luò)(在未加密的數(shù)據(jù)上訓(xùn)練)。得到的神經(jīng)網(wǎng)絡(luò)將具備兩個有益的性質(zhì)。首先,保護(hù)神經(jīng)網(wǎng)絡(luò)的智能免遭竊取,使有價值的AI可以在不安全的環(huán)境中加以訓(xùn)練而不用冒智能遭竊的風(fēng)險。其次,網(wǎng)絡(luò)只能進(jìn)行加密預(yù)測(大概對外部世界毫無影響,因為在沒有密鑰的情況下,外部世界無法理解預(yù)測)。這在用戶和超智能間構(gòu)成了一個有價值的權(quán)力失衡。如果AI是同態(tài)加密的,那么在AI看來,整個外部世界也是同態(tài)加密的。一個控制密鑰的人類可以選擇解鎖AI本身(將AI釋放到世界中)或僅僅解密AI做出的單個預(yù)測(看起來更安全)。

超智能

很多人都擔(dān)憂超智能有一天會選擇傷害人類。史蒂芬·霍金曾呼吁建立新的世界政府來管理我們賦予人工智能的能力,以防人工智能最終摧毀人類。這些是相當(dāng)大膽的主張,我認(rèn)為它們反映了科學(xué)界和整個世界對這一問題的普遍擔(dān)憂。本文將是一篇介紹解決這一問題的潛在技術(shù)方案的教程,我將通過一些玩具樣例代碼來演示這一方法。

目標(biāo)很簡單。我們想要創(chuàng)建未來會變得非常智能的AI技術(shù)(智能到可以解決治愈癌癥、終結(jié)世界上的饑餓等問題),但是這樣的智能受人類的控制(基于密鑰),因而其智能的應(yīng)用是受限的。不受限的學(xué)習(xí)是很棒的,但知識的不受限的應(yīng)用可能具有潛在危險性。

為了介紹這一想法,讓我先簡要介紹兩個非常激動人心的研究領(lǐng)域:深度學(xué)習(xí)和同態(tài)加密。

一、什么是深度學(xué)習(xí)?

深度學(xué)習(xí)是用于自動化智能的工具套件,主要基于神經(jīng)網(wǎng)絡(luò)。這一計算機(jī)科學(xué)的領(lǐng)域,是最近AI技術(shù)爆發(fā)的主要動力,因為深度學(xué)習(xí)在許多智能任務(wù)上超越了先前的表現(xiàn)記錄。例如,他是DeepMind的AlphaGo系統(tǒng)的主要組成部分。

神經(jīng)網(wǎng)絡(luò)基于輸入做出預(yù)測。它通過試錯法學(xué)習(xí)做出有效的預(yù)測。剛開始,它做出一個預(yù)測(起初基本上是隨機(jī)預(yù)測),接著接收一個“錯誤信號”,該信號表明它的預(yù)測過高或過低(通常是概率)。在這一周期重復(fù)數(shù)百萬次后,網(wǎng)絡(luò)開始搞明白情況。想要了解更多神經(jīng)網(wǎng)絡(luò)如何工作的細(xì)節(jié),請參考基于Numpy實現(xiàn)神經(jīng)網(wǎng)絡(luò):反向傳播一文。

這里最神奇的是錯誤信號。如果不告知預(yù)測的表現(xiàn)有多好,神經(jīng)網(wǎng)絡(luò)無法學(xué)習(xí)。牢記這一點(diǎn)。

二、什么是同態(tài)加密?

顧名思義,同態(tài)加密是一種加密的形式。在不對稱情形下,它可以接受完全可讀的文本,然后基于“公鑰”將其轉(zhuǎn)變?yōu)閬y碼。更重要的是,它可以基于“私鑰”將亂碼轉(zhuǎn)回同樣的文本。然而,除非你有“私鑰”,(理論上)你無法解碼加密后的亂碼。

同態(tài)加密是一種特殊形式的加密。它允許某人在無法閱讀信息的前提下以特定的方式修改加密信息。例如,同態(tài)加密可以應(yīng)用于數(shù)字上,讓加密過的數(shù)字可以進(jìn)行乘法和加法運(yùn)算而無需解密數(shù)字。下面是一些玩具樣例。

現(xiàn)在出現(xiàn)了越來越多的同態(tài)加密方案,各有不同的性質(zhì)。這是一個相對年輕的領(lǐng)域,仍有一些明顯的問題有待解決,不過我們將這些內(nèi)容留待以后討論。

就目前而言,讓我們從整數(shù)公鑰加密方案開始。整數(shù)公鑰加密方案是一種乘法和加法上的同態(tài)加密,允許進(jìn)行上圖的操作。不僅如此,由于公鑰允許“單向”加密,你甚至可以進(jìn)行未加密數(shù)字和加密數(shù)字間的運(yùn)算(通過單向加密),上圖的2 * Cypher A就是一個例子。(某些加密方案甚至不要求這一點(diǎn)……不過同樣……我們以后討論這個。)

三、我們可以結(jié)合這兩者嗎?

也許深度學(xué)習(xí)和同態(tài)加密之間最頻繁的互動體現(xiàn)在數(shù)據(jù)隱私上。當(dāng)你同態(tài)加密數(shù)據(jù)時,你無法讀取數(shù)據(jù)但仍然可以保持大多數(shù)有趣的統(tǒng)計學(xué)結(jié)構(gòu)。這讓人們得以在加密數(shù)據(jù)上訓(xùn)練模型(CryptoNets)。甚至有一家名為Numer.ai的初創(chuàng)對沖基金加密昂貴的專有數(shù)據(jù),允許任何人嘗試訓(xùn)練機(jī)器學(xué)習(xí)模型預(yù)測股票市場。通常這不可能辦到,因為會導(dǎo)致放棄極為昂貴的信息(不可能基于通常的加密數(shù)據(jù)訓(xùn)練模型)。

然而,本文將反其道而行,加密神經(jīng)網(wǎng)絡(luò),然后在解密信息上加以訓(xùn)練。

復(fù)雜度驚人的神經(jīng)網(wǎng)絡(luò),事實上可以劃分成很少(少得驚人)幾種組件,這些組件不斷重復(fù)以構(gòu)成神經(jīng)網(wǎng)絡(luò)。其實,僅僅基于如下操作,就可以創(chuàng)建很多最先進(jìn)的神經(jīng)網(wǎng)絡(luò):

加法

乘法

除法

減法

Sigmoid

Tanh

指數(shù)函數(shù)

那么,讓我們提出這一明顯的技術(shù)問題,我們能否同態(tài)加密神經(jīng)網(wǎng)絡(luò)本身?我們會想這么做嗎?結(jié)果發(fā)現(xiàn),基于一些保守的逼近,這是可以辦到的。

加法 —— 開箱即用

乘法 —— 開箱即用

除法 —— 開箱即用?只是乘法的倒數(shù)

加法 —— 開箱即用?只是加上負(fù)數(shù)

Sigmoid —— 嗯……也許有點(diǎn)難度

Tanh —— 嗯……也許有點(diǎn)難度

指數(shù)函數(shù) —— 嗯……也許有點(diǎn)難度

看起來實現(xiàn)除法和減法會是相當(dāng)微不足道的事情,但那些更復(fù)雜的函數(shù)就……好吧……比簡單的加法和乘法更復(fù)雜。為了嘗試同態(tài)加密一個深度神經(jīng)網(wǎng)絡(luò),我們還需要一個秘密原料。

四、泰勒級數(shù)展開

也許你在小學(xué)學(xué)過,泰勒級數(shù)允許我們使用無限項加法、減法、乘法、除法來計算一個復(fù)雜(非線性)函數(shù)。這很完美?。ǔ藷o限部分)。幸運(yùn)的是,如果你早早地停止了計算精確的泰勒級數(shù)展開,你仍然能得到手頭的函數(shù)的一個逼近值。下面是通過泰勒級數(shù)逼近一些流行函數(shù)的例子(來源)。

等下!這里有指數(shù)!別擔(dān)心。指數(shù)不過是反復(fù)相乘。下面是使用泰勒級數(shù)逼近sigmoid函數(shù)的python實現(xiàn)(相關(guān)公式見Wolfram Alpha)。我們將選取級數(shù)的開始幾項,看看能逼近到什么程度。

import numpy as np

def sigmoid_exact(x):

return1 / (1 + np.exp(-x))

# 使用泰勒級數(shù)

def sigmoid_approximation(x):

return (1 / 2) + (x / 4) - (x**3 / 48) + (x**5 / 480)

for lil_number in [0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0]:

print("\n輸入:" + str(lil_number))

print("精確的Sigmoid值:" + str(sigmoid_exact(lil_number)))

print("逼近Sigmoid:" + str(sigmoid_approximation(lil_number)))

結(jié)果:

輸入:0.1

精確的Sigmoid值:0.52497918747894

逼近Sigmoid:0.5249791874999999

輸入:0.2

精確的Sigmoid值:0.549833997312478

逼近Sigmoid:0.549834

輸入:0.3

精確的Sigmoid值:0.574442516811659

逼近Sigmoid:0.5744425624999999

輸入:0.4

精確的Sigmoid值:0.598687660112452

逼近Sigmoid:0.598688

輸入:0.5

精確的Sigmoid值:0.6224593312018546

逼近Sigmoid:0.6224609375000001

輸入:0.6

精確的Sigmoid值:0.6456563062257954

逼近Sigmoid:0.6456620000000001

輸入:0.7

精確的Sigmoid值:0.6681877721681662

逼近Sigmoid:0.6682043125000001

輸入:0.8

精確的Sigmoid值:0.6899744811276125

逼近Sigmoid:0.690016

輸入:0.9

精確的Sigmoid值:0.7109495026250039

逼近Sigmoid:0.7110426875

輸入:1.0

精確的Sigmoid值:0.7310585786300049

逼近Sigmoid:0.73125

僅僅使用了泰勒級數(shù)的前4項,我們已經(jīng)相當(dāng)逼近sigmoid函數(shù)了。既然我們已經(jīng)具備了通用的策略,是時候選擇一個同態(tài)加密算法了。

五、選擇加密算法

同態(tài)加密是一個相對較新的領(lǐng)域,其中的主要里程碑是Craig Gentry在2009年發(fā)現(xiàn)的第一個全同態(tài)加密算法。這一里程碑為許多后來者建立了據(jù)點(diǎn)。大部分關(guān)于同態(tài)加密的激動人心的研究圍繞開發(fā)圖靈完備的同態(tài)加密計算機(jī)展開。因此,對全同態(tài)加密方案的需求讓人們試圖找到一個算法,使得進(jìn)行任意計算所需的多種邏輯門都可以通這一算法高效而安全地計算。大體的希望是人們能夠安全地將工作放到云端,而不必冒發(fā)送到云端的數(shù)據(jù)被發(fā)送者以外的人讀取的風(fēng)險。這是一個非??岬南敕ǎ踩〉昧撕芏噙M(jìn)展。

然而,這一角度存在一些缺陷。一般而言,相比普通電腦,大多數(shù)全同態(tài)加密方案慢得讓人懷疑人生(目前還不實用)。這鼓舞了一系列有趣的研究,將操作種類限制為某種程度上同態(tài),這樣至少可以進(jìn)行某些操作。不那么靈活,但是更快,這是常見的計算上的折衷。

這是我們想要開始查看的地方。理論上,我們想要一個操作浮點(diǎn)數(shù)的同態(tài)加密方案(不過很快我們將看到,最終我們選擇了操作整數(shù)的方案),而不是操作二進(jìn)制值的方案。二進(jìn)制可以工作,但它不僅要求全同態(tài)加密的靈活性(以性能為代價),還要求我們管理二進(jìn)制表示和我們想要計算的數(shù)學(xué)運(yùn)算之間的邏輯。一個不那么強(qiáng)大,為浮點(diǎn)運(yùn)算定制的HE(HE為同態(tài)加密Homomorphic Encryption的縮寫)算法會更合適。

盡管加上了這一限制,仍有非常多的選擇。下面是一些具備我們需要的特性的流行算法:

Efficient Homomorphic Encryption on Integer Vectors and Its Applications(基于整數(shù)向量的高效同態(tài)加密及其應(yīng)用)

Yet Another Somewhat Homomorphic Encryption (YASHE)(又一個某種程度上的同態(tài)加密)

Somewhat Practical Fully Homomorphic Encryption (FV)(某種程度上實用的全同態(tài)加密)

Fully Homomorphic Encryption without Bootstrapping(非自舉的全同態(tài)加密)

最佳的選擇可能是YASHE或FV。YASHE是流行的CryptoNet使用的算法,對浮點(diǎn)運(yùn)算的支持很棒。然而,它相當(dāng)復(fù)雜。為了讓這篇文章容易閱讀、便于嘗試,我們將選擇稍微不那么高級(可能也不那么安全)的Efficient Integer Vector Homomorphic Encryption(高效整數(shù)向量同態(tài)加密)。然而,我認(rèn)為非常值得指出的是,在你閱讀本文的時候,更多新的HE算法正在開發(fā)之中,同時本文展示的想法通用于任何在整數(shù)或浮點(diǎn)數(shù)的加法和乘法上同態(tài)加密的方案。甚至說,我的愿望是引起對HE的這一應(yīng)用的關(guān)注,以便更多的為深度學(xué)習(xí)優(yōu)化的HE算法能被開發(fā)出來。

Yu、Lai、Paylor的論文Efficient Integer Vector Homomorphic Encryption詳細(xì)描述了這一算法,相應(yīng)的實現(xiàn)可以在GitHub上獲?。╦amespayor/vector-homomorphic-encryption)。主要部分在C++文件vhe.cpp中。下面我們引導(dǎo)讀者閱讀代碼的一個python移植,說明代碼是干什么的。如果你選擇實現(xiàn)一個更高級的方案,這也會很有幫助,因為有一些主題相對而言是通用的(一般函數(shù)名,變量名,等等)。

六、Python中的同態(tài)加密

首先是一些同態(tài)加密術(shù)語:

明文(plaintext)未加密數(shù)據(jù)。也叫“消息”。在我們的例子中,這將是一些表示神經(jīng)網(wǎng)絡(luò)的數(shù)字。

密文(cyphertext)加密數(shù)據(jù)。我們將在密文之上進(jìn)行數(shù)學(xué)運(yùn)算,這些運(yùn)算會改變底層的明文。

公鑰(public key)偽隨機(jī)數(shù)字序列,讓任何人得以加密數(shù)據(jù)??梢院蛣e人分享,因為(理論上)公鑰只能用于加密。

私鑰/密鑰(private/secret key)偽隨機(jī)數(shù)字序列,讓你解密被公鑰加密的數(shù)據(jù)。你不想和別人分享私鑰。否則,別人可以解密你的消息。

對應(yīng)的變量名(不同的同態(tài)加密技術(shù)都傾向于使用這些標(biāo)準(zhǔn)變量名):

S表示密鑰/私鑰的矩陣。用于解密。

M公鑰。用于加密和進(jìn)行數(shù)學(xué)運(yùn)算。在有些算法中,不是所有數(shù)學(xué)運(yùn)算都需要公鑰。但這一算法非常廣泛地使用公鑰。

c加密數(shù)據(jù)向量,密文。

x消息,即明文。有些論文使用m作明文的變量名。

w單個“加權(quán)(weighting)”標(biāo)量變量,用于重加權(quán)輸入消息x(讓它一致地更長或更短)。這一變量用于調(diào)節(jié)信噪比。加強(qiáng)信號后,對于給定的操作而言,消息較不容易受噪聲影響。然而,過于加強(qiáng)信號,會增加完全毀壞數(shù)據(jù)的概率。這是一個平衡。

E或e一般指隨機(jī)噪聲。在某些情形下,指用公鑰加密數(shù)據(jù)前添加的噪聲。一般而言,噪聲使解密更困難。噪聲使同一消息的兩次加密可以不一樣,在讓消息難以破解方面,這很重要。注意,取決于算法和實現(xiàn),這可能是一個向量,也可能是一個矩陣。在其他情形下,指隨操作積累的噪聲,詳見后文。

和許多數(shù)學(xué)論文的慣用法一樣,大寫字母對應(yīng)矩陣,小寫字母對應(yīng)向量,斜體小寫對應(yīng)標(biāo)量。我們關(guān)注同態(tài)加密的四種操作:公私鑰對生成,單向加密,解密,數(shù)學(xué)運(yùn)算。讓我們從解密開始。

左邊的公式描述了密鑰S和消息x的一般關(guān)系。右邊的公式顯示了如何使用密鑰解密消息。不知道你注意到?jīng)]有,右邊的公式并不包含e?;旧希瑧B(tài)加密技術(shù)一般引入足夠多的噪聲使沒有密鑰的情況下難以破解出原始消息,但是引入的噪聲的量又足夠少,當(dāng)你確實具有密鑰時噪聲可以通過取整忽略。右邊的公式中的框表示“取整到最接近的整數(shù)”。其他同態(tài)加密算法使用不同的取整。模數(shù)運(yùn)算幾乎普遍存在。而加密則生成使上述關(guān)系為真的c. 如果S是一個隨機(jī)矩陣,那么c很難解密。一個簡單的、非對稱的生成加密鑰的方式是找到密鑰的逆矩陣。讓我們看下相應(yīng)的Python代碼。

import numpy as np

def generate_key(w,m,n):

S = (np.random.rand(m,n) * w / (2 ** 16)) # 可證明 max(S) < w

return S

def encrypt(x,S,m,n,w):

assert len(x) == len(S)

e = (np.random.rand(m)) # 可證明 max(e) < w / 2

c = np.linalg.inv(S).dot((w * x) + e)

return c

def decrypt(c,S,w):

return (S.dot(c) / w).astype('int')

x = np.array([0,1,2,5])

m = len(x)

n = m

w = 16

S = generate_key(w,m,n)

你可以在Jupyter Notebook中試著運(yùn)行上面的代碼,進(jìn)行一些操作:

注意,我們可以對密文進(jìn)行一些基本的運(yùn)算,這些運(yùn)算改動了相應(yīng)的明文。很優(yōu)雅,不是嗎?

七、優(yōu)化加密

重要一課:回顧一下之前的公式。如果密鑰S是一個單位矩陣,那么c不過是輸入x的一個重加權(quán)的、略帶噪聲的版本。如果你不明白上面的話,請Google“單位矩陣教程”。限于篇幅,這里就不詳細(xì)介紹單位矩陣了。

這引導(dǎo)我們思考加密是如何進(jìn)行的。論文作者沒有顯式地分配一對獨(dú)立的“公鑰”和“私鑰”,相反,提出了一種“鑰交換”技術(shù),將私鑰S替換為S'。更具體地,這一私鑰交換技術(shù)涉及生成一個可以進(jìn)行該變換的矩陣M。由于M具備將消息從未加密狀態(tài)(單位矩陣密鑰)轉(zhuǎn)換為加密狀態(tài)(隨機(jī)而難以猜測的密鑰),這個M矩陣正好可以用作我們的公鑰!

上面一段話包含許多信息,我們也許講得太快了。讓我們重新概括一下。

發(fā)生了什么……

基于上面兩個公式,如果密鑰是一個單位矩陣,那么消息是未加密的。

基于上面兩個公式,如果密鑰是一個隨機(jī)矩陣,那么消息是加密的。

我們構(gòu)造一個矩陣M將一個密鑰轉(zhuǎn)換為另一個私鑰。

當(dāng)矩陣M將單位矩陣轉(zhuǎn)換為一個隨機(jī)密鑰時,根據(jù)定義,它使用單向加密方式加密了消息。

由于M充當(dāng)了“單向加密”的角色,我們稱它為“公鑰”,并且可以像公鑰一樣分發(fā)它,因為它無法用于解密。

好了,不多拖延了,讓我們看下這一切是如何通過Python實現(xiàn)的。

import numpy as np

def generate_key(w,m,n):

S = (np.random.rand(m,n) * w / (2 ** 16)) # 可證明 max(S) < w

return S

def encrypt(x,S,m,n,w):

assert len(x) == len(S)

e = (np.random.rand(m)) # 可證明 max(e) < w / 2

c = np.linalg.inv(S).dot((w * x) + e)

return c

def decrypt(c,S,w):

return (S.dot(c) / w).astype('int')

def get_c_star(c,m,l):

c_star = np.zeros(l * m,dtype='int')

for i in range(m):

b = np.array(list(np.binary_repr(np.abs(c[i]))),dtype='int')

if(c[i] < 0):

b *= -1

c_star[(i * l) + (l-len(b)): (i+1) * l] += b

return c_star

def switch_key(c,S,m,n,T):

l = int(np.ceil(np.log2(np.max(np.abs(c)))))

c_star = get_c_star(c,m,l)

S_star = get_S_star(S,m,n,l)

n_prime = n + 1

S_prime = np.concatenate((np.eye(m),T.T),0).T

A = (np.random.rand(n_prime - m, n*l) * 10).astype('int')

E = (1 * np.random.rand(S_star.shape[0],S_star.shape[1])).astype('int')

M = np.concatenate(((S_star - T.dot(A) + E),A),0)

c_prime = M.dot(c_star)

return c_prime,S_prime

def get_S_star(S,m,n,l):

S_star = list()

for i in range(l):

S_star.append(S*2**(l-i-1))

S_star = np.array(S_star).transpose(1,2,0).reshape(m,n*l)

return S_star

def get_T(n):

n_prime = n + 1

T = (10 * np.random.rand(n,n_prime - n)).astype('int')

return T

def encrypt_via_switch(x,w,m,n,T):

c,S = switch_key(x*w,np.eye(m),m,n,T)

return c,S

x = np.array([0,1,2,5])

m = len(x)

n = m

w = 16

S = generate_key(w,m,n)

上面的代碼的基本思路是讓S大體上是單位矩陣,然后在其之上連接一個隨機(jī)向量T。因此T具備所有密鑰所需的信息,不過我們?nèi)匀恍枰獦?gòu)建一個尺寸為S的矩陣使得一切可以工作。

八、創(chuàng)建一個XOR神經(jīng)網(wǎng)絡(luò)

既然我們已經(jīng)知道如何加密和解密消息(以及進(jìn)行基本的加法和乘法計算),是時候嘗試擴(kuò)展剩余的運(yùn)算,以便構(gòu)建一個簡單的XOR神經(jīng)網(wǎng)絡(luò)。盡管從技術(shù)上說,神經(jīng)網(wǎng)絡(luò)不過是一系列非常簡單的操作,我們還是需要一些操作的組合以實現(xiàn)便利的功能。下面我將描述我們需要的每項操作,以及在一個較高的抽象層次上,我們是如何實現(xiàn)這些操作的(基本上是我們將使用的加法和乘法的序列)。接著我會向你展示代碼。關(guān)于一些細(xì)節(jié),請參考前面提到的論文。

浮點(diǎn)數(shù)我們將簡單地scale浮點(diǎn)數(shù)到整數(shù)。我們將在整數(shù)上訓(xùn)練我們的網(wǎng)絡(luò)(把整數(shù)當(dāng)成浮點(diǎn)數(shù))。比如,假設(shè)scale=1000,0.2 * 0.5 = 0.1就是200 * 500 = 100000。還原時,100000 / (1000 * 1000) = 0.1(因為我們使用了乘法,所以需要除以1000的平方)。初看起來這很有技巧性,但你會適應(yīng)的。由于我們使用的HE方案取整到最接近的整數(shù),這也讓我們得以控制神經(jīng)網(wǎng)絡(luò)的精度。

向量矩陣乘法這是我們的黃油面包(最基本的操作)。事實上,轉(zhuǎn)換密鑰的矩陣M是一種線性變換的方式。

內(nèi)積在合適的背景下,上述線性變換可能是內(nèi)積。

sigmoid由于我們可以進(jìn)行向量矩陣乘法運(yùn)算,基于足夠的乘法,我們可以演算任意多項式的值。因為我們已經(jīng)知道了對應(yīng)sigmoid的泰勒級數(shù)多項式,我們可以演算sigmoid的逼近值!

逐元素矩陣乘法這一操作驚人地低效。我們需要進(jìn)行向量矩陣乘法或一系列內(nèi)積運(yùn)算。

外積我們可以通過掩碼和內(nèi)積完成這一運(yùn)算。

聲明一下,可能存在完成這些運(yùn)算的更高效的方法,但我不想冒打破同態(tài)加密方案完整性的風(fēng)險。所以某種程度上我是通過論文中提供的函數(shù)來反推如何完成上述運(yùn)算的(除了算法容許的sigmoid擴(kuò)展)?,F(xiàn)在,讓我們看看完成這些的Python代碼:

def sigmoid(layer_2_c):

out_rows = list()

for position in range(len(layer_2_c)-1):

M_position = M_onehot[len(layer_2_c)-2][0]

layer_2_index_c = innerProd(layer_2_c,v_onehot[len(layer_2_c)-2][position],M_position,l) / scaling_factor

x = layer_2_index_c

x2 = innerProd(x,x,M_position,l) / scaling_factor

x3 = innerProd(x,x2,M_position,l) / scaling_factor

x5 = innerProd(x3,x2,M_position,l) / scaling_factor

x7 = innerProd(x5,x2,M_position,l) / scaling_factor

xs = copy.deepcopy(v_onehot[5][0])

xs[1] = x[0]

xs[2] = x2[0]

xs[3] = x3[0]

xs[4] = x5[0]

xs[5] = x7[0]

out = mat_mul_forward(xs,H_sigmoid[0:1],scaling_factor)

out_rows.append(out)

return transpose(out_rows)[0]

def load_linear_transformation(syn0_text,scaling_factor = 1000):

syn0_text *= scaling_factor

return linearTransformClient(syn0_text.T,getSecretKey(T_keys[len(syn0_text)-1]),T_keys[len(syn0_text)-1],l)

def outer_product(x,y):

flip = False

if(len(x) < len(y)):

flip = True

tmp = x

x = y

y = tmp

y_matrix = list()

for i in range(len(x)-1):

y_matrix.append(y)

y_matrix_transpose = transpose(y_matrix)

outer_result = list()

for i in range(len(x)-1):

outer_result.append(mat_mul_forward(x * onehot[len(x)-1][i],y_matrix_transpose,scaling_factor))

if(flip):

return transpose(outer_result)

return outer_result

def mat_mul_forward(layer_1,syn1,scaling_factor):

input_dim = len(layer_1)

output_dim = len(syn1)

buff = np.zeros(max(output_dim+1,input_dim+1))

buff[0:len(layer_1)] = layer_1

layer_1_c = buff

syn1_c = list()

for i in range(len(syn1)):

buff = np.zeros(max(output_dim+1,input_dim+1))

buff[0:len(syn1[i])] = syn1[i]

syn1_c.append(buff)

layer_2 = innerProd(syn1_c[0],layer_1_c,M_onehot[len(layer_1_c) - 2][0],l) / float(scaling_factor)

for i in range(len(syn1)-1):

layer_2 += innerProd(syn1_c[i+1],layer_1_c,M_onehot[len(layer_1_c) - 2][i+1],l) / float(scaling_factor)

return layer_2[0:output_dim+1]

def elementwise_vector_mult(x,y,scaling_factor):

y =[y]

one_minus_layer_1 = transpose(y)

outer_result = list()

for i in range(len(x)-1):

outer_result.append(mat_mul_forward(x * onehot[len(x)-1][i],y,scaling_factor))

return transpose(outer_result)[0]

有一點(diǎn)我之前沒有告訴你。為了節(jié)省時間,我預(yù)計算了一些鑰、向量、矩陣,并對它們作了排序。這包括完全由1組成的向量,不同長度的one-hot編碼向量。這有助于上面的掩碼操作,以及其他我們希望可以做到的簡單操作。例如,sigmoid的導(dǎo)數(shù)是sigmoid(x) * (1 - sigmoid(x))。因此,預(yù)計算這些變量會很方便。下面是預(yù)計算步驟。

# 在安全的服務(wù)端進(jìn)行

l = 100

w = 2 ** 25

aBound = 10

tBound = 10

eBound = 10

max_dim = 10

scaling_factor = 1000

# 鑰

T_keys = list()

for i in range(max_dim):

T_keys.append(np.random.rand(i+1,1))

# 單向加密變換

M_keys = list()

for i in range(max_dim):

M_keys.append(innerProdClient(T_keys[i],l))

M_onehot = list()

for h in range(max_dim):

i = h+1

buffered_eyes = list()

for row in np.eye(i+1):

buffer = np.ones(i+1)

buffer[0:i+1] = row

buffered_eyes.append((M_keys[i-1].T * buffer).T)

M_onehot.append(buffered_eyes)

c_ones = list()

for i in range(max_dim):

c_ones.append(encrypt(T_keys[i],np.ones(i+1), w, l).astype('int'))

v_onehot = list()

onehot = list()

for i in range(max_dim):

eyes = list()

eyes_txt = list()

for eye in np.eye(i+1):

eyes_txt.append(eye)

eyes.append(one_way_encrypt_vector(eye,scaling_factor))

v_onehot.append(eyes)

onehot.append(eyes_txt)

H_sigmoid_txt = np.zeros((5,5))

H_sigmoid_txt[0][0] = 0.5

H_sigmoid_txt[0][1] = 0.25

H_sigmoid_txt[0][2] = -1/48.0

H_sigmoid_txt[0][3] = 1/480.0

H_sigmoid_txt[0][4] = -17/80640.0

H_sigmoid = list()

for row in H_sigmoid_txt:

H_sigmoid.append(one_way_encrypt_vector(row))

如果你仔細(xì)查看了上面的代碼,你會注意到H_sigmoid矩陣是我們需要的用于演算sigmoid多項式的矩陣。最后,我們使用如下代碼訓(xùn)練我們的神經(jīng)網(wǎng)絡(luò)。如果不明白神經(jīng)網(wǎng)絡(luò)的部分,你可以溫習(xí)下基于Numpy實現(xiàn)神經(jīng)網(wǎng)絡(luò):反向傳播一文。我基本上使用了文中的XOR網(wǎng)絡(luò),使用適當(dāng)?shù)墓ぞ吆瘮?shù)替換了其中一些操作,以加密權(quán)重。

np.random.seed(1234)

input_dataset = [[],[0],[1],[0,1]]

output_dataset = [[0],[1],[1],[0]]

input_dim = 3

hidden_dim = 4

output_dim = 1

alpha = 0.015

# 使用公鑰單向加密訓(xùn)練數(shù)據(jù)(可就地進(jìn)行)

y = list()

for i in range(4):

y.append(one_way_encrypt_vector(output_dataset[i],scaling_factor))

# 生成權(quán)重

syn0_t = (np.random.randn(input_dim,hidden_dim) * 0.2) - 0.1

syn1_t = (np.random.randn(output_dim,hidden_dim) * 0.2) - 0.1

# 單向加密權(quán)重

syn1 = list()

for row insyn1_t:

syn1.append(one_way_encrypt_vector(row,scaling_factor).astype('int64'))

syn0 = list()

for row insyn0_t:

syn0.append(one_way_encrypt_vector(row,scaling_factor).astype('int64'))

# 開始訓(xùn)練

for iter in range(1000):

decrypted_error = 0

encrypted_error = 0

for row_i in range(4):

if(row_i == 0):

layer_1 = sigmoid(syn0[0])

elif(row_i == 1):

layer_1 = sigmoid((syn0[0] + syn0[1])/2.0)

elif(row_i == 2):

layer_1 = sigmoid((syn0[0] + syn0[2])/2.0)

else:

layer_1 = sigmoid((syn0[0] + syn0[1] + syn0[2])/3.0)

layer_2 = (innerProd(syn1[0],layer_1,M_onehot[len(layer_1) - 2][0],l) / float(scaling_factor))[0:2]

layer_2_delta = add_vectors(layer_2,-y[row_i])

syn1_trans = transpose(syn1)

one_minus_layer_1 = [(scaling_factor * c_ones[len(layer_1) - 2]) - layer_1]

sigmoid_delta = elementwise_vector_mult(layer_1,one_minus_layer_1[0],scaling_factor)

layer_1_delta_nosig = mat_mul_forward(layer_2_delta,syn1_trans,1).astype('int64')

layer_1_delta = elementwise_vector_mult(layer_1_delta_nosig,sigmoid_delta,scaling_factor) * alpha

syn1_delta = np.array(outer_product(layer_2_delta,layer_1)).astype('int64')

syn1[0] -= np.array(syn1_delta[0]* alpha).astype('int64')

syn0[0] -= (layer_1_delta).astype('int64')

if(row_i == 1):

syn0[1] -= (layer_1_delta).astype('int64')

elif(row_i == 2):

syn0[2] -= (layer_1_delta).astype('int64')

elif(row_i == 3):

syn0[1] -= (layer_1_delta).astype('int64')

syn0[2] -= (layer_1_delta).astype('int64')

# 如果有安全性要求,可以將加密的損失發(fā)送到別處解密。

encrypted_error += int(np.sum(np.abs(layer_2_delta)) / scaling_factor)

decrypted_error += np.sum(np.abs(s_decrypt(layer_2_delta).astype('float')/scaling_factor))

sys.stdout.write("\r 迭代" + str(iter) + " 加密損失:" + str(encrypted_error) + " 解密損失:" + str(decrypted_error) + " Alpha:" + str(alpha))

# 讓日志好看一點(diǎn)

if(iter % 10 == 0):

print()

# 加密誤差達(dá)到一定水平后停止訓(xùn)練

if(encrypted_error < 25000000):

break

print("\n最終預(yù)測:")

for row_i in range(4):

if(row_i == 0):

layer_1 = sigmoid(syn0[0])

elif(row_i == 1):

layer_1 = sigmoid((syn0[0] + syn0[1])/2.0)

elif(row_i == 2):

layer_1 = sigmoid((syn0[0] + syn0[2])/2.0)

else:

layer_1 = sigmoid((syn0[0] + syn0[1] + syn0[2])/3.0)

layer_2 = (innerProd(syn1[0],layer_1,M_onehot[len(layer_1) - 2][0],l) / float(scaling_factor))[0:2]

print("真預(yù)測:" + str(output_dataset[row_i]) + " 加密預(yù)測:" + str(layer_2) + " 解密預(yù)測:" + str(s_decrypt(layer_2) / scaling_factor))

迭代0 加密損失:84890656 解密損失:2.529Alpha:0.015

迭代10 加密損失:69494197 解密損失:2.071Alpha:0.015

迭代20 加密損失:64017850 解密損失:1.907Alpha:0.015

迭代30 加密損失:62367015 解密損失:1.858Alpha:0.015

迭代40 加密損失:61874493 解密損失:1.843Alpha:0.015

迭代50 加密損失:61399244 解密損失:1.829Alpha:0.015

迭代60 加密損失:60788581 解密損失:1.811Alpha:0.015

迭代70 加密損失:60327357 解密損失:1.797Alpha:0.015

迭代80 加密損失:59939426 解密損失:1.786Alpha:0.015

迭代90 加密損失:59628769 解密損失:1.778Alpha:0.015

迭代100 加密損失:59373621 解密損失:1.769Alpha:0.015

迭代110 加密損失:59148014 解密損失:1.763Alpha:0.015

迭代120 加密損失:58934571 解密損失:1.757Alpha:0.015

迭代130 加密損失:58724873 解密損失:1.75Alpha:0.0155

迭代140 加密損失:58516008 解密損失:1.744Alpha:0.015

迭代150 加密損失:58307663 解密損失:1.739Alpha:0.015

迭代160 加密損失:58102049 解密損失:1.732Alpha:0.015

迭代170 加密損失:57863091 解密損失:1.725Alpha:0.015

迭代180 加密損失:55470158 解密損失:1.653Alpha:0.015

迭代190 加密損失:54650383 解密損失:1.629Alpha:0.015

迭代200 加密損失:53838756 解密損失:1.605Alpha:0.015

迭代210 加密損失:51684722 解密損失:1.541Alpha:0.015

迭代220 加密損失:54408709 解密損失:1.621Alpha:0.015

迭代230 加密損失:54946198 解密損失:1.638Alpha:0.015

迭代240 加密損失:54668472 解密損失:1.63Alpha:0.0155

迭代250 加密損失:55444008 解密損失:1.653Alpha:0.015

迭代260 加密損失:54094286 解密損失:1.612Alpha:0.015

迭代270 加密損失:51251831 解密損失:1.528Alpha:0.015

迭代276 加密損失:24543890 解密損失:0.732Alpha:0.015

最終預(yù)測:

真實預(yù)測:[0] 加密預(yù)測:[-3761423723.07182550.0] 解密預(yù)測:[-0.112]

真實預(yù)測:[1] 加密預(yù)測:[24204806753.1662670.0] 解密預(yù)測:[ 0.721]

真實預(yù)測:[1] 加密預(yù)測:[23090462896.170280.0] 解密預(yù)測:[ 0.688]

真實預(yù)測:[0] 加密預(yù)測:[1748380342.45533540.0] 解密預(yù)測:[ 0.052]

以上是我訓(xùn)練神經(jīng)網(wǎng)絡(luò)時看到的輸出。加密噪聲的某種組合和低精度導(dǎo)致某種程度上笨重的學(xué)習(xí),因此調(diào)優(yōu)具有一定的技巧性。訓(xùn)練也相當(dāng)慢。這些很大程度上是因為轉(zhuǎn)置運(yùn)算非常昂貴。我比較確定本可以通過更簡單的操作完成轉(zhuǎn)置運(yùn)算,但是,如前所述,像這樣證明概念可行的代碼,我更偏向安全性。

小小的總結(jié)

網(wǎng)絡(luò)的權(quán)重都是加密的。

數(shù)據(jù)解密為1和0.

經(jīng)過訓(xùn)練后,可以解密網(wǎng)絡(luò),以提高性能或進(jìn)行進(jìn)一步的訓(xùn)練(或者轉(zhuǎn)用不同的加密鑰)。

訓(xùn)練損失和輸出預(yù)測同樣是加密過的值。我們需要解碼之后才能解讀網(wǎng)絡(luò)表現(xiàn)。

九、情感分類

下面是一個真實一些的例子,我們在IMDB評論情感數(shù)據(jù)上訓(xùn)練同態(tài)加密的網(wǎng)絡(luò),網(wǎng)絡(luò)基于Udacity的深度學(xué)習(xí)課程。完整代碼發(fā)布在GitHub上。

import time

import sys

import numpy as np

# 調(diào)整之前的網(wǎng)絡(luò)以建模這些現(xiàn)象

classSentimentNetwork:

def __init__(self, reviews,labels,min_count = 10,polarity_cutoff = 0.1,hidden_nodes = 8, learning_rate = 0.1):

np.random.seed(1234)

self.pre_process_data(reviews, polarity_cutoff, min_count)

self.init_network(len(self.review_vocab),hidden_nodes, 1, learning_rate)

def pre_process_data(self,reviews, polarity_cutoff,min_count):

print("Pre-processing data...")

positive_counts = Counter()

negative_counts = Counter()

total_counts = Counter()

for i in range(len(reviews)):

if(labels[i] == 'POSITIVE'):

for word in reviews[i].split(" "):

positive_counts[word] += 1

total_counts[word] += 1

else:

for word in reviews[i].split(" "):

negative_counts[word] += 1

total_counts[word] += 1

pos_neg_ratios = Counter()

for term,cnt in list(total_counts.most_common()):

if(cnt >= 50):

pos_neg_ratio = positive_counts[term] / float(negative_counts[term]+1)

pos_neg_ratios[term] = pos_neg_ratio

for word,ratio in pos_neg_ratios.most_common():

if(ratio > 1):

pos_neg_ratios[word] = np.log(ratio)

else:

pos_neg_ratios[word] = -np.log((1 / (ratio + 0.01)))

review_vocab = set()

for review in reviews:

for word in review.split(" "):

if(total_counts[word] > min_count):

if(word in pos_neg_ratios.keys()):

if((pos_neg_ratios[word] >= polarity_cutoff) or (pos_neg_ratios[word] <= -polarity_cutoff)):

review_vocab.add(word)

else:

review_vocab.add(word)

self.review_vocab = list(review_vocab)

label_vocab = set()

for label in labels:

label_vocab.add(label)

self.label_vocab = list(label_vocab)

self.review_vocab_size = len(self.review_vocab)

self.label_vocab_size = len(self.label_vocab)

self.word2index = {}

for i, word in enumerate(self.review_vocab):

self.word2index[word] = i

self.label2index = {}

for i, label in enumerate(self.label_vocab):

self.label2index[label] = i

def init_network(self, input_nodes, hidden_nodes, output_nodes, learning_rate):

# 設(shè)置輸入層、隱藏層、輸出層節(jié)點(diǎn)數(shù)

self.input_nodes = input_nodes

self.hidden_nodes = hidden_nodes

self.output_nodes = output_nodes

print("Initializing Weights...")

self.weights_0_1_t = np.zeros((self.input_nodes,self.hidden_nodes))

self.weights_1_2_t = np.random.normal(0.0, self.output_nodes**-0.5,

(self.hidden_nodes, self.output_nodes))

print("Encrypting Weights...")

self.weights_0_1 = list()

for i,row in enumerate(self.weights_0_1_t):

sys.stdout.write("\rEncrypting Weights from Layer 0 to Layer 1:" + str(float((i+1) * 100) / len(self.weights_0_1_t))[0:4] + "% done")

self.weights_0_1.append(one_way_encrypt_vector(row,scaling_factor).astype('int64'))

print("")

self.weights_1_2 = list()

for i,row in enumerate(self.weights_1_2_t):

sys.stdout.write("\rEncrypting Weights from Layer 1 to Layer 2:" + str(float((i+1) * 100) / len(self.weights_1_2_t))[0:4] + "% done")

self.weights_1_2.append(one_way_encrypt_vector(row,scaling_factor).astype('int64'))

self.weights_1_2 = transpose(self.weights_1_2)

self.learning_rate = learning_rate

self.layer_0 = np.zeros((1,input_nodes))

self.layer_1 = np.zeros((1,hidden_nodes))

def sigmoid(self,x):

return1 / (1 + np.exp(-x))

def sigmoid_output_2_derivative(self,output):

return output * (1 - output)

def update_input_layer(self,review):

# 清除之前的狀態(tài),重置層至全0

self.layer_0 *= 0

for word in review.split(" "):

self.layer_0[0][self.word2index[word]] = 1

def get_target_for_label(self,label):

if(label == 'POSITIVE'):

return1

else:

return0

def train(self, training_reviews_raw, training_labels):

training_reviews = list()

for review in training_reviews_raw:

indices = set()

for word in review.split(" "):

if(word in self.word2index.keys()):

indices.add(self.word2index[word])

training_reviews.append(list(indices))

layer_1 = np.zeros_like(self.weights_0_1[0])

start = time.time()

correct_so_far = 0

total_pred = 0.5

for i in range(len(training_reviews_raw)):

review_indices = training_reviews[i]

label = training_labels[i]

layer_1 *= 0

for index in review_indices:

layer_1 += self.weights_0_1[index]

layer_1 = layer_1 / float(len(review_indices))

layer_1 = layer_1.astype('int64') # 取整至最接近的整數(shù)

layer_2 = sigmoid(innerProd(layer_1,self.weights_1_2[0],M_onehot[len(layer_1) - 2][1],l) / float(scaling_factor))[0:2]

if(label == 'POSITIVE'):

layer_2_delta = layer_2 - (c_ones[len(layer_2) - 2] * scaling_factor)

else:

layer_2_delta = layer_2

weights_1_2_trans = transpose(self.weights_1_2)

layer_1_delta = mat_mul_forward(layer_2_delta,weights_1_2_trans,scaling_factor).astype('int64')

self.weights_1_2 -= np.array(outer_product(layer_2_delta,layer_1)) * self.learning_rate

for index in review_indices:

self.weights_0_1[index] -= (layer_1_delta * self.learning_rate).astype('int64')

# 我們將即時解密,以便查看發(fā)生了什么

total_pred += (s_decrypt(layer_2)[0] / scaling_factor)

if((s_decrypt(layer_2)[0] / scaling_factor) >= (total_pred / float(i+2)) and label == 'POSITIVE'):

correct_so_far += 1

if((s_decrypt(layer_2)[0] / scaling_factor) < (total_pred / float(i+2)) and label == 'NEGATIVE'):

correct_so_far += 1

reviews_per_second = i / float(time.time() - start)

sys.stdout.write("\rProgress:" + str(100 * i/float(len(training_reviews_raw)))[:4] + "% Speed(reviews/sec):" + str(reviews_per_second)[0:5] + " #Correct:" + str(correct_so_far) + " #Trained:" + str(i+1) + " Training Accuracy:" + str(correct_so_far * 100 / float(i+1))[:4] + "%")

if(i % 100 == 0):

print(i)

def test(self, testing_reviews, testing_labels):

correct = 0

start = time.time()

for i in range(len(testing_reviews)):

pred = self.run(testing_reviews[i])

if(pred == testing_labels[i]):

correct += 1

reviews_per_second = i / float(time.time() - start)

sys.stdout.write("\rProgress:" + str(100 * i/float(len(testing_reviews)))[:4] \

+ "% Speed(reviews/sec):" + str(reviews_per_second)[0:5] \

+ "% #Correct:" + str(correct) + " #Tested:" + str(i+1) + " Testing Accuracy:" + str(correct * 100 / float(i+1))[:4] + "%")

def run(self, review):

# 輸入層

# 隱藏層

self.layer_1 *= 0

unique_indices = set()

for word in review.lower().split(" "):

if word in self.word2index.keys():

unique_indices.add(self.word2index[word])

for index in unique_indices:

self.layer_1 += self.weights_0_1[index]

# 輸出層

layer_2 = self.sigmoid(self.layer_1.dot(self.weights_1_2))

if(layer_2[0] >= 0.5):

return"POSITIVE"

else:

return"NEGATIVE"

Progress:0.0% Speed(reviews/sec):0.0#Correct:1 #Trained:1 Training Accuracy:100.%0

Progress:0.41% Speed(reviews/sec):1.978#Correct:66 #Trained:101 Training Accuracy:65.3%100

Progress:0.83% Speed(reviews/sec):2.014#Correct:131 #Trained:201 Training Accuracy:65.1%200

Progress:1.25% Speed(reviews/sec):2.011#Correct:203 #Trained:301 Training Accuracy:67.4%300

Progress:1.66% Speed(reviews/sec):2.003#Correct:276 #Trained:401 Training Accuracy:68.8%400

Progress:2.08% Speed(reviews/sec):2.007#Correct:348 #Trained:501 Training Accuracy:69.4%500

Progress:2.5% Speed(reviews/sec):2.015#Correct:420 #Trained:601 Training Accuracy:69.8%600

Progress:2.91% Speed(reviews/sec):1.974#Correct:497 #Trained:701 Training Accuracy:70.8%700

Progress:3.33% Speed(reviews/sec):1.973#Correct:581 #Trained:801 Training Accuracy:72.5%800

Progress:3.75% Speed(reviews/sec):1.976#Correct:666 #Trained:901 Training Accuracy:73.9%900

Progress:4.16% Speed(reviews/sec):1.983#Correct:751 #Trained:1001 Training Accuracy:75.0%1000

Progress:4.33% Speed(reviews/sec):1.940#Correct:788 #Trained:1042 Training Accuracy:75.6%

....

十、相比數(shù)據(jù)加密的優(yōu)勢

和這一做法最相似的是加密訓(xùn)練數(shù)據(jù),然后在加密數(shù)據(jù)上訓(xùn)練神經(jīng)網(wǎng)絡(luò)(接受加密輸入并預(yù)測加密輸出)。這是一個出色的想法。然而,其實它有一些缺陷。首先也是最重要的,加密數(shù)據(jù)意味著對任何不具有加密數(shù)據(jù)的私鑰的人而言,該神經(jīng)網(wǎng)絡(luò)完全無用。這樣就不可能在不同的私有數(shù)據(jù)源上訓(xùn)練同一深度學(xué)習(xí)模型了。大部分商業(yè)應(yīng)用有這樣的需求,需要匯總消費(fèi)者的數(shù)據(jù)。理論上,我們本來想要讓每個消費(fèi)者用他們自己的密鑰保護(hù)自己的數(shù)據(jù),然而同態(tài)加密數(shù)據(jù)要求所有人使用相同的鑰。

而加密網(wǎng)絡(luò)則沒有這個限制。

基于上述方法,你可以訓(xùn)練一個平常的、解密的神經(jīng)網(wǎng)絡(luò)一段時間,加密它,將它和相應(yīng)的公鑰發(fā)給A方(A方可以基于其所有的數(shù)據(jù)訓(xùn)練網(wǎng)絡(luò)一段時間……A方保留數(shù)據(jù))。接著,你可以收回這個網(wǎng)絡(luò),解密它,用另一個鑰加密網(wǎng)絡(luò),然后發(fā)給B方,B方在其所有的數(shù)據(jù)上進(jìn)行一些訓(xùn)練。由于網(wǎng)絡(luò)自身被加密了,你可以完全控制全過程中你刻畫的智能。A方和B方將無法知道他們各自收到的是同一個網(wǎng)絡(luò),也無法知道之前見過這個網(wǎng)絡(luò),或在自己的數(shù)據(jù)上用過這個網(wǎng)絡(luò)。你的公司保留對神經(jīng)網(wǎng)絡(luò)中的知識產(chǎn)權(quán)的控制,而每個用戶保留對他們自己的數(shù)據(jù)的控制。

十一、以后的工作

存在更快、更安全的同態(tài)加密算法。我相信將本項工作移植到Y(jié)ASHE會是一個正確的方向。由于一些系統(tǒng)復(fù)雜性,也許開發(fā)一個能讓用戶更簡單地進(jìn)行加密的框架會是一個好主意。一般而言,為了達(dá)到生產(chǎn)環(huán)境要求的質(zhì)量,HE需要變得更快。然而,這方面的進(jìn)展十分迅速。我確信我們會在不久的將來達(dá)到這一點(diǎn)。

十二、潛在應(yīng)用

分布式AI商業(yè)公司可以分布式地部署它們的模型(用于訓(xùn)練或使用),而無需冒智能被竊的風(fēng)險。

保護(hù)消費(fèi)者隱私之前的應(yīng)用提供了這樣的可能性:消費(fèi)者保留他們的數(shù)據(jù),選擇不同的模型在自己的設(shè)備上訓(xùn)練,不用將數(shù)據(jù)發(fā)送到別處。如果商業(yè)公司的智能在分布式場景中沒有被竊的風(fēng)險,那么他們不尊重消費(fèi)者隱私的借口就會少很多。數(shù)據(jù)就是力量,它需要回歸到人們手中。

受控超智能網(wǎng)絡(luò)可以充分發(fā)展其智能,不過除非它具有密鑰,否則它只能預(yù)測亂碼。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴

原文標(biāo)題:基于Numpy實現(xiàn)同態(tài)加密神經(jīng)網(wǎng)絡(luò)

文章出處:【微信號:jqr_AI,微信公眾號:論智】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    基于神經(jīng)網(wǎng)絡(luò)混沌吸引子公鑰加密算法的FPGA實現(xiàn)

    【作者】:劉晉明;劉年生;【來源】:《廈門大學(xué)學(xué)報(自然科學(xué)版)》2010年02期【摘要】:利用具有順序和并行執(zhí)行的特點(diǎn)的VHDL語言,設(shè)計并實現(xiàn)了基于神經(jīng)網(wǎng)絡(luò)混沌吸引子的公鑰加密算法,在編
    發(fā)表于 04-24 09:15

    labview BP神經(jīng)網(wǎng)絡(luò)實現(xiàn)

    請問:我在用labview做BP神經(jīng)網(wǎng)絡(luò)實現(xiàn)故障診斷,在NI官網(wǎng)找到了機(jī)器學(xué)習(xí)工具包(MLT),但是里面沒有關(guān)于這部分VI的幫助文檔,對于”BP神經(jīng)網(wǎng)絡(luò)分類“這個范例有很多不懂的地方,比如
    發(fā)表于 02-22 16:08

    【PYNQ-Z2試用體驗】神經(jīng)網(wǎng)絡(luò)基礎(chǔ)知識

    語言,使用numpy.dot方法即可計算矩陣乘法。 以上便是一個簡單神經(jīng)網(wǎng)絡(luò)的基本原理,對神經(jīng)網(wǎng)絡(luò)有了基本的認(rèn)識之后,我們才能進(jìn)行復(fù)雜的神經(jīng)網(wǎng)絡(luò)設(shè)計??偨Y(jié)本文講解了
    發(fā)表于 03-03 22:10

    卷積神經(jīng)網(wǎng)絡(luò)如何使用

    卷積神經(jīng)網(wǎng)絡(luò)(CNN)究竟是什么,鑒于神經(jīng)網(wǎng)絡(luò)在工程上經(jīng)歷了曲折的歷史,您為什么還會在意它呢? 對于這些非常中肯的問題,我們似乎可以給出相對簡明的答案。
    發(fā)表于 07-17 07:21

    人工神經(jīng)網(wǎng)絡(luò)實現(xiàn)方法有哪些?

    人工神經(jīng)網(wǎng)絡(luò)(Artificial Neural Network,ANN)是一種類似生物神經(jīng)網(wǎng)絡(luò)的信息處理結(jié)構(gòu),它的提出是為了解決一些非線性,非平穩(wěn),復(fù)雜的實際問題。那有哪些辦法能實現(xiàn)人工神經(jīng)
    發(fā)表于 08-01 08:06

    簡單神經(jīng)網(wǎng)絡(luò)實現(xiàn)

    最簡單的神經(jīng)網(wǎng)絡(luò)
    發(fā)表于 09-11 11:57

    如何構(gòu)建神經(jīng)網(wǎng)絡(luò)?

    原文鏈接:http://tecdat.cn/?p=5725 神經(jīng)網(wǎng)絡(luò)是一種基于現(xiàn)有數(shù)據(jù)創(chuàng)建預(yù)測的計算系統(tǒng)。如何構(gòu)建神經(jīng)網(wǎng)絡(luò)神經(jīng)網(wǎng)絡(luò)包括:輸入層:根據(jù)現(xiàn)有數(shù)據(jù)獲取輸入的層隱藏層:使用反向傳播優(yōu)化輸入變量權(quán)重的層,以提高模型的預(yù)測
    發(fā)表于 07-12 08:02

    matlab實現(xiàn)神經(jīng)網(wǎng)絡(luò) 精選資料分享

    習(xí)神經(jīng)神經(jīng)網(wǎng)絡(luò),對于神經(jīng)網(wǎng)絡(luò)實現(xiàn)是如何一直沒有具體實現(xiàn)一下:現(xiàn)看到一個簡單的神經(jīng)網(wǎng)絡(luò)模型用于訓(xùn)
    發(fā)表于 08-18 07:25

    基于BP神經(jīng)網(wǎng)絡(luò)的PID控制

    最近在學(xué)習(xí)電機(jī)的智能控制,上周學(xué)習(xí)了基于單神經(jīng)元的PID控制,這周研究基于BP神經(jīng)網(wǎng)絡(luò)的PID控制。神經(jīng)網(wǎng)絡(luò)具有任意非線性表達(dá)能力,可以通過對系統(tǒng)性能的學(xué)習(xí)來實現(xiàn)具有最佳組合的PID控
    發(fā)表于 09-07 07:43

    使用keras搭建神經(jīng)網(wǎng)絡(luò)實現(xiàn)基于深度學(xué)習(xí)算法的股票價格預(yù)測

    本文使用keras搭建神經(jīng)網(wǎng)絡(luò)實現(xiàn)基于深度學(xué)習(xí)算法的股票價格預(yù)測。本文使用的數(shù)據(jù)來源為tushare,一個免費(fèi)開源接口;且只取開票價進(jìn)行預(yù)測。import numpy as npimport
    發(fā)表于 02-08 06:40

    基于Numpy實現(xiàn)神經(jīng)網(wǎng)絡(luò):反向傳播

    和DeepMind數(shù)據(jù)科學(xué)家、Udacity深度學(xué)習(xí)導(dǎo)師Andrew Trask一起,基于Numpy手寫神經(jīng)網(wǎng)絡(luò),更深刻地理解反向傳播這一概念。
    的頭像 發(fā)表于 04-01 09:29 ?5140次閱讀
    基于<b class='flag-5'>Numpy</b><b class='flag-5'>實現(xiàn)</b><b class='flag-5'>神經(jīng)網(wǎng)絡(luò)</b>:反向傳播

    基于Numpy實現(xiàn)神經(jīng)網(wǎng)絡(luò):如何加入和調(diào)整dropout?

    幾乎所有目前最先進(jìn)的神經(jīng)網(wǎng)絡(luò)都用到了dropout. 這篇教程介紹如何通過幾行Python代碼在神經(jīng)網(wǎng)絡(luò)中加入Dropout. 讀完這篇教程之后,你將得到一個可以工作的dropout實現(xiàn),并且掌握在任何
    的頭像 發(fā)表于 04-15 09:59 ?7613次閱讀
    基于<b class='flag-5'>Numpy</b><b class='flag-5'>實現(xiàn)</b><b class='flag-5'>神經(jīng)網(wǎng)絡(luò)</b>:如何加入和調(diào)整dropout?

    如何使用numpy搭建一個卷積神經(jīng)網(wǎng)絡(luò)詳細(xì)方法和程序概述

    內(nèi)容將繼續(xù)秉承之前 DNN 的學(xué)習(xí)路線,在利用Tensorflow搭建神經(jīng)網(wǎng)絡(luò)之前,先嘗試?yán)?b class='flag-5'>numpy手動搭建卷積神經(jīng)網(wǎng)絡(luò),以期對卷積神經(jīng)網(wǎng)絡(luò)的卷積機(jī)制、前向傳播和反向傳播的原理和過
    的頭像 發(fā)表于 10-20 10:55 ?6064次閱讀

    如何使用Numpy搭建神經(jīng)網(wǎng)絡(luò)

    很多同學(xué)入門機(jī)器學(xué)習(xí)之后,直接用TensorFlow調(diào)包實現(xiàn)神經(jīng)網(wǎng)絡(luò),對于神經(jīng)網(wǎng)絡(luò)內(nèi)在機(jī)理知之甚少。
    的頭像 發(fā)表于 05-18 11:02 ?3597次閱讀
    如何使用<b class='flag-5'>Numpy</b>搭建<b class='flag-5'>神經(jīng)網(wǎng)絡(luò)</b>

    使用NumPy實現(xiàn)前饋神經(jīng)網(wǎng)絡(luò)

    要使用NumPy實現(xiàn)一個前饋神經(jīng)網(wǎng)絡(luò)(Feedforward Neural Network),我們需要從基礎(chǔ)開始構(gòu)建,包括初始化網(wǎng)絡(luò)參數(shù)、定義激活函數(shù)及其導(dǎo)數(shù)、
    的頭像 發(fā)表于 07-11 16:30 ?1626次閱讀
    RM新时代网站-首页