Поделиться через


Перемещение данных в этапы конвейера машинного обучения и между ними (Python)

ОБЛАСТЬ ПРИМЕНЕНИЯ: Пакет SDK для Python версии 1

В этой статье предоставляется код для импорта, преобразования и перемещения данных между этапами в конвейере машинного обучения Azure. Общие сведения об использовании данных в Машинном обучении Azure см. в статье Доступ к данным в службах хранилища Azure. Преимущества и структура конвейеров машинного обучения Azure описаны в статье Что представляют собой конвейеры машинного обучения Azure?

Из этой статьи вы узнаете, как выполнять следующие задачи:

  • Использовать объекты Dataset для уже существующих данных
  • Получать доступ к данным при выполнении этапов
  • Разделять данные Dataset на подмножества, например подмножества обучения и проверки
  • Создавать объекты OutputFileDatasetConfig для передачи данных на следующий этап конвейера
  • Использовать объекты OutputFileDatasetConfig в качестве входов для этапов конвейера
  • Создавать новые объекты Dataset из сохраняемыхOutputFileDatasetConfig

Необходимые компоненты

Необходимые компоненты:

Использовать объекты Dataset для уже существующих данных

Предпочтительный способ приема данных в конвейер — это использование объекта DataSet. Объекты Dataset представляют постоянные данные, доступные во всей рабочей области.

Есть много способов создания и регистрации объектов Dataset. Табличные наборы данных предназначены для данных с разделителями, доступных в одном или нескольких файлах. Наборы данных файлов предназначены для двоичных данных (например, изображений) или для данных, которые вы анализируете. Самый простой программный способ создания объектов Dataset — это использование существующих BLOB-объектов в хранилище рабочей области или общедоступных URL:

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)

Другие варианты создания наборов данных с разными параметрами и из разных источников, их регистрации и просмотра в пользовательском интерфейсе Машинного обучения Azure, влияние размера данных на производительность вычислений и управление версиями описаны в разделе Создание наборов данных для Машинного обучения Azure.

Передача наборов данных в сценарий

Чтобы передать путь к набору данных в сценарий, используйте относящийся к объекту Dataset метод as_named_input(). Можно либо передать результирующий объект DatasetConsumptionConfig в сценарий в качестве аргумента, либо использовать аргумент inputs для сценария конвейера, чтобы извлечь набор данных с помощью Run.get_context().input_datasets[].

После создания именованных входных данных можно выбрать режим доступа (только для FileDataset): as_mount() или as_download(). Если сценарий обрабатывает все файлы в наборе данных, и диск в ресурсе вычислений достаточно вместителен для набора данных, лучше использовать режим доступа с загрузкой. Режим доступа к скачиванию позволяет избежать затрат на потоковую передачу данных во время выполнения. Если сценарий получает доступ к подмножеству набора данных или если он слишком велик для вычислений, используйте режим доступа с установкой. Дополнительные сведения см. в статье Сравнение установки и загрузки

Чтобы передать набор данных на этап конвейера, выполните следующие действия.

  1. Используйте TabularDataset.as_named_input() или FileDataset.as_named_input() (без s на конце), чтобы создать объект DatasetConsumptionConfig.
  2. Только:FileDataset. Используйте as_mount() или as_download() задайте режим доступа. TabularDataset не поддерживает режим доступа.
  3. Передайте наборы данных на этапы конвейера, используя аргумент arguments или inputs.

В следующем фрагменте кода показан общий шаблон объединения этих шагов в PythonScriptStep конструкторе с помощью iris_dataset (TabularDataset):


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

Примечание.

Необходимо заменить значения для всех этих аргументов ("train_data" "train.py" cluster и iris_dataset) собственными данными. Приведенный выше фрагмент только демонстрирует форму вызова и не является частью примера Microsoft.

Также можно использовать такие методы как random_split() и take_sample(), чтобы создать несколько входов или уменьшить объем данных, передаваемых на этап конвейера:

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')]
)

Доступ к наборам данных в сценарии

Именованные входы для сценария этапа конвейера доступны в формате словаря внутри объекта Run. Извлеките активный объект Run, используя Run.get_context(), а затем извлеките словарь именованных входов, используя input_datasets. Если объект DatasetConsumptionConfig передан с использованием аргумента arguments, а не аргумента inputs, получите доступ к данным, используя код ArgParser. Оба метода демонстрируются в следующих фрагментах кода:

Скрипт определения конвейера

# 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()]
)

Сценарий train.py , на который ссылается 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']

