譯者 | 布加迪
審校 | 重樓
在云計算和基于機器學(xué)習(xí)的服務(wù)唾手可得的時代,隱私是一大挑戰(zhàn)。將端到端隱私添加到協(xié)作式機器學(xué)習(xí)用例聽起來像是一項艱巨的任務(wù)。幸好,諸如完全同態(tài)加密(FHE)之類的密碼學(xué)突破提供了解決方案。Zama的新演示展示了如何利用開源機器學(xué)習(xí)工具使用聯(lián)合學(xué)習(xí)和FHE來添加端到端隱私。這篇博文解釋了這番演示的底層工作機理,結(jié)合了scikit-learn、聯(lián)合學(xué)習(xí)和FHE。
FHE這種技術(shù)使應(yīng)用程序提供方能夠構(gòu)建基于云的應(yīng)用程序以保護用戶隱私,而Concrete ML這種機器學(xué)習(xí)工具包可以讓模型改而使用FHE。Concrete ML利用了scikit-learn中強大穩(wěn)健的模型訓(xùn)練算法來訓(xùn)練與FHE兼容的模型,無需任何密碼學(xué)知識。
Concrete ML使用scikit-learn作為構(gòu)建與FHE兼容的模型的基礎(chǔ),這是由于scikit-learn擁有出色的易用性、可擴展性、健壯性以及用于構(gòu)建、驗證和調(diào)整數(shù)據(jù)管道的眾多工具。雖然深度學(xué)習(xí)在非結(jié)構(gòu)化數(shù)據(jù)上表現(xiàn)良好,但它通常需要超參數(shù)調(diào)優(yōu)才能達到高精度。在許多用例中,特別是針對結(jié)構(gòu)化數(shù)據(jù),scikit-learn憑借其訓(xùn)練算法的穩(wěn)健性表現(xiàn)出色。
本地訓(xùn)練模型,并安全地部署
當(dāng)數(shù)據(jù)科學(xué)家擁有所有訓(xùn)練數(shù)據(jù)時,訓(xùn)練很安全,因為沒有數(shù)據(jù)離開機器,并且在部署模型時只需要確保推理安全。然而,用FHE保護的推理的訓(xùn)練模型對模型訓(xùn)練實施了一定的限制。雖然過去使用FHE需要密碼學(xué)專業(yè)知識,但像Concrete ML這樣的工具將密碼學(xué)這部分屏蔽起來,使數(shù)據(jù)科學(xué)家可以享用FHE。此外,F(xiàn)HE增加了計算開銷,這意味著機器學(xué)習(xí)模型可能需要針對準(zhǔn)確性和運行時延遲進行調(diào)整。Concrete ML使用scikit-learn實用程序類(比如GridSearchCV)充分利用參數(shù)搜索,從而使這種調(diào)整變得很容易。
若使用Concrete ML本地訓(xùn)練模型,語法對scikit-learn來說一樣,可以在視頻教程中找到解釋。如果是MNIST上的邏輯回歸模型,只需運行以下代碼片段:
from sklearn.datasets import fetch_openml
from sklearn.model_selection import train_test_split
mnist_dataset = fetch_openml("mnist_784")
x_train, x_test, y_train, y_test = train_test_split(
mnist_dataset.data,
mnist_dataset.target.astype("int"),
test_size=10000,
)
接下來,擬合Concrete ML邏輯回歸模型,該模型是scikit-learn等效模型的臨時替代品。只需要一個額外的步驟:編譯,就可以生成對加密數(shù)據(jù)執(zhí)行推理的FHE計算電路。編譯由Concrete完成,它是將程序變成FHE等效程序的過程,直接處理加密后的數(shù)據(jù)。
from concrete.ml.sklearn.linear_model import LogisticRegression
model = LogisticRegression(penalty="l2")
model.fit(X=x_train, y=y_train)
model.compile(x_train)
現(xiàn)在測試模型針對加密數(shù)據(jù)執(zhí)行時的準(zhǔn)確性。該模型的準(zhǔn)確率約為92%。與scikit-learn一樣,Concrete ML支持其他許多線性模型,比如SVM、Lasso和ElasticNet,你通過簡單地更改模型類就可以使用它們。此外,還支持等效scikit-learn模型的所有超參數(shù)(如上面代碼片段中的penalty)。
from sklearn.metrics import accuracy_score
y_preds_clear = model.predict(x_test, fhe="execute")
print(f"The test accuracy of the model on encrypted data {accuracy_score(y_test, y_preds_clear):.2f}")
用于訓(xùn)練數(shù)據(jù)隱私的聯(lián)合學(xué)習(xí)
通常,在有許多用戶的生產(chǎn)系統(tǒng)中,機器學(xué)習(xí)模型需要針對所有用戶數(shù)據(jù)的集合進行訓(xùn)練,同時保留每個用戶的隱私。這種場景下的常見用例包括數(shù)字健康、垃圾郵件檢測、在線廣告,甚至更簡單的用例,比如下一個單詞預(yù)測輔助。
Concrete ML可以導(dǎo)入由Flower等工具使用聯(lián)合學(xué)習(xí)(FL)訓(xùn)練的模型。要使用FL訓(xùn)練與上述相同的模型,必須定義一個客戶端應(yīng)用程序和服務(wù)器應(yīng)用程序。首先,客戶端由partition_id標(biāo)識,partition_id是一個介于0和客戶端數(shù)量之間的數(shù)字。要分割MNIST數(shù)據(jù)集并獲得當(dāng)前客戶端的切片,應(yīng)使用Flower federated_utils軟件包。
(X_train, y_train) = federated_utils.partition(X_train, y_train, 10)[partition_id]
現(xiàn)在定義訓(xùn)練客戶端邏輯:
import flwr as fl
from sklearn.linear_model import LogisticRegression
# Create LogisticRegression Model
model = LogisticRegression(
penalty="l2",
warm_start=True, # prevent refreshing weights when fitting
)
federated_utils.set_initial_params(model)
class MnistClient(fl.client.NumPyClient):
def get_parameters(self, config): # type: ignore
return federated_utils.get_model_parameters(model)
def fit(self, parameters, config): # type: ignore
federated_utils.set_model_params(model, parameters)
model.fit(X_train, y_train)
print(f"Training finished for round {config['server_round']}")
return federated_utils.get_model_parameters(model), len(X_train), {}
def evaluate(self, parameters, config): # type: ignore
federated_utils.set_model_params(model, parameters)
loss = log_loss(y_test, model.predict_proba(X_test))
accuracy = model.score(X_test, y_test)
return loss, len(X_test), {"accuracy": accuracy}
# Start Flower client
fl.client.start_numpy_client(
server_address="0.0.0.0:8080",
client=MnistClient()
)
最后,必須創(chuàng)建一個典型的Flower服務(wù)器實例:
model = LogisticRegression()
federated_utils.set_initial_params(model)
strategy = fl.server.strategy.FedAvg()
fl.server.start_server(
server_address="0.0.0.0:8080",
strategy=strategy,
config=fl.server.ServerConfig(num_rounds=5),
)
訓(xùn)練停止后,客戶端或服務(wù)器可以將模型存儲到文件中:
with open("model.pkl", "wb") as file:
pickle.dump(model, file)
一旦模型得到訓(xùn)練,就可以從pickle文件中加載它,并將其轉(zhuǎn)換成Concrete ML模型,以啟用保護隱私的推理。實際上,Concrete ML既可以訓(xùn)練新模型(如上文所示),也可以轉(zhuǎn)換現(xiàn)有模型(比如FL創(chuàng)建的模型)。使用from_sklearn_model函數(shù)的這個轉(zhuǎn)換步驟在下面用于使用聯(lián)合學(xué)習(xí)訓(xùn)練的模型上。該視頻進一步解釋了如何使用該函數(shù)。
with path_to_model.open("rb") as file:
sklearn_model = pickle.load(file)
compile_set = numpy.random.randint(0, 255, (100, 784)).astype(float)
sklearn_model.classes_ = sklearn_model.classes_.astype(int)
from concrete.ml.sklearn.linear_model import LogisticRegression
model = LogisticRegression.from_sklearn_model(sklearn_model, compile_set)
model.compile(compile_set)
至于本地訓(xùn)練,使用一些測試數(shù)據(jù)評估該模型:
from sklearn.metrics import accuracy_score
y_preds_enc = model.predict(x_test, fhe="execute")
print(f"The test accuracy of the model on encrypted data {accuracy_score(y_test, y_preds_enc):.2f}")
總之,使用scikit-learn、Flower和Concrete ML,只需要幾行代碼,就可以以完全保護隱私的方式訓(xùn)練模型并預(yù)測新數(shù)據(jù):數(shù)據(jù)集片段是保密的,預(yù)測針對加密數(shù)據(jù)執(zhí)行。這里訓(xùn)練的模型針對加密數(shù)據(jù)執(zhí)行時達到了92%的準(zhǔn)確率。
結(jié)論
上面討論了基于Flower和Concrete ML的完整端到端專有訓(xùn)練演示的最重要步驟。你可以在我們的開源代碼存儲庫中找到所有源代碼。與scikit-learn兼容使Concrete ML的用戶能夠使用熟悉的編程模式,并便于與scikit-learn兼容的工具包(比如Flower)兼容。本文中的示例僅對原始scikit-learn管道進行了一些更改,表明了如何使用聯(lián)合學(xué)習(xí)和FHE為使用MNIST訓(xùn)練分類器增添端到端隱私。
原文標(biāo)題:End-to-end privacy for model training and inference with Concrete ML。