Skip to content

Commit d0a1e5b

Browse files
eedorenkodtzar
authored andcommitted
Training a model with R on ML Compute and Databricks (#77)
1 parent 32ae724 commit d0a1e5b

File tree

12 files changed

+296
-24
lines changed

12 files changed

+296
-24
lines changed

.env.example

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,8 @@ IMAGE_VERSION = ''
4545
# ACI Config
4646
ACI_CPU_CORES = ''
4747
ACI_MEM_GB = ''
48-
ACI_DESCRIPTION = ''
48+
ACI_DESCRIPTION = ''
49+
50+
# Optional. Used by a training pipeline with R on Databricks
51+
DB_CLUSTER_ID = ''
52+
DATABRICKS_COMPUTE_NAME = ''

.pipelines/azdo-ci-build-train.yml

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,36 @@ variables:
1515

1616

1717
steps:
18+
1819
- template: azdo-base-pipeline.yml
19-
20+
2021
- bash: |
21-
# Invoke the Python building and publishing a training pipeline
22+
# Invoke the Python building and publishing a training pipeline with Python on ML Compute
2223
python3 $(Build.SourcesDirectory)/ml_service/pipelines/build_train_pipeline.py
2324
failOnStderr: 'false'
2425
env:
2526
SP_APP_SECRET: '$(SP_APP_SECRET)'
26-
displayName: 'Publish Azure Machine Learning Pipeline'
27+
displayName: 'Publish Azure Machine Learning Pipeline. Python on ML'
2728
enabled: 'true'
2829

30+
- bash: |
31+
# Invoke the Python building and publishing a training pipeline with R on ML Compute
32+
python3 $(Build.SourcesDirectory)/ml_service/pipelines/build_train_pipeline_with_r.py
33+
failOnStderr: 'false'
34+
env:
35+
SP_APP_SECRET: '$(SP_APP_SECRET)'
36+
displayName: 'Publish Azure Machine Learning Pipeline. R on ML Compute'
37+
enabled: 'false'
38+
39+
- bash: |
40+
# Invoke the Python building and publishing a training pipeline with R on DataBricks
41+
python3 $(Build.SourcesDirectory)/ml_service/pipelines/build_train_pipeline_with_r_on_dbricks.py
42+
failOnStderr: 'false'
43+
env:
44+
SP_APP_SECRET: '$(SP_APP_SECRET)'
45+
displayName: 'Publish Azure Machine Learning Pipeline. R on DataBricks'
46+
enabled: 'false'
47+
2948
- task: CopyFiles@2
3049
displayName: 'Copy Files to: $(Build.ArtifactStagingDirectory)'
3150
inputs:

code/training/R/r_train.r

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
print(R.version.string)
2+
3+
# COMMAND ----------
4+
5+
path="weight_data.csv"
6+
print(paste("Reading file from",path))
7+
8+
routes<-read.csv(path, header=TRUE)
9+
10+
# The predictor vector (height).
11+
x <- routes$height
12+
# The response vector (weight).
13+
y <- routes$weight
14+
# Apply the lm() function.
15+
model <- lm(y~x)
16+
17+
# COMMAND ----------
18+
19+
routes
20+
21+
# COMMAND ----------
22+
23+
# Make Predictions
24+
df_test_heights <- data.frame(x = as.numeric(c(115,20)))
25+
result <- predict(model,df_test_heights)
26+
print(result)
27+
28+
# COMMAND ----------
29+
30+
# Save the model to blob storage
31+
model_path="model.rds"
32+
saveRDS(model, model_path)
33+
34+
# COMMAND ----------
35+
36+
# View model details
37+
print(model)
38+
39+
# COMMAND ----------
40+
41+
print('Completed')

code/training/R/train_with_r.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import os
2+
3+
os.system("Rscript r_train.r && ls -ltr model.rds")
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import os
2+
import argparse
3+
4+
parser = argparse.ArgumentParser("train")
5+
parser.add_argument(
6+
"--AZUREML_SCRIPT_DIRECTORY_NAME",
7+
type=str,
8+
help="folder",
9+
)
10+
11+
args, unknown = parser.parse_known_args()
12+
folder = args.AZUREML_SCRIPT_DIRECTORY_NAME
13+
14+
os.system("cd " + "/dbfs/" + folder +
15+
" && Rscript r_train.r && ls -ltr model.rds")

code/training/R/weight_data.csv

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
height,weight
2+
79,174
3+
63,250
4+
75,223
5+
75,130
6+
70,120
7+
76,239
8+
63,129
9+
64,185
10+
59,246
11+
80,241
12+
79,217
13+
65,212
14+
74,242
15+
71,223
16+
61,167
17+
78,148
18+
75,229
19+
75,116
20+
75,182
21+
72,237
22+
72,160
23+
79,169
24+
67,219
25+
61,202
26+
65,168
27+
79,181
28+
81,214
29+
78,216
30+
59,245

docs/code_description.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,21 @@
2020

2121
### ML Services
2222

23-
- `ml_service/pipelines/build_train_pipeline.py` : builds and publishes an ML training pipeline.
24-
- `ml_service/pipelines/run_train_pipeline.py` : invokes a published ML training pipeline via REST API.
23+
- `ml_service/pipelines/build_train_pipeline.py` : builds and publishes an ML training pipeline. It uses Python on ML Compute.
24+
- `ml_service/pipelines/build_train_pipeline_with_r.py` : builds and publishes an ML training pipeline. It uses R on ML Compute.
25+
- `ml_service/pipelines/build_train_pipeline_with_r_on_dbricks.py` : builds and publishes an ML training pipeline. It uses R on Databricks Compute.
26+
- `ml_service/pipelines/run_train_pipeline.py` : invokes a published ML training pipeline (Python on ML Compute) via REST API.
2527
- `ml_service/util` : contains common utility functions used to build and publish an ML training pipeline.
2628

2729
### Code
2830

2931
- `code/training/train.py` : a training step of an ML training pipeline.
3032
- `code/evaluate/evaluate_model.py` : an evaluating step of an ML training pipeline which registers a new trained model if evaluation shows the new model is more performant than the previous one.
3133
- `code/evaluate/register_model.py` : (LEGACY) registers a new trained model if evaluation shows the new model is more performant than the previous one.
34+
- `code/training/R/r_train.r` : training a model with R basing on a sample dataset (weight_data.csv).
35+
- `code/training/R/train_with_r.py` : a python wrapper (ML Pipeline Step) invoking R training script on ML Compute
36+
- `code/training/R/train_with_r_on_databricks.py` : a python wrapper (ML Pipeline Step) invoking R training script on Databricks Compute
37+
- `code/training/R/weight_data.csv` : a sample dataset used by R script (r_train.r) to train a model
3238

3339
### Scoring
3440
- code/scoring/score.py : a scoring script which is about to be packed into a Docker Image along with a model while being deployed to QA/Prod environment.

docs/getting_started.md

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -33,23 +33,25 @@ Please name your variable group **``devopsforai-aml-vg``** as we are using this
3333

3434
The variable group should contain the following variables:
3535

36-
| Variable Name | Suggested Value |
37-
| --------------------------- | ---------------------------- |
38-
| AML_COMPUTE_CLUSTER_CPU_SKU | STANDARD_DS2_V2 |
39-
| AML_COMPUTE_CLUSTER_NAME | train-cluster |
40-
| BASE_NAME | [unique base name] |
41-
| EVALUATE_SCRIPT_PATH | evaluate/evaluate_model.py |
42-
| EXPERIMENT_NAME | mlopspython |
43-
| LOCATION | centralus |
44-
| MODEL_NAME | sklearn_regression_model.pkl |
45-
| REGISTER_SCRIPT_PATH | register/register_model.py |
46-
| SOURCES_DIR_TRAIN | code |
47-
| SP_APP_ID | |
48-
| SP_APP_SECRET | |
49-
| SUBSCRIPTION_ID | |
50-
| TENANT_ID | |
51-
| TRAIN_SCRIPT_PATH | training/train.py |
52-
| TRAINING_PIPELINE_NAME | training-pipeline |
36+
| Variable Name | Suggested Value |
37+
| --------------------------- | -----------------------------------|
38+
| AML_COMPUTE_CLUSTER_CPU_SKU | STANDARD_DS2_V2 |
39+
| AML_COMPUTE_CLUSTER_NAME | train-cluster |
40+
| BASE_NAME | [unique base name] |
41+
| DB_CLUSTER_ID | [Optional Databricks cluster Id] |
42+
| DATABRICKS_COMPUTE_NAME | [Optional Databricks compute name] |
43+
| EVALUATE_SCRIPT_PATH | evaluate/evaluate_model.py |
44+
| EXPERIMENT_NAME | mlopspython |
45+
| LOCATION | centralus |
46+
| MODEL_NAME | sklearn_regression_model.pkl |
47+
| REGISTER_SCRIPT_PATH | register/register_model.py |
48+
| SOURCES_DIR_TRAIN | code |
49+
| SP_APP_ID | |
50+
| SP_APP_SECRET | |
51+
| SUBSCRIPTION_ID | |
52+
| TENANT_ID | |
53+
| TRAIN_SCRIPT_PATH | training/train.py |
54+
| TRAINING_PIPELINE_NAME | training-pipeline |
5355

5456
Mark **SP_APP_SECRET** variable as a secret one.
5557

@@ -108,6 +110,8 @@ and checkout a published training pipeline in the **mlops-AML-WS** workspace in
108110

109111
Great, you now have the build pipeline setup, you can either manually trigger it or it gets automatically triggered everytime there is a change in the master branch. The pipeline performs linting, unit testing, builds and publishes an **ML Training Pipeline** in an **ML Workspace**
110112

113+
**Note:** The building pipeline contains disabled steps to build and publish ML pipelines using R to train a model. Enable these steps if you want to play with this approach. For the pipeline training a model with R on Databricks you have to manually create a Databricks cluster and attach it to the ML Workspace as a compute (Values DB_CLUSTER_ID and DATABRICKS_COMPUTE_NAME variables shoud be specified).
114+
111115
### 7. Train the Model
112116

113117
The next step is to invoke the training pipeline created in the previous step. It can be done with a **Release Pipeline**. Click on the Pipelines/Releases menu, and then **New pipeline**, and then click on "Empty Job" on the "Select a template" window that pops to the right:

environment_setup/Dockerfile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ LABEL org.label-schema.vendor = "Microsoft" \
88

99
COPY environment_setup/requirements.txt /setup/
1010

11-
RUN apt-get update && apt-get install gcc -y && pip install --upgrade -r /setup/requirements.txt
11+
RUN apt-get update && apt-get install gcc -y && pip install --upgrade -r /setup/requirements.txt && \
12+
conda install -c r r-essentials
1213

1314
CMD ["python"]

environment_setup/requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
pytest==4.3.0
22
requests>=2.22
3+
azureml>=0.2
34
azureml-sdk>=1.0
45
python-dotenv>=0.10.3
56
flake8

0 commit comments

Comments
 (0)