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


Адаптация скрипта R для выполнения в рабочей среде

В этой статье объясняется, как выполнить существующий скрипт R и внести соответствующие изменения для его запуска в качестве задания в Машинное обучение Azure.

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

Удаление взаимодействия с пользователем

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

Добавление синтаксического анализа

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

Rscript <name-of-r-script>.R
--data_file ${{inputs.<name-of-yaml-input-1>}} 
--brand ${{inputs.<name-of-yaml-input-2>}}

В скрипте R выполните синтаксический анализ входных данных и выполните правильные преобразования типов. Рекомендуется использовать optparse пакет.

В следующем фрагменте кода показано, как:

  • инициирование средства синтаксического анализа
  • добавьте все входные данные в качестве параметров
  • анализ входных данных с соответствующими типами данных

Вы также можете добавить значения по умолчанию, которые удобны для тестирования. Рекомендуется добавить --output параметр со значением ./outputs по умолчанию, чтобы сохранить все выходные данные скрипта.

library(optparse)

parser <- OptionParser()

parser <- add_option(
  parser,
  "--output",
  type = "character",
  action = "store",
  default = "./outputs"
)

parser <- add_option(
  parser,
  "--data_file",
  type = "character",
  action = "store",
  default = "data/myfile.csv"
)

parser <- add_option(
  parser,
  "--brand",
  type = "double",
  action = "store",
  default = 1
)
args <- parse_args(parser)

args — именованный список. Вы можете использовать любой из этих параметров позже в скрипте.

Источник вспомогательного azureml_utils.R скрипта

Необходимо создать вспомогательный скрипт, называемый azureml_utils.R скриптом в том же рабочем каталоге скрипта R, который будет выполняться. Вспомогательный скрипт необходим для запуска скрипта R, чтобы иметь возможность взаимодействовать с сервером MLflow. Вспомогательный скрипт предоставляет метод непрерывного извлечения маркера проверки подлинности, так как маркер быстро изменяется в выполняемом задании. Вспомогательный скрипт также позволяет использовать функции ведения журнала, предоставляемые в API MLflow R, для журналов моделей, параметров, тегов и общих артефактов.

  1. Создайте файл с azureml_utils.Rпомощью этого кода:

    # Azure ML utility to enable usage of the MLFlow R API for tracking with Azure Machine Learning (Azure ML). This utility does the following::
    # 1. Understands Azure ML MLflow tracking url by extending OSS MLflow R client.
    # 2. Manages Azure ML Token refresh for remote runs (runs that execute in Azure Machine Learning). It uses tcktk2 R libraray to schedule token refresh.
    #    Token refresh interval can be controlled by setting the environment variable MLFLOW_AML_TOKEN_REFRESH_INTERVAL and defaults to 30 seconds.
    
    library(mlflow)
    library(httr)
    library(later)
    library(tcltk2)
    
    new_mlflow_client.mlflow_azureml <- function(tracking_uri) {
      host <- paste("https", tracking_uri$path, sep = "://")
      get_host_creds <- function () {
        mlflow:::new_mlflow_host_creds(
          host = host,
          token = Sys.getenv("MLFLOW_TRACKING_TOKEN"),
          username = Sys.getenv("MLFLOW_TRACKING_USERNAME", NA),
          password = Sys.getenv("MLFLOW_TRACKING_PASSWORD", NA),
          insecure = Sys.getenv("MLFLOW_TRACKING_INSECURE", NA)
        )
      }
      cli_env <- function() {
        creds <- get_host_creds()
        res <- list(
          MLFLOW_TRACKING_USERNAME = creds$username,
          MLFLOW_TRACKING_PASSWORD = creds$password,
          MLFLOW_TRACKING_TOKEN = creds$token,
          MLFLOW_TRACKING_INSECURE = creds$insecure
        )
        res[!is.na(res)]
      }
      mlflow:::new_mlflow_client_impl(get_host_creds, cli_env, class = "mlflow_azureml_client")
    }
    
    get_auth_header <- function() {
        headers <- list()
        auth_token <- Sys.getenv("MLFLOW_TRACKING_TOKEN")
        auth_header <- paste("Bearer", auth_token, sep = " ")
        headers$Authorization <- auth_header
        headers
    }
    
    get_token <- function(host, exp_id, run_id) {
        req_headers <- do.call(httr::add_headers, get_auth_header())
        token_host <- gsub("mlflow/v1.0","history/v1.0", host)
        token_host <- gsub("azureml://","https://", token_host)
        api_url <- paste0(token_host, "/experimentids/", exp_id, "/runs/", run_id, "/token")
        GET( api_url, timeout(getOption("mlflow.rest.timeout", 30)), req_headers)
    }
    
    
    fetch_token_from_aml <- function() {
        message("Refreshing token")
        tracking_uri <- Sys.getenv("MLFLOW_TRACKING_URI")
        exp_id <- Sys.getenv("MLFLOW_EXPERIMENT_ID")
        run_id <- Sys.getenv("MLFLOW_RUN_ID")
        sleep_for <- 1
        time_left <- 30
        response <- get_token(tracking_uri, exp_id, run_id)
        while (response$status_code == 429 && time_left > 0) {
            time_left <- time_left - sleep_for
            warning(paste("Request returned with status code 429 (Rate limit exceeded). Retrying after ",
                        sleep_for, " seconds. Will continue to retry 429s for up to ", time_left,
                        " second.", sep = ""))
            Sys.sleep(sleep_for)
            sleep_for <- min(time_left, sleep_for * 2)
            response <- get_token(tracking_uri, exp_id)
        }
    
        if (response$status_code != 200){
            error_response = paste("Error fetching token will try again after sometime: ", str(response), sep = " ")
            warning(error_response)
        }
    
        if (response$status_code == 200){
            text <- content(response, "text", encoding = "UTF-8")
            json_resp <-jsonlite::fromJSON(text, simplifyVector = FALSE)
            json_resp$token
            Sys.setenv(MLFLOW_TRACKING_TOKEN = json_resp$token)
            message("Refreshing token done")
        }
    }
    
    clean_tracking_uri <- function() {
        tracking_uri <- httr::parse_url(Sys.getenv("MLFLOW_TRACKING_URI"))
        tracking_uri$query = ""
        tracking_uri <-httr::build_url(tracking_uri)
        Sys.setenv(MLFLOW_TRACKING_URI = tracking_uri)
    }
    
    clean_tracking_uri()
    tcltk2::tclTaskSchedule(as.integer(Sys.getenv("MLFLOW_TOKEN_REFRESH_INTERVAL_SECONDS", 30))*1000, fetch_token_from_aml(), id = "fetch_token_from_aml", redo = TRUE)
    
    # Set MLFlow related env vars
    Sys.setenv(MLFLOW_BIN = system("which mlflow", intern = TRUE))
    Sys.setenv(MLFLOW_PYTHON_BIN = system("which python", intern = TRUE))
    
  2. Запустите скрипт R со следующей строкой:

