ML-experimenten converteren naar de Python-code voor productie
VAN TOEPASSING OP: Python SDK azureml v1
In deze zelfstudie leert u hoe u Jupyter-notebooks converteert naar Python-scripts om deze te testen en te automatiseren met behulp van de MLOpsPython-codesjabloon en Azure Machine Learning. Normaal gesproken wordt dit proces gebruikt om experimenten/trainingscode uit een Jupyter-notebook te nemen en te converteren naar Python-scripts. Deze scripts kunnen vervolgens worden gebruikt voor testen en CI/CD-automatisering in uw productieomgeving.
Een machine learning-project vereist experimenten waarbij hypothesen worden getest met agile hulpprogram ma's zoals Jupyter Notebook met echte gegevenssets. Zodra het model gereed is voor productie, moet de modelcode in een opslagplaats voor productiecode worden geplaatst. In sommige gevallen moet de modelcode worden geconverteerd naar Python-scripts die in de opslagplaats voor productiecode moeten worden geplaatst. In deze zelfstudie wordt een aanbevolen methode beschreven voor het exporteren van experimenteringscode naar Python-scripts.
In deze zelfstudie leert u het volgende:
- Niet-essentiële code opschonen
- Jupyter Notebook-code herstructureren in functies
- Python-scripts maken voor verwante taken
- Eenheidstests maken
Vereisten
- Genereer de MLOpsPython-sjabloon en gebruik de
experimentation/Diabetes Ridge Regression Training.ipynb
- enexperimentation/Diabetes Ridge Regression Scoring.ipynb
-notebooks. Deze notebooks worden gebruikt als voorbeeld van het converteren van experimenten naar productie. U kunt deze notebooks vinden op https://github.com/microsoft/MLOpsPython/tree/master/experimentation. - Installeer
nbconvert
. Volg alleen de installatie-instructies onder sectie nbconvert installeren op de pagina Installatie.
Alle niet-essentiële code verwijderen
Sommige code die is geschreven tijdens het experiment, is alleen bedoeld voor experimentele doeleinden. Daarom is de eerste stap voor het converteren van experimentele code naar productiecode, deze niet-essentiële code te verwijderen. Als u niet-essentiële code verwijdert, wordt de code ook eenvoudiger te onderhouden. In deze sectie verwijdert u code uit het experimentation/Diabetes Ridge Regression Training.ipynb
-notebook. De instructies voor het afdrukken van de vorm van X
en y
en de cel waarmee features.describe
worden aangeroepen, zijn alleen bedoeld voor het verkennen van gegevens en kunnen worden verwijderd. Na het verwijderen van de niet-essentiële code moet experimentation/Diabetes Ridge Regression Training.ipynb
er als de volgende code uitzien, zonder markdown:
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)
Code herstructureren in functies
Ten tweede moet de Jupyter-code worden geherstructureerd in functies. Het herstructureren van code in functies maakt het gemakkelijker om moduletests uit te voeren en maakt het eenvoudiger om de code te onderhouden. In deze sectie herstructureert u het volgende:
- De Diabetes Ridge Regression Training-notebook(
experimentation/Diabetes Ridge Regression Training.ipynb
) - De Diabetes Ridge Regression Scoring-notebook(
experimentation/Diabetes Ridge Regression Scoring.ipynb
)
Diabetes Ridge Regression Training-notebook herstructureren in functies
Voltooi in experimentation/Diabetes Ridge Regression Training.ipynb
de volgende stappen:
Maak een functie met de naam
split_data
om het gegevensframe te splitsen in test- en trainingsgegevens. De functie moet het gegevensframedf
als parameter gebruiken en een woordenboek met de sleutelstrain
entest
retourneren.Verplaats de code onder de kop Gegevens splitsen in trainings- en validatiesets naar de functie
split_data
en wijzig deze om hetdata
-object te retourneren.Maak een functie met de naam
train_model
, waarbij de parametersdata
enargs
worden gebruikt en een getraind model wordt geretourneerd.Verplaats de code onder de kop Trainingsmodel op trainingsset naar de functie
train_model
en wijzig deze om hetreg_model
-object te retourneren. Verwijder hetargs
-woordenboek, de waarden komen uit de parameterargs
.Maak een functie met de naam
get_model_metrics
, die parametersreg_model
endata
gebruikt, het model evalueert en vervolgens een woordenboek van metrische gegevens retourneert voor het getrainde model.Verplaats de code onder de kop Model valideren op validatieset naar de functie
get_model_metrics
en wijzig deze om hetmetrics
-object te retourneren.
De drie functies moeten er als volgt uitzien:
# 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
Voltooi in experimentation/Diabetes Ridge Regression Training.ipynb
de volgende stappen:
Maak een nieuwe functie met de naam
main
, waarvoor geen parameters worden gebruikt en er niets wordt geretourneerd.Verplaats de code onder de kop 'Gegevens laden' naar de functie
main
.Voeg aanroepen voor de zojuist geschreven functies toe aan de functie
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)
Verplaats de code onder de kop 'Model opslaan' naar de functie
main
.
De functie main
moet eruitzien als de volgende code:
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)
In deze fase mag er geen code meer in de notebook staan die niet in een functie voorkomt, behalve de instructies voor importeren in de eerste cel.
Voeg een instructie toe die de functie main
aanroept.
main()
Na het herstructureren moet experimentation/Diabetes Ridge Regression Training.ipynb
eruitzien als de volgende code maar zonder de markdown:
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()
Diabetes Ridge Regression Scoring-notebook herstructureren in functies
Voltooi in experimentation/Diabetes Ridge Regression Scoring.ipynb
de volgende stappen:
- Maak een nieuwe functie met de naam
init
, waarvoor geen parameters worden gebruikt en er niets wordt geretourneerd. - Kopieer de code onder de kop 'Model opslaan' naar de functie
init
.
De functie init
moet eruitzien als de volgende code:
def init():
model_path = Model.get_model_path(
model_name="sklearn_regression_model.pkl")
model = joblib.load(model_path)
Zodra de functie init
is gemaakt, vervangt u als volgt alle code onder de kop 'Model laden' door één aanroep naar init
:
init()
Voltooi in experimentation/Diabetes Ridge Regression Scoring.ipynb
de volgende stappen:
Maak een nieuwe functie met de naam
run
, dieraw_data
enrequest_headers
als parameters gebruikt en als volgt een woordenlijst met resultaten retourneert:{"result": result.tolist()}
Kopieer de code onder de koppen 'Gegevens voorbereiden' en 'Scoregegevens' naar de functie
run
.De functie
run
moet eruitzien als de volgende code (Vergeet niet om de instructies te verwijderen waarmee de variabelenraw_data
enrequest_headers
worden ingesteld, die later worden gebruikt wanneer de functierun
wordt aangeroepen):def run(raw_data, request_headers): data = json.loads(raw_data)["data"] data = numpy.array(data) result = model.predict(data) return {"result": result.tolist()}
Zodra de functie run
is gemaakt, vervangt u alle code onder de koppen 'Gegevens voorbereiden' en 'Scoregegevens' door de volgende code:
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)
Met de vorige code worden variabelen raw_data
en request_header
ingesteld, wordt de functie run
aangeroepen met raw_data
en request_header
en worden de voorspellingen afgedrukt.
Na het herstructureren moet experimentation/Diabetes Ridge Regression Scoring.ipynb
eruitzien als de volgende code maar zonder de markdown:
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)
Gerelateerde functies in Python-bestanden combineren
Ten derde moeten gerelateerde functies worden samengevoegd in Python-bestanden om de code beter te kunnen hergebruiken. In deze sectie maakt u Python-bestanden voor de volgende notebooks:
- De Diabetes Ridge Regression Training-notebook(
experimentation/Diabetes Ridge Regression Training.ipynb
) - De Diabetes Ridge Regression Scoring-notebook(
experimentation/Diabetes Ridge Regression Scoring.ipynb
)
Python-bestand maken voor de Diabetes Ridge Regression Training-notebook
Converteer uw notebook naar een uitvoerbaar script door de volgende instructie uit te voeren in een opdrachtprompt, die gebruikmaakt van het nbconvert
-pakket en het pad van experimentation/Diabetes Ridge Regression Training.ipynb
:
jupyter nbconvert "Diabetes Ridge Regression Training.ipynb" --to script --output train
Nadat de notebook is geconverteerd naar train.py
, verwijdert u eventuele ongewenste opmerkingen. Vervang de aanroep naar main()
aan het einde van het bestand met een voorwaardelijke aanroep zoals de volgende code:
if __name__ == '__main__':
main()
Uw train.py
-bestand moet eruitzien als de volgende code:
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
kan nu worden aangeroepen vanaf een terminal door python train.py
uit te voeren.
De functies van train.py
kunnen ook worden aangeroepen vanuit andere bestanden.
Het train_aml.py
bestand in de diabetes_regression/training
map in de MLOpsPython-opslagplaats roept de functies aan die zijn gedefinieerd train.py
in de context van een Azure Machine Learning-experimenttaak. De functies kunnen ook worden aangeroepen in moduletests, die verderop in deze handleiding worden besproken.
Python-bestand maken voor de Diabetes Ridge Regression Scoring-notebook
Converteer uw notebook naar een uitvoerbaar script door de volgende instructie uit te voeren in een opdrachtprompt die gebruikmaakt van het nbconvert
pakket en het pad van experimentation/Diabetes Ridge Regression Scoring.ipynb
:
jupyter nbconvert "Diabetes Ridge Regression Scoring.ipynb" --to script --output score
Nadat de notebook is geconverteerd naar score.py
, verwijdert u eventuele ongewenste opmerkingen. Uw score.py
-bestand moet eruitzien als de volgende code:
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)
De variabele model
moet globaal zijn zodat deze overal in het script zichtbaar is. Voeg de volgende instructie toe aan het begin van de functie init
:
global model
Nadat u de vorige instructie hebt toegevoegd, moet de functie init
eruitzien als de volgende code:
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)
Moduletests maken voor elk Python-bestand
Ten vierde maakt u moduletests voor uw Python-functies. Moduletests beveiligen code tegen functionele regressies en maken het gemakkelijker om deze te onderhouden. In deze sectie maakt u moduletests voor de functies in train.py
.
train.py
bevat meerdere functies, maar we maken slechts één moduletest voor de functie train_model
met behulp van het Pytest-framework in deze zelfstudie. Pytest is niet het enige Python-framework voor moduletests, maar het is een van de meest gebruikte frameworks. Ga voor meer informatie naar Pytest.
Een moduletest bevat normaal gesproken drie hoofdacties:
- Object ordenen: benodigde objecten maken en instellen
- Reageren op een object
- Bevestigen wat er wordt verwacht
De moduletest roept train_model
aan met bepaalde in code vastgelegde gegevens en argumenten, en valideert dat train_model
op de verwachte manier heeft gehandeld met behulp van het resulterende getrainde model om een voorspelling te doen en die voorspelling te vergelijken met een verwachte waarde.
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])
Volgende stappen
Nu u weet hoe u kunt converteren van een experiment naar productiecode, raadpleegt u de volgende links voor meer informatie en volgende stappen:
- MLOpsPython: een CI/CD-pijplijn bouwen om uw eigen model te trainen, evalueren en implementeren met behulp van Azure Pipelines en Azure Machine Learning
- Azure Machine Learning-experimenttaken en metrische gegevens bewaken
- Gegevens van ML-webservice-eindpunten bewaken en verzamelen