Creazione di un modello di ML finanziario con lo strumento What-If e Vertex AI

1. Panoramica

In questo lab utilizzerai lo strumento What-if per analizzare un modello XGBoost addestrato su dati finanziari. Dopo aver analizzato il modello, lo eseguirai nel nuovo Vertex AI di Cloud.

Cosa imparerai

Al termine del corso sarai in grado di:

  • Addestrare un modello XGBoost su un set di dati pubblici di mutui in un notebook in hosting
  • Analizza il modello utilizzando lo strumento What-If
  • Esegui il deployment del modello XGBoost in Vertex AI

Il costo totale per l'esecuzione di questo lab su Google Cloud è di circa $1.

2. Introduzione a Vertex AI

Questo lab utilizza la più recente offerta di prodotti AI disponibile su Google Cloud. Vertex AI integra le offerte ML di Google Cloud in un'esperienza di sviluppo fluida. In precedenza, i modelli addestrati con AutoML e i modelli personalizzati erano accessibili tramite servizi separati. La nuova offerta combina entrambi in un'unica API, insieme ad altri nuovi prodotti. Puoi anche migrare progetti esistenti su Vertex AI. In caso di feedback, consulta la pagina di supporto.

Vertex AI include molti prodotti diversi per supportare i flussi di lavoro ML end-to-end. Questo lab si concentrerà sui prodotti evidenziati di seguito: previsione e notebook.

Panoramica dei prodotti Vertex

3. Una breve introduzione a XGBoost

XGBoost è un framework di machine learning che utilizza alberi decisionali e incremento del gradiente per creare modelli predittivi. Funziona raggruppando più alberi decisionali in base al punteggio associato ai diversi nodi foglia in un albero.

Il diagramma seguente è una visualizzazione di un semplice modello di albero decisionale che valuta se una partita di sport debba essere giocata in base alla previsione meteo:

Esempio di modello ad albero

Perché utilizziamo XGBoost per questo modello? Sebbene sia stato dimostrato che le reti neurali tradizionali hanno il rendimento migliore sui dati non strutturati come immagini e testo, gli alberi decisionali spesso hanno un rendimento estremamente elevato sui dati strutturati come il set di dati di mutui che utilizzeremo in questo codelab.

4. Configura l'ambiente

Per eseguire questo codelab, devi avere un progetto Google Cloud con la fatturazione abilitata. Per creare un progetto, segui le istruzioni riportate qui.

Passaggio 1: abilita l'API Compute Engine

Vai a Compute Engine e seleziona Attiva se non è già abilitato. Ne avrai bisogno per creare la tua istanza di blocco note.

Passaggio 2: attiva l'API Vertex AI

Vai alla sezione Vertex AI della tua console Cloud e fai clic su Abilita API Vertex AI.

Dashboard Vertex

Passaggio 3: crea un'istanza di Notebooks

Nella sezione Vertex della console Cloud, fai clic su Notebook:

Seleziona i notebook

Da qui, seleziona Nuova istanza. Quindi, seleziona il tipo di istanza TensorFlow Enterprise 2.3 senza GPU:

Istanza TFE

Utilizza le opzioni predefinite e fai clic su Crea. Una volta creata l'istanza, seleziona Apri JupyterLab.

Passaggio 4: installa XGBoost

Una volta aperta l'istanza JupyterLab, dovrai aggiungere il pacchetto XGBoost.

Per farlo, seleziona Terminale dal menu di avvio:

Quindi, esegui quanto segue per installare la versione più recente di XGBoost supportata da Vertex AI:

pip3 install xgboost==1.2

Al termine, apri un'istanza di blocco note Python 3 dall'Avvio app. Ora puoi iniziare a utilizzare il tuo notebook.

Passaggio 5: importa i pacchetti Python

Nella prima cella del notebook, aggiungi le seguenti importazioni ed esegui la cella. Per eseguirlo, premi il pulsante Freccia destra nel menu in alto o premi Invio:

