Anpassa R-skriptet så att det körs i produktion
Den här artikeln beskriver hur du tar ett befintligt R-skript och gör lämpliga ändringar för att köra det som ett jobb i Azure Machine Learning.
Du måste göra det mesta av, om inte alla, av de ändringar som beskrivs i detalj i den här artikeln.
Ta bort användarinteraktion
R-skriptet måste vara utformat för att köras obevakat och köras via Rscript
kommandot i containern. Se till att du tar bort interaktiva indata eller utdata från skriptet.
Lägg till parsning
Om skriptet kräver någon typ av indataparameter (de flesta skript gör det) skickar du indata till skriptet via anropet Rscript
.
Rscript <name-of-r-script>.R
--data_file ${{inputs.<name-of-yaml-input-1>}}
--brand ${{inputs.<name-of-yaml-input-2>}}
I R-skriptet parsar du indata och gör rätt typkonverteringar. Vi rekommenderar att du använder paketet optparse
.
Följande kodfragment visar hur du:
- initiera parsern
- lägg till alla dina indata som alternativ
- parsa indata med lämpliga datatyper
Du kan också lägga till standardvärden som är praktiska för testning. Vi rekommenderar att du lägger till en --output
parameter med standardvärdet ./outputs
så att alla utdata från skriptet lagras.
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
är en namngiven lista. Du kan använda någon av dessa parametrar senare i skriptet.
Hämta hjälpskriptet azureml_utils.R
Du måste hämta ett hjälpskript med namnet azureml_utils.R
script i samma arbetskatalog för R-skriptet som ska köras. Hjälpskriptet krävs för att R-skriptet som körs ska kunna kommunicera med MLflow-servern. Hjälpskriptet tillhandahåller en metod för att kontinuerligt hämta autentiseringstoken, eftersom token ändras snabbt i ett jobb som körs. Med hjälpskriptet kan du också använda loggningsfunktionerna i R MLflow-API:et för att logga modeller, parametrar, taggar och allmänna artefakter.
Skapa filen ,
azureml_utils.R
med den här koden:# 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))
Starta R-skriptet med följande rad:
source("azureml_utils.R")
Läsa datafiler som lokala filer
När du kör ett R-skript som ett jobb tar Azure Machine Learning de data som du anger i jobböverföringen och monterar dem på den container som körs. Därför kan du läsa datafilerna som om de vore lokala filer i containern som körs.
- Kontrollera att dina källdata är registrerade som en datatillgång
- Skicka datatillgången efter namn i parametrarna för jobböverföring
- Läsa filerna som du normalt skulle läsa en lokal fil
Definiera indataparametern enligt beskrivningen i avsnittet parametrar. Använd parametern , data-file
för att ange en hel sökväg så att du kan använda read_csv(args$data_file)
för att läsa datatillgången.
Spara jobbartefakter (bilder, data osv.)
Viktigt!
Det här avsnittet gäller inte för modeller. Se följande två avsnitt för modellspecifika instruktioner för sparande och loggning.
Du kan lagra godtyckliga skriptutdata som datafiler, bilder, serialiserade R-objekt osv. som genereras av R-skriptet i Azure Machine Learning. Skapa en ./outputs
katalog för att lagra alla genererade artefakter (bilder, modeller, data osv.) Alla filer som sparas i ./outputs
inkluderas automatiskt i körningen och laddas upp till experimentet i slutet av körningen. Eftersom du har lagt till ett standardvärde för parametern --output
i avsnittet indataparametrar ska du ta med följande kodfragment i R-skriptet för att skapa output
katalogen.
if (!dir.exists(args$output)) {
dir.create(args$output)
}
När du har skapat katalogen sparar du artefakterna i katalogen. Till exempel:
# 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
dina modeller med carrier
paketet
Dokumentationen för R MLflow API anger att dina R-modeller måste vara av modellsmakencrate
.
- Om ditt R-skript tränar en modell och du skapar ett modellobjekt måste
crate
du kunna distribuera det senare med Azure Machine Learning. - När du använder
crate
funktionen använder du explicita namnområden när du anropar alla paketfunktioner som du behöver.
Anta att du har ett tidsseriemodellobjekt som heter my_ts_model
skapad med fable
paketet. För att göra den här modellen anropsbar när den distribueras skapar du en crate
plats där du skickar in modellobjektet och en prognoshorisont i antal perioder:
library(carrier)
crated_model <- crate(function(x)
{
fabletools::forecast(!!my_ts_model, h = x)
})
Objektet crated_model
är det som du loggar.
Loggmodeller, parametrar, taggar eller andra artefakter med R MLflow-API:et
Förutom att spara alla genererade artefakter kan du även logga modeller, taggar och parametrar för varje körning. Använd R MLflow-API:et för att göra det.
När du loggar en modell loggar du den crated-modell som du skapade enligt beskrivningen i föregående avsnitt.
Kommentar
När du loggar en modell sparas även modellen och läggs till i körningsartefakterna. Du behöver inte spara en modell uttryckligen om du inte har loggat den.
Så här loggar du en modell och/eller parameter:
- Starta körningen med
mlflow_start_run()
- Logga artefakter med
mlflow_log_model
,mlflow_log_param
ellermlflow_log_batch
- Avsluta inte körningen med
mlflow_end_run()
. Hoppa över det här anropet eftersom det för närvarande orsakar ett fel.
Om du till exempel vill logga crated_model
objektet som det skapades i föregående avsnitt skulle du inkludera följande kod i R-skriptet:
Dricks
Använd models
som värde för artifact_path
när du loggar en modell, det här är en bra idé (även om du kan ge den ett annat namn.)
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()
Skriptstruktur och exempel
Använd dessa kodfragment som en guide för att strukturera R-skriptet genom att följa alla ändringar som beskrivs i den här artikeln.
# 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
Skapa en miljö
Om du vill köra R-skriptet ml
använder du tillägget för Azure CLI, även kallat CLI v2. Kommandot ml
använder en YAML-jobbdefinitionsfil. Mer information om hur du skickar jobb med az ml
finns i Träna modeller med Azure Machine Learning CLI.
YAML-jobbfilen anger en miljö. Du måste skapa den här miljön på din arbetsyta innan du kan köra jobbet.
Du kan skapa miljön i Azure Machine Learning-studio eller med Azure CLI.
Oavsett vilken metod du använder använder du en Dockerfile. Alla Docker-kontextfiler för R-miljöer måste ha följande specifikation för att kunna arbeta med 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/')"
Basavbildningen är rocker/tidyverse:latest
, som redan har många R-paket och deras beroenden installerade.
Viktigt!
Du måste installera alla R-paket som skriptet måste köra i förväg. Lägg till fler rader i Docker-kontextfilen efter behov.
RUN R -e "install.packages('<package-to-install>', dependencies = TRUE, repos = 'https://cloud.r-project.org/')"
Ytterligare förslag
Några ytterligare förslag som du kanske vill överväga:
- Använd R:s funktion för undantags
tryCatch
- och felhantering - Lägga till explicit loggning för felsökning och felsökning