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.
- Jeśli nie masz lakehouse’a w usłudze Microsoft Fabric, utwórz go, wykonując kroki opisane w „Tworzenie lakehouse’a w usłudze Microsoft Fabric”.
Ś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.
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.
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.
Aby otworzyć towarzyszący notatnik do tego samouczka, postępuj zgodnie z instrukcjami w sekcji "Przygotowywanie systemu do nauki o danych" i, aby zaimportować notatnik do swojego obszaru roboczego.
Jeśli wolisz skopiować i wkleić kod z tej strony, możesz utworzyć nowy notes.
Przed rozpoczęciem uruchamiania kodu pamiętaj, aby dołączyć magazyn lakehouse do notesu.
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:
- Wybierz swój obszar roboczy w lewym okienku nawigacyjnym
- Znajdź i wybierz nazwę eksperymentu — w tym przypadku sample_aisample-textclassification
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.")