Udostępnij przez


Samouczek: tworzenie, ocenianie i punktowanie modelu klasyfikacji tekstu

W tym samouczku przedstawiono pełny przykład przepływu pracy usługi Synapse Data Science dla modelu klasyfikacji tekstu w usłudze Microsoft Fabric. Scenariusz używa zarówno przetwarzania języka naturalnego Word2vec (NLP), jak i regresji logistycznej na platformie Spark w celu określenia gatunku książki z zestawu danych książki British Library. Determinacja opiera się wyłącznie na tytule książki.

W tym samouczku opisano następujące kroki:

  • Instalowanie bibliotek niestandardowych
  • Ładowanie danych
  • Omówienie i przetwarzanie danych za pomocą eksploracyjnej analizy danych
  • Szkolenie modelu uczenia maszynowego z użyciem zarówno modelu Word2vec w dziedzinie NLP, jak i regresji logistycznej, oraz śledzenie eksperymentów za pomocą biblioteki MLflow i funkcji automatycznego rejestrowania w Fabric.
  • Ładowanie modelu uczenia maszynowego na potrzeby oceniania i przewidywania

Warunki wstępne

Śledź notatki w notesie

Aby śledzić notatki w zeszycie, masz do wyboru następujące opcje:

  • Otwórz i uruchom wbudowany notes.
  • Prześlij swój notatnik z GitHub.

Otwieranie wbudowanego notesu

Przykładowy notes klasyfikacji gatunku Tytuł towarzyszy temu samouczkowi.

  1. Aby otworzyć przykładowy notes na potrzeby tego samouczka, postępuj zgodnie z instrukcjami w Przygotuj swój system do samouczków z zakresu nauki o danych.

  2. Przed rozpoczęciem uruchamiania kodu upewnij się, że dołączyć magazyn lakehouse do notesu.

Importowanie notesu z usługi GitHub

AIsample - Title Genre Classification.ipynb to jest notatnik, który towarzyszy temu samouczkowi.

Krok 1. Instalowanie bibliotek niestandardowych

W przypadku tworzenia modeli uczenia maszynowego lub analizy danych ad hoc może być konieczne szybkie zainstalowanie biblioteki niestandardowej na potrzeby sesji platformy Apache Spark. Dostępne są dwie opcje instalacji biblioteki.

  • Aby zainstalować bibliotekę tylko w bieżącym notesie, użyj funkcji wbudowanej instalacji (%pip lub %conda) w swoim notesie.
  • Alternatywnie możesz utworzyć środowisko Fabric i zainstalować biblioteki ze źródeł publicznych lub przesłać do niego biblioteki niestandardowe. Następnie administrator obszaru roboczego może dołączyć środowisko jako domyślne dla obszaru roboczego. W tym momencie wszystkie biblioteki w środowisku stają się dostępne do użycia we wszystkich notesach i we wszystkich definicjach zadań platformy Spark w tym obszarze roboczym. Aby uzyskać więcej informacji na temat środowisk, odwiedź stronę tworzenia, konfigurowania i używania środowiska w zasobie usługi Microsoft Fabric .

W przypadku modelu klasyfikacji użyj wordcloud biblioteki, aby reprezentować częstotliwość wyrazów w tekście. W wordcloud zasobach rozmiar słowa reprezentuje jego częstotliwość. Na potrzeby tego samouczka użyj %pip install, aby zainstalować wordcloud w notebooku.

Notatka

Jądro PySpark jest uruchamiane ponownie po uruchomieniu %pip install. Zainstaluj potrzebne biblioteki przed uruchomieniem innych komórek.

# Install wordcloud for text visualization by using pip
%pip install wordcloud

Krok 2. Ładowanie danych

