第三部分:提出研究方案#
在第一部分和第二部分中,我们完全从数据所有者的角度学习了PySyft的功能。
作为实验室管理员的职责和PySyft数据所有者,Owen通过创建并上传"乳腺癌生物标志物"数据集,以及为Rachel创建远程访问凭证来建立数据站点。
现在我们将探讨Rachel作为数据科学家如何与Datasite进行交互,以及PySyft如何确保外部用户无法查看或访问非公开信息。
使用PySyft在私有数据集上进行远程数据科学的工作流程包含三个部分:
(1) 准备研究项目: 这是最全面的部分,也将是本部分的重点;数据科学家会参与这里的每一步。
(2) 真实数据计算: 研究项目中嵌入的代码使用私有数据作为输入运行,以计算真实结果(参见第4部分)
(3) 结果审批与发布: 对真实结果进行检查以确保其符合数据集的隐私政策;若一切正常,则将真实结果返回给数据科学家(参见第五部分)
使用PySyft对非公开数据进行研究的第一步是准备一个研究项目提交。
你将学习的内容#
在第三部分结束时,你将学会:
如何以数据科学家的身份访问数据站点,并探索可用的数据集;
如何使用模拟数据来准备数据分析代码;
如何创建一个PySyft 远程代码请求;
如何创建并向数据站点提交项目提案。
3.1. 登录数据站点#
首先,请确保本地开发数据站点正在运行。如果没有运行,syft.orchestra.launch将再次启动服务器实例。
import syft as sy
data_site = sy.orchestra.launch(name="cancer-research-centre")
现在轮到Rachel使用Owen单独发送的新凭证登录数据站点:
client = data_site.login(email="[email protected]", password="syftrocks")
登录领域后,作为数据科学家的Rachel可以浏览Datasite中可用的数据集。我们可以通过访问client.datasets轻松实现这一点。
client.datasets
如预期所示,Datasite包含一个名为Breast Cancer Biomarker的数据集,其中包含2个资产。
一旦确定我们感兴趣的数据集,就可以通过index索引或唯一的name名称来访问它们:
bc_dataset = client.datasets["Breast Cancer Biomarker"]
我们获取了bc_dataset,这是一个指向远程数据集的指针。
bc_dataset
使用指向远程数据集的指针,我们可以通过index或其唯一名称访问其内部资产。
在我们的示例中,我们可以创建一个指向features资产和targets资产的指针:
features, targets = bc_dataset.assets # using Python tuple unpacking
现在让我们验证以下假设:数据科学家只能访问mock数据,而data是无法访问的。我们将通过使用features和targets这两个变量来实现验证,它们实际上是指向其对应远程资产的指针。
记住
在第一部分中,这两个资产被创建并存储为pandas.DataFrame对象。
features.mock.head(n=3) # pandas.DataFrame
让我们尝试对targets做同样的操作:
targets.mock.head(n=3)
太棒了! 那关于 data 呢?🧐
features.data
targets.data
正如预期的那样,作为数据科学家的Rachel没有对远程资产中存储的非公开信息的读取权限(也没有任何其他权限,编者注)。
资产主要组成部分之间的这种明确区分具有以下优势:
模拟数据是开放获取的,不会给数据所有者带来公开分享非公开信息的风险;
它为数据科学家创建一个模拟环境,以真实的方式模拟他们预期的研究;
降低数据科学家的责任风险,他们不再需要负责安全存储非公开数据;
使数据所有者能够控制数据科学家如何在其研究中使用非公开资产。
3.2. 使用模拟数据准备代码#
Getting access to the mock data allows to get a general understanding of what non-public data would look like. So we can use this data to start preparing our code, to run on this data.
Rachel决定通过使用scikit-learn库运行一个简单的监督机器学习实验来研究乳腺癌数据。
数据集以pandas.DataFrame格式表示,且特征已经符合机器学习模型预期的格式:samples x features矩阵。
这个结论是通过查看模拟数据得出的,因此我们可以假设它同样适用于真实的实际数据。
X, y = features.mock, targets.mock
简而言之,以下是Rachel设想的机器学习实验步骤:
使用
train_test_split函数生成训练和测试分区;应用
StandardScaler来标准化特征;训练一个
LogisticRegression模型;计算训练数据和测试数据上的
accuracy_score。
为简化操作,我们将整个流程封装成一个单一Python函数。这样能更方便地准备要发送给PySyft执行的代码请求。
def ml_experiment_on_breast_cancer_data(features_data, labels, seed: int = 12345) -> tuple[float, float]:
# include the necessary imports in the main body of the function
# to prepare for what PySyft would expect for submitted code.
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score
X, y = features_data, labels.values.ravel()
# 1. Data Partition
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=seed, stratify=y)
# 2. Data normalisation
scaler = StandardScaler()
scaler.fit(X_train, y_train)
X_train = scaler.transform(X_train)
X_test = scaler.transform(X_test)
# 3. Model training
model = LogisticRegression().fit(X_train, y_train)
# 4. Metrics Calculation
acc_train = accuracy_score(y_train, model.predict(X_train))
acc_test = accuracy_score(y_test, model.predict(X_test))
return acc_train, acc_test
让我们在模拟数据上调用这个函数,检查一切是否正常运行:
ml_experiment_on_breast_cancer_data(features_data=features.mock, labels=targets.mock)
3.3. 提交研究项目#
现在我们的代码已经在本地测试完毕,可以开始准备进行远程执行,然后创建一个新的研究项目提交到Datasite。
在上一节中,我们已经验证了ml_experiment_on_breast_cancer_data可以在模拟数据上成功本地运行。现在,我们有兴趣使用PySyft在真实数据上测试该函数。具体来说,我们需要将(本地)Python函数转换为远程代码请求:这是一个PySyft可以处理并在数据站点远程执行的函数,而真实数据就存储在那里。
为此,我们只需要用特殊的装饰器包装我们的Python函数:syft_function_single_use。
remote_user_code = sy.syft_function_single_use(features_data=features, labels=targets)(ml_experiment_on_breast_cancer_data)
syft_function_single_use 装饰器
syft_function_single_use装饰器是更通用的syft_function装饰器的简化快捷方式。该装饰器需要两个主要参数:input_policy和output_policy。前者让数据所有者确信提交的代码仅会在选定的输入资产上运行;后者用于在多次执行间保持状态,例如限制指定代码允许运行的次数上限。
请查看Syft Policy Component获取更多详情。
此时,我们可以继续提交remote_user_code请求。然而,这将给Owen带来极大困扰,因为他们完全无法理解这段代码的意图,也不清楚Rachel计划在"癌症研究中心"数据上进行何种研究!
为了解决这些问题,PySyft允许创建并提交一个研究项目!本质上,一个项目(即syft.Project)由一个(或多个)代码请求组成,并包含一个(简短的)描述,用于向数据所有者传达研究意图。
description = """
The purpose of this study will be to run a machine learning
experimental pipeline on breast cancer data.
As first attempt, the pipelines includes a normalisation steps for
features and labels using a StandardScaler and a LabelEncoder.
The selected ML model is Logistic regression, with the intent
to gather the accuracy scores on both training, and testing
data partitions, randomly generated.
"""
# Create a project
research_project = client.create_project(
name="Breast Cancer ML Project",
description=description,
user_email_address="[email protected]"
)
我们可以通过client访问可用的projects列表:
client.projects
唯一项目名称
项目通过其唯一名称进行标识。这意味着重复提交会导致PySyft报错。
我们可以使用create_code_request方法将新的代码请求附加到我们的syft.Project实例上,即research_project
code_request = research_project.create_code_request(remote_user_code, client)
code_request
现在我们可以通过访问client.code来检查代码请求是否已到达项目:
client.code
我们确实有一个代码请求,状态为PENDING。同样地,我们可以通过访问client.requests来查看现有的请求:
client.requests
继续之前#
假设Rachel非常没有耐心,会试图强制执行一个尚未批准(尚未审核)的请求。让我们看看PySyft允许的操作:
client.code.ml_experiment_on_breast_cancer_data(features_data=features, labels=targets)
正如预期的那样,如果我们尝试执行一个尚未被批准的代码请求,将会返回一个SyftError错误!
恭喜完成第3部分 🎉#
恭喜你完成了教程的第三部分!👏
现在Rachel已经准备并完成了他们的研究项目,该项目已发送给Owen进行评审。 这个项目包含了Rachel在模拟数据上准备和测试的机器学习流程,并已附加到项目中以便在真实数据上远程执行。
在第4部分中,我们将探讨PySyft中的代码修改请求流程如何运作,再次将视角切换到需要审核请求的数据所有者一方,必要时批准这些请求。