Bagikan melalui


Menyesuaikan skrip R Anda untuk dijalankan dalam produksi

Artikel ini menjelaskan cara mengambil skrip R yang sudah ada dan membuat perubahan yang sesuai untuk menjalankannya sebagai pekerjaan di Azure Pembelajaran Mesin.

Anda harus memanfaatkan sebagian besar, jika tidak semua, dari perubahan yang dijelaskan secara rinci dalam artikel ini.

Menghapus interaksi pengguna

Skrip R Anda harus dirancang untuk berjalan tanpa pengawas dan akan dijalankan melalui Rscript perintah dalam kontainer. Pastikan Anda menghapus input atau output interaktif dari skrip.

Menambahkan penguraian

Jika skrip Anda memerlukan parameter input apa pun (sebagian besar skrip melakukannya), teruskan input ke dalam skrip melalui Rscript panggilan.

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

Dalam skrip R Anda, urai input dan buat konversi jenis yang tepat. Kami menyarankan agar Anda menggunakan paket.optparse

Cuplikan berikut menunjukkan cara:

  • memulai pengurai
  • tambahkan semua input Anda sebagai opsi
  • mengurai input dengan jenis data yang sesuai

Anda juga dapat menambahkan default, yang berguna untuk pengujian. Kami menyarankan agar Anda menambahkan --output parameter dengan nilai ./outputs default sehingga output skrip apa pun akan disimpan.

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 adalah daftar bernama. Anda dapat menggunakan salah satu parameter ini nanti di skrip Anda.

Sumber skrip pembantu azureml_utils.R

Anda harus sumber skrip pembantu yang disebut azureml_utils.R skrip di direktori kerja yang sama dari skrip R yang akan dijalankan. Skrip pembantu diperlukan agar skrip R yang sedang berjalan dapat berkomunikasi dengan server MLflow. Skrip pembantu menyediakan metode untuk terus mengambil token autentikasi, karena token berubah dengan cepat dalam pekerjaan yang sedang berjalan. Skrip pembantu juga memungkinkan Anda menggunakan fungsi pengelogan yang disediakan dalam API MLflow R untuk mencatat model, parameter, tag, dan artefak umum.

  1. Buat file Anda, azureml_utils.R, dengan kode ini:

    # 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. Mulai skrip R Anda dengan baris berikut:

source("azureml_utils.R")

Membaca file data sebagai file lokal

Saat Anda menjalankan skrip R sebagai pekerjaan, Azure Pembelajaran Mesin mengambil data yang Anda tentukan dalam pengiriman pekerjaan dan memasangnya di kontainer yang sedang berjalan. Oleh karena itu, Anda akan dapat membaca file data seolah-olah file tersebut adalah file lokal pada kontainer yang sedang berjalan.

  • Pastikan data sumber Anda terdaftar sebagai aset data
  • Meneruskan aset data menurut nama dalam parameter pengiriman pekerjaan
  • Membaca file seperti biasa akan membaca file lokal

Tentukan parameter input seperti yang ditunjukkan di bagian parameter. Gunakan parameter , data-file, untuk menentukan seluruh jalur, sehingga Anda dapat menggunakan read_csv(args$data_file) untuk membaca aset data.

Simpan artefak pekerjaan (gambar, data, dll.)

Penting

Bagian ini tidak berlaku untuk model. Lihat dua bagian berikut untuk instruksi penyimpanan dan pengelogan khusus model.

Anda dapat menyimpan output skrip arbitrer seperti file data, gambar, objek R berseri, dll. yang dihasilkan oleh skrip R di Azure Pembelajaran Mesin. Buat ./outputs direktori untuk menyimpan artefak yang dihasilkan (gambar, model, data, dll.) File apa pun yang disimpan ./outputs akan secara otomatis disertakan dalam proses dan diunggah ke eksperimen di akhir proses. Karena Anda menambahkan nilai default untuk --output parameter di bagian parameter input, sertakan cuplikan kode berikut dalam skrip R Anda untuk membuat output direktori.

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

