Udostępnij za pośrednictwem


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 word2vec i regresji logistycznej w Spark do określenia gatunku książki z zbioru danych książek British Library, wyłącznie na podstawie tytułu 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 przy użyciu Word2vec i regresji logistycznej oraz śledzenie eksperymentów za pomocą MLflow i funkcji automatycznego rejestrowania Fabric.
  • Ładowanie modelu uczenia maszynowego na potrzeby oceniania i przewidywania

Warunki wstępne

  • Pobierz subskrypcję usługi Microsoft Fabric . Możesz też utworzyć bezpłatne konto wersji próbnej usługi Microsoft Fabric.

  • Zaloguj się do usługi Microsoft Fabric.

  • Użyj przełącznika środowiska w lewej dolnej części strony głównej, aby przełączyć się na Fabric.

    Zrzut ekranu przedstawiający menu przełącznika środowiska, pokazujący, gdzie wybrać opcję Nauka o danych.

Śledź notatki w notesie

Możesz wybrać jedną z tych opcji, z którą będziesz podążać w notesie:

  • 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 instalowania bibliotek.

  • Użyj możliwości instalacji inline (%pip lub %conda) notebooka, aby zainstalować bibliotekę właśnie w tym bieżącym notebooku.
  • Alternatywnie możesz utworzyć środowisko Fabric, zainstalować biblioteki ze źródeł publicznych lub przesłać do niego biblioteki niestandardowe, a następnie administrator obszaru roboczego może ustawić to środowisko jako domyślne dla obszaru roboczego. Wszystkie biblioteki w środowisku staną się następnie dostępne do użycia w dowolnych notesach i definicjach zadań platformy Spark w obszarze roboczym. Aby uzyskać więcej informacji na temat środowisk, zobacz twórz, konfiguruj i używaj środowiska w usłudze Microsoft Fabric.

W przypadku modelu klasyfikacji użyj biblioteki wordcloud do reprezentowania częstotliwości słów w tekście, gdzie 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 wymagane biblioteki przed uruchomieniem innych komórek.

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

Krok 2. Ładowanie danych

Zestaw danych zawiera metadane dotyczące książek z Biblioteki Brytyjskiej, zdigitalizowanych w ramach współpracy między biblioteką a firmą Microsoft. Metadane to informacje o klasyfikacji wskazujące, czy książka jest fikcją, czy nonfiction. W przypadku tego zestawu danych celem jest trenowanie modelu klasyfikacji, który określa gatunek książki, tylko na podstawie jego tytułu.

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łsz

Zdefiniuj następujące parametry, aby można było 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

Ten kod pobiera publicznie dostępną wersję zestawu danych, a następnie przechowuje go w lakehouse Fabric.

Ważny

Dodaj lakehouse do notesu przed jego uruchomieniem. Niepowodzenie w tym celu spowoduje 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.blob.core.windows.net/public/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 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

Zdefiniuj niektóre hiperparametry na potrzeby 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 dowiedzieć się więcej na temat automatycznego rejestrowania, zobacz automatyczne rejestrowanie w usłudze Microsoft Fabric.

# Set up Mlflow for experiment tracking

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

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

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

Usuń duplikaty, aby wyczyścić dane:

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))

Podziel akapity i zdania na mniejsze jednostki, aby tokenizować zestaw danych. 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).

# 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 to wizualnie widoczna prezentacja słów kluczowych, które są często wyświetlane w danych tekstowych. Biblioteka wordcloud jest skuteczna, ponieważ renderowanie słów kluczowych tworzy obraz przypominający chmurę, co pozwala lepiej uchwycić główne dane tekstowe na pierwszy rzut oka. Dowiedz się więcej ochmurze wyrazów.

# 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 słowa2vec, aby wektoryzować tekst. Technika 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.

# 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

# 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

Eksperyment uczenia maszynowego to podstawowa jednostka organizacji i kontroli dla wszystkich powiązanych przebiegów uczenia maszynowego. Przebieg odpowiada pojedynczemu wykonaniu kodu modelu.

Ś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ę wszystkich wymaganych składników określonego eksperymentu uczenia maszynowego. Umożliwia również łatwe odtworzenie poprzednich wyników z zapisanymi eksperymentami. Dowiedz się więcej o eksperymentach uczenia maszynowego w usłudze Microsoft Fabric.

# 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 utwórz estymator międzyewaluacyjny, do stworzenia modelu CrossValidator:

# 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 osiągać wysoką wydajność na odpowiednich metrykach podczas testowania na zestawach danych walidacyjnych i testowych.

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 MLflow, aby śledzić wszystkie eksperymenty oraz logować parametry, metryki i modele. Wszystkie te informacje są rejestrowane pod nazwą eksperymentu w obszarze roboczym.

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

Microsoft Fabric umożliwia użytkownikom operacjonalizowanie modeli uczenia maszynowego przy użyciu skalowalnej funkcji PREDICT. Ta funkcja obsługuje ocenianie wsadowe (lub wnioskowanie wsadowe) w dowolnym silniku obliczeniowym. Przewidywania wsadowe można tworzyć bezpośrednio z notesu lub strony elementu dla określonego modelu. Aby dowiedzieć się więcej na temat funkcji PREDICT i sposobu jej używania w usłudze Fabric, zobacz Ocenianie modelu uczenia maszynowego za pomocą funkcji PREDICT w usłudze Microsoft Fabric.

Na podstawie powyższych wyników oceny, model 1 ma najwyższe wskaźniki dla obu miar: AUPRC (pole pod krzywą Precision-Recall) i obszar pod krzywą charakterystyki operacyjnej odbiornika (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 precyzję (dodatnią wartość predykcyjną lub PPV) i czułość (współczynnik prawdziwie dodatni lub TPR) w jednej wizualizacji.

# 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.")