diff --git a/.github/workflows/runtests.yml b/.github/workflows/runtests.yml index 51fd19b..9ee01b1 100644 --- a/.github/workflows/runtests.yml +++ b/.github/workflows/runtests.yml @@ -14,6 +14,8 @@ permissions: jobs: test_packages: + # exclude pull requests spawned by the generate_notebooks workflow: + if: ${{ !startsWith(github.head_ref, 'auto-update-notebooks') }} runs-on: ${{ matrix.os }} strategy: matrix: diff --git a/slides/README.md b/slides/README.md new file mode 100644 index 0000000..546aa06 --- /dev/null +++ b/slides/README.md @@ -0,0 +1,5 @@ +# Source files for generating the "Using MLJ" slides + +This folder contains Quarto source only. Rendered PDF slides can be found in the relevant +notebook source, e.g., +[/docs/src/notebooks/UsingMLJ/01_basics/slides.pdf](/docs/src/notebooks/UsingMLJ/01_basics/slides.pdf]). diff --git a/slides/src/figures/Pumas_AI_Primary_Black_1098x398.png b/slides/src/figures/Pumas_AI_Primary_Black_1098x398.png new file mode 100755 index 0000000..1f81414 Binary files /dev/null and b/slides/src/figures/Pumas_AI_Primary_Black_1098x398.png differ diff --git a/slides/src/img/QRcodeLearnMLJ.svg b/slides/src/img/QRcodeLearnMLJ.svg new file mode 100644 index 0000000..bad7e03 --- /dev/null +++ b/slides/src/img/QRcodeLearnMLJ.svg @@ -0,0 +1,579 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/slides/src/img/machine_construct.drawio b/slides/src/img/machine_construct.drawio new file mode 100644 index 0000000..1bb5b14 --- /dev/null +++ b/slides/src/img/machine_construct.drawio @@ -0,0 +1 @@ +7Zddb5swFIZ/DZeVwA4fuVxpu0lrNWnRNO3SwQasGR9knBL262eC+RJU66Qkk6JJucDvOT74PK+DwcFxcfyoSJm/AGXCQS49OvjBQcjzEHLan0ubTol6IVOc2qRR2PFfzIquVQ+csmqWqAGE5uVcTEBKluiZRpSCep6WgpjftSQZWwi7hIil+p1Tnfd9Bdsx8InxLNd9f2EXKEifbDupckKhnkj40cGxAtDdVXGMmWjh9Vy6eU9vRIeFKSb1eyYEu6YEiKof6ef9V135zTf55c5WeSXiYBu2i9VNT0DBQVLWFvEcfF/nXLNdSZI2WhvPjZbrQthwpRX8HEhho6RciBgEqFM1TH0W0c2QOYlEaI+DwETskpjS7Phmr95A0Gw9BgXTqjEpdkLPvJkP69HBcGu1fGLesOuI3TXZUHkEay4s27/gjK7NOU1TlCRrnGmwD/wzcfbnnD13CXpgOgUdXoozvk3OaPtn0F5wTdCb2wS9eQdotPbouBhofwG6IEnOJVvwNl3rNag9Kglm0pyrlYjgmTTDxFBiRr9vGXJzCH6wgYJT2t5m1cXRZ7ctD1LbYxwjO34iBRct0edDwikxy45BVnCqeMq3TbhncDCYG7hZ+aOEK/75l/IvXPrXvSTdhHvnN8zz/rVj0cIxSjT5b9hwGIXXc8wMxzfkU2zynYEffwM= \ No newline at end of file diff --git a/slides/src/img/machine_construct.svg b/slides/src/img/machine_construct.svg new file mode 100644 index 0000000..1fbed0e --- /dev/null +++ b/slides/src/img/machine_construct.svg @@ -0,0 +1,3 @@ + + +
machine
machine
model
model
data
data
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/slides/src/img/machine_fit.drawio b/slides/src/img/machine_fit.drawio new file mode 100644 index 0000000..4698d9a --- /dev/null +++ b/slides/src/img/machine_fit.drawio @@ -0,0 +1 @@ +7Zldb9sgFIZ/yy5y2coY20ku2/Rj0jatWjRtvZqowTEaNhEmTbxfP4jxJ26aao0zRblKeMHY53mxOUeM4CzZ3Au0jL9wTNjIdfBmBG9GrguAE6gfreSFMtEtLSwExWZQLczpH2JEx6griknWGig5Z5Iu22LI05SEsqUhIfi6PSzirH3XJVoQS5iHiNnqD4plXMYVTOuOj4QuYlnGNy46ElQONpFkMcJ83ZDg7QjOBOey+JdsZoRpeCWX4rq7F3qrBxMklftcEMzzJeeT7DH69PRNZn7+Pf16YWZ5RmxlAjYPK/OSgOCrFBM9CRjB63VMJZkvUah718pzpcUyYaY7k4L/rkhBpUSUsRlnXGxng9gnE+xVIxs9E/cJBoHqsQMrn5IISTYNyQR6T3hCpMjVENNbMs/bzXXt4HhqtLhhXrXqkFk1i2rmGqz6Y9i+gbM7NOcoitww7OOMg6fAfyfOfpszcGzQFdMm6PGhOMPT5OxOXwcNgiFBe6cJ2tsDtNv36TgYaN8CnaAwpimxeKsQZR/UElXK1UVtrkZCjC5S1QwVOKL0aw2Mqk3wynQkFGN9m14Xa58dPT1PpdnGoWvadyihTBP9vAopRuqxZzzN+HbG7XgThPMODgZtA72eF2Xc459/KP/Gtn9FknQS7r2/YQAc27GJ5RhGEp0Nqzaj8f/m2HTozWiYLBa0OcOytDheGltOfHLbfnfTsEkPm8eCwQuzgRLZyeukh01kwYmWZt4epIfNZIFdnJ1T2TdU19DreVcG3WeBXfWdk9ldlnng6JbZ9eM5m23tSN2C8fiWBZZlEZWS4F8qUJRkZ++qt62btx3fO7t4tOwiKb7SJxOaO0NZRsO2eXttMw3Qip/If2oXLn0AS+FRCRfOpeP4pXKzMU4VrbzZeiCCKgJ6DWxFO4l50a6Mr0RIdjEpxkkkFkTuGGeqOIJbJzK2+Q1z/R3eCsKQpM+k9bB9hps7PHCqInuxyg26a6aI21zlNs5dOhN1vi+B05mn4GLNs11+VdT/sCLt4lh9TT6cPyJVogw7h0WlYQf4iKhmfeBXOFwfm8Lbvw== \ No newline at end of file diff --git a/slides/src/img/machine_fit.svg b/slides/src/img/machine_fit.svg new file mode 100644 index 0000000..904e198 --- /dev/null +++ b/slides/src/img/machine_fit.svg @@ -0,0 +1,3 @@ + + +
machine
machine
model
model
data
data
machine
machine
model
model
data
data
fitted_params
fitted_para...
fit!
fit!
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/slides/src/img/machine_predict.drawio b/slides/src/img/machine_predict.drawio new file mode 100644 index 0000000..b39425b --- /dev/null +++ b/slides/src/img/machine_predict.drawio @@ -0,0 +1 @@ +7VrLcpswFP2WLrxMBhAPe5k4iTuTdpo27TReZRQkG00BeYQcm3x9hZF4iTjOwzjjYWV0JC7cc6Sre5EHYBytJwwugu8U4XBgGWg9ABcDyzJNwxU/GZLmyDBrZcCcESQHlcAtecISNCS6JAgntYGc0pCTRR30aRxjn9cwyBhd1YfNaFh/6gLOsQbc+jDU0b8E8UD55Y7Kjq+YzAOu/PPyjgiqwdKTJICIrioQuByAMaOU51fReozDjDzFS37f1TO9xYsxHPNdbnBv0wWlw2Q6u374xRMn/RP/OJFWHmG4lA7Ll+WpYoDRZYxwZsQcgPNVQDi+XUA/610JzQUW8CiU3Qln9F/BFBDIjIThmIaUbawB5OAhsouRlZ6h9QBcV/Tojqm3xIzjdQWSjk4wjTBnqRgiexXnab25KhX0RhILKuIVsw7KWTMvLJfEigvJ7St4trrmeTabWb7fxjNyH1zng3h26jybhk50wWmVaG9fPIPj5NkavUy06XZJtH2cRNs7EG21hY69Ee1oREfQD0iMNb6Fi7yNVEVVTMVNdV4lBEMyj0XTF8RhgZ9nhBGxCZ7JjogglD2mVcVSZyMzT2Mut3FgyfYVjEiYMfpt6RMExWuPaZzQjcXNeOmE8QEKunUB7ZaF4rXo5+xLP0/XL0+SjkK9jxfMNA+t2FBTDEEOe8GKzcj7bIqNut6MuslizTrPQJUWh0tjleGj2/abm4bOdLd5rNl5YdZRIjt8meluE1nzSEszewemu81kTb0461PZV1TXwG5ZK53us6Ze9fXJ7DbJbPPgkun1Y5/N1nakZsF4eMlcTbIZ4Ryje+EojJJeu2K1NfO2w2unF4+aXDhGZ9nJRMZ7CJOE+HXxdtpmKkQL/lh6l6lw6phAAVMBnBinhuEo5GItlcpbabV1gxkRDGRzYAPqScyzciV0yXy8jZN8HIdsjvmWcbKKw6h2IqOLXxHX2aItwyHk5BHXXrZNcPmEG0qEZ89WuW5zzuR+y7usyrlLw1AjvrhGw07Oi2ZnM/0Kr98xI/XiWESTL30QKRJl0DgsUoIdLIio46r3BJGWKuS1YWVN+J20ll1P8wgjW2UwyRoqlrw9SHyuxT9qfHpxXO9ti980GgcKNrA6Xf6W/iFhwTAiPu8jgBJp2Cy03A7TiGvP+z1Ko8liPHm6NiY/3enyruVYPsar+z5x36aavce4LZrlHzXypVn+3QVc/gc= \ No newline at end of file diff --git a/slides/src/img/machine_predict.svg b/slides/src/img/machine_predict.svg new file mode 100644 index 0000000..eae18ef --- /dev/null +++ b/slides/src/img/machine_predict.svg @@ -0,0 +1,3 @@ + + +
machine
machine
model
model
data
data
machine
machine
model
model
data
data
fitted_params
fitted_para...
fit!
fit!
predict
predict
new_data
new_data
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/slides/src/img/machine_save.svg b/slides/src/img/machine_save.svg new file mode 100644 index 0000000..be7aac3 --- /dev/null +++ b/slides/src/img/machine_save.svg @@ -0,0 +1,3 @@ + + +
machine
machine
model
model
data
data
machine
machine
model
model
data
data
fitted_params
fitted_para...
fit!
fit!
predict
predict
machine
machine
model
model
fitted_params
fitted_para...
MLJ.save
MLJ.save
new_data
new_data
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/slides/src/img/nested_resampling.png b/slides/src/img/nested_resampling.png new file mode 100644 index 0000000..0a33396 Binary files /dev/null and b/slides/src/img/nested_resampling.png differ diff --git a/slides/src/img/overfitting0.png b/slides/src/img/overfitting0.png new file mode 100755 index 0000000..2a022e5 Binary files /dev/null and b/slides/src/img/overfitting0.png differ diff --git a/slides/src/img/overfitting1.png b/slides/src/img/overfitting1.png new file mode 100755 index 0000000..fa6fdd5 Binary files /dev/null and b/slides/src/img/overfitting1.png differ diff --git a/slides/src/img/overfitting2.png b/slides/src/img/overfitting2.png new file mode 100755 index 0000000..139dbd8 Binary files /dev/null and b/slides/src/img/overfitting2.png differ diff --git a/slides/src/img/overfitting3.png b/slides/src/img/overfitting3.png new file mode 100755 index 0000000..0ee4435 Binary files /dev/null and b/slides/src/img/overfitting3.png differ diff --git a/slides/src/img/overfitting4.png b/slides/src/img/overfitting4.png new file mode 100755 index 0000000..bf7ed4f Binary files /dev/null and b/slides/src/img/overfitting4.png differ diff --git a/slides/src/img/overfitting5.png b/slides/src/img/overfitting5.png new file mode 100755 index 0000000..3482927 Binary files /dev/null and b/slides/src/img/overfitting5.png differ diff --git a/slides/src/img/overfitting6.png b/slides/src/img/overfitting6.png new file mode 100755 index 0000000..459c904 Binary files /dev/null and b/slides/src/img/overfitting6.png differ diff --git a/slides/src/img/overfitting7.png b/slides/src/img/overfitting7.png new file mode 100755 index 0000000..347ce42 Binary files /dev/null and b/slides/src/img/overfitting7.png differ diff --git a/slides/src/img/pipeline.drawio b/slides/src/img/pipeline.drawio new file mode 100644 index 0000000..e2e8a23 --- /dev/null +++ b/slides/src/img/pipeline.drawio @@ -0,0 +1 @@ +7Vjfb5swEP5r8tgqwUDI45r+mLROkxpNXZ8mBxvwZjhmTBP2188kR4DiVJVG2qnaU3LfHeb8fb47JxOyTLc3iubJZ2BcTpwp207I5cRxZu7cMx81UiEyXfh7JFaCIdYCK/GbN4GIloLxoheoAaQWeR8MIct4qHsYVQo2/bAIZP+tOY35AFiFVA7Re8F0gujMX7SOj1zECb46cOZ7R0qbYNxJkVAGmw5EriZkqQD0/lu6XXJZs9fwsn/u+oj3kJjimX7JA/6qygGC4iH6tL7ThVd9zb6c4SqPVJa4YUxWVw0DCsqM8XqR2YRcbBKh+SqnYe3dGNENluhUorvQCn4emCIGiYSUS5CgdqsR5vGAuYfIjidw1sT3jWe4sSZLrjTfdiDc6A2HlGtVmRD0EuQcT10jwaajIHERTDrqHSIpHpv4sHTLrPmC5NqJ5nca3A0t7+6d74tfJZ0TsT3zBrxyZg4amqB0AjFkVF616EXL/NRYbcwtQI58/+BaV1g1tNTQV8MQqKpv+PzOeKiNc68xL7dd52WF1lDFffZ1ykdPH0IFlCrkzxw5PGGaqpjrZ+KIXWHFJdXisZ/H38j1XJKvVxdRFDlhaKsL5q99b6S6WPTrYjYbFgZxLHXRtPHReSbvk2dv9pRoct5w2OXas3Dtz89PxbY3YDsXOZci4wPWzUa1jdqGsAwy/oRdhKgUcWbM0NDHDX5R0ybMRP2AjlQwtutvNi37PS+CTGN3Iw7a1zQVsub1tgwFoybtJWQF7FbcxeMmpiPo6PdldC1zZG6R0BthilgFnA8ENJyfJeYKYZpzFprrl3onSo4v3sw5FFa3BAOLfu6pbgGLt7gFnHSaB8Npbt158JbTPBiUTaFpxqhihrP/FXN8bDkvnFnuCBPLemyGDe9fuR8MWLVwf/we9rQ3vfr94HiR9tg2v8lNk6jrNFa8KOB9Fcu4Gp6wWIzZ/lGw83X+byFXfwA= \ No newline at end of file diff --git a/slides/src/img/pipeline.svg b/slides/src/img/pipeline.svg new file mode 100644 index 0000000..627abff --- /dev/null +++ b/slides/src/img/pipeline.svg @@ -0,0 +1,3 @@ + + +
pipeline
pipeline
one-hot encoder
one-hot encoder
standardizer
standardizer
ridge regressor
ridge regressor
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/slides/src/img/scitypes_small.png b/slides/src/img/scitypes_small.png new file mode 100644 index 0000000..8e04fad Binary files /dev/null and b/slides/src/img/scitypes_small.png differ diff --git a/slides/src/img/target_transformer.drawio b/slides/src/img/target_transformer.drawio new file mode 100644 index 0000000..9bebfc9 --- /dev/null +++ b/slides/src/img/target_transformer.drawio @@ -0,0 +1 @@ +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 \ No newline at end of file diff --git a/slides/src/img/target_transformer.svg b/slides/src/img/target_transformer.svg new file mode 100644 index 0000000..f41f799 --- /dev/null +++ b/slides/src/img/target_transformer.svg @@ -0,0 +1,3 @@ + + +
machines store
learned parameters
machines store...

