Adapte seu script R para ser executado em produção
Este artigo explica como usar um script R existente e fazer as alterações apropriadas para executá-lo como um trabalho no Aprendizado de Máquina do Azure.
Você terá que fazer a maioria, se não todas, as alterações descritas em detalhes neste artigo.
Remover a interação do usuário
Seu script R deve ser projetado para ser executado sem supervisão e será executado através do Rscript
comando dentro do contêiner. Certifique-se de remover todas as entradas ou saídas interativas do script.
Adicionar análise
Se o script requer qualquer tipo de parâmetro de entrada (a maioria dos scripts faz), passe as entradas para o script através da Rscript
chamada.
Rscript <name-of-r-script>.R
--data_file ${{inputs.<name-of-yaml-input-1>}}
--brand ${{inputs.<name-of-yaml-input-2>}}
No script R, analise as entradas e faça as conversões de tipo adequadas. Recomendamos que você use o optparse
pacote.
O trecho a seguir mostra como:
- Iniciar o analisador
- adicionar todas as suas entradas como opções
- Analise as entradas com os tipos de dados apropriados
Você também pode adicionar padrões, que são úteis para testes. Recomendamos que você adicione um --output
parâmetro com um valor padrão de ./outputs
para que qualquer saída do script seja armazenada.
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
é uma lista nomeada. Você pode usar qualquer um desses parâmetros posteriormente em seu script.
Originar o azureml_utils.R
script auxiliar
Você deve originar um script auxiliar chamado azureml_utils.R
script no mesmo diretório de trabalho do script R que será executado. O script auxiliar é necessário para que o script R em execução possa se comunicar com o servidor MLflow. O script auxiliar fornece um método para recuperar continuamente o token de autenticação, uma vez que o token muda rapidamente em um trabalho em execução. O script auxiliar também permite que você use as funções de log fornecidas na API R MLflow para registrar modelos, parâmetros, tags e artefatos gerais.
Crie o seu ficheiro,
azureml_utils.R
, com este código:# 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))
Inicie o script R com a seguinte linha:
source("azureml_utils.R")
Ler arquivos de dados como arquivos locais
Quando você executa um script R como um trabalho, o Aprendizado de Máquina do Azure pega os dados especificados no envio do trabalho e os monta no contêiner em execução. Portanto, você poderá ler o(s) arquivo(s) de dados como se fossem arquivos locais no contêiner em execução.
- Verifique se os dados de origem estão registrados como um ativo de dados
- Passar o ativo de dados pelo nome nos parâmetros de envio de trabalho
- Leia os arquivos como você normalmente leria um arquivo local
Defina o parâmetro de entrada como mostrado na seção de parâmetros. Use o parâmetro, data-file
, para especificar um caminho inteiro, para que você possa usar read_csv(args$data_file)
para ler o ativo de dados.
Salvar artefatos de trabalho (imagens, dados, etc.)
Importante
Esta secção não se aplica aos modelos. Consulte as duas seções a seguir para obter instruções de salvamento e registro específicas do modelo.
Você pode armazenar saídas de script arbitrárias, como arquivos de dados, imagens, objetos R serializados, etc., que são geradas pelo script R no Aprendizado de Máquina do Azure. Crie um ./outputs
diretório para armazenar todos os artefatos gerados (imagens, modelos, dados, etc.) Todos os arquivos salvos serão ./outputs
automaticamente incluídos na execução e carregados para o experimento no final da execução. Como você adicionou um valor padrão para o --output
parâmetro na seção de parâmetros de entrada, inclua o seguinte trecho de código no script R para criar o output
diretório.
if (!dir.exists(args$output)) {
dir.create(args$output)
}
Depois de criar o diretório, salve seus artefatos nesse diretório. Por exemplo:
# 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
os seus modelos com a carrier
embalagem
A documentação da API R MLflow especifica que seus modelos R precisam ter o crate
tipo de modelo.
- Se o script R treinar um modelo e você produzir um objeto de
crate
modelo, precisará dele para poder implantá-lo posteriormente com o Aprendizado de Máquina do Azure. - Ao usar a
crate
função, use namespaces explícitos ao chamar qualquer função de pacote necessária.
Digamos que você tenha um objeto de modelo de série temporal chamado my_ts_model
criado com o fable
pacote. Para tornar esse modelo chamável quando for implantado, crie um crate
local onde você passará no objeto do modelo e um horizonte de previsão em número de períodos:
library(carrier)
crated_model <- crate(function(x)
{
fabletools::forecast(!!my_ts_model, h = x)
})
O crated_model
objeto é aquele que você registrará.
Registrar modelos, parâmetros, tags ou outros artefatos com a API R MLflow
Além de salvar todos os artefatos gerados, você também pode registrar modelos, tags e parâmetros para cada execução. Use a API R MLflow para fazer isso.
Ao registrar um modelo, você registra o modelo criado conforme descrito na seção anterior.
Nota
Quando você registra um modelo, o modelo também é salvo e adicionado aos artefatos de execução. Não há necessidade de salvar explicitamente um modelo, a menos que você não o registre.
Para registrar um modelo e/ou parâmetro:
- Inicie a execução com
mlflow_start_run()
- Registrar artefatos com
mlflow_log_model
,mlflow_log_param
oumlflow_log_batch
- Não termine a corrida com
mlflow_end_run()
. Ignore esta chamada, pois ela atualmente causa um erro.
Por exemplo, para registrar o crated_model
objeto conforme criado na seção anterior, você deve incluir o seguinte código no script R:
Gorjeta
Use models
como valor para artifact_path
ao registrar um modelo, essa é uma prática recomendada (embora você possa nomeá-lo de outra forma).
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()
Estrutura e exemplo de script
Use esses trechos de código como um guia para estruturar seu script R, seguindo todas as alterações descritas neste artigo.
# 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
Criar um ambiente
Para executar seu script R, você usará a extensão para a CLI ml
do Azure, também conhecida como CLI v2. O ml
comando usa um arquivo de definições de trabalho YAML. Para obter mais informações sobre como enviar trabalhos com az ml
o , consulte Treinar modelos com a CLI do Azure Machine Learning.
O arquivo de trabalho YAML especifica um ambiente. Você precisará criar esse ambiente em seu espaço de trabalho antes de executar o trabalho.
Você pode criar o ambiente no estúdio do Azure Machine Learning ou com a CLI do Azure.
Seja qual for o método usado, você usará um Dockerfile. Todos os arquivos de contexto do Docker para ambientes R devem ter a seguinte especificação para funcionar no Azure Machine Learning:
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/')"
A imagem base é rocker/tidyverse:latest
, que tem muitos pacotes R e suas dependências já instaladas.
Importante
Você deve instalar todos os pacotes R que seu script precisará executar com antecedência. Adicione mais linhas ao arquivo de contexto do Docker conforme necessário.
RUN R -e "install.packages('<package-to-install>', dependencies = TRUE, repos = 'https://cloud.r-project.org/')"
Sugestões adicionais
Algumas sugestões adicionais que você pode querer considerar:
- Use a função de R para tratamento de
tryCatch
exceções e erros - Adicionar log explícito para solução de problemas e depuração