Samouczek: tworzenie, ocenianie i ocenianie modelu klasyfikacji tekstu

W tym samouczku zobaczysz pełny przepływ pracy nauki o danych dla modelu klasyfikacji tekstu przy użyciu usługi Microsoft Fabric. Scenariusz polega na użyciu słów2vec i regresji logistycznej na platformie Spark w celu określenia gatunku książki z zestawu danych książki British Library wyłącznie na podstawie tytułu książki.

Ważne

Usługa Microsoft Fabric jest dostępna w wersji zapoznawczej.

Główne kroki w tym notesie to:

  • Instalowanie bibliotek niestandardowych
  • Ładowanie danych
  • Omówienie i przetwarzanie danych przy użyciu eksploracyjnej analizy danych
  • Trenowanie modelu uczenia maszynowego przy użyciu regresji logistycznej i śledzenia eksperymentów przy użyciu word2vec funkcji automatycznego rejestrowania MLflow i sieci szkieletowej
  • Ładowanie modelu uczenia maszynowego do oceniania i przewidywania

Wymagania wstępne

  • Uzyskaj subskrypcję usługi Microsoft Fabric. Możesz też utworzyć bezpłatną wersję próbną usługi Microsoft Fabric (wersja zapoznawcza).

  • Zaloguj się do usługi Microsoft Fabric.

  • Przejdź do środowiska Nauka o danych przy użyciu ikony przełącznika środowiska po lewej stronie głównej.

    Screenshot of the experience switcher menu, showing where to select Data Science.

Postępuj zgodnie z instrukcjami w notesie

AIsample — tytuł Klasyfikacja gatunku.ipynb to notes, który towarzyszy temu samouczkowi.

Jeśli chcesz otworzyć dołączony notes na potrzeby tego samouczka, postępuj zgodnie z instrukcjami w temacie Przygotowywanie systemu do nauki o danych, aby zaimportować notesy samouczka do obszaru roboczego.

Jeśli jednak chcesz skopiować i wkleić kod z tej strony, możesz utworzyć nowy notes.

Przed rozpoczęciem uruchamiania kodu pamiętaj, aby dołączyć usługę Lakehouse do notesu .

Krok 1. Instalowanie bibliotek niestandardowych

Podczas tworzenia modelu uczenia maszynowego lub analizy danych ad hoc może być konieczne szybkie zainstalowanie biblioteki niestandardowej na potrzeby sesji platformy Apache Spark. W tym celu użyj narzędzia %pip install lub %conda install. Możesz też zainstalować wymagane biblioteki w obszarze roboczym, przechodząc do ustawienia obszaru roboczego, aby znaleźć zarządzanie biblioteką.

W przypadku modelu klasyfikacji użyjesz wordcloud biblioteki do reprezentowania częstotliwości wyrazów w tekście, w którym rozmiar słowa reprezentuje jego częstotliwość. W tym miejscu zainstalujesz program wordcloud%pip.

Uwaga

Jądro PySpark rozpocznie się po .%pip install Przed uruchomieniem innych komórek zainstaluj biblioteki.

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

Krok 2. Ładowanie danych

Dataset

Zestaw danych pochodzi z zestawu danych książki British Library i składa się z metadanych dotyczących książek, które zostały zdigitalizowane dzięki współpracy między Biblioteką Brytyjską a firmą Microsoft. Zestaw danych składa się z klasyfikacji utworzonych przez ludzi, aby wskazać, czy książka jest "fikcją", czy "nonfiction". W tym zestawie danych celem jest trenowanie modelu klasyfikacji, który określa gatunek książki wyłącznie na podstawie jego tytułu.