Zestaw danych książek Biblioteki Brytyjskiej zawiera metadane dotyczące książek z tej biblioteki. Współpraca między biblioteką a firmą Microsoft zwirtualizowała oryginalne zasoby, które stały się zestawem danych. Metadane to informacje o klasyfikacji wskazujące, czy książka jest fikcją, czy nonfiction. Na poniższym diagramie przedstawiono przykładowy wiersz zestawu danych.

Identyfikator rekordu BL Typ zasobu Nazwa Daty skojarzone z nazwą Typ nazwy Rola Wszystkie nazwy Tytuł Tytuły wariantów Tytuł serii Numer w serii Kraj publikacji Miejsce publikacji Wydawca Data publikacji Wydanie Opis fizyczny Klasyfikacja Dewey Sygnatura BL Tematy Gatunek Języki Notatki Identyfikator rekordu BL dla zasobu fizycznego identyfikator_klasyfikacji identyfikator_użytkownika utworzono_o subject_ids data_publikacji_annotatora korektor_znormalizowana_data_publikacji oświadczenie_dotyczące_wersji_edycyjnej annotator_genre adnotator_FAST_terminy_gatunkowe annotator_FAST_subject_terms annotator_comments główny_język_annotatora podsumowania_adnotatora_inne_języki streszczenia_języka_annotatora tłumaczenie przez anotatora język_oryginalny_annotatora wydawca-adiustator annotator_place_pub kraj_adnotatora tytuł anotatora Link do książki cyfrowej Oznaczony
014602826 Monografia Yearsley, Ann 1753-1806 osoba More, Hannah, 1745-1833 [osoba]; Yearsley, Ann, 1753-1806 [osoba] Wiersze na różne okazje [Z listem wprowadzającym autorstwa Hannah More.] Anglia Londyn 1786 Notatka RĘKOPIS czwartej edycji Sklep cyfrowy 11644.d.32 Angielski 003996603 Fałszywy
014602830 Monografia A, T. osoba Oldham, John, 1653-1683 [person]; A, T. [person] Satyr przeciwko Vertue. (Wiersz: do wygłoszenia przez Town-Hector [Autor: John Oldham. Podpis wstępu: T. A.]) Anglia Londyn 1679 15 strony (4°) Sklep cyfrowy 11602.ee.10. (2.) Angielski 000001143 Fałszywy

W tym zestawie danych naszym celem jest trenowanie modelu klasyfikacji, który określa gatunek książki na podstawie tytułu książki.

Zdefiniuj następujące parametry, aby zastosować ten notes w różnych zestawach danych:

IS_CUSTOM_DATA = False  # If True, the user must manually upload the dataset
DATA_FOLDER = "Files/title-genre-classification"
DATA_FILE = "blbooksgenre.csv"

# Data schema
TEXT_COL = "Title"
LABEL_COL = "annotator_genre"
LABELS = ["Fiction", "Non-fiction"]

EXPERIMENT_NAME = "sample-aisample-textclassification"  # MLflow experiment name

Pobierz zestaw danych i prześlij do Lakehouse

Poniższy fragment kodu pobiera publicznie dostępną wersję zestawu danych, a następnie przechowuje ją w lakehous'ie platformy Fabric.

Ważny

Dodaj lakehouse do notesu przed jego uruchomieniem. Brak wykonania tej czynności powoduje wystąpienie błędu.

if not IS_CUSTOM_DATA:
    # Download demo data files into the lakehouse, if they don't exist
    import os, requests

    remote_url = "https://synapseaisolutionsa.z13.web.core.windows.net/data/Title_Genre_Classification"
    fname = "blbooksgenre.csv"
    download_path = f"/lakehouse/default/{DATA_FOLDER}/raw"

    if not os.path.exists("/lakehouse/default"):
        # Add a lakehouse, if no default lakehouse was added to the notebook
        # A new notebook won't link to any lakehouse by default
        raise FileNotFoundError(
            "Default lakehouse not found, please add a lakehouse and restart the session."
        )
    os.makedirs(download_path, exist_ok=True)
    if not os.path.exists(f"{download_path}/{fname}"):
        r = requests.get(f"{remote_url}/{fname}", timeout=30)
        with open(f"{download_path}/{fname}", "wb") as f:
            f.write(r.content)
    print("Downloaded demo data files into lakehouse.")

