Delen via


Uitlegbare boostingmachines trainen - classificatie (voorbeeldweergave)

In dit artikel leert u hoe u classificatiemodellen traint met behulp van uitlegbare boostmachines (EBM). Een verklaarbare boosting machine is een machine learning-techniek die de kracht van gradient boosting combineert met een nadruk op modelinterpretatie. Het creëert een ensemble van beslissingsbomen, vergelijkbaar met gradient boosting, maar met een unieke focus op het genereren van door mensen leesbare modellen. EBM's bieden niet alleen nauwkeurige voorspellingen, maar bieden ook duidelijke en intuïtieve uitleg voor deze voorspellingen. Ze zijn geschikt voor toepassingen waarbij het begrijpen van de onderliggende factoren die bepalend zijn voor modelbeslissingen essentieel is, zoals gezondheidszorg, financiën en naleving van regelgeving.

In SynapseML kunt u een schaalbare implementatie van een EBM gebruiken, mogelijk gemaakt door Apache Spark, voor het trainen van nieuwe modellen. In dit artikel wordt u begeleid bij het toepassen van de schaalbaarheid en interpreteerbaarheid van EBM's in Microsoft Fabric door Apache Spark te gebruiken.

Belangrijk

Deze functie bevindt zich in preview-versie.

In dit artikel doorloopt u het proces voor het ophalen en voorbewerken van gegevens uit Azure Open Datasets waarin NYC Yellow Taxi-ritten worden vastgelegd. Vervolgens traint u een voorspellend model met het uiteindelijke doel om te bepalen of een bepaalde reis al dan niet plaatsvindt.

Voordelen van uitlegbare stimulerende machines

EBM's bieden een unieke mix van interpreteerbaarheid en voorspellende kracht, waardoor ze een ideale keuze zijn wanneer transparantie en begrijpelijkheid van machine learning-modellen cruciaal zijn. Met EBM's kunnen gebruikers waardevolle inzichten krijgen in de onderliggende factoren die voorspellingen stimuleren, zodat ze kunnen begrijpen waarom een model specifieke beslissingen of voorspellingen neemt, wat essentieel is voor het bouwen van vertrouwen in AI-systemen.

Hun vermogen om complexe relaties binnen de gegevens te ontdekken en tegelijkertijd duidelijke en interpreteerbare resultaten te bieden, zijn ze waardevol in velden zoals financiën, gezondheidszorg en fraudedetectie. In deze velden is model verklaarbaarheid niet alleen wenselijk, maar vaak een wettelijke vereiste. Uiteindelijk kunnen gebruikers die kiezen voor EBM's een balans vinden tussen modelprestaties en transparantie, zodat AI-oplossingen nauwkeurig, begrijpelijk en verantwoordelijk zijn.

Voorwaarden

  • Maak een nieuw notitieblok in uw werkruimte door + te selecteren en Notebook.

Bibliotheken installeren

Installeer eerst de Azure Machine Learning Open Datasets-bibliotheek, die toegang verleent tot de gegevensset. Deze installatiestap is essentieel voor het effectief openen en gebruiken van de gegevensset.

%pip install azureml-opendatasets

MLflow importeren

Met MLflow kunt u de parameters en resultaten van het model bijhouden. Het volgende codefragment laat zien hoe u MLflow gebruikt voor experimenten en traceringsdoeleinden. De ebm_classification_nyc_taxi waarde is de naam van het experiment waarin de informatie wordt vastgelegd.

import mlflow

# Set up the experiment name
mlflow.set_experiment("ebm_classification_nyc_taxi")

Bibliotheken importeren

Importeer vervolgens de essentiële pakketten die worden gebruikt voor analyse:

# 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

Deze geïmporteerde pakketten bieden de fundamentele hulpprogramma's en functionaliteiten die nodig zijn voor uw analyse- en modelleringstaken.

Gegevens laden

Haal vervolgens de NYC Yellow Taxi-gegevens op uit Azure Machine Learning Open Datasets en verklein eventueel de dataset om de ontwikkeling te versnellen.

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

Om de ontwikkeling te vergemakkelijken en de rekenkundige overhead te verminderen, kunt u de gegevensset downsamplen:

# For development convenience, consider down-sampling the dataset
sampled_taxi_df = nyc_tlc_df.sample(True, 0.001, seed=1234)

Met downsampling kunt u sneller en rendabeler ontwikkelen, met name bij het werken met grote gegevenssets.

De gegevens voorbereiden

In dit gedeelte bereidt u de dataset voor door rijen met uitbijters en irrelevante variabelen te filteren.

Functies genereren