source("azureml_utils.R")

Чтение файлов данных в виде локальных файлов

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

  • Убедитесь, что исходные данные зарегистрированы в качестве ресурса данных
  • Передача ресурса данных по имени в параметрах отправки задания
  • Чтение файлов, как правило, считывает локальный файл.

Определите входной параметр, как показано в разделе параметров. Используйте параметр, data-fileчтобы указать весь путь, чтобы считывать read_csv(args$data_file) ресурс данных.

Сохранение артефактов заданий (изображения, данные и т. д.)

Внимание

Этот раздел не применяется к моделям. Ознакомьтесь со следующими двумя разделами для конкретных инструкций по сохранению и ведению журнала модели.

Вы можете хранить произвольные выходные данные скрипта, такие как файлы данных, изображения, сериализованные объекты R и т. д., созданные скриптом R в Машинное обучение Azure. ./outputs Создайте каталог для хранения любых созданных артефактов (изображений, моделей, данных и т. д.) Все сохраненные файлы ./outputs будут автоматически включены в выполнение и отправлены в эксперимент в конце выполнения. Так как вы добавили значение по умолчанию для --output параметра в разделе входных параметров , добавьте следующий фрагмент кода в скрипт R для создания output каталога.

if (!dir.exists(args$output)) {
  dir.create(args$output)
}

После создания каталога сохраните артефакты в этом каталоге. Например:

# create and save a plot
library(ggplot2)

myplot <- ggplot(...)

ggsave(myplot, 
       filename = file.path(args$output,"forecast-plot.png"))


# save an rds serialized object
saveRDS(myobject, file = file.path(args$output,"myobject.rds"))

crateмодели с пакетом carrier

Документация по API MLflow R указывает, что модели R должны соответствовать вкусуcrate модели.

  • Если скрипт R обучает модель и создает объект модели, его необходимо crate будет развернуть позже с помощью Машинное обучение Azure.
  • При использовании функции используйте явные crate пространства имен при вызове любой нужной функции пакета.

Предположим, что у вас есть объект модели таймерий, созданный my_ts_model с fable помощью пакета. Чтобы сделать эту модель вызываемой при развертывании, создайте crate место, где вы будете передавать объект модели и горизонт прогнозирования в количестве периодов:

library(carrier)
crated_model <- crate(function(x)
{
  fabletools::forecast(!!my_ts_model, h = x)
})

Объект crated_model — это тот, который вы будете записывать.

Модели журналов, параметры, теги или другие артефакты с ПОМОЩЬЮ API R MLflow

Помимо сохранения созданных артефактов, можно также регистрировать модели, теги и параметры для каждого запуска. Используйте API MLflow R для этого.

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