Importowanie wymaganych bibliotek

Przed rozpoczęciem przetwarzania należy zaimportować wymagane biblioteki, w tym biblioteki dla platform Spark i synapseML:

import numpy as np
from itertools import chain

from wordcloud import WordCloud
import matplotlib.pyplot as plt
import seaborn as sns

import pyspark.sql.functions as F

from pyspark.ml import Pipeline
from pyspark.ml.feature import *
from pyspark.ml.tuning import CrossValidator, ParamGridBuilder
from pyspark.ml.classification import LogisticRegression
from pyspark.ml.evaluation import (
    BinaryClassificationEvaluator,
    MulticlassClassificationEvaluator,
)

from synapse.ml.stages import ClassBalancer
from synapse.ml.train import ComputeModelStatistics

import mlflow

Definiowanie hiperparametrów

Poniższy fragment kodu definiuje niezbędne hiperparametry do trenowania modelu:

Ważny

Zmodyfikuj te hiperparametry tylko wtedy, gdy rozumiesz każdy parametr.

# Hyperparameters 
word2vec_size = 128  # The length of the vector for each word
min_word_count = 3  # The minimum number of times that a word must appear to be considered
max_iter = 10  # The maximum number of training iterations
k_folds = 3  # The number of folds for cross-validation

Rozpocznij rejestrowanie czasu potrzebnego do uruchomienia tego notesu:

# Record the notebook running time
import time

ts = time.time()

Konfigurowanie śledzenia eksperymentów MLflow

Automatyczne rejestrowanie rozszerza możliwości rejestrowania MLflow. Automatyczne rejestrowanie automatycznie przechwytuje wartości parametrów wejściowych i metryki wyjściowe modelu uczenia maszynowego podczas trenowania. Następnie rejestrujesz te informacje w obszarze roboczym. W obszarze roboczym możesz uzyskiwać dostęp do informacji i wizualizować je za pomocą interfejsów API platformy MLflow lub odpowiedniego eksperymentu w obszarze roboczym. Aby uzyskać więcej informacji na temat automatycznego rejestrowania, odwiedź zasób Automatyczne rejestrowanie w usłudze Microsoft Fabric .

Aby wyłączyć automatyczne rejestrowanie w Microsoft Fabric podczas sesji w notebooku, wywołaj mlflow.autolog() i ustaw disable=True:

# Set up Mlflow for experiment tracking

mlflow.set_experiment(EXPERIMENT_NAME)
mlflow.autolog(disable=True)  # Disable Mlflow autologging

Odczytywanie nieprzetworzonych danych daty z lakehouse

raw_df = spark.read.csv(f"{DATA_FOLDER}/raw/{DATA_FILE}", header=True, inferSchema=True)

Krok 3. Wykonywanie eksploracyjnej analizy danych

Zapoznaj się z zestawem danych za pomocą polecenia display, aby wyświetlić statystyki wysokiego poziomu dla zestawu danych i wyświetlić widoki wykresów:

display(raw_df.limit(20))

Przygotowywanie danych

Aby wyczyścić dane, usuń duplikaty:

df = (
    raw_df.select([TEXT_COL, LABEL_COL])
    .where(F.col(LABEL_COL).isin(LABELS))
    .dropDuplicates([TEXT_COL])
    .cache()
)

display(df.limit(20))

Zastosuj równoważenie klas, aby rozwiązać wszelką stronniczość:

# Create a ClassBalancer instance, and set the input column to LABEL_COL
cb = ClassBalancer().setInputCol(LABEL_COL)

# Fit the ClassBalancer instance to the input DataFrame, and transform the DataFrame
df = cb.fit(df).transform(df)

