Как сохранить встроенный преобразователь в большой двоичный объект, чтобы конвейер прогнозирования мог использовать его в службе AML?

Я создаю конвейер преобразования данных и обучения в Azure Machine Leaning Service. Я хотел бы сохранить свой установленный преобразователь (например, tf-idf) в большой двоичный объект, чтобы мой конвейер прогнозирования мог позже получить к нему доступ.

transformed_data = PipelineData("transformed_data", 
                               datastore = default_datastore,
                               output_path_on_compute = "my_project/tfidf")

step_tfidf = PythonScriptStep(name = "tfidf_step",
                              script_name = "transform.py",
                              arguments = ['--input_data', blob_train_data, 
                                           '--output_folder', transformed_data],
                              inputs = [blob_train_data],
                              outputs = [transformed_data],
                              compute_target = aml_compute,
                              source_directory = project_folder,
                              runconfig = run_config,
                              allow_reuse = False)

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

Я хочу сохранить преобразователь в фиксированном месте в большом двоичном объекте, чтобы я мог получить к нему доступ позже при вызове конвейера прогнозирования.

Я попытался использовать экземпляр класса DataReference в качестве вывода PythonScriptStep, но это приводит к ошибке: ValueError: Unexpected output type: <class 'azureml.data.data_reference.DataReference'>

Это потому, что PythonScriptStep принимает только PipelineData или OutputPortBinding объекты в качестве выходных данных.

Как я могу сохранить свой подогнанный преобразователь, чтобы позже он был доступен любому произвольному процессу (например, моему конвейеру прогнозирования)?

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
3
0
907
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Это, вероятно, недостаточно гибко для ваших нужд (к тому же, я еще не тестировал это), но если вы используете scikit-learn, одна из возможностей — включить шаг tf-idf/transformation в объект scikit-learn Pipeline и зарегистрировать это в ваше рабочее пространство.

Таким образом, ваш сценарий обучения будет содержать:

pipeline = Pipeline([
    ('vectorizer', TfidfVectorizer(stop_words = list(text.ENGLISH_STOP_WORDS))),
    ('classifier', SGDClassifier()
])

pipeline.fit(train[label].values, train[pred_label].values)

# Serialize the pipeline
joblib.dump(value=pipeline, filename='outputs/model.pkl')

и ваш сценарий отправки эксперимента будет содержать

run = exp.submit(src)
run.wait_for_completion(show_output = True)
model = run.register_model(model_name='my_pipeline', model_path='outputs/model.pkl')

Затем вы можете использовать зарегистрированную «модель» и развернуть ее как службу как поясняется в документации, загрузив ее в сценарий оценки через

model_path = Model.get_model_path('my_pipeline')
# deserialize the model file back into a sklearn model
model = joblib.load(model_path) 

Однако это приведет к преобразованию в вашем конвейере и, следовательно, не будет таким модульным, как вы просите...

Спасибо, @Davide. Я думаю, это отличная идея! Собираюсь проверить.

Aleksander Molak 17.06.2019 10:18
Ответ принят как подходящий

Другое решение — передать DataReference в качестве входных данных для вашего PythonScriptStep.

Затем внутри transform.py вы можете прочитать это DataReference как аргумент командной строки.

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

Например. ты сможешь:

step_tfidf = PythonScriptStep(name = "tfidf_step",
                              script_name = "transform.py",
                              arguments = ['--input_data', blob_train_data, 
                                           '--output_folder', transformed_data,
                                           '--transformer_path', trained_transformer_path],
                              inputs = [blob_train_data, trained_transformer_path],
                              outputs = [transformed_data],
                              compute_target = aml_compute,
                              source_directory = project_folder,
                              runconfig = run_config,
                              allow_reuse = False)

Затем внутри вашего скрипта (transform.py в приведенном выше примере) вы можете, например:

import argparse
import joblib as jbl
import os

from sklearn.feature_extraction.text import TfidfVectorizer

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

tfidf = ### HERE CREATE AND TRAIN YOUR VECTORIZER ###

vect_filename = os.path.join(args.transformer_path, 'my_vectorizer.jbl')


ДОПОЛНИТЕЛЬНО: третий способ — просто зарегистрировать векторизатор как другую модель в вашем рабочем пространстве. Затем вы можете использовать его точно так же, как любую другую зарегистрированную модель. (Хотя этот параметр не требует явной записи в большой двоичный объект, как указано в вопросе выше)

Привет @PythoLove, вышеупомянутый подход сработал для меня. Какую ошибку вы получаете?

Aleksander Molak 17.02.2021 19:17

Другой вариант — использовать DataTransferStep и использовать его для копирования вывода в «известное место». Этот блокнот содержит примеры использования DataTransferStep для копирования данных из различных поддерживаемых хранилищ данных и в них.

from azureml.data.data_reference import DataReference
from azureml.exceptions import ComputeTargetException
from azureml.core.compute import ComputeTarget, DataFactoryCompute
from azureml.pipeline.steps import DataTransferStep

blob_datastore = Datastore.get(ws, "workspaceblobstore")

blob_data_ref = DataReference(
    datastore=blob_datastore,
    data_reference_name = "knownloaction",
    path_on_datastore = "knownloaction")

data_factory_name = 'adftest'

def get_or_create_data_factory(workspace, factory_name):
    try:
        return DataFactoryCompute(workspace, factory_name)
    except ComputeTargetException as e:
        if 'ComputeTargetNotFound' in e.message:
            print('Data factory not found, creating...')
            provisioning_config = DataFactoryCompute.provisioning_configuration()
            data_factory = ComputeTarget.create(workspace, factory_name, provisioning_config)
            data_factory.wait_for_completion()
            return data_factory
        else:
            raise e

data_factory_compute = get_or_create_data_factory(ws, data_factory_name)

# Assuming output data is your output from the step that you want to copy

transfer_to_known_location = DataTransferStep(
    name = "transfer_to_known_location",
    source_data_reference=[output_data],
    destination_data_reference=blob_data_ref,
    compute_target=data_factory_compute
    )

from azureml.pipeline.core import Pipeline
from azureml.core import Workspace, Experiment

pipeline_01 = Pipeline(
    description = "transfer_to_known_location",
    workspace=ws,
    steps=[transfer_to_known_location])

pipeline_run_01 = Experiment(ws, "transfer_to_known_location").submit(pipeline_01)
pipeline_run_01.wait_for_completion()

Другие вопросы по теме