Tutorial: Criar, avaliar e pontuar um modelo de classificação de texto
Este tutorial apresenta um exemplo de ponta a ponta de um fluxo de trabalho de Ciência de Dados do Synapse para um modelo de classificação de texto, no Microsoft Fabric. O cenário usa word2vec e regressão logística, no Spark, para determinar o gênero de um livro do conjunto de dados de livros da Biblioteca Britânica, baseado apenas no título do livro.
Este tutorial aborda estas etapas:
- Instalar bibliotecas personalizadas
- Carregar os dados
- Entender e processar os dados com a análise de dados exploratória
- Treinar um modelo de machine learning com o word2vec e a regressão logística e acompanhar experimentos com o MLflow e o recurso de registro automático do Fabric
- Carregar o modelo de machine learning para pontuação e previsões
Pré-requisitos
Obtenha uma assinatura do Microsoft Fabric. Ou cadastre-se para uma avaliação gratuita do Microsoft Fabric.
Entre no Microsoft Fabric.
Use o alternador de experiência na parte inferior esquerda da sua página inicial para alternar para o Fabric.
- Se você não tiver um Lakehouse do Microsoft Fabric, crie um seguindo as etapas em Criar um Lakehouse no Microsoft Fabric.
Acompanhar em um notebook
Você pode escolher uma destas opções para acompanhar em um caderno:
- Abra e execute o notebook embutido.
- Carregue seu bloco de anotações no GitHub.
Abrir o bloco de anotações interno
O notebook de exemplo Classificação de gênero do título acompanha este tutorial.
Para abrir o bloco de anotações de exemplo para este tutorial, siga as instruções em Preparar seu sistema para tutoriais de ciência de dados.
Certifique-se de anexar um lakehouse ao notebook antes de começar a executar o código.
Importar o notebook do GitHub
AIsample - Title Genre Classification.ipynb é o notebook que acompanha esse tutorial.
Para abrir o notebook que acompanha este tutorial, siga as instruções em Preparar seu sistema para tutoriais de ciência de dados para importar o notebook para o seu ambiente de trabalho.
Se você prefere copiar e colar o código desta página, pode criar um notebook.
Certifique-se de anexar um lakehouse ao notebook antes de começar a executar o código.
Etapa 1: Instalar bibliotecas personalizadas
Para desenvolvimento de modelo de machine learning ou análise de dados ad hoc, talvez seja necessário instalar rapidamente uma biblioteca personalizada para sua sessão do Apache Spark. Você tem duas opções para instalar bibliotecas.
- Use os recursos de instalação embutida (
%pip
ou%conda
) do seu notebook para instalar uma biblioteca, somente no notebook atual. - Como alternativa, você pode criar um ambiente do Fabric, instalar bibliotecas de fontes públicas ou carregar bibliotecas personalizadas nele e, em seguida, o administrador do workspace pode anexar o ambiente como o padrão para o workspace. Todas as bibliotecas no ambiente ficarão disponíveis para uso em quaisquer notebooks e definições de trabalho do Spark no workspace. Para obter mais informações sobre ambientes, consulte criar, configurar e usar um ambiente no Microsoft Fabric.
Para o modelo de classificação, use a biblioteca de wordcloud
para representar a frequência da palavra no texto, em que o tamanho de uma palavra representa sua frequência. Para este tutorial, use %pip install
para instalar wordcloud
em seu notebook.
Nota
O kernel do PySpark é reiniciado após a execução do %pip install
. Instale as bibliotecas necessárias antes de executar outras células.
# Install wordcloud for text visualization by using pip
%pip install wordcloud
Etapa 2: Carregar os dados
O conjunto de dados tem metadados sobre livros da Biblioteca Britânica que uma colaboração entre a biblioteca e a Microsoft digitalizou. Os metadados são informações de classificação para indicar se um livro é ficção ou não-ficção. Com esse conjunto de dados, a meta é treinar um modelo de classificação que determine o gênero de um livro, somente com base em seu título.
ID de registro da BL | Tipo de recurso | Nome | Datas associadas ao nome | Tipo de nome | Função | Todos os nomes | Título | Títulos variantes | Título da série | Número dentro da série | País da publicação | Local da publicação | Editor | Data da publicação | Edição | Descrição física | Classificação de dewey | Símbolos de livro da BL | Tópicos | Gênero | Idiomas | Anotações | ID do registro da BL para recurso físico | classification_id | id_do_usuário | created_at | subject_ids | annotator_date_pub | annotator_normalised_date_pub | annotator_edition_statement | annotator_genre | annotator_FAST_genre_terms | annotator_FAST_subject_terms | comentários_do_annotador | annotator_main_language | annotator_other_languages_summaries | annotator_summaries_language | annotator_translation | annotator_original_language | annotator_publisher | annotator_place_pub | annotator_country | título do anotador | Link para o livro digitalizado | annotated |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
014602826 | Monografia | Yearsley, Ann | 1753-1806 | pessoa | More, Hannah, 1745-1833 [pessoa]; Yearsley, Ann, 1753-1806 [pessoa] | Poemas em ocasiões diversas [Com uma carta prefatória de Hannah More.] | Inglaterra | Londres | 1786 | Nota de manuscrito da quarta edição | Digital Store 11644.d.32 | Inglês | 003996603 | Falso | |||||||||||||||||||||||||||||||
014602830 | Monografia | A, T. | pessoa | Oldham, John, 1653-1683 [pessoa]; A, T. [pessoa] | A Satyr against Vertue. (Um poema: suposto ser falado por um Town-Hector [Por John Oldham. Prefácio assinado: T. A.]) | Inglaterra | Londres | 1679 | 15 páginas (4°) | Digital Store 11602.ee.10. (2.) | Inglês | 000001143 | Falso |
Defina os seguintes parâmetros para que você possa aplicar este notebook em conjuntos de dados diferentes:
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
Baixar o conjunto de dados e carregar no lakehouse
Esse código baixa uma versão disponível publicamente do conjunto de dados e, em seguida, armazena-a em um lakehouse do Fabric.
Importante
Adicione um lakehouse ao notebook antes de executá-lo. A falha ao fazer isso resultará em um erro.
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.")
Importar bibliotecas necessárias
Antes de qualquer processamento, você precisa importar bibliotecas necessárias, incluindo as bibliotecas para Spark e 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
Definir hiperparâmetros
Defina alguns hiperparâmetros para treinamento de modelo.
Importante
Modifique esses hiperparâmetros somente se você entender cada parâmetro.
# 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
Inicie o registro do tempo necessário para executar este notebook.
# Record the notebook running time
import time
ts = time.time()
Configurar o acompanhamento de experimentos do MLflow
O registro automático estende os recursos de log do MLflow. O registro automático captura automaticamente os valores de parâmetro de entrada e as métricas de saída de um modelo de machine learning enquanto você o treina. Em seguida, você registra essas informações no workspace. No workspace, você pode acessar e visualizar as informações com as APIs do MLflow ou o experimento correspondente. Para saber mais sobre o registro automático, consulte Registro automático no Microsoft Fabric.
# Set up Mlflow for experiment tracking
mlflow.set_experiment(EXPERIMENT_NAME)
mlflow.autolog(disable=True) # Disable Mlflow autologging
Para desabilitar o registro automático do Microsoft Fabric em uma sessão de notebook, chame mlflow.autolog()
e defina disable=True
:
Ler dados de data brutos do lakehouse
raw_df = spark.read.csv(f"{DATA_FOLDER}/raw/{DATA_FILE}", header=True, inferSchema=True)
Etapa 3: executar análise de dados exploratória
Explore o conjunto de dados com o comando display
para exibir estatísticas de alto nível para o conjunto de dados e mostrar as exibições do gráfico:
display(raw_df.limit(20))
Preparar os dados
Remova as duplicatas para limpar os dados:
df = (
raw_df.select([TEXT_COL, LABEL_COL])
.where(F.col(LABEL_COL).isin(LABELS))
.dropDuplicates([TEXT_COL])
.cache()
)
display(df.limit(20))
Aplique o balanceamento de classe para resolver qualquer viés:
# 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))
Divida os parágrafos e frases em unidades menores para tokenizar o conjunto de dados. Dessa forma, fica mais fácil atribuir significado. Em seguida, remova as palavras irrelevantes para aprimorar o desempenho. A remoção de palavras de parada envolve eliminar palavras que normalmente ocorrem em todos os documentos no corpus. A remoção de stopwords é uma das etapas de pré-processamento mais usadas em aplicativos de processamento de linguagem natural (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))
Exiba a biblioteca do wordcloud para cada classe. Uma biblioteca de wordcloud é uma apresentação visualmente proeminente de palavras-chave que aparecem com frequência em dados de texto. A biblioteca de nuvem de palavras é eficaz porque a renderização de palavras-chave forma uma imagem colorida semelhante a uma nuvem para capturar melhor os principais dados de textos em um relance. Saiba mais sobre odo 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")
Por fim, use word2vec para vetorizar o texto. A técnica word2vec cria uma representação de vetor de cada palavra no texto. Palavras usadas em contextos semelhantes, ou que têm relações semânticas, são capturadas efetivamente por meio de sua proximidade no espaço vetor. Essa proximidade indica que palavras semelhantes têm vetores de palavra semelhantes.
# 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))
Etapa 4: Treinar e avaliar o modelo
Com os dados em vigor, defina o modelo. Nesta seção, você treinará um modelo de regressão logística para classificar o texto vetorizado.
Preparar conjuntos de dados de treinamento e teste
# Split the dataset into training and testing
(train_df, test_df) = vec_df.randomSplit((0.8, 0.2), seed=42)
Acompanhar experimentos de aprendizado de máquina
Um experimento de machine learning é a principal unidade de organização e controle para todas as execuções de machine learning relacionadas. Uma execução corresponde a uma única execução do código do modelo.
O acompanhamento de experimentos de machine learning gerencia todos os experimentos e seus componentes, por exemplo, parâmetros, métricas, modelos e outros artefatos. O acompanhamento permite a organização de todos os componentes necessários de um experimento de machine learning específico. Ele também permite a reprodução fácil de resultados passados com experimentos salvos. Saiba mais sobre experimentos de machine learning no Microsoft Fabric.
# Build the logistic regression classifier
lr = (
LogisticRegression()
.setMaxIter(max_iter)
.setFeaturesCol("features")
.setLabelCol("labelIdx")
.setWeightCol("weight")
)
Ajustar hiperparâmetros
Crie uma grade de parâmetros para pesquisar sobre os hiperparâmetros. Em seguida, crie um estimador de validação cruzada para produzir um modelo 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,
)
Avaliar o modelo
Podemos avaliar os modelos no conjunto de dados de teste para compará-los. Um modelo bem treinado deve demonstrar alto desempenho, nas métricas relevantes, quando executado em relação aos conjuntos de dados de validação e teste.
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
Acompanhar experimentos usando o MLflow
Inicie o processo de treinamento e avaliação. Use o MLflow para acompanhar todos os experimentos e parâmetros de log, métricas e modelos. Todas essas informações são registradas no nome do experimento no workspace.
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,
}
)
Para ver seus experimentos:
- Selecione seu workspace na navegação à esquerda
- Localize e selecione o nome do experimento, nesse caso, sample_aisample-textclassification
Etapa 5: Pontuar e salvar os resultados da previsão
O Microsoft Fabric permite que os usuários operacionalizem modelos de machine learning com a função escalonável PREDICT
. Essa função dá suporte à pontuação em lote (ou inferência em lote) em qualquer mecanismo de computação. Você pode criar previsões em lote diretamente de um bloco de anotações ou da página de item para um modelo específico. Para saber mais sobre o PREDICT e como usá-lo no Fabric, consulte avaliação de modelo de aprendizado de máquina com PREDICT no Microsoft Fabric.
Nos resultados de avaliação anteriores, o modelo 1 tem as maiores métricas para a AUPRC (área sob a curva de precisão/recall) e para a AUC-ROC (área sob a curva de característica de operação do receptor). Portanto, você deve usar o modelo 1 para previsão.
A medida AUC-ROC é amplamente usada para medir o desempenho dos classificadores binários. No entanto, às vezes, torna-se mais apropriado avaliar o classificador com base em medidas AUPRC. O gráfico AUC-ROC visualiza a compensação entre a TPR (taxa verdadeira positiva) e a taxa de falso positivo (FPR). A curva AUPRC combina precisão (valor preditivo positivo ou PPV) e recall (taxa positiva verdadeira ou TPR) em uma única visualização.
# 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.")