import pandas as pd
import xgboost as xgb
import numpy as np
import collections
import witwidget

from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, confusion_matrix
from sklearn.utils import shuffle
from witwidget.notebook.visualization import WitWidget, WitConfigBuilder

5. Scaricare ed elaborare i dati

Utilizzeremo un set di dati di mutui da ffiec.gov per addestrare un modello XGBoost. Abbiamo eseguito una certa pre-elaborazione sul set di dati originale e creato una versione più piccola che potrai utilizzare per addestrare il modello. Il modello prevede se una determinata richiesta di mutuo verrà approvata o meno.

Passaggio 1: scarica il set di dati pre-elaborato

Abbiamo reso disponibile una versione del set di dati in Google Cloud Storage. Puoi scaricarlo eseguendo il seguente comando gsutil nel tuo Jupyter Notebook:

!gsutil cp 'gs://mortgage_dataset_files/mortgage-small.csv' .

Passaggio 2: leggi il set di dati con Pandas

Prima di creare il DataFrame Pandas, creeremo un dict del tipo di dati di ogni colonna in modo che Pandas legga correttamente il nostro set di dati:

COLUMN_NAMES = collections.OrderedDict({
 'as_of_year': np.int16,
 'agency_code': 'category',
 'loan_type': 'category',
 'property_type': 'category',
 'loan_purpose': 'category',
 'occupancy': np.int8,
 'loan_amt_thousands': np.float64,
 'preapproval': 'category',
 'county_code': np.float64,
 'applicant_income_thousands': np.float64,
 'purchaser_type': 'category',
 'hoepa_status': 'category',
 'lien_status': 'category',
 'population': np.float64,
 'ffiec_median_fam_income': np.float64,
 'tract_to_msa_income_pct': np.float64,
 'num_owner_occupied_units': np.float64,
 'num_1_to_4_family_units': np.float64,
 'approved': np.int8
})

Quindi creeremo un DataFrame, passando i tipi di dati che abbiamo specificato sopra. È importante mescolare i dati nel caso in cui il set di dati originale sia ordinato in un modo specifico. A questo scopo utilizziamo un'utilità sklearn denominata shuffle, che abbiamo importato nella prima cella:

data = pd.read_csv(
 'mortgage-small.csv',
 index_col=False,
 dtype=COLUMN_NAMES
)
data = data.dropna()
data = shuffle(data, random_state=2)
data.head()

data.head() ci consente di visualizzare l'anteprima delle prime 5 righe del nostro set di dati in Pandas. Dopo aver eseguito la cella in alto, dovresti vedere qualcosa di simile a questo:

Anteprima del set di dati sui mutui

Queste sono le funzionalità che utilizzeremo per addestrare il modello. Se scorri fino in fondo, vedrai l'ultima colonna approved, che è ciò che stiamo prevedendo. Il valore 1 indica che una determinata richiesta è stata approvata, mentre 0 indica che è stata rifiutata.

Per visualizzare la distribuzione dei valori approvati / rifiutati nel set di dati e creare un array numpy delle etichette, esegui quanto segue:

# Class labels - 0: denied, 1: approved
print(data['approved'].value_counts())

labels = data['approved'].values
data = data.drop(columns=['approved'])

Circa il 66% del set di dati contiene applicazioni approvate.

Passaggio 3: crea una colonna fittizia per i valori categorici

Questo set di dati contiene una combinazione di valori categorici e numerici, ma XGBoost richiede che tutte le funzionalità siano numeriche. Anziché rappresentare i valori categorici utilizzando la codifica one-hot, per il nostro modello XGBoost utilizzeremo la funzione get_dummies di Pandas.

get_dummies prende una colonna con più valori possibili e la converte in una serie di colonne contenenti solo 0 e 1. Ad esempio, se avessimo una colonna "colore" con possibili valori "blu" e "rosso", get_dummies la trasformerebbe in due colonne denominate "colore_blu" e "colore_rosso" con tutti i valori booleani 0 e 1.