Примечание.

При регистрации модели модель также сохраняется и добавляется в артефакты запуска. Нет необходимости явно сохранять модель, если вы не выполнили ее журнал.

Чтобы регистрировать модель и /или параметр, выполните приведенные ниже действия.

  1. Запуск с помощью mlflow_start_run()
  2. Артефакты журнала с mlflow_log_model, mlflow_log_paramили mlflow_log_batch
  3. Не завершайте выполнение с mlflow_end_run()помощью . Пропустите этот вызов, так как в настоящее время вызывает ошибку.

Например, чтобы записать crated_model объект, созданный в предыдущем разделе, в скрипт R можно включить следующий код:

Совет

Используйте models в качестве значения artifact_path для ведения журнала модели, это рекомендуется (даже если вы можете назвать его чем-то другим.)

mlflow_start_run()

mlflow_log_model(
  model = crated_model, # the crate model object
  artifact_path = "models" # a path to save the model object to
  )

mlflow_log_param(<key-name>, <value>)

# mlflow_end_run() - causes an error, do not include mlflow_end_run()

Структура скрипта и пример

Используйте эти фрагменты кода в качестве руководства по структуре скрипта R, следуя всем изменениям, описанным в этой статье.

# BEGIN R SCRIPT

# source the azureml_utils.R script which is needed to use the MLflow back end
# with R
source("azureml_utils.R")

# load your packages here. Make sure that they are installed in the container.
library(...)

# parse the command line arguments.
library(optparse)

parser <- OptionParser()

parser <- add_option(
  parser,
  "--output",
  type = "character",
  action = "store",
  default = "./outputs"
)

parser <- add_option(
  parser,
  "--data_file",
  type = "character",
  action = "store",
  default = "data/myfile.csv"
)

parser <- add_option(
  parser,
  "--brand",
  type = "double",
  action = "store",
  default = 1
)
args <- parse_args(parser)

# your own R code goes here
# - model building/training
# - visualizations
# - etc.

# create the ./outputs directory
if (!dir.exists(args$output)) {
  dir.create(args$output)
}

# log models and parameters to MLflow
mlflow_start_run()

mlflow_log_model(
  model = crated_model, # the crate model object
  artifact_path = "models" # a path to save the model object to
  )

mlflow_log_param(<key-name>, <value>)

# mlflow_end_run() - causes an error, do not include mlflow_end_run()
## END OF R SCRIPT

Создать среду

Чтобы запустить скрипт R, вы будете использовать ml расширение для Azure CLI, также называемое CLI версии 2. Команда ml использует файл определений заданий YAML. Дополнительные сведения о отправке заданий с помощью см. в разделе "Обучение моделей с az mlпомощью интерфейса командной строки Машинное обучение Azure".

Файл задания YAML указывает среду. Перед запуском задания необходимо создать эту среду в рабочей области.

Среду можно создать в Студия машинного обучения Azure или с помощью Azure CLI.

Какой бы метод вы ни использовали, вы будете использовать Dockerfile. Все файлы контекста Docker для сред R должны иметь следующую спецификацию, чтобы работать с Машинное обучение Azure:

FROM rocker/tidyverse:latest

# Install python
RUN apt-get update -qq && \
 apt-get install -y python3-pip tcl tk libz-dev libpng-dev

RUN ln -f /usr/bin/python3 /usr/bin/python
RUN ln -f /usr/bin/pip3 /usr/bin/pip
RUN pip install -U pip

# Install azureml-MLflow
RUN pip install azureml-MLflow
RUN pip install MLflow

# Create link for python
RUN ln -f /usr/bin/python3 /usr/bin/python

# Install R packages required for logging with MLflow (these are necessary)
RUN R -e "install.packages('mlflow', dependencies = TRUE, repos = 'https://cloud.r-project.org/')"
RUN R -e "install.packages('carrier', dependencies = TRUE, repos = 'https://cloud.r-project.org/')"
RUN R -e "install.packages('optparse', dependencies = TRUE, repos = 'https://cloud.r-project.org/')"
RUN R -e "install.packages('tcltk2', dependencies = TRUE, repos = 'https://cloud.r-project.org/')"

Базовый образ— это rocker/tidyverse:latest, который содержит множество пакетов R и их зависимостей, уже установленных.

Внимание

Необходимо заранее установить все пакеты R, которые потребуется запустить скрипт. Добавьте дополнительные строки в файл контекста Docker по мере необходимости.

RUN R -e "install.packages('<package-to-install>', dependencies = TRUE, repos = 'https://cloud.r-project.org/')"

Дополнительные предложения

Некоторые дополнительные предложения, которые вы можете рассмотреть, выполните следующие действия.

  • Использование функции R tryCatch для обработки исключений и ошибок
  • Добавление явного ведения журнала для устранения неполадок и отладки

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