yhat

yhat

z

z

zhat

zhat

y

y
predict
predict
 inverse transform
inver...
transform
transf...
using mach1
using mach1
using  mach1
using  mach1

Prediction

Prediction

X

X
using mach2
using mach2
mach1
mach1

X

X

y

y

z

z
mach2
mach2

Training

Training
models store
hyper-parameters
models store...
Standardizer()
Standardizer()
RidgeRegressor()
RidgeRegressor()
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/slides/src/mlj1_basics.qmd b/slides/src/mlj1_basics.qmd new file mode 100644 index 0000000..013edac --- /dev/null +++ b/slides/src/mlj1_basics.qmd @@ -0,0 +1,234 @@ +--- +title: "Using MLJ. Lesson 1: Basics" +author: "Anthony Blaom" +format: + revealjs: + title: | + Using MLJ + + Lesson 1: Basics + theme: [default, theme.scss] + margin-left: '3rem' + aspectratio: 32 + navigation: horizontal + toc: false + section-titles: true + slide-level: 2 + self-contained-math: true + auto-stretch: false + embed-resources: true + logo: figures/Pumas_AI_Primary_Black_1098x398.png + css: styles.css + slide-number: true + template-partials: + - title-slide.html + +--- + +## Introducing the "Using MLJ" lessons + +**MLJ** is a Machine Learning toolbox written for Julia. + +This series of video lessons focuses on how to **use** MLJ. + +The lessons are not a replacement for a formal machine learning course, but can be used in +conjunction with such a course. + +The lessons have been developed by **PumasAI**, and are used in the *AI for Drug +Development Course* offered by **PumasAI** and its partner **SOPHAS**. + +## Introducing the "Using MLJ" lessons + +### Series prerequisites + +We assume you already know some Julia. At the very least: + +- You are confident interacting with Julia using the **REPL**. + +- You know how to install new Julia packages and how to manage Julia **package + environments**. + +There are lots of online resources for getting up to speed with Julia. + +Any machine learning practice depends on a solid grounding in Statistics and Linear +Algebra. + + +## Lesson 1 Goals + + We want to: + +1. Get to know the basic MLJ objects: **models**, **machines** +2. Understand the basic **fit**/**predict** workflow +3. Know how to estimate model **performance**: + - by hand + - with advanced tools (`evaluate`) +4. Understand **scientific types** and their role in data preparation (`scitype`, `schema`) + + +## Lesson 1 Prerequisites + +1. Familiarity with the concept of **supervised learning** +2. Understand the distinction between **hyper-parameters** and **learned parameters** in + learning. +3. Previous exposure to the idea of **cross-validation** + +## Getting more help + +The **Resources** page linked below contains: + +- Slides for this presentation +- Julia code for the demos +- Links to general MLJ learning resources + +![](/img/QRcodeLearnMLJ.svg){fig-align="center" width="25%"} + + https://github.com/JuliaAI/MLJ.jl/tree/dev/examples/using_mlj + + +## Supervised learning + +You are given **hourly** temperature readings in a room: + +![](/img/overfitting0.png){fig-align="center" width="100%"} + + +## Supervised learning {.pause} + +You are given **hourly** temperature readings in a room: + +![](/img/overfitting1.png){fig-align="center" width="100%"} + +. . . + +**Your mission:** Predict the temperature at any time. + + +## Supervised learning + +You try linear regression: + +![](/img/overfitting2.png){fig-align="center" width="100%"} + + +## Supervised learning + +You try fitting a cubic: + +![](/img/overfitting3.png){fig-align="center" width="100%"} + + +## Supervised learning {.pause} + +How about a 12th order polynomial? + +![](/img/overfitting4.png){fig-align="center" width="100%"} + +Fits all the data perfectly! + + +## Performance evaluation + +Lucky for me, I held back readings on the **half-hour** to test your skills. + +![](/img/overfitting6.png){fig-align="center" width="100%"} + + +## Performance evaluation + +Luck for me, I held back readings on the **half-hour** to test your skills. + +![](/img/overfitting7.png){fig-align="center" width="100%"} + +Adding the lengths of the red lines, we get a **performance estimate** (mean absolute +error). + + +## What's a model? {.pause} + +In MLJ, a **model** is the specification of a learning algorithm and its hyper-parameters +(specified before learning begins). + +**Examples:** + +- Polynomial (by least squares) of degree 5. +- A decision tree classifier with maximum depth 3. +- A ridge regressor with L2 regularization of 0.1. + +. . . + +A **model** does *not* include learned parameters (**fitted_params** in MLJ docs). + +*Warning:* Outside of MLJ, a "model" might include learned parameters. + + +## Machines + +A machine starts life as a marriage of a **model** and **data**: + +![](/img/machine_construct.svg){fig-align="center" width="54%"} + + +## Life cycle of a machine {.pause} + +![](/img/machine_fit.svg){fig-align="center" width="54%"} + +. . . + +*Aside:* In `fit` we can specify `rows=...` to say which `data` observations to train +on. So `data` could be *all* available training data. Or, you might exclude a holdout test +set. + +## Life cycle of a machine + +![](/img/machine_predict.svg){fig-align="center" width="73%"} + + +## Life cycle of a machine + +![](/img/machine_save.svg){fig-align="center" width="73%"} + +## Why machines? + +The machine syntax anticipates an advanced MLJ feature called **learning networks**, in +which complex MLJ workflows are "exported" as new standalone models. + +Learning networks are outside of the scope of this lesson. + +## Live coding demonstration + +We now demonstrate a **regression** task in which we: + +- Split data into `X` and `y` +- Split observation indices into `test` and `train` +- Choose a regression model +- Estimate the performance by hand +- Use a shortcut +- Estimate using cross-validation + + +## Scientific types + +**Machine types**: indicate how data is represented on the machine: `Float64`, `String`, +etc. + +**Scitypes:** indicate how data will be *interpreted*: + +![](/img/scitypes_small.png){fig-align="center" width="80%"} + +MLJ provides: + +- `scitype(object)`: to see how MLJ models will interpret `object`, as it is + currently encoded (use `schema` instead for tables) + +- `coerce`: to change the machine encoding to match the desired interpretation (scitype) + + +## More live coding + +We now demonstrate a **classification** task in which we: + +- Coerce data scitypes to ensure correct interpretation by MLJ +- Horizontally and vertically split data as before +- Demonstrate **one-hot encoding** to get `Continuous` input scitypes +- Estimate performance by hand and with `evaluate`. diff --git a/slides/src/mlj2_model_composition.qmd b/slides/src/mlj2_model_composition.qmd new file mode 100644 index 0000000..47cd8ac --- /dev/null +++ b/slides/src/mlj2_model_composition.qmd @@ -0,0 +1,261 @@ +--- +title: "Using MLJ. Lesson 2: Model Composition" +author: "Anthony Blaom" +from: markdown+emoji +format: + revealjs: + title: | + Using MLJ + + Lesson 2: Model Composition + theme: [default, theme.scss] + margin-left: '3rem' + aspectratio: 32 + navigation: horizontal + toc: false + section-titles: true + slide-level: 2 + self-contained-math: true + auto-stretch: false + embed-resources: true + logo: figures/Pumas_AI_Primary_Black_1098x398.png + css: styles.css + slide-number: true + template-partials: + - title-slide.html +--- + +## Goals + +MLJ's design enables flexible **model composition**. Here we learn: + +1. What a **composite model** is +2. How to construct model **pipelines** +2. How composite models help us avoid **data leakage** +3. About the **model wrapper**, `TransformedTargetModel` +4. About other model wrappers +5. Other kinds of model composition + +## Prerequisites + + +1. **Lesson 1: Basics** (supervised learning, + machines, models, evaluation) +2. Prior exposure to common ML pre-processing operations, such as one-hot encoding and + standardization +3. Familiarity with cross-validation and the concept of **data leakage** + +## Getting more help + +The **Resources** page linked below contains: + +- Slides for this presentation +- Julia code for the demos +- Links to general MLJ learning resources + +![](/img/QRcodeLearnMLJ.svg){fig-align="center" width="25%"} + + https://github.com/JuliaAI/MLJ.jl/tree/dev/examples/using_mlj + + +## What is a composite model? + +A **composite model** is a model that has other models as hyper-parameters. + +. . . + +```julia +julia> forest = EnsembleModel(DecisionTreeClassifier()) +ProbabilisticEnsembleModel( + model = DecisionTreeClassifier( + max_depth = -1, + min_samples_leaf = 1, + min_samples_split = 2, + min_purity_increase = 0.0, + n_subfeatures = 0, + post_prune = false, + merge_purity_threshold = 1.0, + display_depth = 5, + feature_importance = :impurity, + rng = Random.TaskLocalRNG()), + atomic_weights = Float64[], + bagging_fraction = 0.8, + rng = Random.TaskLocalRNG(), + n = 100, + acceleration = CPU1{Nothing}(nothing), + out_of_bag_measure = Any[]) +``` + +. . . + +`forest.model.max_depth` is a **nested hyper-parameter**. + +## Kinds of composite models in MLJ + +The simplest kinds of model composition in MLJ: + +- **pipelines** +- **model wrappers** + +Not discussed here: + +- A **model stack** (`Stack`) wraps multiple supervised learners + +- **Learning networks** are maximally flexible. Used internally to implement all the + above + +## Model pipelines + +![](img/pipeline.svg){fig-align="center" width="100%"} + +**Main point**: `pipeline` is new, standalone, supervised model, behaving like any +other. + +For example, you can use `evaluate` to estimate the performance of `pipeline`. + +. . . + +### Syntax + +```julia +pipeline = OneHotEncoder() |> Standardization() |> RidgeRegressor() +``` + +which is syntactic sugar for + +```julia +pipeline = Pipeline(OneHotEncoder(), Standardizer(), RidgeRegressor()) +``` +which also allows for passing some keyword options. + +## Data leakage + +Why does the following workflow, combining standardization and ridge regression, have +**data leakage**? + +**Step 1.** Standardize all the input data: + +```julia +mach = machine(Standardizer(), X) |> fit! +Xstand = transform(mach, X) +``` + +**Step 2.** Evaluate the performance of a ridge regressor: + +```julia +evaluate(RidgeRegressor(), Xstand, y, resampling=CV(nfolds=2), measure=rms) +``` + +. . . + + +**Answer:** Let `fold1` and `fold2` be the CV folds. When training the ridge regressor on +`fold1`, `evaluate` is using data standardized using parameters learned from **all** the +data, which includes `fold2`. So `fold2` is a "tainted" dataset, not appropriate for +getting an unbiased estimate of the model's performance, which what +`evaluate` does to get the first CV score. + + +## Data Leakage + +In the following workflow, training on each CV fold includes learning appropriate +standardization parameters, but using only data from that fold. So data leakage is +avoided: + +```julia +pipeline = Standardizer() |> RidgeRegressor() +evaluate(pipeline, X, y, resampling=CV(nfolds=2), measure=rms) +``` + +. . . + +**Model wrappers**, discussed next, similarly help us to avoid many other sources of data +leakage. + +## A model wrapper for target transformations + +Some supervised models perform poorly unless the **target** data is standardized. + +Sample task: + +1. Learn standardization parameters for target $y$. +2. Apply standardization to $y$ to get $z$ +2. Train a ridge regressor using some input features $X$ and target $z$ +3. Predict on some new data $X_{\mathrm{new}}$ to obtain $\hat z$ +4. *Inverse* transform $\hat z$ to obtain $\hat y$. + +Notice Steps 2 and 5 both make use of the same learned standardization parameters. + + +## Target transformations + +In code: + +```julia +pstandardizer = Standardizer() +regressor = RidgeRegressor() + +mach1 = machine(standardizer, y) |> fit! +z = transform(mach1, y) + +mach2 = machine(regressor, X, z) |> fit! +ẑ = predict(mach2, X) +ŷ = inverse_transform(mach1, ẑ) +``` + +The fitted machine `mach1` gets used twice, in lines 10 and 14. + +A simple pipeline cannot replicate this workflow. + +## Target transformations + +![](img/target_transformer.svg){fig-align="center" width="65%"} + +## Target transformations + +Model wrappers to the rescue: + +`model = RidgeRegressor()` + +`wrapped_model = TransformedTargetModel(model, transformer=Standardizer())` + +. . . + +The `wrapped_model` behaves like `model`, but with target standardization automatically +enforced internally, protecting against data leakage. + + +## Live coding + +We now demonstrate a supervised learning task making use of both a **pipeline** and the +`TransformedTargetModel` **wrapper** to mitigate data leakage. + +## Other model wrappers in MLJ + +- `TunedModel(model)`: for tuning hyperparameters of `model` - see Lesson 3! + +. . . + +- `BalancedModel(model)`: to use `model` in conjunction with oversampling/undersampling + algorithms that correct for **class imbalance** + +. . . + +- `EnsembleModel(model)`: to create a **bagged** ensemble of `model` clones (e.g, random + forest) + +. . . + + +- `IteratedModel(model)`: to wrap an iterative `model` in various iteration controls or + callbacks, such as **early stopping** criteria and live inspection of training losses + +. . . + +- `BinaryThresholdPredictor(model)`: for converting a probabilistic predictor into a + deterministic one, given a threshold probability for the "positive" outcome. + +. . . + +- `RecursiveFeatureElimination(model)`: for selecting features based on rankings of a + supervised `model` that reports feature importances (wrapped model is a transformer) diff --git a/slides/src/mlj3_model_tuning.qmd b/slides/src/mlj3_model_tuning.qmd new file mode 100644 index 0000000..573add3 --- /dev/null +++ b/slides/src/mlj3_model_tuning.qmd @@ -0,0 +1,169 @@ +--- +title: "Using MLJ. Lesson 3: Model Tuning" +author: "Anthony Blaom" +format: + revealjs: + title: | + Using MLJ + + Lesson 3: Model Tuning + theme: [default, theme.scss] + margin-left: '3rem' + aspectratio: 32 + navigation: horizontal + toc: false + section-titles: true + slide-level: 2 + self-contained-math: true + auto-stretch: false + embed-resources: true + logo: figures/Pumas_AI_Primary_Black_1098x398.png + css: styles.css + slide-number: true + template-partials: + - title-slide.html + +--- + +## Goals + +Model **tuning** (or **optimization**) refers to the process of choosing the "best" +hyper-parameters of a model. The same principles apply to choosing between *different* +models (algorithms). + +Here we learn: + +1. How to generate a **learning curve**, a visual tool for tuning a **single** model + hyperparameter. +2. How to conceptualize model tuning as a **model wrapper**. +3. How to use the `TunedModel` wrapper in practice, to tune **multiple** parameters + while guarding against data leakage. +4. How to use `TunedModel` to choose from a **list** of models, of possibly varying type. +4. Why tuning-as-wrapper can lead to **nested resampling**. + +## Prerequisites + +1. **Lesson 1: Basics** (supervised learning, machines, models, evaluation) +2. **Lesson 2: Model Composition** (pipelines and model wrappers) +3. Previous exposure to random forest models helpful. + +## Getting more help + +The **resources page** below contains: + +- Slides for this presentation +- Julia code for the demos +- Links to general MLJ learning resources + +![](/img/QRcodeLearnMLJ.svg){fig-align="center" width="25%"} + + https://github.com/JuliaAI/MLJ.jl/tree/dev/examples/using_mlj + + +## Live coding + +We will now demonstrate the use of MLJ **learning curves** to examine the effect of a single +hyper-parameter. + +## Tuning as model wrapper + +We want to automate the +process of optimizing one or more hyper-parameters. + +## Tuning as model wrapper + +In MLJ we wrap a supervised `model` in a "tuning strategy" like this: + +`tuned_model = ` + + `TunedModel(model; ranges=..., resampling=CV(), measure=..., ...)` + + +. . . + + +### Fitting + +Fitting `tuned_model` to some data does this: + +1. Construct a sequence of `model` mutations `model1`, `model2`, `model3`, ... , of `model` + with hyper-parameters varying over the specified `range`. + +2. Calls `evaluate` on each model mutant, using the specified `resampling` strategy and + `measure` to get **out-of-sample** estimates of performance + +3. Identifies the model with the best performance + +4. **Retrains** the best model **using all supplied data**. + + +## Tuning as model wrapper + +### What does this mean for new predictions? + +```julia +mach = machine(tuned_model, X, y) |> fit! +ŷ₁ = predict(mach, Xnew) +``` + +```julia +best_model = report(mach).best_model +mach = machine(best_model, X, y) |> fit! +ŷ₂ = predict(mach, Xnew) +``` + +Then `ŷ₁ == ŷ₂`. + +## Tuning as model wrapper + +You can think of `tuned_model` as a "self-tuning" counterpart of `model`. + +More precisely, in `tuned_model` the hyper-parameters specified by `range` have been +transformed from **hyper-parameters** to **learned parameters**. + +::: {.callout-caution title="Warning"} + +Adding to the learned parameters **adds complexity** and whence the risk of over-fitting. + +::: + +## Live coding + +We now demonstrate the use of the `TunedModel` wrapper. + +## Nested resampling + +In our live coding we: + +**1.** Wrapped a model called `pipe` in a tuning strategy: + +`tuned_pipe = TunedModel(pipe, resampling=CV(nfolds=4), ...)` + +Here the `CV` is called **inner resampling **. + +**2.** Evaluated the wrapped model: + +`evaluate(tuned_pipe, X, y; resampling=CV(nfolds=3)` + +Here the `CV` is called **outer resampling **. + + +## Nested resampling + +![](img/nested_resampling.png){fig-align="center" width="60%"} + +Image source: The `mlr` project. + + +## Final observations + +- It's important to remember that a `TunedModel` is *not* a model + pre-optimized + hyperparameters. Hyperparameters are not optimized until training the model. In + particular, the optimized hyperparameters generally assume *different* values on each + training fold in CV estimation of the model's performance. + +- While the wrapper approach is the safest way to avoid common data leakage pitfalls in + model tuning, nested resampling can make it computationally expensive, especially when + used in conjunction with other model wrapping algorithms, such as `IteratedModel` or + `Stack`. In those cases, one may decide to "freeze" the hyper-parameters by extracting + `best_model` from `report(mach)`. diff --git a/slides/src/styles.css b/slides/src/styles.css new file mode 100755 index 0000000..02ccde5 --- /dev/null +++ b/slides/src/styles.css @@ -0,0 +1,75 @@ +/* --------------------------------------------- + Slide Logo Positioning +--------------------------------------------- */ +.reveal .slide-logo { + top: 0; + right: 12px; + max-height: 1.5em; + position: absolute; +} + +/* --------------------------------------------- + Base Font Settings +--------------------------------------------- */ +.reveal div { + font-size: 20pt; + line-height: 1.6; +} + +/* --------------------------------------------- + Headings +--------------------------------------------- */ +.reveal h1, +.reveal h2, +.reveal h3, +.reveal h4, +.reveal h5, +.reveal h6 { + font-weight: normal; + margin: 0.5rem 0 1rem 0.5rem; +} + +/* h1: Big centered title */ +.reveal h1 { + font-size: 2.5rem; + margin-bottom: 3rem; + text-align: center; +} + +/* h2: Section heading */ +.reveal h2 { + font-size: 2.5rem; + margin-bottom: 3rem; + padding: 10px 0; +} + +/* h3: Sub-section heading */ +.reveal h3 { + font-size: 1.75rem; + padding: 10px 0; +} + +/* h4: Emphasized inline heading */ +.reveal h4 { + font-size: 1.25rem; + font-weight: bold; +} + +/* --------------------------------------------- + Title Page Metadata +--------------------------------------------- */ +.quarto-title-author-name, +.date { + font-size: 1.5rem; +} + +/* --------------------------------------------- + Slide Number Positioning +--------------------------------------------- */ +.slide-number, +.reveal.has-logo .slide-number { + bottom: 14px; + left: 50px; + top: unset; + color: #777; +} diff --git a/slides/src/theme.scss b/slides/src/theme.scss new file mode 100755 index 0000000..a98496b --- /dev/null +++ b/slides/src/theme.scss @@ -0,0 +1,27 @@ +/*-- scss:defaults --*/ + +// fonts +$font-family-sans-serif: "Computer Modern" !default; +// $font-family-serif: 'Computer Modern' !default; + +// colors +$body-bg: #ffffff !default; +$body-color: #000 !default; +$link-color: #51483d !default; +$selection-bg: #26351c !default; + +// headings +$presentation-heading-font: 'Computer Modern' !default; +$presentation-heading-color: #3333b3 !default; + +/*-- scss:rules --*/ + +.reveal a { + line-height: 1.3em; +} + +.reveal .progress { + background: rgba(0, 0, 0, 0.2); + color: #3333b3; + height: 1%; +} diff --git a/slides/src/title-slide.html b/slides/src/title-slide.html new file mode 100755 index 0000000..8f2058f --- /dev/null +++ b/slides/src/title-slide.html @@ -0,0 +1,43 @@ +
+