Per creare colonne fittizie per le caratteristiche categoriche, esegui questo codice:

dummy_columns = list(data.dtypes[data.dtypes == 'category'].index)
data = pd.get_dummies(data, columns=dummy_columns)

data.head()

Questa volta, quando esamini l'anteprima dei dati, vedrai le singole funzionalità (come purchaser_type nella foto sotto) suddivise in più colonne:

Colonne fittizie di panda

Passaggio 4: suddivisione dei dati in set di addestramento e test

Un concetto importante nel machine learning è la suddivisione tra addestramento e test. Prenderemo la maggior parte dei dati e li utilizzeremo per addestrare il modello, mentre il resto lo metteremo da parte per testare il modello su dati mai visti prima.

Aggiungi il seguente codice al tuo notebook, che utilizza la funzione Scikit-learn train_test_split per suddividere i dati:

x,y = data.values,labels
x_train,x_test,y_train,y_test = train_test_split(x,y)

Ora è tutto pronto per creare e addestrare il modello.

6. Creare, addestrare e valutare un modello XGBoost

Passaggio 1: definisci e addestra il modello XGBoost

Creare un modello in XGBoost è semplice. Utilizzeremo la classe XGBClassifier per creare il modello e dovremo solo passare il parametro objective corretto per la nostra attività di classificazione specifica. In questo caso utilizziamo reg:logistic perché abbiamo un problema di classificazione binaria e vogliamo che il modello restituisca un singolo valore nell'intervallo (0,1): 0 per non approvato e 1 per approvato.

Il seguente codice crea un modello XGBoost:

model = xgb.XGBClassifier(
    objective='reg:logistic'
)

Puoi addestrare il modello con una riga di codice, chiamando il metodo fit() e passandogli i dati di addestramento e le etichette.

model.fit(x_train, y_train)

Passaggio 2: valuta l'accuratezza del modello

Ora possiamo utilizzare il modello addestrato per generare previsioni sui dati di test con la funzione predict().

Poi utilizzeremo la funzione accuracy_score() di Scikit-learn per calcolare l'accuratezza del nostro modello in base al suo rendimento sui dati di test. Passeremo i valori basati su dati empirici reali insieme ai valori previsti dal modello per ogni esempio del set di test:

y_pred = model.predict(x_test)
acc = accuracy_score(y_test, y_pred.round())
print(acc, '\n')

Dovresti ottenere una precisione di circa 87%, ma il tuo valore varierà leggermente poiché nel machine learning è sempre presente un elemento di casualità.

Passaggio 3: salva il modello

Per eseguire il deployment del modello, esegui questo codice per salvarlo in un file locale:

model.save_model('model.bst')

7. Utilizzare lo strumento What-If per interpretare il modello

Passaggio 1: crea la visualizzazione dello strumento What-if

Per collegare lo strumento What-if al tuo modello locale, devi passargli un sottoinsieme di esempi di test insieme ai valori basati su dati empirici reali per questi esempi. Creiamo un array Numpy di 500 dei nostri esempi di test insieme alle relative etichette basate su dati empirici reali:

num_wit_examples = 500
test_examples = np.hstack((x_test[:num_wit_examples],y_test[:num_wit_examples].reshape(-1,1)))

Per creare un'istanza per lo strumento What-if è sufficiente creare un oggetto WitConfigBuilder e trasmettergli il modello da analizzare.

Poiché lo strumento What-If si aspetta un elenco di punteggi per ogni classe del nostro modello (in questo caso 2), utilizzeremo il metodo predict_proba di XGBoost con lo strumento What-If:

config_builder = (WitConfigBuilder(test_examples.tolist(), data.columns.tolist() + ['mortgage_status'])
  .set_custom_predict_fn(model.predict_proba)
  .set_target_feature('mortgage_status')
  .set_label_vocab(['denied', 'approved']))
