Delen via


Uw R-script aanpassen om in productie te worden uitgevoerd

In dit artikel wordt uitgelegd hoe u een bestaand R-script kunt gebruiken en de juiste wijzigingen kunt aanbrengen om het script uit te voeren als een taak in Azure Machine Learning.

U moet optimaal gebruikmaken van de wijzigingen die in dit artikel in detail worden beschreven.

Gebruikersinteractie verwijderen

Uw R-script moet zijn ontworpen om zonder toezicht uit te voeren en wordt uitgevoerd via de Rscript opdracht in de container. Zorg ervoor dat u interactieve invoer of uitvoer uit het script verwijdert.

Parseren toevoegen

Als voor uw script een soort invoerparameter is vereist (de meeste scripts wel), geeft u de invoer via de aanroep door aan het Rscript script door.

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

Parseer de invoer in uw R-script en voer de juiste typeconversies uit. U wordt aangeraden het optparse pakket te gebruiken.

In het volgende codefragment ziet u hoe u:

  • de parser initiëren
  • al uw invoer toevoegen als opties
  • de invoer parseren met de juiste gegevenstypen

U kunt ook standaardinstellingen toevoegen, wat handig is voor het testen. U wordt aangeraden een --output parameter met een standaardwaarde ./outputs toe te voegen, zodat elke uitvoer van het script wordt opgeslagen.

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 is een benoemde lijst. U kunt een van deze parameters later in uw script gebruiken.

azureml_utils.R Het helperscript bronen

U moet een helperscript met de naam azureml_utils.R script in dezelfde werkmap van het R-script zoeken dat wordt uitgevoerd. Het helperscript is vereist voor het uitvoeren van het R-script om te kunnen communiceren met de MLflow-server. Het helperscript biedt een methode voor het continu ophalen van het verificatietoken, omdat het token snel verandert in een actieve taak. Met het helperscript kunt u ook de logboekregistratiefuncties in de R MLflow-API gebruiken om modellen, parameters, tags en algemene artefacten te registreren.

  1. Maak uw bestand met azureml_utils.Rdeze code:

    # 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. Start uw R-script met de volgende regel:

source("azureml_utils.R")

Gegevensbestanden lezen als lokale bestanden

Wanneer u een R-script uitvoert als een taak, neemt Azure Machine Learning de gegevens die u opgeeft in het verzenden van de taak en koppelt het aan de actieve container. Daarom kunt u de gegevensbestanden lezen alsof ze lokale bestanden in de actieve container zijn.

  • Zorg ervoor dat uw brongegevens zijn geregistreerd als een gegevensasset
  • Geef de gegevensasset op naam door in de parameters voor het verzenden van taken
  • Lees de bestanden zoals u normaal gesproken een lokaal bestand zou lezen

Definieer de invoerparameter zoals wordt weergegeven in de sectie parameters. Gebruik de parameter, data-fileom een heel pad op te geven, zodat u de gegevensasset kunt read_csv(args$data_file) lezen.

Taakartefacten opslaan (afbeeldingen, gegevens, enzovoort)

Belangrijk

Deze sectie is niet van toepassing op modellen. Zie de volgende twee secties voor modelspecifieke instructies voor opslaan en logboekregistratie.

U kunt willekeurige scriptuitvoer opslaan, zoals gegevensbestanden, afbeeldingen, geserialiseerde R-objecten, enzovoort, die worden gegenereerd door het R-script in Azure Machine Learning. Maak een ./outputs map voor het opslaan van gegenereerde artefacten (afbeeldingen, modellen, gegevens, enzovoort) Alle bestanden die zijn opgeslagen ./outputs , worden automatisch opgenomen in de uitvoering en geüpload naar het experiment aan het einde van de uitvoering. Omdat u een standaardwaarde hebt toegevoegd voor de --output parameter in de sectie invoerparameters , neemt u het volgende codefragment op in uw R-script om de output map te maken.

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

Nadat u de map hebt gemaakt, slaat u uw artefacten op in die map. Voorbeeld:

# 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 uw modellen met het carrier pakket

De documentatie van de R MLflow-API geeft aan dat uw R-modellen van de crate modelsmaak moeten zijn.

  • Als uw R-script een model traint en u een modelobject produceert, moet crate u het op een later tijdstip kunnen implementeren met Azure Machine Learning.
  • Wanneer u de crate functie gebruikt, gebruikt u expliciete naamruimten bij het aanroepen van een pakketfunctie die u nodig hebt.

Stel dat u een tijdreeksmodelobject my_ts_model hebt dat is gemaakt met het fable pakket. Als u dit model aanroepbaar wilt maken wanneer het wordt geïmplementeerd, maakt u een crate locatie waar u het modelobject en een prognoseperiode in het aantal perioden doorgeeft:

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

Het crated_model object is het object dat u gaat registreren.

Logboekmodellen, parameters, tags of andere artefacten met de R MLflow-API

Naast het opslaan van gegenereerde artefacten, kunt u ook modellen, tags en parameters vastleggen voor elke uitvoering. Gebruik de R MLflow-API om dit te doen.

Wanneer u een model aanmeldt, meldt u het crated-model dat u hebt gemaakt, zoals beschreven in de vorige sectie.

Notitie

Wanneer u een model aanmeldt, wordt het model ook opgeslagen en toegevoegd aan de runartefacten. Het is niet nodig om een model expliciet op te slaan, tenzij u het niet hebt vastgelegd.

Een model en/of parameter registreren:

  1. De uitvoering starten met mlflow_start_run()
  2. Logboekartefacten met mlflow_log_model, mlflow_log_paramof mlflow_log_batch
  3. Beëindig de uitvoering niet met mlflow_end_run(). Sla deze aanroep over, omdat deze momenteel een fout veroorzaakt.

Als u bijvoorbeeld het crated_model object wilt registreren zoals gemaakt in de vorige sectie, moet u de volgende code opnemen in uw R-script:

Tip

Als models waarde gebruiken voor artifact_path het vastleggen van een model, is dit een best practice (ook al kunt u dit een andere naam noemen.)

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

Scriptstructuur en voorbeeld

Gebruik deze codefragmenten als richtlijn voor het structuren van uw R-script, waarbij u alle wijzigingen volgt die in dit artikel worden beschreven.

# 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

Een omgeving maken

Als u uw R-script wilt uitvoeren, gebruikt u de ml extensie voor Azure CLI, ook wel CLI v2 genoemd. De ml opdracht maakt gebruik van een YAML-taakdefinitiebestand. Zie Modellen trainen met Azure Machine Learning CLI voor meer informatie over het verzenden van takenaz ml.

Het YAML-taakbestand geeft een omgeving op. U moet deze omgeving maken in uw werkruimte voordat u de taak kunt uitvoeren.

U kunt de omgeving maken in Azure Machine Learning-studio of met de Azure CLI.

Welke methode u ook gebruikt, u gebruikt een Dockerfile. Alle Docker-contextbestanden voor R-omgevingen moeten de volgende specificatie hebben om te kunnen werken met 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/')"

De basisinstallatiekopieën zijn rocker/tidyverse:latest, waarop veel R-pakketten en hun afhankelijkheden al zijn geïnstalleerd.

Belangrijk

U moet R-pakketten installeren die uw script moet uitvoeren. Voeg indien nodig meer regels toe aan het Docker-contextbestand.

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

Aanvullende suggesties

Enkele aanvullende suggesties die u kunt overwegen:

  • De functie R tryCatch gebruiken voor uitzonderings- en foutafhandeling
  • Expliciete logboekregistratie toevoegen voor probleemoplossing en foutopsporing

Volgende stappen