Переданное значение — это путь к файлам набора данных.

Также можно получить доступ к зарегистрированному Dataset напрямую. Поскольку зарегистрированные наборы данных являются постоянными и открыты для общего доступа во всей рабочей области, их можно извлечь напрямую.

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

Примечание.

Приведенные выше фрагменты иллюстрируют форму вызовов и не являются частью примера Microsoft. Требуется заменить аргументы значениями из собственного проекта.

Использование OutputFileDatasetConfig для промежуточных данных

Объекты Dataset представляют только постоянные данные, но при этом объект (-ы) OutputFileDatasetConfig можно использовать для временного вывода из этапов конвейера постоянных выходных данных и . OutputFileDatasetConfig поддерживает запись данных в хранилище BLOB-объектов, общую папку, fileshare, adlsgen1 или adlsgen2. Он поддерживает режим с установкой и режим с загрузкой. В режиме с установкой файлы, записанные в установленный каталог, помещаются на постоянное хранение при закрытии файла. В режиме с загрузкой файлы, записанные в выходной каталог, загружаются по окончании задания. Если задание завершается ошибкой или отменено, выходной каталог не будет отправлен.

Поведение объекта OutputFileDatasetConfig по умолчанию — это запись в используемое по умолчанию хранилище данных рабочей области. Передайте объекты OutputFileDatasetConfig в PythonScriptStep с параметром arguments.

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]
    )

Примечание.

Параллельная одновременная запись в OutputFileDatasetConfig приведет к сбою. Не пытайтесь использовать один OutputFileDatasetConfig параллельно и одновременно. Не предоставляйте общий доступ к одному OutputFileDatasetConfig в ситуации многопроцессной обработки, например при использовании распределенного обучения.

Использование OutputFileDatasetConfig в качестве выходов этапа обучения

В PythonScriptStep конвейера можно получить доступные пути вывода с помощью аргументов программы. Если этот шаг является первым и будет инициализировать выходные данные, необходимо создать каталог по указанному пути. Затем можно записать любые файлы, которые должны содержаться в 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")

Считайте OutputFileDatasetConfig как входы для неначальных этапов

После того как начальный этап конвейера записывает те или иные данные в путь OutputFileDatasetConfig, который становится выходом этого начального этапа, его можно использовать в качестве входа для последующего этапа.

В приведенном ниже коде выполняется следующее:

  • step1_output_data показывает, что выход PythonScriptStep, step1, записывается в хранилище данных ADLS Gen 2, my_adlsgen2, в режиме доступа с загрузкой. Прочитайте дополнительные сведения о настройке разрешений роли для записи данных в ADLS Gen 2.

  • После того как step1 завершается и выходные данные записываются в место назначения, указанное в параметре step1_output_data, этап 2 готов использовать step1_output_data в качестве входных данных.

# 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])

Совет

Чтение данных в скрипте step2.py Python совпадает с документом, описанным ранее в наборах данных Access в скрипте; используйте ArgumentParser для добавления аргумента --pd в скрипт для доступа к данным.

Регистрация объектов OutputFileDatasetConfig для повторного использования

Чтобы сделать OutputFileDatasetConfig доступным на период, превышающий длительность эксперимента, зарегистрируйте его в рабочей области для общего доступа и повторного использования в экспериментах.

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

Удаление OutputFileDatasetConfig содержимого, которое впредь не требуется

Azure не удаляет промежуточные данные, записанные с помощью OutputFileDatasetConfigazure. Чтобы избежать расходов на хранение больших объемов ненужных данных, необходимо выполнять одно из следующих действий.

Внимание

Удалите промежуточные данные только через 30 дней с даты последнего изменения данных. Удаление данных ранее может привести к сбою запуска конвейера, так как конвейер предполагает, что промежуточные данные существуют в течение 30 дней для повторного использования.

  • Программное удаление промежуточных данных в конце задания конвейера, когда оно больше не требуется.
  • Используйте хранилище BLOB-объектов с краткосрочной политикой хранения промежуточных данных (см. статью "Оптимизация затрат путем автоматизации Хранилище BLOB-объектов Azure уровней доступа"). Эта политика может быть задана только в хранилище данных, отличном от рабочей области по умолчанию. Используется OutputFileDatasetConfig для экспорта промежуточных данных в другое хранилище данных, которое не является стандартным.
    # 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()
    
  • Регулярно просматривайте и удаляйте ненужные данные.

Дополнительные сведения см. в статье Планирование и управление затратами на машинное обучение Azure.

Следующие шаги