Maak nieuwe afgeleide functies die naar verwachting de modelprestaties verbeteren:

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"}))
                                )

Nu u nieuwe variabelen hebt gemaakt, verwijdert u de kolommen waaruit ze zijn afgeleid. Het dataframe is nu gestroomlijnder voor modelinvoer. Daarnaast kunt u nog meer functies genereren op basis van de zojuist gemaakte kolommen:

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))

Deze stappen voor gegevensvoorbereiding zorgen ervoor dat uw gegevensset zowel is verfijnd als geoptimaliseerd voor volgende modelleringsprocessen.

De gegevens coderen

In de context van SynapseML EBM's verwacht de Estimator invoergegevens in de vorm van een org.apache.spark.mllib.linalg.Vector, in wezen een vector van Doubles. Het is dus nodig om categorische variabelen (tekenreeksvariabelen) te converteren naar numerieke weergaven en variabelen die numerieke waarden bevatten, maar niet-numerieke gegevenstypen moeten worden omgezet in numerieke gegevenstypen.

Op dit moment maken SynapseML EBM's gebruik van de StringIndexer benadering voor het beheren van categorische variabelen. Op dit moment bieden SynapseML EBM's geen gespecialiseerde verwerking voor categorische functies.

Hier volgt een reeks stappen voor het voorbereiden van de gegevens voor gebruik met SynapseML EBM's:

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

Deze stappen voor gegevensvoorbereiding zijn van cruciaal belang voor het afstemmen van de gegevensindeling met de vereisten van SynapseML EBM's, waardoor nauwkeurige en effectieve modeltraining wordt gegarandeerd.

Test- en trainingsgegevenssets genereren

Verdeel de gegevensset nu in trainings- en testsets met behulp van een eenvoudige splitsing. 70% van de gegevens wordt toegewezen voor training en 30% voor het testen van het model:

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

Met deze gegevensverdeling kunnen we het model op een aanzienlijk deel trainen terwijl we een ander gedeelte reserveren om de prestaties effectief te beoordelen.

Het model trainen

Train nu het EBM-model en evalueer vervolgens de prestaties met behulp van de Area under the Receiver Operating Characteristic (ROC) curve (AUROC) als meetwaarde:

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

Dit proces omvat het trainen van het EBM-model op de trainingsgegevensset en het vervolgens gebruiken om voorspellingen te doen op de testgegevensset, gevolgd door de prestaties van het model te beoordelen met AUROC als een belangrijke metrische waarde.

Algemene uitleg weergeven

Als u de algemene uitleg van het model wilt visualiseren, kunt u de visualisatiewikkelaar verkrijgen en de show methode van de interpret bibliotheek gebruiken. De visualisatielaag fungeert als een brug om de gebruikerservaring met het model te vergemakkelijken. U kunt dit als volgt doen:

wrapper = model.getVizWrapper()
explanation = wrapper.explain_global()

Importeer vervolgens de interpret-bibliotheek en gebruik de methode show om de uitleg weer te geven:

import interpret
interpret.show(explanation)

Schermopname van globale uitleg.

De term 'belangrijken' vertegenwoordigt de gemiddelde absolute bijdrage (score) van elke term (kenmerk of interactie) bij voorspellingen. Deze bijdragen worden gemiddeld over de trainingsdataset, rekening houdend met het aantal steekproef in elke groep en steekproefgewichten (indien van toepassing). De belangrijkste 15 belangrijkste termen worden weergegeven in de uitleg.

Lokale uitleg weergeven

De opgegeven uitleg is wereldwijd, maar er zijn scenario's waarin uitvoer per functie ook waardevol is. Zowel de trainer als het model bieden de mogelijkheid om de featurescoresin te stellen, wat, wanneer deze wordt gevuld, een andere vectorwaardekolom introduceert. Elke vector in deze kolom komt overeen met de lengte van de functiekolom, waarbij elke waarde overeenkomt met de functie in dezelfde index. Deze waarden vertegenwoordigen de bijdrage van elke functie aan de uiteindelijke uitvoer van het model.

In tegenstelling tot globale uitleg is er momenteel geen directe integratie met de interpret visualisatie voor uitvoer per functie. Dit komt doordat globale visualisaties voornamelijk worden geschaald met het aantal functies (meestal klein), terwijl lokale uitleg wordt geschaald met het aantal rijen (dat, als een Spark-dataframe, aanzienlijk kan zijn).

U kunt als volgt de featurescoresinstellen en gebruiken:

prediction2 = model.setFeatureScoresCol("featurescores").transform(train_data_df)

Laten we ter illustratie de details van het eerste voorbeeld afdrukken:

# 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'])