译者 | 布加迪
审校 | 重楼
在云计算和基于机器学习的服务唾手可得的时代,隐私是一大挑战。将端到端隐私添加到协作式机器学习用例听起来像是一项艰巨的任务。幸好,诸如完全同态加密(FHE)之类的密码学突破提供了解决方案。Zama的新演示展示了如何利用开源机器学习工具使用联合学习和FHE来添加端到端隐私。这篇博文解释了这番演示的底层工作机理,结合了scikit-learn、联合学习和FHE。
FHE这种技术使应用程序提供方能够构建基于云的应用程序以保护用户隐私,而Concrete ML这种机器学习工具包可以让模型改而使用FHE。Concrete ML利用了scikit-learn中强大稳健的模型训练算法来训练与FHE兼容的模型,无需任何密码学知识。
Concrete ML使用scikit-learn作为构建与FHE兼容的模型的基础,这是由于scikit-learn拥有出色的易用性、可扩展性、健壮性以及用于构建、验证和调整数据管道的众多工具。虽然深度学习在非结构化数据上表现良好,但它通常需要超参数调优才能达到高精度。在许多用例中,特别是针对结构化数据,scikit-learn凭借其训练算法的稳健性表现出色。
本地训练模型,并安全地部署
当数据科学家拥有所有训练数据时,训练很安全,因为没有数据离开机器,并且在部署模型时只需要确保推理安全。然而,用FHE保护的推理的训练模型对模型训练实施了一定的限制。虽然过去使用FHE需要密码学专业知识,但像Concrete ML这样的工具将密码学这部分屏蔽起来,使数据科学家可以享用FHE。此外,FHE增加了计算开销,这意味着机器学习模型可能需要针对准确性和运行时延迟进行调整。Concrete ML使用scikit-learn实用程序类(比如GridSearchCV)充分利用参数搜索,从而使这种调整变得很容易。
若使用Concrete ML本地训练模型,语法对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等效模型的临时替代品。只需要一个额外的步骤:编译,就可以生成对加密数据执行推理的FHE计算电路。编译由Concrete完成,它是将程序变成FHE等效程序的过程,直接处理加密后的数据。
from concrete.ml.sklearn.linear_model import LogisticRegression
model = LogisticRegression(penalty="l2")
model.fit(X=x_train, y=y_train)
model.compile(x_train)
现在测试模型针对加密数据执行时的准确性。该模型的准确率约为92%。与scikit-learn一样,Concrete ML支持其他许多线性模型,比如SVM、Lasso和ElasticNet,你通过简单地更改模型类就可以使用它们。此外,还支持等效scikit-learn模型的所有超参数(如上面代码片段中的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}")
用于训练数据隐私的联合学习
通常,在有许多用户的生产系统中,机器学习模型需要针对所有用户数据的集合进行训练,同时保留每个用户的隐私。这种场景下的常见用例包括数字健康、垃圾邮件检测、在线广告,甚至更简单的用例,比如下一个单词预测辅助。
Concrete ML可以导入由Flower等工具使用联合学习(FL)训练的模型。要使用FL训练与上述相同的模型,必须定义一个客户端应用程序和服务器应用程序。首先,客户端由partition_id标识,partition_id是一个介于0和客户端数量之间的数字。要分割MNIST数据集并获得当前客户端的切片,应使用Flower federated_utils软件包。
(X_train, y_train) = federated_utils.partition(X_train, y_train, 10)[partition_id]
现在定义训练客户端逻辑:
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()
)
最后,必须创建一个典型的Flower服务器实例:
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),
)
训练停止后,客户端或服务器可以将模型存储到文件中:
with open("model.pkl", "wb") as file:
pickle.dump(model, file)
一旦模型得到训练,就可以从pickle文件中加载它,并将其转换成Concrete ML模型,以启用保护隐私的推理。实际上,Concrete ML既可以训练新模型(如上文所示),也可以转换现有模型(比如FL创建的模型)。使用from_sklearn_model函数的这个转换步骤在下面用于使用联合学习训练的模型上。该视频进一步解释了如何使用该函数。
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)
至于本地训练,使用一些测试数据评估该模型:
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,只需要几行代码,就可以以完全保护隐私的方式训练模型并预测新数据:数据集片段是保密的,预测针对加密数据执行。这里训练的模型针对加密数据执行时达到了92%的准确率。
结论
上面讨论了基于Flower和Concrete ML的完整端到端专有训练演示的最重要步骤。你可以在我们的开源代码存储库中找到所有源代码。与scikit-learn兼容使Concrete ML的用户能够使用熟悉的编程模式,并便于与scikit-learn兼容的工具包(比如Flower)兼容。本文中的示例仅对原始scikit-learn管道进行了一些更改,表明了如何使用联合学习和FHE为使用MNIST训练分类器增添端到端隐私。
原文End-to-end privacy for model training and inference with Concrete ML。