Självstudie: Skapa, utvärdera och poängsätta en textklassificeringsmodell
I den här självstudien visas ett exempel från slutpunkt till slutpunkt på ett Synapse-Datavetenskap arbetsflöde för en textklassificeringsmodell i Microsoft Fabric. Scenariot använder word2vec och logistisk regression, på Spark, för att bestämma genren för en bok från british library-bokdatauppsättningen, enbart baserat på bokens titel.
Den här självstudien beskriver följande steg:
- Installera anpassade bibliotek
- Läsa in data
- Förstå och bearbeta data med undersökande dataanalys
- Träna en maskininlärningsmodell med word2vec och logistisk regression och spåra experiment med hjälp av MLflow och funktionen För automatisk loggning av infrastrukturresurser
- Läs in maskininlärningsmodellen för bedömning och förutsägelser
Förutsättningar
Skaffa en Microsoft Fabric-prenumeration. Eller registrera dig för en kostnadsfri utvärderingsversion av Microsoft Fabric.
Logga in på Microsoft Fabric.
Använd upplevelseväxlaren till vänster på startsidan för att växla till Synapse Datavetenskap upplevelse.
- Om du inte har ett Microsoft Fabric-sjöhus skapar du ett genom att följa stegen i Skapa ett sjöhus i Microsoft Fabric.
Följ med i en notebook-fil
Du kan välja något av följande alternativ för att följa med i en notebook-fil:
- Öppna och kör den inbyggda notebook-filen i Synapse Datavetenskap-upplevelsen
- Ladda upp din notebook-fil från GitHub till Synapse Datavetenskap-upplevelsen
Öppna den inbyggda notebook-filen
Exempelanteckningsboken För rubrikgenrklassificering medföljer den här självstudien.
Så här öppnar du självstudiekursens inbyggda exempelanteckningsbok i Synapse Datavetenskap upplevelse:
Gå till startsidan för Synapse Datavetenskap.
Välj Använd ett exempel.
Välj motsvarande exempel:
- Från standardfliken för arbetsflöden från slutpunkt till slutpunkt (Python) om exemplet är för en Python-självstudie.
- Från fliken Arbetsflöden från slutpunkt till slutpunkt (R) om exemplet är för en R-självstudie.
- Om exemplet är för en snabb självstudie på fliken Snabbsjälvstudier.
Koppla ett lakehouse till notebook-filen innan du börjar köra kod.
Importera anteckningsboken från GitHub
AIsample – Title Genre Classification.ipynb är anteckningsboken som medföljer den här självstudien.
Om du vill öppna den medföljande notebook-filen för den här självstudien följer du anvisningarna i Förbereda systemet för självstudier för datavetenskap för att importera anteckningsboken till din arbetsyta.
Om du hellre vill kopiera och klistra in koden från den här sidan kan du skapa en ny notebook-fil.
Se till att bifoga ett lakehouse i notebook-filen innan du börjar köra kod.
Steg 1: Installera anpassade bibliotek
För utveckling av maskininlärningsmodeller eller ad hoc-dataanalys kan du snabbt behöva installera ett anpassat bibliotek för Apache Spark-sessionen. Du har två alternativ för att installera bibliotek.
- Använd de infogade installationsfunktionerna (
%pip
eller%conda
) i notebook-filen för att installera ett bibliotek, endast i den aktuella notebook-filen. - Du kan också skapa en Infrastrukturmiljö, installera bibliotek från offentliga källor eller ladda upp anpassade bibliotek till den och sedan kan din arbetsyteadministratör koppla miljön som standard för arbetsytan. Alla bibliotek i miljön blir sedan tillgängliga för användning i alla notebook-filer och Spark-jobbdefinitioner på arbetsytan. Mer information om miljöer finns i skapa, konfigurera och använda en miljö i Microsoft Fabric.
För klassificeringsmodellen använder du wordcloud
biblioteket för att representera ordfrekvensen i text, där storleken på ett ord representerar dess frekvens. I den här självstudien använder du %pip install
för att installera wordcloud
i notebook-filen.
Kommentar
PySpark-kerneln startas om efter %pip install
körningar. Installera de bibliotek som behövs innan du kör andra celler.
# Install wordcloud for text visualization by using pip
%pip install wordcloud
Steg 2: Läs in data
Datamängden har metadata om böcker från British Library som ett samarbete mellan biblioteket och Microsoft digitaliserade. Metadata är klassificeringsinformation för att ange om en bok är fiktion eller nonfiction. Med den här datamängden är målet att träna en klassificeringsmodell som avgör genren för en bok, endast baserat på dess titel.
BL-post-ID | Typ av resurser | Name | Datum som är associerade med namn | Typ av namn | Role | Alla namn | Title | Variantrubriker | Serierubrik | Tal inom serien | Publikationsland | Publikationens plats | Publisher | Publiceringsdatum | Edition | Fysisk beskrivning | Dewey-klassificering | BL-hylla | Ämnen | Genre | Språk | Kommentar | BL-post-ID för fysisk resurs | 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 | Länk till digitaliserad bok | Kommenterad |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
014602826 | Monografi | Yearsley, Ann | 1753-1806 | person | Mer, Hannah, 1745-1833 [person]; Yearsley Ann, 1753-1806 [person] | Dikter vid flera tillfällen [Med ett prefatory brev av Hannah More.] | England | London | 1786 | Anteckning om FJÄRDE utgåvan AV MANUSKRIPT | Digital Store 11644.d.32 | Engelska | 003996603 | Falsk | |||||||||||||||||||||||||||||||
014602830 | Monografi | A, T. | person | Oldham John, 1653-1683 [person]; A, T. [person] | En Satyr mot Vertue. (En dikt: tänkt att talas av en Town-Hector [Av John Oldham. Förordet signerat: T. A.]) | England | London | 1679 | 15 sidor (4°) | Digital Store 11602.ee.10. (2.) | Engelska | 000001143 | Falsk |
Definiera följande parametrar så att du kan använda den här notebook-filen på olika datauppsättningar:
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
Ladda ned datauppsättningen och ladda upp till lakehouse
Den här koden laddar ned en offentligt tillgänglig version av datamängden och lagrar den sedan i en Infrastruktursjöhus.
Viktigt!
Lägg till ett lakehouse i anteckningsboken innan du kör det. Om du inte gör det uppstår ett fel.
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.")
Importera obligatoriska bibliotek
Innan bearbetningen måste du importera nödvändiga bibliotek, inklusive biblioteken för Spark och 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
Definiera hyperparametrar
Definiera några hyperparametrar för modellträning.
Viktigt!
Ändra endast dessa hyperparametrar om du förstår varje parameter.
# 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
Börja spela in den tid som krävs för att köra den här notebook-filen:
# Record the notebook running time
import time
ts = time.time()
Konfigurera MLflow-experimentspårning
Automatisk loggning utökar MLflow-loggningsfunktionerna. Automatisk loggning fångar automatiskt indataparametervärdena och utdatamåtten för en maskininlärningsmodell när du tränar den. Sedan loggar du den här informationen till arbetsytan. På arbetsytan kan du komma åt och visualisera informationen med MLflow-API:erna eller motsvarande experiment på arbetsytan. Mer information om automatisk loggning finns i Autologgning i Microsoft Fabric.
# Set up Mlflow for experiment tracking
mlflow.set_experiment(EXPERIMENT_NAME)
mlflow.autolog(disable=True) # Disable Mlflow autologging
Om du vill inaktivera automatisk loggning av Microsoft Fabric i en notebook-session anropar mlflow.autolog()
du och anger disable=True
:
Läsa rådata från lakehouse
raw_df = spark.read.csv(f"{DATA_FOLDER}/raw/{DATA_FILE}", header=True, inferSchema=True)
Steg 3: Utföra undersökande dataanalys
Utforska datauppsättningen display
med kommandot för att visa statistik på hög nivå för datamängden och för att visa diagramvyerna:
display(raw_df.limit(20))
Förbereda data
Ta bort dubbletter för att rensa data:
df = (
raw_df.select([TEXT_COL, LABEL_COL])
.where(F.col(LABEL_COL).isin(LABELS))
.dropDuplicates([TEXT_COL])
.cache()
)
display(df.limit(20))
Använd klassutjämning för att hantera eventuella fördomar:
# 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))
Dela upp styckena och meningarna i mindre enheter för att tokenisera datauppsättningen. På så sätt blir det lättare att tilldela mening. Ta sedan bort stopporden för att förbättra prestandan. Stoppordsborttagning innebär borttagning av ord som ofta förekommer i alla dokument i corpus. Stoppordsborttagning är ett av de vanligaste förbearbetningsstegen i NLP-program (natural language processing).
# 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))
Visa wordcloud-biblioteket för varje klass. Ett wordcloud-bibliotek är en visuellt framträdande presentation av nyckelord som ofta visas i textdata. Wordcloud-biblioteket är effektivt eftersom renderingen av nyckelord utgör en molnliknande färgbild, för att bättre samla in huvudtextdata snabbt. Läs mer om 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 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")
Använd slutligen word2vec för att vektorisera texten. Tekniken word2vec skapar en vektorrepresentation av varje ord i texten. Ord som används i liknande kontexter, eller som har semantiska relationer, fångas effektivt genom sin närhet i vektorutrymmet. Den här närheten anger att liknande ord har liknande ordvektorer.
# 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))
Steg 4: Träna och utvärdera modellen
Definiera modellen med data på plats. I det här avsnittet tränar du en logistisk regressionsmodell för att klassificera den vektoriserade texten.
Förbereda tränings- och testdatauppsättningar
# Split the dataset into training and testing
(train_df, test_df) = vec_df.randomSplit((0.8, 0.2), seed=42)
Spåra maskininlärningsexperiment
Ett maskininlärningsexperiment är den primära enheten för organisation och kontroll för alla relaterade maskininlärningskörningar. En körning motsvarar en enda körning av modellkod.
Spårning av maskininlärningsexperiment hanterar alla experiment och deras komponenter, till exempel parametrar, mått, modeller och andra artefakter. Spårning möjliggör organisation av alla nödvändiga komponenter i ett specifikt maskininlärningsexperiment. Det möjliggör också enkel reproduktion av tidigare resultat med sparade experiment. Läs mer om maskininlärningsexperiment i Microsoft Fabric.
# Build the logistic regression classifier
lr = (
LogisticRegression()
.setMaxIter(max_iter)
.setFeaturesCol("features")
.setLabelCol("labelIdx")
.setWeightCol("weight")
)
Justering av hyperparametrar
Skapa ett rutnät med parametrar för att söka över hyperparametrar. Skapa sedan en korsutvärderingsberäknare för att skapa en CrossValidator
modell:
# 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,
)
Utvärdera modellen
Vi kan utvärdera modellerna på testdatauppsättningen för att jämföra dem. En vältränad modell bör visa höga prestanda, på relevanta mått, när den körs mot validerings- och testdatauppsättningarna.
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
Spåra experiment med hjälp av MLflow
Starta tränings- och utvärderingsprocessen. Använd MLflow för att spåra alla experiment och loggparametrar, mått och modeller. All den här informationen loggas under experimentnamnet på arbetsytan.
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,
}
)
Så här visar du dina experiment:
- Välj din arbetsyta i det vänstra navigeringsfältet
- Leta upp och välj experimentnamnet – i det här fallet sample_aisample textklassificering
Steg 5: Poängsätta och spara förutsägelseresultat
Med Microsoft Fabric kan användare operationalisera maskininlärningsmodeller med den PREDICT
skalbara funktionen. Den här funktionen stöder batchbedömning (eller batch-slutsatsdragning) i en beräkningsmotor. Du kan skapa batchförutsägelser direkt från en notebook-fil eller objektsidan för en viss modell. Mer information om PREDICT och hur du använder det i Infrastruktur finns i Bedömning av maskininlärningsmodeller med PREDICT i Microsoft Fabric.
Från föregående utvärderingsresultat har modell 1 de största måtten för både Area Under precisionsåterkallningskurvan (AUPRC) och för Area Under Curve Receiver Operating Characteristic (AUC-ROC). Därför bör du använda modell 1 för förutsägelse.
Måttet AUC-ROC används ofta för att mäta prestanda för binära klassificerare. Ibland blir det dock mer lämpligt att utvärdera klassificeraren baserat på AUPRC-mätningar. AUC-ROC-diagrammet visualiserar kompromissen mellan sann positiv ränta (TPR) och falsk positiv ränta (FPR). AUPRC-kurvan kombinerar precision (positivt prediktivt värde eller PPV) och träffsäkerhet (sann positiv hastighet eller TPR) i en enda visualisering.
# 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.")