WitWidget(config_builder, height=800)

Tieni presente che il caricamento della visualizzazione richiederà un minuto. Al termine del caricamento, dovresti vedere quanto segue:

Visualizzazione iniziale dello strumento What-If

L'asse y mostra la previsione del modello, dove 1 è una previsione approved con un'alta affidabilità e 0 è una previsione denied con un'alta affidabilità. L'asse x è semplicemente la diffusione di tutti i punti di dati caricati.

Passaggio 2: esplora i singoli punti dati

La visualizzazione predefinita nello strumento What-if è la scheda Editor dei punti dati. Qui puoi fare clic su un singolo punto dati per visualizzarne le caratteristiche, modificare i valori delle caratteristiche e vedere in che modo questa modifica influisce sulla previsione del modello per un singolo punto dati.

Nell'esempio riportato di seguito, abbiamo scelto un punto dati vicino alla soglia di 0,5. La richiesta di mutuo associata a questo particolare punto dati ha avuto origine dalla CFPB. Abbiamo modificato questa caratteristica in 0 e anche il valore di agency_code_Department of Housing and Urban Development (HUD) è impostato su 1 per vedere cosa succederebbe alla previsione del modello se il prestito proveniva invece da HUD:

Come possiamo vedere nella sezione in basso a sinistra dello strumento What-if, la modifica di questa funzionalità ha ridotto in modo significativo la previsione approved del modello del 32%. Ciò potrebbe indicare che l'agenzia da cui è stato originato un prestito ha un forte impatto sull'output del modello, ma dovremo effettuare ulteriori analisi per esserne certi.

Nella parte in basso a sinistra dell'interfaccia utente, possiamo anche vedere il valore basato su dati empirici reali per ciascun punto dati e confrontarlo con la previsione del modello:

Passaggio 3: analisi controfattuale

Successivamente, fai clic su un punto dati qualsiasi e sposta verso destra il cursore Mostra punto dati controfattuale più vicino:

Se selezioni questa opzione, verrà mostrato il punto dati con i valori delle caratteristiche più simili a quello originale selezionato, ma la previsione opposta. Puoi quindi scorrere i valori delle caratteristiche per vedere dove differiscono i due punti dati (le differenze sono evidenziate in verde e in grassetto).

Passaggio 4: esamina i grafici di dipendenza parziale

Per vedere in che modo ogni caratteristica influisce sulle previsioni complessive del modello, seleziona la casella Grafici di dipendenza parziale e assicurati che sia selezionata l'opzione Grafici di dipendenza parziale globale:

Qui possiamo vedere che i prestiti provenienti dall'HUD hanno una probabilità leggermente superiore di essere rifiutati. Il grafico ha questa forma perché il codice agenzia è una funzionalità booleana, quindi i valori possono essere esattamente 0 o 1.

applicant_income_thousands è un attributo numerico e nel grafico della dipendenza parziale possiamo vedere che un reddito più elevato aumenta leggermente la probabilità che una richiesta venga approvata, ma solo fino a circa 200.000 $. Oltre i 200.000 $, questa funzionalità non influisce sulla previsione del modello.

Passaggio 5: esamina il rendimento e l'equità complessivi

Poi vai alla scheda Rendimento ed equità. Vengono mostrate le statistiche sul rendimento complessivo dei risultati del modello sul set di dati fornito, tra cui matrici di confusione, curve PR e curve ROC.

Seleziona mortgage_status come funzionalità di dati empirici reali per visualizzare una matrice di confusione:

Questa matrice di confusione mostra le previsioni corrette ed errate del nostro modello come percentuale del totale. Se sommi i quadrati Risultato effettivo Sì / Risultato previsto Sì e Risultato effettivo No / Risultato previsto No, dovresti ottenere la stessa accuratezza del tuo modello (in questo caso circa l'87%, anche se il modello potrebbe variare leggermente poiché esiste un elemento di casualità nell'addestramento dei modelli di ML).

