问题描述
我是 azure-ml
的新手,我的任务是为几个管道步骤进行一些集成测试。我准备了一些输入测试数据和一些预期的输出数据,我将它们存储在 'test_datastore'
中。以下示例代码是我想要做的简化版本:
ws = Workspace.from_config('blabla/config.json')
ds = Datastore.get(ws,datastore_name='test_datastore')
main_ref = DataReference(datastore=ds,data_reference_name='main_ref'
)
data_ref = DataReference(datastore=ds,data_reference_name='main_ref',path_on_datastore='/data'
)
data_prep_step = PythonScriptStep(
name='data_prep',script_name='pipeline_steps/data_prep.py',source_directory='/.',arguments=['--main_path',main_ref,'--data_ref_folder',data_ref
],inputs=[main_ref,data_ref],outputs=[data_ref],runconfig=arbitrary_run_config,allow_reuse=False
)
我想:
- 我要运行的
data_prep_step
, - 让它在我的
data_ref
的路径上存储一些数据,并且 - 然后我想在管道之外访问这些存储的数据
但是,我在文档中找不到有用的功能。任何指导将不胜感激。
解决方法
这里有两个重要的想法——让我们从主要的想法开始。
主要问题
使用 Azure ML 管道,如何在管道上下文之外访问 PythonScriptStep
的输出数据?
简答
考虑使用 OutputFileDatasetConfig
(docs example),而不是 DataReference
。
对于您上面的示例,我只想更改您的最后两个定义。
data_ref = OutputFileDatasetConfig(
name='data_ref',destination=(ds,'/data')
).as_upload()
data_prep_step = PythonScriptStep(
name='data_prep',script_name='pipeline_steps/data_prep.py',source_directory='/.',arguments=[
'--main_path',main_ref,'--data_ref_folder',data_ref
],inputs=[main_ref,data_ref],outputs=[data_ref],runconfig=arbitrary_run_config,allow_reuse=False
)
一些注意事项:
- 请务必查看
DataPath
的工作原理。乍一看可能很棘手。 - 如果您不希望以后的运行覆盖第一次运行的数据,请在 `.as_upload() 方法中设置
overwrite=False
。
更多背景
PipelineData
曾经是在管道步骤之间临时传递数据的事实上的对象。这个想法是为了让事情变得容易:
- 将步骤缝合在一起
- 如果需要,在管道运行后获取数据 (
datastore/azureml/{run_id}/data_ref
)
缺点是您无法控制保存管道的位置。如果您想要的数据不仅仅是在步骤之间传递的指挥棒,您可以使用 DataTransferStep
在 PipelineData
完成后将 PythonScriptStep
放在任何您喜欢的地方。
这个缺点是促使OutputFileDatasetConfig
辅助提问
如何以编程方式测试 Azure ML 管道的功能?
没有足够的人谈论数据管道测试,恕我直言。
数据管道测试分为三个方面:
- 单元测试(步骤中的代码有效吗?
- 集成测试(代码在提交到 Azure ML 服务时有效)
- 数据期望测试(得出的数据符合我的期望)
对于#1,我认为它应该在管道之外完成,也许作为辅助函数包的一部分 对于#2,为什么不看看整个管道是否完成,我想通过这种方式获得更多信息。这就是我们运行 CI 的方式。
#3 是最多汁的,我们使用 Great Expectations (GE) Python 库在我们的管道中执行此操作。 GE 社区称这些为“预期测试”。对我来说,在 Azure ML 管道中包含期望测试有两种选择:
- 在
PythonScriptStep
本身内,即- 运行您拥有的任何代码
- 在写出之前用 GE 测试输出;或者,
- 对于每个函数
PythonScriptStep
,在它的下游挂一个PythonScriptStep
,您可以在其中根据输出数据运行您的期望。
我们的团队做了 #1,但任何一种策略都应该奏效。这种方法的优点在于,您只需运行管道即可运行预期测试(这也使集成测试变得容易)。