Zautomatyzowane uczenie maszynowe¶
Algorytmów uczenia maszynowego jest wiele i rzadko da się z góry powiedzieć, który poradzi sobie najlepiej z konkretnymi danymi. Na jakość modelu mocno wpływa też wstępne przetwarzanie danych (ang. preprocessing) - normalizacja, uzupełnianie brakujących wartości i podobne zabiegi. Szukanie najlepszego rozwiązania oznacza więc sprawdzenie wielu kombinacji algorytmu i przekształceń, a to kosztuje czas i moc obliczeniową.
Azure Machine Learning potrafi to porównanie zautomatyzować. Możesz skorzystać z interfejsu graficznego w Azure Machine Learning studio albo z zestawu SDK. Interfejs graficzny jest prostszy, SDK daje większą kontrolę nad ustawieniami. W tym ćwiczeniu użyjesz SDK.
Po co to robimy: celem nie jest wyręczenie się automatem. Chodzi o to, żeby szybko uzyskać punkt odniesienia - wynik, o którym wiadomo, że da się go osiągnąć bez szczególnej wiedzy o danych. Model budowany ręcznie ma sens wtedy, gdy ten punkt odniesienia pobije.
Połączenie z obszarem roboczym¶
Zacznij od połączenia z obszarem roboczym (ang. workspace) przy użyciu zestawu Azure ML SDK.
Uwaga: jeśli od poprzedniego ćwiczenia wygasła sesja uwierzytelniania z subskrypcją Azure, zobaczysz prośbę o ponowne zalogowanie.
from azure.ai.ml import MLClient
from azure.identity import DefaultAzureCredential
credential = DefaultAzureCredential()
ml_client = MLClient.from_config(credential=credential)
print(f"Azure ML gotowe do pracy z obszarem roboczym {ml_client.workspace_name}")
Przygotowanie danych dla zadania¶
W tym ćwiczeniu użyjesz zasobu danych (ang. data asset) z wynikami badań pacjentów pod kątem cukrzycy. Uruchom poniższą komórkę, aby go utworzyć (jeśli powstał już we wcześniejszym ćwiczeniu, zarejestrowana zostanie jego nowa wersja).
Uwaga na kolumnę PatientID: pliki z danymi zawierają kolumnę PatientID. To numer nadany przez system rejestracji, a nie wynik badania, więc nie wolno traktować go jako cechy (ang. feature). Zautomatyzowane uczenie maszynowe wykorzystuje wszystkie kolumny poza kolumną docelową - zostawienie identyfikatora dałoby modelowi wartość, którą może po prostu zapamiętać. Powstałby model wyglądający na dokładny przy znanych pacjentach i bezużyteczny przy nowych. Poniższy kod usuwa tę kolumnę.
# Pakiet mltable wraz z silnikiem odczytu danych. Wystarczy raz na instancję obliczeniową.
%pip install -q -U mltable "azureml-dataprep[pandas]"
import mltable
from azure.ai.ml.entities import Data
from azure.ai.ml.constants import AssetTypes
# Połącz oba pliki CSV w jedną tabelę
sciezki = [
{'file': './data/diabetes.csv'},
{'file': './data/diabetes2.csv'},
]
tbl = mltable.from_delimited_files(paths=sciezki)
# Usuń identyfikator pacjenta. To numer z rejestracji, a nie wynik badania - nie niesie
# żadnej informacji o cukrzycy, ale model potrafi go zapamiętać i wyglądać na dokładny
# na danych, które już widział.
tbl = tbl.drop_columns(['PatientID'])
tbl.save('./diabetes-mltable', colocated=True, overwrite=True)
# Zarejestruj tabelę jako zasób danych
data_asset = Data(
path='./diabetes-mltable',
type=AssetTypes.MLTABLE,
description='diabetes data',
name='diabetes_mltable',
)
ml_client.data.create_or_update(data_asset)
print('Zasób danych gotowy.')
Przygotowanie danych do zautomatyzowanego uczenia¶
Dla zautomatyzowanego uczenia maszynowego nie piszesz skryptu trenującego - wystarczy wskazać dane. Zadanie przyjmuje pojedynczy zasób danych typu MLTable i samo wydziela z niego część walidacyjną (albo stosuje walidację krzyżową, ang. cross-validation), więc nie musisz dzielić danych ręcznie. Użyjesz zasobu zarejestrowanego przed chwilą.
# Pobieramy zarejestrowany zasob danych treningowych
diabetes_data_asset = ml_client.data.get(name="diabetes_mltable", label="latest")
print("Dane gotowe!")
Przygotowanie zasobu obliczeniowego¶
Zadanie uruchomisz na klastrze aml-cluster, utworzonym we wcześniejszym ćwiczeniu (jeśli go nie ma, poniższy kod go utworzy). Klaster pozwala liczyć wiele prób równolegle - każda sprawdza inną kombinację algorytmu i przekształceń danych.
from azure.ai.ml.entities import AmlCompute
cluster_name = "aml-cluster"
try:
# Pobieramy klaster, jesli juz istnieje
training_cluster = ml_client.compute.get(cluster_name)
print('Znaleziono istniejacy klaster - uzywamy go.')
except Exception:
# Jesli nie istnieje - tworzymy go
compute_config = AmlCompute(
name=cluster_name,
type="amlcompute",
size="Standard_D2as_v4",
min_instances=0,
max_instances=4,
idle_time_before_scale_down=300,
)
training_cluster = ml_client.compute.begin_create_or_update(compute_config).result()
print(f"Zasob obliczeniowy '{training_cluster.name}' jest gotowy do uzycia.")
Konfiguracja zautomatyzowanego uczenia maszynowego¶
Teraz skonfigurujesz samo zadanie. Tworzy je funkcja automl.classification(), a metoda set_limits() określa, ile prób wykonać i jak długo mogą trwać.
Dlaczego limity są ważne: bez nich zadanie potrafi liczyć godzinami i zużyć budżet klastra.
max_trialsogranicza liczbę prób,timeout_minutescałe zadanie, atrial_timeout_minutespojedynczą próbę - dzięki temu jeden algorytm, który utknął, nie zablokuje pozostałych.
from azure.ai.ml import automl, Input
from azure.ai.ml.constants import AssetTypes
classification_job = automl.classification(
compute="aml-cluster",
experiment_name="diabetes-automl",
training_data=Input(type=AssetTypes.MLTABLE, path=diabetes_data_asset.id),
target_column_name="Diabetic",
primary_metric="AUC_weighted",
)
# Inżynieria cech: "auto" pozwala AutoML samodzielnie dobrać przekształcenia
classification_job.set_featurization(mode="auto")
# Wszystkie limity sa opcjonalne
classification_job.set_limits(
timeout_minutes=30,
trial_timeout_minutes=10,
max_trials=6,
max_concurrent_trials=4,
)
print("Gotowe do uruchomienia zadania AutoML.")
Uruchomienie zadania¶
Wszystko gotowe - uruchom zadanie.
Uwaga: potrwa to dłuższą chwilę. Najpierw trzeba przygotować klaster, co może wymagać zatrzymania węzłów pracujących jeszcze nad poprzednim zadaniem. Potem zadanie ruszy, a postęp będzie wyświetlany w miarę kończenia kolejnych prób. Stan zasobu obliczeniowego i zadania możesz też śledzić w Azure Machine Learning studio.
returned_job = ml_client.jobs.create_or_update(classification_job)
print(f"Wyslano zadanie: {returned_job.name}")
# Strumieniujemy dziennik zadania do notatnika w trakcie jego dzialania
ml_client.jobs.stream(returned_job.name)
Wskazanie najlepszego modelu¶
Po zakończeniu zadania możesz obejrzeć jego próby (zadania podrzędne, ang. child jobs) - z poziomu kodu albo w Azure Machine Learning studio, gdzie po otwarciu zadania znajdziesz je na kartach Models i Child jobs wraz z użytym algorytmem i uzyskanymi metrykami.
Porównaj próby, a następnie użyj MLflow, żeby wskazać tę, która dała najlepszy model.
# Porownujemy proby (zadania podrzedne) uruchomione przez AutoML
for child in ml_client.jobs.list(parent_job_name=returned_job.name):
print(f"{child.name}: {child.display_name} (stan: {child.status})")
Pobierz teraz najlepszą próbę i model, który z niej powstał.
import mlflow
from mlflow.tracking import MlflowClient
mlflow.set_tracking_uri(ml_client.workspaces.get(ml_client.workspace_name).mlflow_tracking_uri)
mlflow_client = MlflowClient()
# Zadanie nadrzedne AutoML zapisuje identyfikator najlepszej proby jako znacznik
mlflow_parent_run = mlflow_client.get_run(returned_job.name)
best_child_run_id = mlflow_parent_run.data.tags["automl_best_child_run_id"]
print(f"Identyfikator najlepszej proby: {best_child_run_id}")
best_run = mlflow_client.get_run(best_child_run_id)
best_run_metrics = best_run.data.metrics
print("Metryki najlepszej proby:")
for metric_name, value in best_run_metrics.items():
print(f"\t{metric_name}: {value}")
Zautomatyzowane uczenie maszynowe może samo dobierać wstępne przetwarzanie danych. Robi to za pomocą potoków przekształceń scikit-learn - nie mylić z potokami Azure Machine Learning. Powstały model zawiera więc nie tylko sam algorytm, ale i kroki przygotowania danych, wykonywane przed każdą predykcją.
Zobacz, co próba po sobie zostawiła - obok samego modelu także gotowy skrypt oceniający i definicję środowiska, w którym model da się uruchomić:
Gdzie zobaczyć nazwę algorytmu: w Azure Machine Learning studio otwórz zadanie AutoML i przejdź na kartę Models + child jobs. Kolumna Algorithm name pokazuje, co wybrała każda próba. SDK v2 nie udostępnia tej informacji: próby AutoML nie są dostępne przez
ml_client.jobs.get(), a MLflow nie zapisuje dla nich parametrów. Sam potok odtworzysz tylko w środowisku z pakietami uruchomieniowymi AutoML - dlatego modeli AutoML używa się przez wdrożenie, a nie przez wczytanie w notatniku.
import mlflow.artifacts
# Adres artefaktów bierzemy z przebiegu. Przez samo list_artifacts(run_id, ścieżka)
# MLflow 3 sięga po API, którego Azure ML nie udostępnia.
adres = mlflow_client.get_run(best_child_run_id).info.artifact_uri
print("Artefakty najlepszej próby:")
for artefakt in mlflow.artifacts.list_artifacts(artifact_uri=f"{adres}/outputs"):
print(f"\t{artefakt.path}")
Wśród tych plików jest featurization_summary.json - AutoML zapisuje w nim, co zrobił z każdą kolumną danych wejściowych. Pobierz go i obejrzyj:
import json
import pandas as pd
import mlflow.artifacts
sciezka = mlflow.artifacts.download_artifacts(
artifact_uri=f"{adres}/outputs/featurization_summary.json"
)
with open(sciezka, encoding="utf-8") as plik:
podsumowanie = pd.DataFrame(json.load(plik))
# Pomijamy TransformationParams - pełne parametry każdego przekształcenia
kolumny = ["RawFeatureName", "TypeDetected", "Dropped",
"EngineeredFeatureCount", "Transformations"]
print(podsumowanie[kolumny].to_string(index=False))
Zwróć uwagę na wykryte typy: kolumna
Pregnancieszawiera liczby, ale AutoML może uznać ją za kategoryczną - ma niewiele różnych wartości. Wtedy zamiast jednej cechy liczbowej powstaje kilkanaście cech zakodowanych tekstowo. Automat nie wie, że to liczba ciąż; widzi wyłącznie rozkład wartości. Warto sprawdzić, czy wykryte typy zgadzają się z tym, co wiesz o danych - bo od nich zależy, czego model się nauczy.
Na koniec zarejestruj model, który wypadł najlepiej.
from azure.ai.ml.entities import Model
from azure.ai.ml.constants import AssetTypes
# Rejestrujemy model z wyjscia MLflow najlepszej proby
model = Model(
path=f"azureml://jobs/{best_child_run_id}/outputs/artifacts/outputs/mlflow-model/",
name="diabetes_model_automl",
description="Best model from an automated ML job",
type=AssetTypes.MLFLOW_MODEL,
properties={
'AUC_weighted': best_run_metrics.get('AUC_weighted'),
'accuracy': best_run_metrics.get('accuracy'),
},
)
registered_model = ml_client.models.create_or_update(model)
# Wypisujemy zarejestrowane modele
for m in ml_client.models.list(name="diabetes_model_automl"):
print(m.name, 'wersja:', m.version)
Więcej informacji: o zautomatyzowanym uczeniu maszynowym przeczytasz w dokumentacji Azure ML.