在管道运行中使用环境类

时间:2019-10-08 19:53:08

标签: azure-machine-learning-service

我正在使用环境类在管道中使用估算器步骤,以便具有自定义Docker镜像,因为我需要一些apt-get软件包才能安装特定的pip软件包。从日志中看来,它完全被忽略了,这与估计器的非管道版本不同,它是环境变量的docker部分。很简单,这似乎很糟糕:

我在SDK v1.0.65上运行,我的dockerfile被完全忽略,我正在使用

FROM mcr.microsoft.com/azureml/base:latest\nRUN apt-get update && apt-get -y install freetds-dev freetds-bin vim gcc
我的代码的base_dockerfile属性中的

。 这是我的代码的片段:

from azureml.core import Environment
from azureml.core.environment import CondaDependencies
conda_dep = CondaDependencies()
conda_dep.add_pip_package('pymssql==2.1.1')
myenv = Environment(name="mssqlenv")
myenv.python.conda_dependencies=conda_dep
myenv.docker.enabled = True
myenv.docker.base_dockerfile = 'FROM mcr.microsoft.com/azureml/base:latest\nRUN apt-get update && apt-get -y install freetds-dev freetds-bin vim gcc'
myenv.docker.base_image = None

当我单独使用Estimator时,此方法效果很好,但是如果我在管道中插入此Estimator,则会失败。这是从管道运行中启动它的代码:

from azureml.pipeline.steps import EstimatorStep

sql_est_step = EstimatorStep(name="sql_step", 
                         estimator=est, 
                         estimator_entry_script_arguments=[],
                         runconfig_pipeline_params=None, 
                         compute_target=cpu_cluster)
from azureml.pipeline.core import Pipeline
from azureml.core import Experiment
pipeline = Pipeline(workspace=ws, steps=[sql_est_step])
pipeline_run = exp.submit(pipeline)

启动此操作时,容器构建服务的日志将显示:

FROM continuumio/miniconda3:4.4.10... etc.

这表明它忽略了与该Estimator关联的Environment类中的FROM mcr....语句,而我的pip install失败了。

我想念什么吗?有解决方法吗?

3 个答案:

答案 0 :(得分:2)

我现在找到了一种解决方法,即构建您自己的Docker映像。您可以通过使用环境的DockerSection的以下选项来做到这一点:

myenv.docker.base_image_registry.address = '<your_acr>.azurecr.io'
myenv.docker.base_image_registry.username = '<your_acr>'
myenv.docker.base_image_registry.password = '<your_acr_password>'
myenv.docker.base_image = '<your_acr>.azurecr.io/testimg:latest'

并且显然使用您构建并推送到链接到Azure机器学习工作区的容器注册表的任何docker映像。

要创建映像,您将在可以构建基于linux的容器(例如Notebook VM)的计算机的命令行上运行以下内容:

docker build . -t <your_image_name>
# Tag it for upload
docker tag <your_image_name:latest <your_acr>.azurecr.io/<your_image_name>:latest
# Login to Azure
az login
# login to the container registry so that the push will work
az acr login --name <your_acr>
# push the image
docker push <your_acr>.azurecr.io/<your_image_name>:latest

一旦图像被推送,您就应该能够正常工作。

答案 1 :(得分:2)

我可以确认这是AML管道方面的错误。特别是,在管道作业中未正确传递runco​​nfig属性environment.docker.base_dockerfile。我们正在努力解决。同时,您可以使用以下线程中的变通方法:首先构建docker映像,并使用environment.docker.base_image(正确传递)进行指定。

答案 2 :(得分:0)

我最初也使用EstimatorStep来定制图像,但是最近发现了如何成功地将Environment的首字母成功传递给RunConfiguration,然后传递给PythonScriptStep' s。 (下面的示例)

与您的解决方法类似的另一种解决方法是将自定义docker映像发布到Docker中心,然后参数docker_base_image成为URI,在我们的情况下为mmlspark:0.16

def get_environment(env_name, yml_path, user_managed_dependencies, enable_docker, docker_base_image):
    env = Environment(env_name)
    cd = CondaDependencies(yml_path)
    env.python.conda_dependencies = cd
    env.python.user_managed_dependencies = user_managed_dependencies
    env.docker.enabled = enable_docker
    env.docker.base_image = docker_base_image
    return env


spark_env = f.get_environment(env_name='spark_env',
                              yml_path=os.path.join(os.getcwd(), 'compute/aml_config/spark_compute_dependencies.yml'),
                              user_managed_dependencies=False, enable_docker=True,
                              docker_base_image='microsoft/mmlspark:0.16')

# use pyspark framework
spark_run_config = RunConfiguration(framework="pyspark")
spark_run_config.environment = spark_env

roll_step = PythonScriptStep(
    name='rolling window',
    script_name='roll.py',
    arguments=['--input_dir', joined_data,
                '--output_dir', rolled_data,
                '--script_dir', ".",
                '--min_date', '2015-06-30',
                '--pct_rank', 'True'],
    compute_target=compute_target_spark,
    inputs=[joined_data],
    outputs=[rolled_data],
    runconfig=spark_run_config,
    source_directory=os.path.join(os.getcwd(), 'compute', 'roll'),
    allow_reuse=pipeline_reuse
)


其他几点(可能是错误的):

  • PythonScriptStep实际上是ScriptRunConfig的包装,它以run_config作为参数
  • EstimatorScriptRunConfig的包装,其中RunConfig设置可作为参数使用
  • IMHO EstimatorStep不应该存在,因为最好分别定义Env和Steps,而不是一次调用。
相关问题