$title$

+$if(subtitle)$ +

$subtitle$

+$endif$ + +
+Authors: $for(by-author)$ +
+
+$if(by-author.url)$$endif$$if(by-author.name.literal)$$by-author.name.literal$$endif$$if(by-author.url)$$endif$ $if(by-author.orcid)$ $endif$ +
+$if(by-author.email)$ + +$endif$ +$if(by-author.affiliations)$ + $for(by-author.affiliations)$ +

+ $if(it.url)$ + + $endif$ + $it.name$ + $if(it.url)$ + + $endif$ +

+ $endfor$ +$endif$ +
+$endfor$ +
+ +$if(date)$ +

$date$

+$endif$ + +
+ +
+ +
diff --git a/typos.toml b/typos.toml index ad97efd..f64a1c7 100644 --- a/typos.toml +++ b/typos.toml @@ -1,6 +1,6 @@ [files] # we exclude markdown in the notebooks, as they are auto-generated: -extend-exclude = ["*.svg", "*.drawio", "*.html", "*.pdf", "docs/src/notebooks/**/*.md"] +extend-exclude = ["*.js", "*.css", "*.svg", "*.drawio", "*.html", "*.pdf", "docs/src/notebooks/**/*.md"] [default.extend-words] # Don't correct "mape" to "map"