# Display the first 20 rows of the transformed DataFrame
display(df.limit(20))

Aby tokenizować zestaw danych, podziel akapity i zdania na mniejsze jednostki. Dzięki temu łatwiej jest przypisać znaczenie. Następnie usuń stopwords, aby poprawić wydajność. Usuwanie stopwordów polega na usunięciu słów, które często pojawiają się we wszystkich dokumentach w korpusie. Usuwanie stopwordu jest jednym z najczęściej używanych kroków przetwarzania wstępnego w aplikacjach przetwarzania języka naturalnego (NLP). Poniższy fragment kodu obejmuje następujące kroki:

# Text transformer
tokenizer = Tokenizer(inputCol=TEXT_COL, outputCol="tokens")
stopwords_remover = StopWordsRemover(inputCol="tokens", outputCol="filtered_tokens")

# Build the pipeline
pipeline = Pipeline(stages=[tokenizer, stopwords_remover])

token_df = pipeline.fit(df).transform(df)

display(token_df.limit(20))

Wyświetl bibliotekę wordcloud dla każdej klasy. Biblioteka wordcloud przedstawia słowa kluczowe, które są często wyświetlane w danych tekstowych, jest wizualnie wyróżniającą się prezentacją. Biblioteka wordcloud jest skuteczna, ponieważ renderowanie słów kluczowych tworzy obrazek w formie kolorowej chmury, aby łatwiej uchwycić główne dane tekstowe na pierwszy rzut oka. Odwiedź ten zasób , aby uzyskać więcej informacji na temat usługi Wordcloud.

Poniższy fragment kodu obejmuje następujące kroki:

# WordCloud
for label in LABELS:
    tokens = (
        token_df.where(F.col(LABEL_COL) == label)
        .select(F.explode("filtered_tokens").alias("token"))
        .where(F.col("token").rlike(r"^\w+$"))
    )

    top50_tokens = (
        tokens.groupBy("token").count().orderBy(F.desc("count")).limit(50).collect()
    )

    # Generate a wordcloud image
    wordcloud = WordCloud(
        scale=10,
        background_color="white",
        random_state=42,  # Make sure the output is always the same for the same input
    ).generate_from_frequencies(dict(top50_tokens))

    # Display the generated image by using matplotlib
    plt.figure(figsize=(10, 10))
    plt.title(label, fontsize=20)
    plt.axis("off")
    plt.imshow(wordcloud, interpolation="bilinear")

Na koniec użyj narzędzia Word2vec NLP, aby wektoryzować tekst. Technika NLP Word2vec tworzy wektorową reprezentację każdego wyrazu w tekście. Słowa używane w podobnych kontekstach lub które mają relacje semantyczne, są przechwytywane skutecznie przez ich bliskość w przestrzeni wektorowej. Ta bliskość wskazuje, że podobne wyrazy mają podobne wektory wyrazów. Poniższy fragment kodu obejmuje następujące kroki:

# Label transformer
label_indexer = StringIndexer(inputCol=LABEL_COL, outputCol="labelIdx")
vectorizer = Word2Vec(
    vectorSize=word2vec_size,
    minCount=min_word_count,
    inputCol="filtered_tokens",
    outputCol="features",
)

# Build the pipeline
pipeline = Pipeline(stages=[label_indexer, vectorizer])
vec_df = (
    pipeline.fit(token_df)
    .transform(token_df)
    .select([TEXT_COL, LABEL_COL, "features", "labelIdx", "weight"])
)

display(vec_df.limit(20))

Krok 4. Trenowanie i ocenianie modelu

Po określeniu danych zdefiniuj model. W tej sekcji wytrenujesz model regresji logistycznej, aby sklasyfikować wektoryzowany tekst.

Przygotowywanie zestawów danych trenowania i testowania

Poniższy fragment kodu dzieli zestaw danych:

# Split the dataset into training and testing
(train_df, test_df) = vec_df.randomSplit((0.8, 0.2), seed=42)