Puoi anche fare esperimenti con il cursore della soglia, aumentando e diminuendo il punteggio di classificazione positiva che il modello deve restituire prima di decidere di prevedere approved per il prestito e vedere in che modo cambia l'accuratezza, i falsi positivi e i falsi negativi. In questo caso, l'accuratezza è massima intorno a una soglia di 0,55.

Quindi, nel menu a discesa Esegui segmentazione per a sinistra, seleziona loan_purpose_Home_purchase:

Ora vedrai il rendimento dei due sottoinsiemi di dati: la frazione "0" indica quando il prestito non è per l'acquisto di una casa, mentre la frazione "1" indica quando il prestito è per l'acquisto di una casa. Controlla l'accuratezza, i falsi positivi e la percentuale di falsi negativi tra i due segmenti per individuare le differenze di rendimento.

Se espandi le righe per esaminare le matrici di confusione, puoi vedere che il modello prevede "Approvato" per circa il 70% delle richieste di prestito per l'acquisto di case e solo per il 46% dei prestiti non destinati all'acquisto di case (le percentuali esatte variano in base al modello):

Se selezioni Parità demografica dai pulsanti di opzione a sinistra, le due soglie verranno regolate in modo che il modello preveda approved per una percentuale simile di richiedenti in entrambi i segmenti. Che cosa succede all'accuratezza, ai falsi positivi e ai falsi negativi per ogni segmento?

Passaggio 6: esplora la distribuzione delle funzionalità

Infine, vai alla scheda Funzionalità nello strumento What-If. Viene visualizzata la distribuzione dei valori per ogni funzionalità nel set di dati:

Puoi usare questa scheda per assicurarti che il set di dati sia bilanciato. Ad esempio, sembra che pochissimi prestiti nel set di dati provengano da Farm Service Agency. Per migliorare l'accuratezza del modello, potremmo prendere in considerazione l'aggiunta di altri prestiti di quell'agenzia, se i dati sono disponibili.

Qui abbiamo descritto solo alcune idee per esplorare lo strumento What-If. Non esitare a continuare a utilizzare lo strumento: ci sono molte altre aree da esplorare.

8. Esegui il deployment del modello in Vertex AI

Il nostro modello funziona localmente, ma sarebbe bello poter fare previsioni da qualsiasi luogo (non solo da questo notebook). In questo passaggio lo eseguiremo nel cloud.

Passaggio 1: crea un bucket Cloud Storage per il nostro modello

Innanzitutto, definiamo alcune variabili di ambiente che utilizzeremo per il resto del codelab. Inserisci i valori seguenti con il nome del tuo progetto Google Cloud, il nome del bucket Cloud Storage che vuoi creare (deve essere univoco a livello globale) e il nome della versione della prima versione del modello:

# Update the variables below to your own Google Cloud project ID and GCS bucket name. You can leave the model name we've specified below:
GCP_PROJECT = 'your-gcp-project'
MODEL_BUCKET = 'gs://storage_bucket_name'
MODEL_NAME = 'xgb_mortgage'

Ora è tutto pronto per creare un bucket di archiviazione in cui archiviare il file del modello XGBoost. Indirizzeremo Vertex AI a questo file durante il deployment.

Esegui questo comando gsutil dal tuo notebook per creare un bucket di archiviazione a livello di regione:

!gsutil mb -l us-central1 $MODEL_BUCKET

Passaggio 2: copia il file del modello in Cloud Storage

Ora copieremo il file del modello salvato di XGBoost in Cloud Storage. Esegui il seguente comando gsutil:

!gsutil cp ./model.bst $MODEL_BUCKET

Vai al browser Storage nella console Cloud per verificare che il file sia stato copiato:

Passaggio 3: crea il modello ed esegui il deployment in un endpoint

