分散式機器學習與同態加密-part2
所有的據科學家都會告訴你,資料集是人工智慧(AI)的命脈。在之前的文章中,我們演示了使用python-paillier 庫來實現聯合學習的簡單安全協議。在這篇文章中,我們將探討如何使用加密模型對遠端資料進行評分。
使用加密模型進行預測
在之前的文章中,我們演示了使用python-paillier 庫來實現聯合學習的簡單安全協議。在這篇文章中,我們將探討如何使用加密模型對遠端資料進行評分。此技術解決方案的可行性非常有趣並且出於隱私原因而相關。這意味著模型的所有者(以及訓練資料)不需要破壞遠端資料所有者的隱私,以便對其資料進行評分;反之亦然,遠端資料所有者對有關評分模型(以及訓練資料)的任何資訊視而不見,因為模型本身是加密的。
我們將假設對Paillier密碼系統以及邏輯迴歸有所瞭解。這個例子的靈感來自部落格文章@iamtrask。
我們使用Enron垃圾郵件資料集的子集。Alice在她擁有的電子郵件上訓練垃圾郵件分類器。她希望將其應用於Bob的個人電子郵件,而不是:
-
要求鮑勃在任何地方傳送他的電子郵件。
-
洩漏有關她所學習的模型或資料集的資訊。
-
讓鮑勃知道他的哪些電子郵件是垃圾郵件。 完整的程式碼可以在github上找到。
首先,我們進行必要的匯入幷包裝下載和準備資料的程式碼。
import time
import os.path
from zipfile import ZipFile
from urllib.request import urlopen
from contextlib import contextmanager
import numpy as np
from sklearn.linear_model import LogisticRegression
from sklearn.feature_extraction.text import CountVectorizer
import phe as paillier
np.random.seed(42)
# Enron spam dataset hosted by https://cloudstor.aarnet.edu.au
url = [ 'https://cloudstor.aarnet.edu.au/plus/index.php/s/RpHZ57z2E3BTiSQ/download', 'https://cloudstor.aarnet.edu.au/plus/index.php/s/QVD4Xk5Cz3UVYLp/download' ]
def download_data():
“““Download two sets of Enron1 spam/ham e-mails if they are not here We will use the first as trainset and the second as testset. Return the path prefix to us to load the data from disk.““”
n_datasets = 2
for d in range(1, n_datasets + 1):
if not os.path.isdir('enron%d' % d):
URL = url[d-1]
print(“Downloading %d/%d: %s” % (d, n_datasets, URL))
folderzip = 'enron%d.zip' % d
with urlopen(URL) as remotedata:
with open(folderzip, 'wb') as z: z.write(remotedata.read())
with ZipFile(folderzip) as z:
z.extractall() os.remove(folderzip)
為了簡單起見,電子郵件被表示為限制詞匯表中單詞的向量,其中每個特徵值都計算一個單詞在電子郵件中出現的時間。我們為此使用了一個
CountVectorzer。
def preprocess_data():
““” Get the Enron e-mails from disk. Represent them as bag-of-words. Shuffle and split train/test. ““” print(“Importing dataset from disk…“)
path = 'enron1/ham/'
ham1 = [open(path + f, 'r', errors='replace').read().strip(r”\n”)
for f in
os.listdir(path) if
os.path.isfile(path + f)]
path = 'enron1/spam/'
spam1 = [open(path + f, 'r', errors='replace').read().strip(r”\n”)
for f in
os.listdir(path) if
os.path.isfile(path + f)]
path = 'enron2/ham/'
ham2 = [open(path + f, 'r', errors='replace').read().strip(r”\n”)
for f in
os.listdir(path) if
os.path.isfile(path + f)]
path = 'enron2/spam/'
spam2 = [open(path + f, 'r', errors='replace').read().strip(r”\n”)
for f in
os.listdir(path) if
os.path.isfile(path + f)]
# Merge and create labels
emails = ham1 + spam1 + ham2 + spam2
y = np.array([-1] * len(ham1) + [1] * len(spam1) + [-1] * len(ham2) + [1] * len(spam2))
# Words count, keep only frequent words
count_vect = CountVectorizer(decode_error='replace', stop_words='english', min_df=0.001)
X = count_vect.fit_transform(emails)
print('Vocabulary size: %d' % X.shape[1])
# Shuffle
perm = np.random.permutation(X.shape[0])
X, y = X[perm, :], y[perm]
# Split train and test
split = 500
X_train, X_test = X[-split:, :], X[:-split, :]
y_train, y_test = y[-split:], y[:-split]
print(“Labels in trainset are {:.2f} spam : {:.2f} ham”.format( np.mean(y_train == 1),
np.mean(y_train == -1))) return X_train, y_train, X_test, y_test
該方案的工作原理如下。Alice根據她擁有的資料對垃圾郵件分類器進行邏輯迴歸訓練。學習之後,她使用Paillier密碼方案生成公鑰/私鑰對。使用公鑰加密模型。公鑰和加密模型被髮送給Bob。Bob將加密模型應用於他自己的資料,獲取每封電子郵件的加密分數。Bob將這些加密的分數傳送給Alice。Alice用私鑰解密它們以獲得垃圾郵件與垃圾郵件的預測。
該協議滿足上述三個條件。特別是,Bob只看到加密的模型和加密的分數,並且在不知道私鑰的情況下無法從中獲取任何內容。
現在來實施。Alice需要能夠對明文資料進行邏輯迴歸,加密模型以供遠端使用,並使用私鑰解密加密的分數。
class Alice:
def __init__(self): self.model = LogisticRegression()
def generate_paillier_keypair(self, n_length): self.pubkey, self.privkey = \ paillier.generate_paillier_keypair(n_length=n_length)
def fit(self, X, y): self.model = self.model.fit(X, y)
def predict(self, X): return self.model.predict(X)
def encrypt_weights(self): coef = self.model.coef_[0, :] encrypted_weights = [self.pubkey.encrypt(coef[i])
for i in range(coef.shape[0])] encrypted_intercept = self.pubkey.encrypt(self.model.intercept_[0]) return encrypted_weights, encrypted_intercept
def decrypt_scores(self, encrypted_scores):
return [self.privkey.decrypt(s)
for s in encrypted_scores]
Bob獲得加密模型和公鑰。他必須能夠使用加密模型對本地明文資料進行評分,但如果沒有Alice持有的私鑰,則無法解密分數。
class Bob:
def __init__(self, pubkey): self.pubkey = pubkey
def set_weights(self, weights, intercept):
self.weights = weights
self.intercept = intercept
def encrypted_score(self, x): “““Compute the score of `x` by multiplying with the encrypted model, which is a vector of `paillier.EncryptedNumber`““”
score = self.intercept _, idx = x.nonzero()
for i in idx: score += x[0, i] * self.weights[i]
return score
def encrypted_evaluate(self, X): return
[self.encrypted_score(X[i, :]) for i in range(X.shape[0])]
讓我們看看指令碼在執行中。我們首先按順序得到資料,並檢驗問題的維數:
download_data() X, y, X_test, y_test = preprocess_data() X.shape (500, 7994)
我們正在處理大約8000項功能。接下來,我們例項化Alice,它生成金鑰對並在本地資料上擬合她的邏輯模型。
alice = Alice() alice.generate_paillier_keypair(n_length=1024) alice.fit(X, y)
尚未執行加密。讓我們看看Alice的分類器的錯誤是_if_她可以訪問Bob的原始(未加密)資料。當然,由於Bob的資料不可用,因此無法在實際場景中瞭解這一點。
np.mean(alice.predict(X_test) != y_test) 0.045683350745559882
現在,Alice加密分類器。
encrypted_weights, encrypted_intercept = alice.encrypt_weights()
我們用Alice的公鑰例項化Bob。Bob使用加密分類器進行評分。
bob = Bob(alice.pubkey) bob.set_weights(encrypted_weights, encrypted_intercept) encrypted_scores = bob.encrypted_evaluate(X_test)
讓我們看看其中一個加密分數是怎樣的。
print(encrypted_scores[0].ciphertext()) 4975557101598019607333115657955782044002134197013151844631125970114580057948777697681679333578395930647500175104718976826465398554390717765586649503985800812276599674119580862642667636337378406851541955675614078001941547394030888287811317521894539431449722023192072949095429036555137484530752817765976765269293455734683337022787581827841503790798807907517815490376905382493360989832127082449724104557596689227300380104999472764265118788640333048806552912736240459059453425987302997946039793991525213509904102136530661457492688678688561944802008308534596837051863930132631396095952823207091622450117172795188329566587
愛麗絲解密鮑勃的分數。
scores = alice.decrypt_scores(encrypted_scores) scores[:5] [-14.511058062671882, -9.188384491859484, -1.746647646814274, -16.91595050694431, -6.716934039494412]
這些分數的符號相當於預測的等級。作為一個正確的檢查,讓我們看看這個模型的錯誤是什麼。請記住,愛麗絲並不瞭解這一點,因為愛麗絲不擁有鮑勃的地面真相標籤。錯誤與上面相同。
np.mean(np.sign(scores) != y_test) 0.045683350745559882 此處(一個連結)
提供了第二個示例的完整程式碼 ,執行時它將輸出與協議的每個步驟相關的時序資訊。
您可能會問:此協議和上一篇文章中的協議是否可以合併?事實上,他們可以模仿前者進行分類而後者進行迴歸的事實。原則上,您可以設定聯合學習方案,其中由客戶端培訓的模型以加密形式遠端部署,然後將預測傳送回該客戶端。
你可能還會喜歡:
ofollow,noindex" target="_blank">什麼是後量子密碼學?
區塊鏈雜談節目薈萃
比特幣網路動量——比特幣價格在主要市場週期中的一個新的領先指標
歡迎收聽“區塊鏈雜談”節目,國內最有質量的區塊鏈知識分享節目。
寧波格密鏈網路科技有限公司,專注於區塊鏈上的密碼技術研發。