Setelah Anda membuat direktori, simpan artefak Anda ke direktori tersebut. Contohnya:

# 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 model Anda dengan carrier paket

Dokumentasi R MLflow API menentukan bahwa model R Anda harus dari crate rasa model.

  • Jika skrip R melatih model dan menghasilkan objek model, Anda harus crate dapat menyebarkannya di lain waktu dengan Azure Pembelajaran Mesin.
  • Saat menggunakan crate fungsi , gunakan namespace eksplisit saat memanggil fungsi paket apa pun yang Anda butuhkan.

Katakanlah Anda memiliki objek model timeseries yang disebut my_ts_model dibuat dengan fable paket. Untuk membuat model ini dapat dipanggil saat disebarkan, buat crate tempat Anda akan meneruskan objek model dan cakrawala prakiraan dalam jumlah periode:

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

Objek crated_model adalah objek yang akan Anda catat.

Model log, parameter, tag, atau artefak lainnya dengan API R MLflow

Selain menyimpan artefak yang dihasilkan, Anda juga dapat mencatat model, tag, dan parameter untuk setiap eksekusi. Gunakan API R MLflow untuk melakukannya.

Saat mencatat model, Anda mencatat model klimaks yang Anda buat seperti yang dijelaskan di bagian sebelumnya.

Catatan

Saat Anda mencatat model, model juga disimpan dan ditambahkan ke artefak eksekusi. Tidak perlu menyimpan model secara eksplisit kecuali Anda tidak mencatatnya.

Untuk mencatat model, dan/atau parameter:

  1. Memulai eksekusi dengan mlflow_start_run()
  2. Mencatat artefak dengan mlflow_log_model, , mlflow_log_paramatau mlflow_log_batch
  3. Jangan akhiri eksekusi dengan mlflow_end_run(). Lewati panggilan ini, karena saat ini menyebabkan kesalahan.

Misalnya, untuk mencatat objek seperti yang crated_model dibuat di bagian sebelumnya, Anda akan menyertakan kode berikut dalam skrip R Anda:

Tip

Gunakan models sebagai nilai untuk artifact_path saat mencatat model, ini adalah praktik terbaik (meskipun Anda dapat menamainya sesuatu yang lain.)

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

Struktur dan contoh skrip

Gunakan cuplikan kode ini sebagai panduan untuk menyusun skrip R Anda, mengikuti semua perubahan yang diuraikan dalam artikel ini.

# 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

Membuat lingkungan

Untuk menjalankan skrip R, Anda akan menggunakan ml ekstensi untuk Azure CLI, juga disebut sebagai CLI v2. Perintah ml menggunakan file definisi pekerjaan YAML. Untuk informasi selengkapnya tentang mengirimkan pekerjaan dengan az ml, lihat Melatih model dengan Azure Pembelajaran Mesin CLI.

File pekerjaan YAML menentukan lingkungan. Anda harus membuat lingkungan ini di ruang kerja sebelum dapat menjalankan pekerjaan.

Anda dapat membuat lingkungan di studio Azure Pembelajaran Mesin atau dengan Azure CLI.

Metode apa pun yang Anda gunakan, Anda akan menggunakan Dockerfile. Semua file konteks Docker untuk lingkungan R harus memiliki spesifikasi berikut untuk bekerja di Azure Pembelajaran Mesin:

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/')"

Gambar dasarnya adalah rocker/tidyverse:latest, yang memiliki banyak paket R dan dependensinya sudah diinstal.

Penting

Anda harus menginstal paket R apa pun yang perlu dijalankan skrip Anda terlebih dahulu. Tambahkan lebih banyak baris ke file konteks Docker sesuai kebutuhan.

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

Saran tambahan

Beberapa saran tambahan yang mungkin ingin Anda pertimbangkan:

  • Gunakan fungsi R tryCatch untuk pengecualian dan penanganan kesalahan
  • Menambahkan pengelogan eksplisit untuk pemecahan masalah dan penelusuran kesalahan

Langkah berikutnya