Siamo quasi pronti per eseguire il deployment del modello nel cloud. In Vertex AI un modello può contenere più endpoint. Per prima cosa creeremo un modello, poi creeremo un endpoint all'interno del modello ed eseguiremo il deployment.

Innanzitutto, utilizza l'interfaccia a riga di comando gcloud per creare il tuo modello:

!gcloud beta ai models upload \
--display-name=$MODEL_NAME \
--artifact-uri=$MODEL_BUCKET \
--container-image-uri=us-docker.pkg.dev/cloud-aiplatform/prediction/xgboost-cpu.1-2:latest \
--region=us-central1

Il parametro artifact-uri indicherà la posizione di archiviazione in cui hai salvato il modello XGBoost. Il parametro container-image-uri indica a Vertex AI quale container predefinito utilizzare per la pubblicazione. Al termine di questo comando, vai alla sezione Modelli della console Vertex per ottenere l'ID del nuovo modello. Puoi trovarlo qui:

Recuperare l'ID modello dalla console

Copia l'ID e salvalo in una variabile:

MODEL_ID = "your_model_id"

Ora è il momento di creare un endpoint all'interno di questo modello. Possiamo farlo con questo comando gcloud:

!gcloud beta ai endpoints create \
--display-name=xgb_mortgage_v1 \
--region=us-central1

Al termine, dovresti vedere la posizione del tuo endpoint registrata nell'output del nostro notebook. Cerca la riga che indica che l'endpoint è stato creato con un percorso simile al seguente: projects/project_ID/locations/us-central1/endpoints/endpoint_ID. Quindi sostituisci i valori riportati di seguito con gli ID dell'endpoint creato sopra:

ENDPOINT_ID = "your_endpoint_id"

Per eseguire il deployment dell'endpoint, esegui il comando gcloud seguente:

!gcloud beta ai endpoints deploy-model $ENDPOINT_ID \
--region=us-central1 \
--model=$MODEL_ID \
--display-name=xgb_mortgage_v1 \
--machine-type=n1-standard-2 \
--traffic-split=0=100

Il deployment dell'endpoint richiede circa 5-10 minuti. Durante il deployment dell'endpoint, vai alla sezione Modelli della console. Fai clic sul tuo modello e dovresti vedere il deployment endpiont:

Al termine del deployment, vedrai un segno di spunta verde al posto della rotellina di caricamento.

Passaggio 4: testa il modello di cui è stato eseguito il deployment

Per assicurarti che il modello di cui hai eseguito il deployment funzioni, testalo utilizzando gcloud per fare una previsione. Innanzitutto, salva un file JSON con un esempio del nostro set di test:

%%writefile predictions.json
{
  "instances": [
    [2016.0, 1.0, 346.0, 27.0, 211.0, 4530.0, 86700.0, 132.13, 1289.0, 1408.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0]
  ]
}

Testa il modello eseguendo questo comando gcloud:

!gcloud beta ai endpoints predict $ENDPOINT_ID \
--json-request=predictions.json \
--region=us-central1

Nell'output dovresti vedere la previsione del modello. Questo esempio specifico è stato approvato, quindi dovresti vedere un valore vicino a 1.

9. Esegui la pulizia

Se desideri continuare a utilizzare questo blocco note, ti consigliamo di disattivarlo quando non lo usi. Dall'interfaccia utente di Notebooks nella console Cloud, seleziona il blocco note, quindi seleziona Interrompi:

Se vuoi eliminare tutte le risorse che hai creato in questo lab, elimina l'istanza del notebook anziché interromperla.

Per eliminare l'endpoint di cui hai eseguito il deployment, vai alla sezione Endpoint della console Vertex e fai clic sull'icona di eliminazione:

Per eliminare il bucket di archiviazione, utilizza il menu di navigazione nella console Cloud, vai su Storage, seleziona il bucket e fai clic su Elimina: