Mover dados para e entre os passos de pipeline de ML (Python)

APLICA-SE A:SDK python azureml v1

Este artigo fornece código para importar, transformar e mover dados entre passos num pipeline do Azure Machine Learning. Para obter uma descrição geral de como os dados funcionam no Azure Machine Learning, veja Aceder a dados nos serviços de armazenamento do Azure. Para obter as vantagens e a estrutura dos pipelines do Azure Machine Learning, veja O que são os pipelines do Azure Machine Learning?

Este artigo mostra-lhe como:

  • Utilizar Dataset objetos para dados pré-existentes
  • Aceder a dados nos seus passos
  • Dividir Dataset dados em subconjuntos, tais como subconjuntos de preparação e validação
  • Criar OutputFileDatasetConfig objetos para transferir dados para o próximo passo do pipeline
  • Utilizar OutputFileDatasetConfig objetos como entrada para passos de pipeline
  • Criar novos Dataset objetos a partir dos OutputFileDatasetConfig quais pretende manter

Pré-requisitos

É necessário:

Utilizar Dataset objetos para dados pré-existentes

A forma preferencial de ingerir dados num pipeline é utilizar um objeto Conjunto de Dados . Dataset Os objetos representam dados persistentes disponíveis numa área de trabalho.

Existem várias formas de criar e registar Dataset objetos. Os conjuntos de dados tabulares destinam-se a dados delimitados disponíveis num ou mais ficheiros. Os conjuntos de dados de ficheiros destinam-se a dados binários (como imagens) ou a dados que analisa. As formas programáticas mais simples de criar Dataset objetos são utilizar blobs existentes no armazenamento de áreas de trabalho ou URLs públicos:

datastore = Datastore.get(workspace, 'training_data')
iris_dataset = Dataset.Tabular.from_delimited_files(DataPath(datastore, 'iris.csv'))

datastore_path = [
    DataPath(datastore, 'animals/dog/1.jpg'),
    DataPath(datastore, 'animals/dog/2.jpg'),
    DataPath(datastore, 'animals/cat/*.jpg')
]
cats_dogs_dataset = Dataset.File.from_files(path=datastore_path)

Para obter mais opções sobre como criar conjuntos de dados com diferentes opções e origens diferentes, registá-los e revê-los na IU do Azure Machine Learning, compreender como o tamanho dos dados interage com a capacidade de computação e controlo de versões, veja Criar conjuntos de dados do Azure Machine Learning.

Transmitir conjuntos de dados para o script

Para transmitir o caminho do conjunto de dados para o script, utilize o Dataset método do as_named_input() objeto. Pode transmitir o objeto resultante DatasetConsumptionConfig para o script como um argumento ou, ao utilizar o argumento para o inputs script do pipeline, pode obter o conjunto de dados com Run.get_context().input_datasets[].

Depois de criar uma entrada com nome, pode escolher o respetivo modo de acesso (apenas para FileDataset): as_mount() ou as_download(). Se o script processar todos os ficheiros no conjunto de dados e o disco no recurso de computação for suficientemente grande para o conjunto de dados, o modo de acesso de transferência é a melhor opção. O modo de acesso de transferência evita a sobrecarga da transmissão em fluxo dos dados no runtime. Se o script aceder a um subconjunto do conjunto de dados ou for demasiado grande para a computação, utilize o modo de acesso de montagem. Para obter mais informações, leia Montar vs. Transferir

Para transmitir um conjunto de dados para o passo do pipeline:

  1. Utilizar TabularDataset.as_named_input() ou FileDataset.as_named_input() (sem 's' no final) para criar um DatasetConsumptionConfig objeto
  2. Apenas para FileDataset :. Utilize as_mount() ou as_download() para definir o modo de acesso. TabularDataset não suporta o modo de acesso definido.
  3. Transmita os conjuntos de dados para os passos do pipeline com o arguments argumento ou inputs

O fragmento seguinte mostra o padrão comum de combinar estes passos no PythonScriptStep construtor com iris_dataset (TabularDataset):


train_step = PythonScriptStep(
    name="train_data",
    script_name="train.py",
    compute_target=cluster,
    inputs=[iris_dataset.as_named_input('iris')]
)

Nota

Teria de substituir os valores de todos estes argumentos (ou seja, "train_data", "train.py", clustere iris_dataset) pelos seus próprios dados. O fragmento acima mostra apenas a forma da chamada e não faz parte de um exemplo da Microsoft.

Também pode utilizar métodos como random_split() e take_sample() para criar várias entradas ou reduzir a quantidade de dados transmitidos ao passo do pipeline:

seed = 42 # PRNG seed
smaller_dataset = iris_dataset.take_sample(0.1, seed=seed) # 10%
train, test = smaller_dataset.random_split(percentage=0.8, seed=seed)

train_step = PythonScriptStep(
    name="train_data",
    script_name="train.py",
    compute_target=cluster,
    inputs=[train.as_named_input('train'), test.as_named_input('test')]
)

Aceder a conjuntos de dados no script

As entradas nomeadas para o script de passo do pipeline estão disponíveis como um dicionário dentro do Run objeto. Obtenha o objeto ativo Run com Run.get_context() e, em seguida, obtenha o dicionário de entradas nomeadas com input_datasets. Se transmitiu o DatasetConsumptionConfig objeto com o arguments argumento em vez do inputs argumento , aceda aos dados com ArgParser código. Ambas as técnicas são demonstradas nos seguintes fragmentos:

O script de definição do pipeline

# Code for demonstration only: It would be very confusing to split datasets between `arguments` and `inputs`
train_step = PythonScriptStep(
    name="train_data",
    script_name="train.py",
    compute_target=cluster,
    # datasets passed as arguments
    arguments=['--training-folder', train.as_named_input('train').as_download()],
    # datasets passed as inputs
    inputs=[test.as_named_input('test').as_download()]
)

O train.py script referenciado a partir do PythonScriptStep

# In pipeline script
parser = argparse.ArgumentParser()
# Retreive the dataset passed as an argument
parser.add_argument('--training-folder', type=str, dest='train_folder', help='training data folder mounting point')
args = parser.parse_args()
training_data_folder = args.train_folder
# Retrieve the dataset passed as an input
testing_data_folder = Run.get_context().input_datasets['test']

O valor transmitido é o caminho para os ficheiros do conjunto de dados.

Também é possível aceder diretamente a um registado Dataset . Uma vez que os conjuntos de dados registados são persistentes e partilhados numa área de trabalho, pode obtê-los diretamente:

run = Run.get_context()
ws = run.experiment.workspace
ds = Dataset.get_by_name(workspace=ws, name='mnist_opendataset')

Nota

Os fragmentos anteriores mostram a forma das chamadas e não fazem parte de um exemplo da Microsoft. Tem de substituir os vários argumentos por valores do seu próprio projeto.

Utilizar OutputFileDatasetConfig para dados intermédios

Embora Dataset os objetos representem apenas dados persistentes, OutputFileDatasetConfig os objetos podem ser utilizados para a saída temporária de dados a partir dos passos do pipeline e dos dados de saída persistentes. OutputFileDatasetConfig suporta a escrita de dados para armazenamento de blobs, partilha de ficheiros, adlsgen1 ou adlsgen2. Suporta o modo de montagem e o modo de carregamento. No modo de montagem, os ficheiros escritos no diretório montado são armazenados permanentemente quando o ficheiro é fechado. No modo de carregamento, os ficheiros escritos no diretório de saída são carregados no final da tarefa. Se a tarefa falhar ou for cancelada, o diretório de saída não será carregado.

OutputFileDatasetConfig O comportamento predefinido do objeto é escrever no arquivo de dados predefinido da área de trabalho. Transmita os objetos OutputFileDatasetConfig para o parâmetro PythonScriptStep com o arguments parâmetro .

from azureml.data import OutputFileDatasetConfig
dataprep_output = OutputFileDatasetConfig()
input_dataset = Dataset.get_by_name(workspace, 'raw_data')

dataprep_step = PythonScriptStep(
    name="prep_data",
    script_name="dataprep.py",
    compute_target=cluster,
    arguments=[input_dataset.as_named_input('raw_data').as_mount(), dataprep_output]
    )

Nota

As escritas simultâneas num OutputFileDatasetConfig irão falhar. Não tente utilizar um único OutputFileDatasetConfig em simultâneo. Não partilhe um único OutputFileDatasetConfig numa situação de multiprocessamento, como quando utilizar a preparação distribuída.

Utilizar OutputFileDatasetConfig como saídas de um passo de preparação

No PythonScriptStep do pipeline, pode obter os caminhos de saída disponíveis com os argumentos do programa. Se este passo for o primeiro e inicializar os dados de saída, terá de criar o diretório no caminho especificado. Em seguida, pode escrever os ficheiros que pretende que estejam contidos no OutputFileDatasetConfig.

parser = argparse.ArgumentParser()
parser.add_argument('--output_path', dest='output_path', required=True)
args = parser.parse_args()

# Make directory for file
os.makedirs(os.path.dirname(args.output_path), exist_ok=True)
with open(args.output_path, 'w') as f:
    f.write("Step 1's output")

Ler OutputFileDatasetConfig como entradas para passos não iniciais

Depois de o passo inicial do pipeline escrever alguns dados no OutputFileDatasetConfig caminho e se tornar uma saída desse passo inicial, pode ser utilizado como uma entrada para um passo posterior.

No seguinte código:

  • step1_output_data indica que o resultado do PythonScriptStep foi step1 escrito no arquivo de dados do ADLS Gen2, my_adlsgen2 no modo de acesso de carregamento. Saiba mais sobre como configurar permissões de função para escrever dados de volta nos arquivos de dados do ADLS Gen2.

  • Depois de step1 concluída e a saída ser escrita no destino indicado por step1_output_data, o passo2 estará pronto para ser utilizado step1_output_data como entrada.

# get adls gen 2 datastore already registered with the workspace
datastore = workspace.datastores['my_adlsgen2']
step1_output_data = OutputFileDatasetConfig(name="processed_data", destination=(datastore, "mypath/{run-id}/{output-name}")).as_upload()

step1 = PythonScriptStep(
    name="generate_data",
    script_name="step1.py",
    runconfig = aml_run_config,
    arguments = ["--output_path", step1_output_data]
)

step2 = PythonScriptStep(
    name="read_pipeline_data",
    script_name="step2.py",
    compute_target=compute,
    runconfig = aml_run_config,
    arguments = ["--pd", step1_output_data.as_input()]

)

pipeline = Pipeline(workspace=ws, steps=[step1, step2])

Dica

Ler os dados no script step2.py python é o mesmo que documentado anteriormente nos conjuntos de dados do Access no script; utilize ArgumentParser para adicionar um argumento de --pd no script para aceder aos dados.

Registar OutputFileDatasetConfig objetos para reutilização

Se quiser disponibilizar a sua OutputFileDatasetConfig experiência durante mais tempo do que a sua experimentação, registe-a na área de trabalho para partilhar e reutilizar em experimentações.

step1_output_ds = step1_output_data.register_on_complete(
    name='processed_data', 
    description = 'files from step1'
)

Eliminar OutputFileDatasetConfig conteúdo quando já não for necessário

O Azure não elimina automaticamente os dados intermédios escritos com OutputFileDatasetConfig. Para evitar custos de armazenamento para grandes quantidades de dados desnecessários, deve:

Atenção

Elimine apenas dados intermédios após 30 dias a partir da data da última alteração dos dados. Eliminar os dados anteriormente pode fazer com que a execução do pipeline falhe porque o pipeline assumirá que os dados intermédios existem num período de 30 dias para reutilização.

  • Elimine programaticamente dados intermédios no final de uma tarefa de pipeline, quando já não for necessário.
  • Utilize o armazenamento de blobs com uma política de armazenamento de curto prazo para dados intermédios (veja Otimizar os custos ao automatizar Armazenamento de Blobs do Azure camadas de acesso). Esta política só pode ser definida para o arquivo de dados não predefinido de uma área de trabalho. Utilize OutputFileDatasetConfig para exportar dados intermédios para outro arquivo de dados que não seja a predefinição.
    # Get adls gen 2 datastore already registered with the workspace
    datastore = workspace.datastores['my_adlsgen2']
    step1_output_data = OutputFileDatasetConfig(name="processed_data", destination=(datastore, "mypath/{run-id}/{output-name}")).as_upload()
    
  • Reveja e elimine regularmente os dados que já não são necessários.

Para obter mais informações, veja Planear e gerir os custos do Azure Machine Learning.

Passos seguintes