Trenowanie modeli scikit-learn na dużą skalę przy użyciu usługi Azure Machine Learning
DOTYCZY: Zestaw PYTHON SDK azure-ai-ml w wersji 2 (bieżąca)
Z tego artykułu dowiesz się, jak uruchamiać skrypty szkoleniowe biblioteki scikit-learn przy użyciu zestawu SDK języka Python usługi Azure Machine Learning w wersji 2.
Przykładowe skrypty w tym artykule służą do klasyfikowania obrazów kwiatów irysów w celu utworzenia modelu uczenia maszynowego na podstawie zestawu danych irysów scikit-learn.
Niezależnie od tego, czy trenujesz model scikit-learn uczenia maszynowego od podstaw, czy wprowadzasz istniejący model do chmury, możesz użyć usługi Azure Machine Learning, aby skalować zadania szkoleniowe typu open source przy użyciu elastycznych zasobów obliczeniowych w chmurze. Za pomocą usługi Azure Machine Learning można tworzyć, wdrażać, wersję i monitorować modele klasy produkcyjnej.
Wymagania wstępne
Kod tego artykułu można uruchomić w wystąpieniu obliczeniowym usługi Azure Machine Learning lub własnym notesie Jupyter Notebook.
Wystąpienie obliczeniowe usługi Azure Machine Learning
- Ukończ tworzenie zasobów, aby rozpocząć tworzenie wystąpienia obliczeniowego. Każde wystąpienie obliczeniowe zawiera wstępnie załadowany dedykowany serwer notesu z zestawem SDK i przykładowym repozytorium notesów.
- Wybierz kartę notesu w usłudze Azure Machine Learning Studio. W folderze szkoleniowym przykłady znajdź ukończony i rozszerzony notes, przechodząc do tego katalogu: zadania zestawu SDK > w wersji 2 > w jednym kroku > scikit-learn > train-hyperparameter-tune-deploy-with-sklearn>.
- Aby ukończyć ten samouczek, możesz użyć wstępnie wypełnianego kodu w folderze przykładowym trenowania.
Serwer notesu Jupyter.
Konfigurowanie zadania
Ta sekcja konfiguruje zadanie trenowania przez załadowanie wymaganych pakietów języka Python, nawiązanie połączenia z obszarem roboczym, utworzenie zasobu obliczeniowego w celu uruchomienia zadania polecenia i utworzenie środowiska do uruchomienia zadania.
Nawiązywanie połączenia z obszarem roboczym
Najpierw musisz nawiązać połączenie z obszarem roboczym usługi Azure Machine Learning. Obszar roboczy usługi Azure Machine Learning to zasób najwyższego poziomu dla usługi. Zapewnia scentralizowane miejsce do pracy ze wszystkimi artefaktami tworzonymi podczas korzystania z usługi Azure Machine Learning.
Używamy DefaultAzureCredential
polecenia , aby uzyskać dostęp do obszaru roboczego. To poświadczenie powinno być w stanie obsługiwać większość scenariuszy uwierzytelniania zestawu Azure SDK.
Jeśli DefaultAzureCredential
nie zadziała, zobacz azure-identity reference documentation
lub Set up authentication
w przypadku większej liczby dostępnych poświadczeń.
# Handle to the workspace
from azure.ai.ml import MLClient
# Authentication package
from azure.identity import DefaultAzureCredential
credential = DefaultAzureCredential()
Jeśli wolisz używać przeglądarki do logowania się i uwierzytelniania, należy usunąć komentarze w poniższym kodzie i użyć go zamiast tego.
# Handle to the workspace
# from azure.ai.ml import MLClient
# Authentication package
# from azure.identity import InteractiveBrowserCredential
# credential = InteractiveBrowserCredential()
Następnie uzyskaj dojście do obszaru roboczego, podając identyfikator subskrypcji, nazwę grupy zasobów i nazwę obszaru roboczego. Aby znaleźć następujące parametry:
- Wyszukaj w prawym górnym rogu paska narzędzi usługi Azure Machine Learning Studio nazwę obszaru roboczego.
- Wybierz nazwę obszaru roboczego, aby wyświetlić identyfikator grupy zasobów i subskrypcji.
- Skopiuj wartości dla pola Grupa zasobów i Identyfikator subskrypcji do kodu.
# Get a handle to the workspace
ml_client = MLClient(
credential=credential,
subscription_id="<SUBSCRIPTION_ID>",
resource_group_name="<RESOURCE_GROUP>",
workspace_name="<AML_WORKSPACE_NAME>",
)
Wynikiem uruchomienia tego skryptu jest uchwyt obszaru roboczego używany do zarządzania innymi zasobami i zadaniami.
Uwaga
Tworzenie MLClient
nie spowoduje połączenia klienta z obszarem roboczym. Inicjowanie klienta jest leniwe i będzie czekać po raz pierwszy, aby wykonać wywołanie. W tym artykule będzie to miało miejsce podczas tworzenia zasobów obliczeniowych.
Tworzenie zasobu obliczeniowego
Usługa Azure Machine Learning wymaga zasobu obliczeniowego do uruchomienia zadania. Ten zasób może być maszynami z jednym lub wieloma węzłami z systemem operacyjnym Linux lub Windows albo określoną siecią szkieletową obliczeniową, taką jak Spark.
W poniższym przykładowym skry skrycie aprowizujemy system Linux compute cluster
. Zostanie wyświetlona Azure Machine Learning pricing
strona zawierająca pełną listę rozmiarów maszyn wirtualnych i cen. W tym przykładzie potrzebujemy tylko podstawowego klastra; dlatego wybieramy model Standard_DS3_v2 z 2 rdzeniami procesorów wirtualnych i 7 GB pamięci RAM w celu utworzenia obliczeń usługi Azure Machine Learning.
from azure.ai.ml.entities import AmlCompute
# Name assigned to the compute cluster
cpu_compute_target = "cpu-cluster"
try:
# let's see if the compute target already exists
cpu_cluster = ml_client.compute.get(cpu_compute_target)
print(
f"You already have a cluster named {cpu_compute_target}, we'll reuse it as is."
)
except Exception:
print("Creating a new cpu compute target...")
# Let's create the Azure ML compute object with the intended parameters
cpu_cluster = AmlCompute(
name=cpu_compute_target,
# Azure ML Compute is the on-demand VM service
type="amlcompute",
# VM Family
size="STANDARD_DS3_V2",
# Minimum running nodes when there is no job running
min_instances=0,
# Nodes in cluster
max_instances=4,
# How many seconds will the node running after the job termination
idle_time_before_scale_down=180,
# Dedicated or LowPriority. The latter is cheaper but there is a chance of job termination
tier="Dedicated",
)
# Now, we pass the object to MLClient's create_or_update method
cpu_cluster = ml_client.compute.begin_create_or_update(cpu_cluster).result()
print(
f"AMLCompute with name {cpu_cluster.name} is created, the compute size is {cpu_cluster.size}"
)
Tworzenie środowiska zadań
Aby uruchomić zadanie usługi Azure Machine Learning, potrzebne jest środowisko. Środowisko usługi Azure Machine Learning hermetyzuje zależności (takie jak środowisko uruchomieniowe oprogramowania i biblioteki) wymagane do uruchomienia skryptu trenowania uczenia maszynowego na zasobie obliczeniowym. To środowisko jest podobne do środowiska języka Python na komputerze lokalnym.
Usługa Azure Machine Learning umożliwia korzystanie ze środowiska nadzorowanego (lub gotowego) albo tworzenia środowiska niestandardowego przy użyciu obrazu platformy Docker lub konfiguracji conda. W tym artykule utworzysz niestandardowe środowisko dla zadań przy użyciu pliku YAML Conda.
Tworzenie środowiska niestandardowego
Aby utworzyć środowisko niestandardowe, należy zdefiniować zależności Conda w pliku YAML. Najpierw utwórz katalog do przechowywania pliku. W tym przykładzie nazwaliśmy katalog env
.
import os
dependencies_dir = "./env"
os.makedirs(dependencies_dir, exist_ok=True)
Następnie utwórz plik w katalogu dependencies. W tym przykładzie nazwaliśmy plik conda.yml
.
%%writefile {dependencies_dir}/conda.yaml
name: sklearn-env
channels:
- conda-forge
dependencies:
- python=3.8
- pip=21.2.4
- scikit-learn=0.24.2
- scipy=1.7.1
- pip:
- azureml-mlflow==1.42.0
- mlflow-skinny==2.3.2
Specyfikacja zawiera niektóre zwykłe pakiety (takie jak numpy i), których używasz w zadaniu.
Następnie użyj pliku YAML, aby utworzyć i zarejestrować to środowisko niestandardowe w obszarze roboczym. Środowisko jest pakowane do kontenera platformy Docker w czasie wykonywania.
from azure.ai.ml.entities import Environment
custom_env_name = "sklearn-env"
job_env = Environment(
name=custom_env_name,
description="Custom environment for sklearn image classification",
conda_file=os.path.join(dependencies_dir, "conda.yaml"),
image="mcr.microsoft.com/azureml/openmpi4.1.0-ubuntu20.04:latest",
)
job_env = ml_client.environments.create_or_update(job_env)
print(
f"Environment with name {job_env.name} is registered to workspace, the environment version is {job_env.version}"
)
Aby uzyskać więcej informacji na temat tworzenia i używania środowisk, zobacz Tworzenie i używanie środowisk oprogramowania w usłudze Azure Machine Learning.
[Opcjonalnie] Tworzenie środowiska niestandardowego za pomocą rozszerzenia Intel® dla biblioteki Scikit-Learn
Chcesz przyspieszyć skrypty scikit-learn na sprzęcie firmy Intel? Spróbuj dodać rozszerzenie Intel® dla biblioteki Scikit-Learn do pliku yaml conda i wykonaj kolejne kroki opisane powyżej. W dalszej części tego przykładu pokażemy, jak włączyć te optymalizacje:
%%writefile {dependencies_dir}/conda.yaml
name: sklearn-env
channels:
- conda-forge
dependencies:
- python=3.8
- pip=21.2.4
- scikit-learn=0.24.2
- scikit-learn-intelex
- scipy=1.7.1
- pip:
- azureml-mlflow==1.42.0
- mlflow-skinny==2.3.2
Konfigurowanie i przesyłanie zadania szkoleniowego
W tej sekcji omówiono sposób uruchamiania zadania szkoleniowego przy użyciu udostępnionego skryptu szkoleniowego. Aby rozpocząć, skompilujesz zadanie trenowania, konfigurując polecenie do uruchamiania skryptu szkoleniowego. Następnie przesyłasz zadanie szkoleniowe do uruchomienia w usłudze Azure Machine Learning.
Przygotowywanie skryptu szkoleniowego
W tym artykule udostępniliśmy skrypt szkoleniowy train_iris.py. W praktyce powinno być możliwe użycie dowolnego niestandardowego skryptu szkoleniowego w następujący sposób i uruchomienie go za pomocą usługi Azure Machine Learning bez konieczności modyfikowania kodu.
Uwaga
Podany skrypt szkoleniowy wykonuje następujące czynności:
- pokazuje, jak zarejestrować niektóre metryki w uruchomieniu usługi Azure Machine Learning;
- pobiera i wyodrębnia dane treningowe przy użyciu elementu
iris = datasets.load_iris()
; i - trenuje model, a następnie zapisuje i rejestruje go.
Aby korzystać z własnych danych i uzyskiwać do nich dostęp, zobacz , jak odczytywać i zapisywać dane w zadaniu , aby udostępnić dane podczas trenowania.
Aby użyć skryptu trenowania, najpierw utwórz katalog, w którym będzie przechowywany plik.
import os
src_dir = "./src"
os.makedirs(src_dir, exist_ok=True)
Następnie utwórz plik skryptu w katalogu źródłowym.
%%writefile {src_dir}/train_iris.py
# Modified from https://www.geeksforgeeks.org/multiclass-classification-using-scikit-learn/
import argparse
import os
# importing necessary libraries
import numpy as np
from sklearn import datasets
from sklearn.metrics import confusion_matrix
from sklearn.model_selection import train_test_split
import joblib
import mlflow
import mlflow.sklearn
def main():
parser = argparse.ArgumentParser()
parser.add_argument('--kernel', type=str, default='linear',
help='Kernel type to be used in the algorithm')
parser.add_argument('--penalty', type=float, default=1.0,
help='Penalty parameter of the error term')
# Start Logging
mlflow.start_run()
# enable autologging
mlflow.sklearn.autolog()
args = parser.parse_args()
mlflow.log_param('Kernel type', str(args.kernel))
mlflow.log_metric('Penalty', float(args.penalty))
# loading the iris dataset
iris = datasets.load_iris()
# X -> features, y -> label
X = iris.data
y = iris.target
# dividing X, y into train and test data
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)
# training a linear SVM classifier
from sklearn.svm import SVC
svm_model_linear = SVC(kernel=args.kernel, C=args.penalty)
svm_model_linear = svm_model_linear.fit(X_train, y_train)
svm_predictions = svm_model_linear.predict(X_test)
# model accuracy for X_test
accuracy = svm_model_linear.score(X_test, y_test)
print('Accuracy of SVM classifier on test set: {:.2f}'.format(accuracy))
mlflow.log_metric('Accuracy', float(accuracy))
# creating a confusion matrix
cm = confusion_matrix(y_test, svm_predictions)
print(cm)
registered_model_name="sklearn-iris-flower-classify-model"
##########################
#<save and register model>
##########################
# Registering the model to the workspace
print("Registering the model via MLFlow")
mlflow.sklearn.log_model(
sk_model=svm_model_linear,
registered_model_name=registered_model_name,
artifact_path=registered_model_name
)
# # Saving the model to a file
print("Saving the model via MLFlow")
mlflow.sklearn.save_model(
sk_model=svm_model_linear,
path=os.path.join(registered_model_name, "trained_model"),
)
###########################
#</save and register model>
###########################
mlflow.end_run()
if __name__ == '__main__':
main()
[Opcjonalnie] Włączanie rozszerzenia Intel® dla optymalizacji Scikit-Learn w celu uzyskania większej wydajności sprzętu firmy Intel
Jeśli zainstalowano rozszerzenie Intel® dla biblioteki Scikit-Learn (jak pokazano w poprzedniej sekcji), możesz włączyć optymalizacje wydajności, dodając dwa wiersze kodu na początku pliku skryptu, jak pokazano poniżej.
Aby dowiedzieć się więcej na temat rozszerzenia Intel® dla biblioteki Scikit-Learn, odwiedź dokumentację pakietu.
%%writefile {src_dir}/train_iris.py
# Modified from https://www.geeksforgeeks.org/multiclass-classification-using-scikit-learn/
import argparse
import os
# Import and enable Intel Extension for Scikit-learn optimizations
# where possible
from sklearnex import patch_sklearn
patch_sklearn()
# importing necessary libraries
import numpy as np
from sklearn import datasets
from sklearn.metrics import confusion_matrix
from sklearn.model_selection import train_test_split
import joblib
import mlflow
import mlflow.sklearn
def main():
parser = argparse.ArgumentParser()
parser.add_argument('--kernel', type=str, default='linear',
help='Kernel type to be used in the algorithm')
parser.add_argument('--penalty', type=float, default=1.0,
help='Penalty parameter of the error term')
# Start Logging
mlflow.start_run()
# enable autologging
mlflow.sklearn.autolog()
args = parser.parse_args()
mlflow.log_param('Kernel type', str(args.kernel))
mlflow.log_metric('Penalty', float(args.penalty))
# loading the iris dataset
iris = datasets.load_iris()
# X -> features, y -> label
X = iris.data
y = iris.target
# dividing X, y into train and test data
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)
# training a linear SVM classifier
from sklearn.svm import SVC
svm_model_linear = SVC(kernel=args.kernel, C=args.penalty)
svm_model_linear = svm_model_linear.fit(X_train, y_train)
svm_predictions = svm_model_linear.predict(X_test)
# model accuracy for X_test
accuracy = svm_model_linear.score(X_test, y_test)
print('Accuracy of SVM classifier on test set: {:.2f}'.format(accuracy))
mlflow.log_metric('Accuracy', float(accuracy))
# creating a confusion matrix
cm = confusion_matrix(y_test, svm_predictions)
print(cm)
registered_model_name="sklearn-iris-flower-classify-model"
##########################
#<save and register model>
##########################
# Registering the model to the workspace
print("Registering the model via MLFlow")
mlflow.sklearn.log_model(
sk_model=svm_model_linear,
registered_model_name=registered_model_name,
artifact_path=registered_model_name
)
# # Saving the model to a file
print("Saving the model via MLFlow")
mlflow.sklearn.save_model(
sk_model=svm_model_linear,
path=os.path.join(registered_model_name, "trained_model"),
)
###########################
#</save and register model>
###########################
mlflow.end_run()
if __name__ == '__main__':
main()
Tworzenie zadania szkoleniowego
Teraz, gdy masz wszystkie zasoby wymagane do uruchomienia zadania, nadszedł czas, aby skompilować go przy użyciu zestawu SDK języka Python usługi Azure Machine Learning w wersji 2. Aby uruchomić zadanie, utworzymy element command
.
Usługa Azure Machine Learning command
to zasób, który określa wszystkie szczegóły potrzebne do wykonania kodu szkoleniowego w chmurze. Te szczegóły obejmują dane wejściowe i wyjściowe, typ sprzętu do użycia, oprogramowanie do zainstalowania i sposób uruchamiania kodu. Zawiera command
informacje umożliwiające wykonanie pojedynczego polecenia.
Konfigurowanie polecenia
Używasz ogólnego przeznaczenia command
do uruchamiania skryptu szkoleniowego i wykonywania żądanych zadań. Utwórz obiekt, Command
aby określić szczegóły konfiguracji zadania trenowania.
- Dane wejściowe dla tego polecenia obejmują liczbę epok, szybkość nauki, pęd i katalog wyjściowy.
- Dla wartości parametrów:
- podaj klaster
cpu_compute_target = "cpu-cluster"
obliczeniowy utworzony na potrzeby uruchamiania tego polecenia; - podaj środowisko
sklearn-env
niestandardowe utworzone do uruchamiania zadania usługi Azure Machine Learning; - skonfiguruj samą akcję wiersza polecenia — w tym przypadku polecenie to
python train_iris.py
. Dostęp do danych wejściowych i wyjściowych można uzyskać w poleceniu${{ ... }}
za pośrednictwem notacji; i - skonfiguruj metadane, takie jak nazwa wyświetlana i nazwa eksperymentu; gdzie eksperyment jest kontenerem dla wszystkich iteracji, które wykonuje w określonym projekcie. Wszystkie zadania przesłane pod tą samą nazwą eksperymentu zostaną wyświetlone obok siebie w usłudze Azure Machine Learning Studio.
- podaj klaster
from azure.ai.ml import command
from azure.ai.ml import Input
job = command(
inputs=dict(kernel="linear", penalty=1.0),
compute=cpu_compute_target,
environment=f"{job_env.name}:{job_env.version}",
code="./src/",
command="python train_iris.py --kernel ${{inputs.kernel}} --penalty ${{inputs.penalty}}",
experiment_name="sklearn-iris-flowers",
display_name="sklearn-classify-iris-flower-images",
)
Przesyłanie zadania
Nadszedł czas na przesłanie zadania do uruchomienia w usłudze Azure Machine Learning. Tym razem użyjesz polecenia create_or_update
w systemie ml_client.jobs
.
ml_client.jobs.create_or_update(job)
Po zakończeniu zadanie rejestruje model w obszarze roboczym (w wyniku trenowania) i wyświetli link do wyświetlania zadania w usłudze Azure Machine Learning Studio.
Ostrzeżenie
Usługa Azure Machine Learning uruchamia skrypty szkoleniowe, kopiując cały katalog źródłowy. Jeśli masz poufne dane, które nie chcesz przekazywać, użyj pliku .ignore lub nie dołącz go do katalogu źródłowego.
Co się dzieje podczas wykonywania zadania
Po wykonaniu zadania przechodzi on przez następujące etapy:
Przygotowywanie: obraz platformy Docker jest tworzony zgodnie ze zdefiniowanym środowiskiem. Obraz jest przekazywany do rejestru kontenerów obszaru roboczego i buforowany w celu późniejszego uruchomienia. Dzienniki są również przesyłane strumieniowo do historii uruchamiania i można je wyświetlić w celu monitorowania postępu. Jeśli zostanie określone wyselekcjonowane środowisko, używany jest buforowany obraz obsługujący wyselekcjonowane środowisko.
Skalowanie: klaster próbuje skalować w górę, jeśli klaster wymaga więcej węzłów do wykonania przebiegu, niż jest obecnie dostępne.
Uruchomione: wszystkie skrypty w folderze skryptu src są przekazywane do docelowego obiektu obliczeniowego, magazyny danych są instalowane lub kopiowane, a skrypt jest wykonywany. Dane wyjściowe ze strumienia stdout i folderu ./logs są przesyłane strumieniowo do historii uruchamiania i mogą służyć do monitorowania przebiegu.
Dostrajanie hiperparametrów modelu
Teraz, gdy już wiesz, jak wykonać prosty przebieg trenowania Scikit-learn przy użyciu zestawu SDK, zobaczmy, czy możesz jeszcze bardziej poprawić dokładność modelu. Hiperparametry naszego modelu można dostroić i zoptymalizować przy użyciu możliwości usługi Azure Machine Learning sweep
.
Aby dostroić hiperparametry modelu, zdefiniuj przestrzeń parametrów, w której mają być wyszukiwane podczas trenowania. W tym celu należy zastąpić niektóre parametry (kernel
i penalty
) przekazane do zadania szkoleniowego specjalnymi danymi wejściowymi z azure.ml.sweep
pakietu.
from azure.ai.ml.sweep import Choice
# we will reuse the command_job created before. we call it as a function so that we can apply inputs
# we do not apply the 'iris_csv' input again -- we will just use what was already defined earlier
job_for_sweep = job(
kernel=Choice(values=["linear", "rbf", "poly", "sigmoid"]),
penalty=Choice(values=[0.5, 1, 1.5]),
)
Następnie skonfigurujesz zamiatanie zadania polecenia, używając niektórych parametrów specyficznych dla zamiatania, takich jak metryka podstawowa do obserwowania i algorytm próbkowania do użycia.
W poniższym kodzie używamy losowego próbkowania do wypróbowania różnych zestawów konfiguracji hiperparametrów w celu zmaksymalizowania podstawowej metryki . Accuracy
sweep_job = job_for_sweep.sweep(
compute="cpu-cluster",
sampling_algorithm="random",
primary_metric="Accuracy",
goal="Maximize",
max_total_trials=12,
max_concurrent_trials=4,
)
Teraz możesz przesłać to zadanie tak jak wcześniej. Tym razem uruchamiasz zadanie zamiatania, które zamiata się nad zadaniem pociągu.
returned_sweep_job = ml_client.create_or_update(sweep_job)
# stream the output and wait until the job is finished
ml_client.jobs.stream(returned_sweep_job.name)
# refresh the latest status of the job after streaming
returned_sweep_job = ml_client.jobs.get(name=returned_sweep_job.name)
Zadanie można monitorować przy użyciu linku interfejsu użytkownika programu Studio, który jest prezentowany podczas uruchamiania zadania.
Znajdowanie i rejestrowanie najlepszego modelu
Po zakończeniu wszystkich przebiegów można znaleźć przebieg, który wygenerował model z najwyższą dokładnością.
from azure.ai.ml.entities import Model
if returned_sweep_job.status == "Completed":
# First let us get the run which gave us the best result
best_run = returned_sweep_job.properties["best_child_run_id"]
# lets get the model from this run
model = Model(
# the script stores the model as "sklearn-iris-flower-classify-model"
path="azureml://jobs/{}/outputs/artifacts/paths/sklearn-iris-flower-classify-model/".format(
best_run
),
name="run-model-example",
description="Model created from run.",
type="custom_model",
)
else:
print(
"Sweep job status: {}. Please wait until it completes".format(
returned_sweep_job.status
)
)
Następnie możesz zarejestrować ten model.
registered_model = ml_client.models.create_or_update(model=model)
Wdrażanie modelu
Po zarejestrowaniu modelu możesz wdrożyć go w taki sam sposób, jak w przypadku dowolnego innego zarejestrowanego modelu w usłudze Azure Machine Learning. Aby uzyskać więcej informacji na temat wdrażania, zobacz Deploy and score a machine learning model with managed online endpoint using Python SDK v2 (Wdrażanie i ocenianie modelu uczenia maszynowego za pomocą zarządzanego punktu końcowego online przy użyciu zestawu SDK języka Python w wersji 2).
Następne kroki
W tym artykule wytrenujesz i zarejestrowano model scikit-learn oraz przedstawiono opcje wdrażania. Zapoznaj się z innymi artykułami, aby dowiedzieć się więcej o usłudze Azure Machine Learning.