Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Neste artigo, você aprenderá a treinar modelos de classificação usando EBM (máquinas de aumento explicaíveis). Uma máquina de explainable boosting é uma técnica de aprendizado de máquina que combina o poder do gradient boosting com ênfase na interpretabilidade do modelo. Ele cria um conjunto de árvores de decisão, semelhante ao aumento de gradiente, mas com um foco exclusivo na geração de modelos legíveis por humanos. Os EBMs não só fornecem previsões precisas, mas também oferecem explicações claras e intuitivas para essas previsões. Elas são adequadas para aplicativos em que a compreensão dos fatores subjacentes que conduzem decisões de modelo é essencial, como saúde, finanças e conformidade regulatória.
No SynapseML, você pode usar uma implementação escalonável de um EBM, alimentado pelo Apache Spark, para treinar novos modelos. Este artigo orienta você pelo processo de aplicação da escalabilidade e interpretabilidade de EBMs no Microsoft Fabric utilizando o Apache Spark.
Importante
Esse recurso está na versão prévia.
Neste artigo, você percorre o processo de aquisição e pré-processamento de dados de conjuntos de dados abertos do Azure que registram viagens de Táxi Amarelo de NYC. Em seguida, você treina um modelo preditivo com o objetivo final de determinar se uma determinada viagem ocorrerá ou não.
Benefícios das máquinas de explainable boosting
Os EBMs oferecem uma combinação exclusiva de interpretabilidade e poder preditivo, tornando-os uma opção ideal quando a transparência e a compreensão dos modelos de machine learning são cruciais. Com os EBMs, os usuários podem obter informações valiosas sobre os fatores subjacentes que impulsionam previsões, permitindo que eles entendam por que um modelo toma decisões ou previsões específicas, o que é essencial para criar confiança em sistemas de IA.
Sua capacidade de descobrir relações complexas dentro dos dados, fornecendo resultados claros e interpretáveis, torna-os inestimáveis em campos como finanças, saúde e detecção de fraudes. Nesses campos, a explicabilidade do modelo não é apenas desejável, mas muitas vezes um requisito regulatório. Por fim, os usuários que optam por EBMs podem encontrar um equilíbrio entre o desempenho do modelo e a transparência, garantindo que as soluções de IA sejam precisas, facilmente compreensíveis e responsáveis.
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 no canto inferior esquerdo da sua página inicial para mudar para o Fabric.
- Crie um novo caderno de notas em seu espaço de trabalho selecionando + e, em seguida, Notebook.
Instalar bibliotecas
Para começar, instale a biblioteca de Conjuntos de Dados Abertos do Azure Machine Learning, que concede acesso ao conjunto de dados. Essa etapa de instalação é essencial para acessar e utilizar o conjunto de dados efetivamente.
%pip install azureml-opendatasets
Importar MLflow
O MLflow permite que você acompanhe os parâmetros e os resultados do modelo. O snippet de código a seguir demonstra como usar o MLflow para fins de experimentação e acompanhamento. O valor ebm_classification_nyc_taxi
é o nome do experimento em que as informações são registradas.
import mlflow
# Set up the experiment name
mlflow.set_experiment("ebm_classification_nyc_taxi")
Importar bibliotecas
Em seguida, adicione o seguinte código para importar os pacotes essenciais usados para análise:
# Import necessary packages
import interpret
from pyspark.ml.feature import StringIndexer, VectorAssembler
from pyspark.ml import Pipeline
from pyspark.mllib.evaluation import BinaryClassificationMetrics
from pyspark.sql import SparkSession
from pyspark.sql.functions import *
from pyspark.sql.types import DoubleType
from synapse.ml.ebm import EbmClassification
Esses pacotes importados fornecem as ferramentas e funcionalidades fundamentais necessárias para suas tarefas de análise e modelagem.
Carregar dados
Em seguida, adicione o seguinte código para recuperar os dados do Táxi Amarelo de NYC dos conjuntos de dados abertos do Azure Machine Learning e, opcionalmente, reduzir a amostra do conjunto de dados para agilizar o desenvolvimento:
# Import NYC Yellow Taxi data from Azure Open Datasets
from azureml.opendatasets import NycTlcYellow
from datetime import datetime
from dateutil import parser
# Define the start and end dates for the dataset
end_date = parser.parse('2018-05-08 00:00:00')
start_date = parser.parse('2018-05-01 00:00:00')
# Load the NYC Yellow Taxi dataset within the specified date range
nyc_tlc = NycTlcYellow(start_date=start_date, end_date=end_date)
nyc_pd = nyc_tlc.to_pandas_dataframe()
nyc_tlc_df = spark.createDataFrame(nyc_pd)
Para facilitar o desenvolvimento e reduzir a sobrecarga computacional, você pode reduzir a amostra do conjunto de dados:
# For development convenience, consider down-sampling the dataset
sampled_taxi_df = nyc_tlc_df.sample(True, 0.001, seed=1234)
A amostragem para baixo permite uma experiência de desenvolvimento mais rápida e econômica, especialmente ao trabalhar com grandes conjuntos de dados.
Preparar os dados
Nesta seção, você prepara o conjunto de dados filtrando linhas com exceções e variáveis irrelevantes.
Gerar recursos
Crie um código de adição para novos recursos derivados que devem melhorar o desempenho do modelo:
taxi_df = sampled_taxi_df.select('totalAmount', 'fareAmount', 'tipAmount', 'paymentType', 'rateCodeId', 'passengerCount',
'tripDistance', 'tpepPickupDateTime', 'tpepDropoffDateTime',
date_format('tpepPickupDateTime', 'hh').alias('pickupHour'),
date_format('tpepPickupDateTime', 'EEEE').alias('weekdayString'),
(unix_timestamp(col('tpepDropoffDateTime')) - unix_timestamp(col('tpepPickupDateTime'))).alias('tripTimeSecs'),
(when(col('tipAmount') > 0, 1).otherwise(0)).alias('tipped')
)\
.filter((sampled_taxi_df.passengerCount > 0) & (sampled_taxi_df.passengerCount < 8)
& (sampled_taxi_df.tipAmount >= 0) & (sampled_taxi_df.tipAmount <= 25)
& (sampled_taxi_df.fareAmount >= 1) & (sampled_taxi_df.fareAmount <= 250)
& (sampled_taxi_df.tipAmount < sampled_taxi_df.fareAmount)
& (sampled_taxi_df.tripDistance > 0) & (sampled_taxi_df.tripDistance <= 100)
& (sampled_taxi_df.rateCodeId <= 5)
& (sampled_taxi_df.paymentType.isin({"1", "2"}))
)
Agora que você criou novas variáveis, adicione código para remover as colunas das quais elas foram derivadas. O dataframe agora é mais simplificado para a entrada do modelo. Além disso, você pode gerar mais recursos com base nas colunas recém-criadas:
taxi_featurised_df = taxi_df.select('totalAmount', 'fareAmount', 'tipAmount', 'paymentType', 'passengerCount',
'tripDistance', 'weekdayString', 'pickupHour', 'tripTimeSecs', 'tipped',
when((taxi_df.pickupHour <= 6) | (taxi_df.pickupHour >= 20), "Night")
.when((taxi_df.pickupHour >= 7) & (taxi_df.pickupHour <= 10), "AMRush")
.when((taxi_df.pickupHour >= 11) & (taxi_df.pickupHour <= 15), "Afternoon")
.when((taxi_df.pickupHour >= 16) & (taxi_df.pickupHour <= 19), "PMRush")
.otherwise(0).alias('trafficTimeBins'))\
.filter((taxi_df.tripTimeSecs >= 30) & (taxi_df.tripTimeSecs <= 7200))
Essas etapas de preparação de dados garantem que seu conjunto de dados seja refinado e otimizado para processos de modelagem subsequentes.
Codificar os dados
No contexto das EBMs do SynapseML, o Estimator
espera que os dados de entrada estejam na forma de um org.apache.spark.mllib.linalg.Vector
, essencialmente um vetor de Doubles
. Portanto, é necessário converter variáveis categóricas (cadeia de caracteres) em representações numéricas e todas as variáveis que possuem valores numéricos, mas tipos de dados não numéricos, devem ser convertidas em tipos de dados numéricos.
Atualmente, os EBMs SynapseML empregam a abordagem StringIndexer
para gerenciar variáveis categóricas. Atualmente, as EBMs do SynapseML não oferecem tratamento especializado para recursos categóricos.
Aqui está uma série de etapas para adicionar ao código para preparar os dados para uso com EBMs SynapseML:
# Convert categorical features into numerical representations using StringIndexer
sI1 = StringIndexer(inputCol="trafficTimeBins", outputCol="trafficTimeBinsIndex")
sI2 = StringIndexer(inputCol="weekdayString", outputCol="weekdayIndex")
# Apply the encodings to create a new dataframe
encoded_df = Pipeline(stages=[sI1, sI2]).fit(taxi_featurised_df).transform(taxi_featurised_df)
final_df = encoded_df.select('fareAmount', 'paymentType', 'passengerCount', 'tripDistance',
'pickupHour', 'tripTimeSecs', 'trafficTimeBinsIndex', 'weekdayIndex',
'tipped')
# Ensure that any string representations of numbers in the data are cast to numeric data types
final_df = final_df.withColumn('paymentType', final_df['paymentType'].cast(DoubleType()))
final_df = final_df.withColumn('pickupHour', final_df['pickupHour'].cast(DoubleType()))
# Define the label column name
labelColumnName = 'tipped'
# Assemble the features into a vector
assembler = VectorAssembler(outputCol='features')
assembler.setInputCols([c for c in final_df.columns if c != labelColumnName])
vectorized_final_df = assembler.transform(final_df)
Essas etapas de preparação de dados são cruciais para alinhar o formato de dados com os requisitos de EBMs SynapseML, garantindo um treinamento de modelo preciso e eficaz.
Gerar conjuntos de dados de teste e treinamento
Agora, adicione código para dividir o conjunto de dados em conjuntos de treinamento e teste usando uma divisão simples. 70% dos dados são alocados para treinamento e 30% para testar o modelo:
# Decide on the split between training and test data from the dataframe
trainingFraction = 0.7
testingFraction = (1-trainingFraction)
seed = 1234
# Split the dataframe into test and training dataframes
train_data_df, test_data_df = vectorized_final_df.randomSplit([trainingFraction, testingFraction], seed=seed)
Essa divisão de dados nos permite treinar o modelo em uma parte substancial, reservando outra parte para avaliar seu desempenho efetivamente.
Treinar o modelo
Agora, adicione código para treinar o modelo EBM e, em seguida, avalie seu desempenho usando a Área sob a curva ROC (Característica Operacional do Receptor) (AUROC) como a métrica:
# Create an instance of the EBMClassifier
estimator = EbmClassification()
estimator.setLabelCol(labelColumnName)
# Fit the EBM model to the training data
model = estimator.fit(train_data_df)
# Make predictions for tip (1/0 - yes/no) on the test dataset and evaluate using AUROC
predictions = model.transform(test_data_df)
predictionsAndLabels = predictions.select("prediction", labelColumnName)
predictionsAndLabels = predictionsAndLabels.withColumn(labelColumnName, predictionsAndLabels[labelColumnName].cast(DoubleType()))
# Calculate AUROC using BinaryClassificationMetrics
metrics = BinaryClassificationMetrics(predictionsAndLabels.rdd)
print("Area under ROC = %s" % metrics.areaUnderROC)
Esse processo envolve o treinamento do modelo EBM no conjunto de dados de treinamento e, em seguida, utilizá-lo para fazer previsões no conjunto de dados de teste, seguido por avaliar o desempenho do modelo usando a AUROC como uma métrica chave.
Exibir explicações globais
Para visualizar a explicação geral do modelo, você pode adicionar código para obter o método show
da biblioteca interpret
e utilizar o envoltório de visualização. O invólucro de visualização atua como uma ponte para facilitar a experiência de observar o modelo. Veja como você pode fazer isso:
wrapper = model.getVizWrapper()
explanation = wrapper.explain_global()
Em seguida, adicione o código para importar a interpret
biblioteca e use o show
método para exibir a explicação:
import interpret
interpret.show(explanation)
O termo "importâncias" representa a contribuição absoluta média (pontuação) de cada termo (recurso ou interação) para previsões. Essas contribuições são calculadas em toda a base de dados de treinamento, levando em conta o número de amostras em cada compartimento e os pesos das amostras (se aplicável). Os 15 termos mais importantes são exibidos na explicação.
Exibir explicações locais
As explicações fornecidas estão em um nível global, mas há cenários em que as saídas por recurso também são valiosas. Tanto o treinador quanto o modelo oferecem a capacidade de definir o featurescores
, que, quando preenchido, introduz outra coluna com valor de vetor. Cada vetor nessa coluna corresponde ao comprimento da coluna de recurso, com cada valor correspondente ao recurso no mesmo índice. Esses valores representam a contribuição do valor de cada recurso para a saída final do modelo.
Ao contrário das explicações globais, atualmente não há nenhuma integração direta com a visualização interpret
para saídas por recurso. Isso ocorre porque as visualizações globais são dimensionadas principalmente com o número de recursos (que normalmente é pequeno), enquanto as explicações locais são dimensionadas com o número de linhas (que, se um dataframe do Spark, pode ser substancial).
Este é o código a ser adicionado para configurar e usar :featurescores
prediction2 = model.setFeatureScoresCol("featurescores").transform(train_data_df)
Para fins de ilustração, vamos adicionar código para imprimir os detalhes do primeiro exemplo:
# Convert to Pandas for easier inspection
predictions_pandas = prediction2.toPandas()
predictions_list = prediction2.collect()
# Extract the first example from the collected predictions.
first = predictions_list[0]
# Print the lengths of the features and feature scores.
print('Length of the features is', len(first['features']), 'while the feature scores have length', len(first['featurescores']))
# Print the values of the features and feature scores.
print('Features are', first['features'])
print('Feature scores are', first['featurescores'])