Śledzenie eksperymentów uczenia maszynowego

Śledzenie eksperymentów uczenia maszynowego zarządza wszystkimi eksperymentami i ich składnikami — na przykład parametrami, metrykami, modelami i innymi artefaktami. Śledzenie umożliwia organizację i zarządzanie wszystkimi składnikami, których wymaga określony eksperyment uczenia maszynowego. Umożliwia również łatwe odtworzenie poprzednich wyników z zapisanymi eksperymentami. Aby uzyskać więcej informacji, odwiedź stronę Eksperymenty uczenia maszynowego w usłudze Microsoft Fabric .

Eksperyment uczenia maszynowego to podstawowa jednostka organizacji i kontroli dla wszystkich powiązanych przebiegów uczenia maszynowego. Przebieg odpowiada pojedynczemu wykonaniu kodu modelu. Poniższy fragment kodu obejmuje następujące kroki:

# Build the logistic regression classifier
lr = (
    LogisticRegression()
    .setMaxIter(max_iter)
    .setFeaturesCol("features")
    .setLabelCol("labelIdx")
    .setWeightCol("weight")
)

Dopasowanie hiperparametrów

Utwórz siatkę parametrów do wyszukiwania za pośrednictwem hiperparametrów. Następnie zbuduj estymator krzyżowy, aby utworzyć CrossValidator model, jak pokazano w poniższym fragmencie kodu:

# Build a grid search to select the best values for the training parameters
param_grid = (
    ParamGridBuilder()
    .addGrid(lr.regParam, [0.03, 0.1])
    .addGrid(lr.elasticNetParam, [0.0, 0.1])
    .build()
)

if len(LABELS) > 2:
    evaluator_cls = MulticlassClassificationEvaluator
    evaluator_metrics = ["f1", "accuracy"]
else:
    evaluator_cls = BinaryClassificationEvaluator
    evaluator_metrics = ["areaUnderROC", "areaUnderPR"]
evaluator = evaluator_cls(labelCol="labelIdx", weightCol="weight")

# Build a cross-evaluator estimator
crossval = CrossValidator(
    estimator=lr,
    estimatorParamMaps=param_grid,
    evaluator=evaluator,
    numFolds=k_folds,
    collectSubModels=True,
)

Ocena modelu

Możemy ocenić modele w zestawie danych testowych, aby je porównać. Dobrze wytrenowany model powinien wykazywać się wysoką wydajnością zgodnie z odpowiednimi metrykami podczas przetwarzania na zestawach danych weryfikacji i testowania. Poniższy fragment kodu obejmuje następujące kroki:

def evaluate(model, df):
    log_metric = {}
    prediction = model.transform(df)
    for metric in evaluator_metrics:
        value = evaluator.evaluate(prediction, {evaluator.metricName: metric})
        log_metric[metric] = value
        print(f"{metric}: {value:.4f}")
    return prediction, log_metric

Śledzenie eksperymentów przy użyciu biblioteki MLflow

Rozpocznij proces trenowania i oceny. Użyj biblioteki MLflow, aby śledzić wszystkie eksperymenty i rejestrować parametry, metryki i modele. W obszarze roboczym wszystkie te informacje są rejestrowane pod nazwą eksperymentu. Poniższy fragment kodu obejmuje następujące kroki:

with mlflow.start_run(run_name="lr"):
    models = crossval.fit(train_df)
    best_metrics = {k: 0 for k in evaluator_metrics}
    best_index = 0
    for idx, model in enumerate(models.subModels[0]):
        with mlflow.start_run(nested=True, run_name=f"lr_{idx}") as run:
            print("\nEvaluating on test data:")
            print(f"subModel No. {idx + 1}")
            prediction, log_metric = evaluate(model, test_df)

            if log_metric[evaluator_metrics[0]] > best_metrics[evaluator_metrics[0]]:
                best_metrics = log_metric
                best_index = idx

            print("log model")
            mlflow.spark.log_model(
                model,
                f"{EXPERIMENT_NAME}-lrmodel",
                registered_model_name=f"{EXPERIMENT_NAME}-lrmodel",
                dfs_tmpdir="Files/spark",
            )

            print("log metrics")
            mlflow.log_metrics(log_metric)

            print("log parameters")
            mlflow.log_params(
                {
                    "word2vec_size": word2vec_size,
                    "min_word_count": min_word_count,
                    "max_iter": max_iter,
                    "k_folds": k_folds,
                    "DATA_FILE": DATA_FILE,
                }
            )

    # Log the best model and its relevant metrics and parameters to the parent run
    mlflow.spark.log_model(
        models.subModels[0][best_index],
        f"{EXPERIMENT_NAME}-lrmodel",
        registered_model_name=f"{EXPERIMENT_NAME}-lrmodel",
        dfs_tmpdir="Files/spark",
    )
    mlflow.log_metrics(best_metrics)
    mlflow.log_params(
        {
            "word2vec_size": word2vec_size,
            "min_word_count": min_word_count,
            "max_iter": max_iter,
            "k_folds": k_folds,
            "DATA_FILE": DATA_FILE,
        }
    )

Aby móc wyświetlić eksperymenty:

  1. Wybierz swój obszar roboczy w lewym okienku nawigacyjnym
  2. Znajdź i wybierz nazwę eksperymentu — w tym przypadku sample_aisample-textclassification

zrzut ekranu przedstawiający eksperyment.

Krok 5. Generowanie wyników przewidywania i zapisywanie ich

Usługa Microsoft Fabric umożliwia użytkownikom operacjonalizacja modeli uczenia maszynowego za pomocą skalowalnej PREDICT funkcji. Ta funkcja obsługuje ocenianie wsadowe (lub wnioskowanie wsadowe) w dowolnym silniku obliczeniowym. Możesz tworzyć przewidywania wsadowe bezpośrednio z notesu lub ze strony elementu dotyczącej konkretnego modelu. Aby uzyskać więcej informacji na temat PREDICT funkcji i sposobu jej używania w usłudze Fabric, odwiedź stronę Machine Learning model scoring with PREDICT in Microsoft Fabric (Ocenianie modelu uczenia maszynowego za pomocą funkcji PREDICT w usłudze Microsoft Fabric).

Na podstawie naszych wyników oceny, model 1 ma najwyższe wskaźniki zarówno dla Area Under the Precision-Recall Curve (AUPRC), jak i Area Under the Curve Receiver Operating Characteristic (AUC-ROC). W związku z tym należy użyć modelu 1 do przewidywania.

Miara AUC-ROC jest powszechnie używana do mierzenia wydajności klasyfikatorów binarnych. Jednak czasami bardziej odpowiednie jest obliczenie klasyfikatora na podstawie pomiarów AUPRC. Wykres AUC-ROC wizualizuje kompromis między prawdziwie dodatnim współczynnikiem (TPR) i współczynnikiem fałszywie dodatnim (FPR). Krzywa AUPRC łączy zarówno precyzję (dodatnią wartość predykcyjną, PPV), jak i czułość (współczynnik prawdziwie dodatni lub TPR) w jednej wizualizacji. Następujące fragmenty kodu obejmują następujące kroki:

# Load the best model
model_uri = f"models:/{EXPERIMENT_NAME}-lrmodel/1"
loaded_model = mlflow.spark.load_model(model_uri, dfs_tmpdir="Files/spark")

# Verify the loaded model
batch_predictions = loaded_model.transform(test_df)
batch_predictions.show(5)
# Code to save userRecs in the lakehouse
batch_predictions.write.format("delta").mode("overwrite").save(
    f"{DATA_FOLDER}/predictions/batch_predictions"
)
# Determine the entire runtime
print(f"Full run cost {int(time.time() - ts)} seconds.")