Identyfikator rekordu obiektu bl Typ zasobu Nazwisko Daty skojarzone z nazwą Typ nazwy Rola Wszystkie nazwy Tytuł Tytuły wariantów Tytuł serii Liczba w serii Kraj publikacji Miejsce publikacji Wydawca Data publikacji Wersja Opis fizyczny Klasyfikacja Dewey Półka bl Tematy Gatunek Języki Uwagi Identyfikator rekordu obiektu bl dla zasobu fizycznego classification_id User_id created_at subject_ids annotator_date_pub annotator_normalised_date_pub annotator_edition_statement annotator_genre annotator_FAST_genre_terms annotator_FAST_subject_terms annotator_comments annotator_main_language annotator_other_languages_summaries annotator_summaries_language annotator_translation annotator_original_language annotator_publisher annotator_place_pub annotator_country annotator_title Link do książki cyfrowej Adnotacjami
014602826 Monografii Yearsley, Ann 1753-1806 osoba Więcej, Hannah, 1745-1833 [osoba]; Yearsley, Ann, 1753-1806 [person] Wiersze kilka razy [Z prefatoryjnym listem Hannah More.] Anglii Londyn 1786 Notatka RĘKOPIS czwartej edycji Sklep cyfrowy 11644.d.32 angielski 003996603 Fałsz
014602830 Monografii A, T. osoba Oldham, John, 1653-1683 [person]; A, T. [person] Satyr przeciwko Vertue. (Wiersz: powinien być mówiony przez Town-Hector [Przez John Oldham. Podpis wstępu: T. A.]) Anglii Londyn 1679 15 stron (4°) Sklep cyfrowy 11602.ee.10. (2.) angielski 000001143 Fałsz

Napiwek

Definiując następujące parametry, można łatwo zastosować ten notes w różnych zestawach danych.

IS_CUSTOM_DATA = False  # if True, dataset has to be uploaded manually by user
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

Pobieranie zestawu danych i przekazywanie do usługi Lakehouse

Poniższy kod pobiera publicznie dostępną wersję zestawu danych, a następnie przechowuje go w lakehouse usługi Fabric.

Ważne

Przed uruchomieniem tego notesu upewnij się, że dodasz magazyn lakehouse . Niepowodzenie w tym celu spowoduje wystąpienie błędu.

if not IS_CUSTOM_DATA:
    # Download demo data files into lakehouse if it does not 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 has been added to the notebook
        # A new notebook will not 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 te 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

Zdefiniuj niektóre hiperparametry na potrzeby trenowania modelu.

Ważne

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

# Hyper-parameters 
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 nagrywanie czasu potrzebny na uruchomienie tego notesu.

# Record the notebook running time
import time

ts = time.time()

Konfigurowanie śledzenia eksperymentów MLflow

Rozszerzanie możliwości automatycznego rejestrowania MLflow działa przez automatyczne przechwytywanie wartości parametrów wejściowych i metryk wyjściowych modelu uczenia maszynowego podczas trenowania. Te informacje są następnie rejestrowane w obszarze roboczym, gdzie można uzyskać do niego dostęp i wizualizować przy użyciu 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

Jeśli chcesz wyłączyć automatyczne rejestrowanie usługi Microsoft Fabric w sesji notesu, wywołaj mlflow.autolog() i ustaw polecenie 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. Eksploracyjna analiza danych

Zapoznaj się z zestawem display danych przy użyciu polecenia , aby wyświetlić ogólne statystyki zestawu danych i wyświetlić widoki wykresów.

display(raw_df.limit(20))

Przygotowywanie danych

Przygotowywanie danych obejmuje następujące kroki:

  • Czyszczenie zestawu danych
  • Radzenie sobie z dysproporcją zestawu danych
  • Tokenizowanie zestawu danych
  • Wyświetlanie chmury słów
  • Wektoryzacja zestawu danych

Rozpocznij czyszczenie danych, usuwając duplikaty.

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

display(df.limit(20))

Następnie zastosuj równoważenie klas w celu rozwiązania wszelkich stronniczość.

# Create an instance of ClassBalancer 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))

Tokenizowanie przez podzielenie akapitów i zdań na mniejsze jednostki, które mogą być łatwiejsze do przypisania znaczenia. Następnie usuń stopwords, aby poprawić wydajność. Usuwanie stopwordu jest jednym z najczęściej używanych kroków przetwarzania wstępnego w aplikacjach przetwarzania języka naturalnego (NLP), gdzie chodzi o usunięcie wyrazów, które występują często we wszystkich dokumentach w korpusie.

# 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 chmurę słów dla każdej klasy.

Chmura słów to wizualnie widoczna prezentacja "słów kluczowych", które są często wyświetlane w danych tekstowych. Chmura słów jest skuteczna, ponieważ renderowanie słów kluczowych tworzy obraz koloru przypominającego chmurę, aby lepiej przechwytywać główne dane tekstowe na pierwszy rzut oka. Dowiedz się więcej o usłudze wordcloud.

# 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 word cloud 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 using matplotlib
    plt.figure(figsize=(10, 10))
    plt.title(label, fontsize=20)
    plt.axis("off")
    plt.imshow(wordcloud, interpolation="bilinear")

Na koniec użyj polecenia word2vec , aby wektoryzować tekst. word2vec Tworzy reprezentację każdego wyrazu obecnego w tekście w wektorze. Wyrazy używane w podobnych kontekstach lub relacje semantyczne są przechwytywane skutecznie przez ich bliskość w przestrzeni wektorowej, co oznacza, ż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 ewaluacja modelu

Teraz zdefiniuj model za pomocą Twoich danych. W tej sekcji wytrenuj model regresji logistycznej, aby sklasyfikować wektoryzowany tekst.

Przygotowywanie zestawów danych trenowania i testowania

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

Trenowanie modeli i eksperymenty 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 odnosi się do procesu zarządzania wszystkimi różnymi eksperymentami i ich składnikami, takimi jak parametry, metryki, modele i inne artefakty. Śledzenie umożliwia organizowanie wszystkich wymaganych składników określonego eksperymentu uczenia maszynowego i łatwe odtworzenie poprzednich wyników przy użyciu zapisanych eksperymentów. 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")
)

Trenowanie modelu i dostrajanie hiperparametryczne

Skonstruuj siatkę parametrów do przeszukiwania hiperparametrów i narzędzia do szacowania krzyżowego w celu utworzenia modelu CrossValidatorModel.

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

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

Ocena modelu

Teraz masz różne modele do porównania, oceniając je na testowym zestawie danych. Jeśli model został dobrze wytrenowany, powinien zademonstrować wysoką wydajność odpowiednich metryk dotyczących zestawów danych sprawdzania poprawności i testowania.

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 za pomocą biblioteki MLflow

Rozpocznij szkolenie i ocenę i użyj biblioteki MLflow, aby śledzić wszystkie eksperymenty i parametry dziennika, 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 testing 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 wyświetlić eksperymenty:

  1. Po lewej stronie wybierz swój obszar roboczy.
  2. Znajdź i wybierz nazwę eksperymentu, w tym przypadku sample_aisample-textclassification.

Screenshot of an experiment.

Krok 5. Generowanie wyników przewidywania i zapisywanie ich

Usługa Microsoft Fabric oferuje skalowalną funkcję o nazwie PREDICT, która obsługuje ocenianie wsadowe w dowolnym aucie obliczeniowym i umożliwia klientom operacjonalizacja modeli uczenia maszynowego. Przewidywania wsadowe można tworzyć bezpośrednio z notesu lub strony elementu dla określonego modelu. Dowiedz się więcej na temat funkcji PREDICT i sposobu jej używania w usłudze Microsoft Fabric.

Z powyższych wyników oceny model 1 ma największe metryki Area Under the Precision-Recall Curve (AUPRC) 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 stosowana do oceny wydajności klasyfikatorów binarnych. Jednak czasami bardziej odpowiednie jest obliczenie klasyfikatora na podstawie pomiaru AUPRC. AUC-ROC to wykres, który wizualizuje kompromis między prawdziwie dodatnim współczynnikiem (TPR) i współczynnikiem fałszywie dodatnim (FPR). AUPRC to krzywa łącząca precyzję (dodatnią wartość predykcyjną lub PPV) i kompletność (prawdziwie dodatnie współczynniki 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 the userRecs into 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.")

Następne kroki