Převod experimentů ML na produkční kód Pythonu
PLATÍ PRO: Python SDK azureml v1
V tomto kurzu se dozvíte, jak převést poznámkové bloky Jupyter na skripty Pythonu, aby bylo testování a automatizace přívětivé pomocí šablony kódu MLOpsPython a Azure Machine Learning. Tento proces se obvykle používá k experimentování / trénování kódu z poznámkového bloku Jupyter a jeho převodu na skripty Pythonu. Tyto skripty se pak dají použít k testování a automatizaci CI/CD v produkčním prostředí.
Projekt strojového učení vyžaduje experimentování, kdy se hypotézy testují pomocí agilních nástrojů, jako je Jupyter Notebook, pomocí skutečných datových sad. Jakmile je model připravený pro produkční prostředí, měl by se kód modelu umístit do úložiště produkčního kódu. V některých případech musí být kód modelu převeden na skripty Pythonu, které se umístí do úložiště produkčního kódu. Tento kurz popisuje doporučený přístup k exportu experimentovacího kódu do skriptů Pythonu.
V tomto kurzu se naučíte:
- Vyčištění nestředného kódu
- Refaktoring kódu Jupyter Notebook do funkcí
- Vytváření skriptů Pythonu pro související úlohy
- Vytvoření testů jednotek
Požadavky
- Vygenerujte šablonu MLOpsPython a použijte
experimentation/Diabetes Ridge Regression Training.ipynb
poznámkové bloky.experimentation/Diabetes Ridge Regression Scoring.ipynb
Tyto poznámkové bloky se používají jako příklad převodu z experimentování na produkční prostředí. Tyto poznámkové bloky najdete na adrese https://github.com/microsoft/MLOpsPython/tree/master/experimentation. - Nainstalujte
nbconvert
. Postupujte pouze podle pokynů k instalaci v části Instalace nbconvert na stránce Instalace .
Odebrání veškerého nepotřebného kódu
Kód napsaný během experimentování je určený pouze pro průzkumné účely. Prvním krokem k převodu experimentálního kódu do produkčního kódu je proto odebrání tohoto žádného nepotřebného kódu. Odebráním žádného kódu také zajistíte, aby byl kód lépe udržovatelný. V této části odeberete kód z poznámkového experimentation/Diabetes Ridge Regression Training.ipynb
bloku. Příkazy, které tisknou tvar X
a y
volání features.describe
buněk, jsou určené jen ke zkoumání dat a je možné je odebrat. Po odebrání žádného nepotřebného kódu experimentation/Diabetes Ridge Regression Training.ipynb
by měl vypadat jako následující kód bez markdownu:
from sklearn.datasets import load_diabetes
from sklearn.linear_model import Ridge
from sklearn.metrics import mean_squared_error
from sklearn.model_selection import train_test_split
import joblib
import pandas as pd
sample_data = load_diabetes()
df = pd.DataFrame(
data=sample_data.data,
columns=sample_data.feature_names)
df['Y'] = sample_data.target
X = df.drop('Y', axis=1).values
y = df['Y'].values
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=0)
data = {"train": {"X": X_train, "y": y_train},
"test": {"X": X_test, "y": y_test}}
args = {
"alpha": 0.5
}
reg_model = Ridge(**args)
reg_model.fit(data["train"]["X"], data["train"]["y"])
preds = reg_model.predict(data["test"]["X"])
mse = mean_squared_error(preds, y_test)
metrics = {"mse": mse}
print(metrics)
model_name = "sklearn_regression_model.pkl"
joblib.dump(value=reg, filename=model_name)
Refaktoring kódu na funkce
Za druhé, kód Jupyter musí být refaktorován na funkce. Refaktoring kódu do funkcí usnadňuje testování jednotek a usnadňuje správu kódu. V této části refaktorujete:
- The Diabetes Ridge Regression Training notebook(
experimentation/Diabetes Ridge Regression Training.ipynb
) - Poznámkový blok
experimentation/Diabetes Ridge Regression Scoring.ipynb
bodování diabetes Ridge
Refaktoring diabetes Ridge Regression Training notebook into functions
Proveďte experimentation/Diabetes Ridge Regression Training.ipynb
následující kroky:
Vytvořte funkci volanou
split_data
pro rozdělení datového rámce na testovací a trénovací data. Funkce by měla datový rámecdf
převzít jako parametr a vrátit slovník obsahující klíčetrain
atest
.Přesuňte kód pod nadpis Rozdělit data do trénovacích a ověřovacích sad do
split_data
funkce a upravte hodata
tak, aby vrátil objekt.Vytvořte funkci s názvem
train_model
, která přebírá parametrydata
aargs
vrací natrénovaný model.Přesuňte kód pod nadpisem Training Model on Training Set do
train_model
funkce a upravte horeg_model
tak, aby vrátil objekt.args
Odeberte slovník, hodnoty budou pocházet z parametruargs
.Vytvořte funkci s názvem
get_model_metrics
, která přebírá parametryreg_model
adata
a vyhodnocuje model a pak vrátí slovník metrik pro natrénovaný model.Přesuňte kód pod nadpisEm Validate Model on Validation Set do
get_model_metrics
funkce a upravte hometrics
tak, aby vrátil objekt.
Tyto tři funkce by měly být následující:
# Split the dataframe into test and train data
def split_data(df):
X = df.drop('Y', axis=1).values
y = df['Y'].values
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=0)
data = {"train": {"X": X_train, "y": y_train},
"test": {"X": X_test, "y": y_test}}
return data
# Train the model, return the model
def train_model(data, args):
reg_model = Ridge(**args)
reg_model.fit(data["train"]["X"], data["train"]["y"])
return reg_model
# Evaluate the metrics for the model
def get_model_metrics(reg_model, data):
preds = reg_model.predict(data["test"]["X"])
mse = mean_squared_error(preds, data["test"]["y"])
metrics = {"mse": mse}
return metrics
Stále v experimentation/Diabetes Ridge Regression Training.ipynb
, proveďte následující kroky:
Vytvořte novou funkci s názvem
main
, která nepřijímá žádné parametry a nevrací nic.Přesuňte kód pod nadpisEm Načíst data do
main
funkce.Přidejte do funkce vyvolání nově zapsaných funkcí
main
:# Split Data into Training and Validation Sets data = split_data(df)
# Train Model on Training Set args = { "alpha": 0.5 } reg = train_model(data, args)
# Validate Model on Validation Set metrics = get_model_metrics(reg, data)
Přesuňte kód pod nadpisem Uložit model do
main
funkce.
Funkce main
by měla vypadat jako následující kód:
def main():
# Load Data
sample_data = load_diabetes()
df = pd.DataFrame(
data=sample_data.data,
columns=sample_data.feature_names)
df['Y'] = sample_data.target
# Split Data into Training and Validation Sets
data = split_data(df)
# Train Model on Training Set
args = {
"alpha": 0.5
}
reg = train_model(data, args)
# Validate Model on Validation Set
metrics = get_model_metrics(reg, data)
# Save Model
model_name = "sklearn_regression_model.pkl"
joblib.dump(value=reg, filename=model_name)
V této fázi by v poznámkovém bloku neměl být žádný kód, který není ve funkci, kromě příkazů importu v první buňce.
Přidejte příkaz, který volá main
funkci.
main()
Po refaktoringu experimentation/Diabetes Ridge Regression Training.ipynb
by měl vypadat jako následující kód bez markdownu:
from sklearn.datasets import load_diabetes
from sklearn.linear_model import Ridge
from sklearn.metrics import mean_squared_error
from sklearn.model_selection import train_test_split
import pandas as pd
import joblib
# Split the dataframe into test and train data
def split_data(df):
X = df.drop('Y', axis=1).values
y = df['Y'].values
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=0)
data = {"train": {"X": X_train, "y": y_train},
"test": {"X": X_test, "y": y_test}}
return data
# Train the model, return the model
def train_model(data, args):
reg_model = Ridge(**args)
reg_model.fit(data["train"]["X"], data["train"]["y"])
return reg_model
# Evaluate the metrics for the model
def get_model_metrics(reg_model, data):
preds = reg_model.predict(data["test"]["X"])
mse = mean_squared_error(preds, data["test"]["y"])
metrics = {"mse": mse}
return metrics
def main():
# Load Data
sample_data = load_diabetes()
df = pd.DataFrame(
data=sample_data.data,
columns=sample_data.feature_names)
df['Y'] = sample_data.target
# Split Data into Training and Validation Sets
data = split_data(df)
# Train Model on Training Set
args = {
"alpha": 0.5
}
reg = train_model(data, args)
# Validate Model on Validation Set
metrics = get_model_metrics(reg, data)
# Save Model
model_name = "sklearn_regression_model.pkl"
joblib.dump(value=reg, filename=model_name)
main()
Refaktoring poznámkového bloku s hodnocením Diabetes Ridge do funkcí
Proveďte experimentation/Diabetes Ridge Regression Scoring.ipynb
následující kroky:
- Vytvořte novou funkci s názvem
init
, která nepřijímá žádné parametry a nevrací nic. - Zkopírujte kód pod nadpisem Načíst model do
init
funkce.
Funkce init
by měla vypadat jako následující kód:
def init():
model_path = Model.get_model_path(
model_name="sklearn_regression_model.pkl")
model = joblib.load(model_path)
init
Po vytvoření funkce nahraďte veškerý kód pod nadpisem Load Model jedním voláním init
následujícím způsobem:
init()
Proveďte experimentation/Diabetes Ridge Regression Scoring.ipynb
následující kroky:
Vytvořte novou funkci s názvem
run
, která přebíráraw_data
arequest_headers
jako parametry a vrací slovník výsledků následujícím způsobem:{"result": result.tolist()}
Zkopírujte kód pod nadpisy Připravit data a Skóre dat do
run
funkce.Funkce
run
by měla vypadat jako následující kód (Nezapomeňte odebrat příkazy, které nastavují proměnnéraw_data
arequest_headers
které budou použity později přirun
zavolání funkce):def run(raw_data, request_headers): data = json.loads(raw_data)["data"] data = numpy.array(data) result = model.predict(data) return {"result": result.tolist()}
run
Po vytvoření funkce nahraďte veškerý kód v nadpisech Připravit data a Skóre dat následujícím kódem:
raw_data = '{"data":[[1,2,3,4,5,6,7,8,9,10],[10,9,8,7,6,5,4,3,2,1]]}'
request_header = {}
prediction = run(raw_data, request_header)
print("Test result: ", prediction)
Předchozí kód nastaví proměnné raw_data
a request_header
zavolá run
funkci a request_header
raw_data
vytiskne předpovědi.
Po refaktoringu experimentation/Diabetes Ridge Regression Scoring.ipynb
by měl vypadat jako následující kód bez markdownu:
import json
import numpy
from azureml.core.model import Model
import joblib
def init():
model_path = Model.get_model_path(
model_name="sklearn_regression_model.pkl")
model = joblib.load(model_path)
def run(raw_data, request_headers):
data = json.loads(raw_data)["data"]
data = numpy.array(data)
result = model.predict(data)
return {"result": result.tolist()}
init()
test_row = '{"data":[[1,2,3,4,5,6,7,8,9,10],[10,9,8,7,6,5,4,3,2,1]]}'
request_header = {}
prediction = run(test_row, {})
print("Test result: ", prediction)
Kombinování souvisejících funkcí v souborech Pythonu
Za třetí, související funkce je potřeba sloučit do souborů Pythonu, aby se lépe pomohlo znovu použít kód. V této části budete vytvářet soubory Pythonu pro následující poznámkové bloky:
- The Diabetes Ridge Regression Training notebook(
experimentation/Diabetes Ridge Regression Training.ipynb
) - Poznámkový blok
experimentation/Diabetes Ridge Regression Scoring.ipynb
bodování diabetes Ridge
Vytvoření souboru Pythonu pro poznámkový blok pro regresi Diabetes Ridge
Převeďte poznámkový blok na spustitelný skript spuštěním následujícího příkazu v příkazovém řádku, který používá nbconvert
balíček a cestu experimentation/Diabetes Ridge Regression Training.ipynb
:
jupyter nbconvert "Diabetes Ridge Regression Training.ipynb" --to script --output train
Po převodu poznámkového bloku na train.py
tento poznámkový blok odeberte všechny nežádoucí komentáře. Volání na main()
konci souboru nahraďte podmíněným vyvoláním, jako je následující kód:
if __name__ == '__main__':
main()
Soubor train.py
by měl vypadat jako následující kód:
from sklearn.datasets import load_diabetes
from sklearn.linear_model import Ridge
from sklearn.metrics import mean_squared_error
from sklearn.model_selection import train_test_split
import pandas as pd
import joblib
# Split the dataframe into test and train data
def split_data(df):
X = df.drop('Y', axis=1).values
y = df['Y'].values
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=0)
data = {"train": {"X": X_train, "y": y_train},
"test": {"X": X_test, "y": y_test}}
return data
# Train the model, return the model
def train_model(data, args):
reg_model = Ridge(**args)
reg_model.fit(data["train"]["X"], data["train"]["y"])
return reg_model
# Evaluate the metrics for the model
def get_model_metrics(reg_model, data):
preds = reg_model.predict(data["test"]["X"])
mse = mean_squared_error(preds, data["test"]["y"])
metrics = {"mse": mse}
return metrics
def main():
# Load Data
sample_data = load_diabetes()
df = pd.DataFrame(
data=sample_data.data,
columns=sample_data.feature_names)
df['Y'] = sample_data.target
# Split Data into Training and Validation Sets
data = split_data(df)
# Train Model on Training Set
args = {
"alpha": 0.5
}
reg = train_model(data, args)
# Validate Model on Validation Set
metrics = get_model_metrics(reg, data)
# Save Model
model_name = "sklearn_regression_model.pkl"
joblib.dump(value=reg, filename=model_name)
if __name__ == '__main__':
main()
train.py
nyní lze vyvolat z terminálu spuštěním python train.py
příkazu .
Funkce z train.py
jiných souborů lze také volat.
Soubor train_aml.py
nalezený v diabetes_regression/training
adresáři v úložišti MLOpsPython volá funkce definované v train.py
kontextu úlohy experimentu Azure Machine Learning. Funkce lze také volat v testech jednotek, které jsou popsané dále v této příručce.
Vytvoření souboru Pythonu pro poznámkový blok pro bodování diabetes Ridge
Převeďte poznámkový blok na spustitelný skript spuštěním následujícího příkazu na příkazovém řádku, který používá nbconvert
balíček a cestu experimentation/Diabetes Ridge Regression Scoring.ipynb
:
jupyter nbconvert "Diabetes Ridge Regression Scoring.ipynb" --to script --output score
Po převodu poznámkového bloku na score.py
tento poznámkový blok odeberte všechny nežádoucí komentáře. Soubor score.py
by měl vypadat jako následující kód:
import json
import numpy
from azureml.core.model import Model
import joblib
def init():
model_path = Model.get_model_path(
model_name="sklearn_regression_model.pkl")
model = joblib.load(model_path)
def run(raw_data, request_headers):
data = json.loads(raw_data)["data"]
data = numpy.array(data)
result = model.predict(data)
return {"result": result.tolist()}
init()
test_row = '{"data":[[1,2,3,4,5,6,7,8,9,10],[10,9,8,7,6,5,4,3,2,1]]}'
request_header = {}
prediction = run(test_row, request_header)
print("Test result: ", prediction)
Proměnná model
musí být globální, aby byla viditelná v celém skriptu. Na začátek init
funkce přidejte následující příkaz:
global model
Po přidání předchozího příkazu init
by funkce měla vypadat jako následující kód:
def init():
global model
# load the model from file into a global object
model_path = Model.get_model_path(
model_name="sklearn_regression_model.pkl")
model = joblib.load(model_path)
Vytvoření testů jednotek pro každý soubor Pythonu
Za čtvrté vytvořte testy jednotek pro funkce Pythonu. Testy jednotek chrání kód před funkčními regresemi a usnadňují údržbu. V této části vytvoříte testy jednotek pro funkce v train.py
.
train.py
obsahuje více funkcí, ale v tomto kurzu vytvoříme pouze jeden test jednotek pro train_model
funkci pomocí architektury Pytest. Pytest není jedinou architekturou testování částí Pythonu, ale je to jedna z nejčastěji používaných architektur. Další informace najdete v Pytestu.
Test jednotek obvykle obsahuje tři hlavní akce:
- Uspořádání objektu – vytváření a nastavení nezbytných objektů
- Akce na objektu
- Assert what is expected
Test jednotek bude volat train_model
s některými pevně zakódovanými daty a argumenty a pomocí výsledného natrénovaného modelu ověřit, že train_model
se bude chovat podle očekávání, aby se vytvořil predikce a porovnával ji s očekávanou hodnotou.
import numpy as np
from code.training.train import train_model
def test_train_model():
# Arrange
X_train = np.array([1, 2, 3, 4, 5, 6]).reshape(-1, 1)
y_train = np.array([10, 9, 8, 8, 6, 5])
data = {"train": {"X": X_train, "y": y_train}}
# Act
reg_model = train_model(data, {"alpha": 1.2})
# Assert
preds = reg_model.predict([[1], [2]])
np.testing.assert_almost_equal(preds, [9.93939393939394, 9.03030303030303])
Další kroky
Teď, když rozumíte tomu, jak převést z experimentu na produkční kód, najdete na následujících odkazech další informace a další kroky:
- MLOpsPython: Vytvoření kanálu CI/CD pro trénování, vyhodnocení a nasazení vlastního modelu pomocí Azure Pipelines a Azure Machine Learning
- Monitorování úloh experimentů a metrik služby Azure Machine Learning
- Monitorování a shromažďování dat z koncových bodů webové služby ML