GraphReduce Utilizzando i grafi per astrazioni di ingegneria delle caratteristiche

GraphReduce Using graphs for feature engineering abstractions

Nota dell’editore: Wes Madrigal è un relatore per ODSC West dal 30 ottobre al 2 novembre. Assicurati di seguire il suo intervento, “Utilizzo dei grafi per la costruzione di pipeline di ingegneria delle feature di grandi dimensioni”, per saperne di più su GraphReduce e altro!

Per i lettori che lavorano in ML / AI, è ben noto che i modelli di apprendimento automatico preferiscono vettori di informazioni numeriche. Quando abbiamo un vettore di dati, manipolarlo per la codifica, la filtrazione degli outlier, la normalizzazione, l’imputazione, ecc. è relativamente semplice. Molto lavoro è stato fatto nell’area dell’automazione dell’ingegneria delle feature, ma gran parte di esso assume che l’input sia un vettore di feature piatte. Tuttavia, la maggior parte dei dati aziendali rimane inutilizzata dal punto di vista dell’analisi e dell’apprendimento automatico, e molte delle informazioni più preziose rimangono negli schemi dei database relazionali come OLAP. Accedere a questi schemi e estrarre vettori di feature pronti per l’apprendimento automatico può essere non banale, in quanto è necessario sapere dove si trova l’entità di dati di interesse (ad esempio, i clienti), quali sono le sue relazioni e come sono collegate, e scrivere SQL o simili per selezionare, filtrare, unire e aggregare le informazioni a una determinata granularità. Per complicare ulteriormente le cose, la perdita di dati causa seri problemi nei modelli di apprendimento automatico, quindi il tempo deve essere gestito attentamente tra le entità. In parole povere, “perdita di dati” significa semplicemente consentire ai dati del periodo di etichettatura di fuoriuscire nei dati di addestramento del modello. Infine, man mano che vengono ideate, proposte e aggiunte caratteristiche, l’interfaccia può diventare un mostro di pipeline SQL o Python difficile da estendere, mantenere o riutilizzare. In questo articolo, proponiamo GraphReduce come astrazione per questi problemi. Illustreremo un processo di ingegneria delle feature di esempio su uno schema di e-commerce e come GraphReduce gestisce la complessità dell’ingegneria delle feature sullo schema relazionale.

Supponiamo di dover prevedere se un cliente interagirà con una notifica al fine di promuovere l’outreach. Purtroppo, i nostri team di ingegneria dei dati e di machine learning ops non hanno costruito un vettore di feature per noi, quindi tutti i dati rilevanti si trovano nello schema relazionale in tabelle separate. Lo schema di esempio è il seguente:

  • Clienti
  • Ordini
  • Eventi dell’ordine
  • Prodotti dell’ordine
  • Notifiche
  • Interazioni delle notifiche

Dato che stiamo prevedendo qualcosa riguardo al cliente, modelleremo la granularità del cliente.

Comprensione delle relazioni:

GraphReduce non aiuta in questa parte, quindi dovrai profilare i dati, parlare con un esperto di dati o usare tecnologie emergenti. In questo caso, lo schema è il seguente:

  • Clienti -> ordini
    • Clienti.id = ordini.id_cliente
  • Ordini -> eventi_ordini
    • Ordini.id = eventi_ordini.id_ordine
  • Ordini -> prodotti_ordini
    • Ordini.id = prodotti_ordini.id_ordine
  • Clienti -> notifiche
    • Clienti.id = notifiche.id_cliente
  • Notifiche -> interazioni_notifiche
    • Notifiche.id = interazioni_notifiche.id_notifica

Comprensione della cardinalità:

Dato che stiamo modellando al livello di dettaglio del cliente, è necessario avere una buona comprensione di come le relazioni interagiscono dal punto di vista della cardinalità. Modellare al livello di dettaglio del cliente richiede che uniamo tutte le relazioni rilevanti al cliente e riduciamo qualsiasi relazione alla granularità del cliente. Ad esempio, se il cliente ha 10 righe e una relazione figlia ordine ha 100 righe, dobbiamo ridurre l’entità dell’ordine alla granularità del cliente emettendo una aggregazione GROUP BY sull’entità dell’ordine e quindi unire nuovamente al cliente per un totale di 10 righe con informazioni sul cliente e sull’ordine aggregate / ridotte. Di solito la comprensione della granularità è abbastanza intuitiva, ma in questo caso forniremo il conteggio delle righe in modo che sia chiaro fin dall’inizio.

Le tabelle hanno i seguenti conteggi delle righe:

  • Clienti: 2 righe
  • Ordini: 4 righe
  • Prodotti dell’ordine: 16 righe
  • Eventi dell’ordine: 26 righe
  • Notifiche: 10 righe
  • Interazioni delle notifiche: 15 righe

Preparazione e filtraggio dei dati:

La preparazione dei dati comporta la rimozione dei dati errati o anomali. Questo includerà l’utilizzo di filtri, l’eliminazione di righe, la trasformazione o l’eliminazione dei valori di colonna con valori anomali o errati e l’imputazione dei valori mancanti. La preparazione dei dati avviene prima a livello di entità in modo che gli errori e le anomalie non si propaghino nell’insieme di dati aggregati. Ecco un esempio di come potrebbe apparire in Pandas nel nostro entità ordini:

Join e cardinalità:

Assumendo che ci siamo occupati della preparazione e della qualità dei dati, ora siamo pronti per unire le nostre entità dati e appiattirle in un unico dataframe a livello di cliente. La chiave per farlo correttamente è garantire che una tabella figlia venga ridotta alla granularità della tabella madre mediante un operatore GROUP BY in modo da non introdurre duplicazione dei dati. Ecco un esempio di come potrebbe apparire in Pandas:

Gestione del tempo:

Per evitare la fuoriuscita di dati, è necessario assicurarsi di utilizzare chiavi di data affidabili e filtrare correttamente i dati nel periodo di formazione e nel periodo di etichettatura. Il periodo di formazione contiene informazioni fino a una determinata data e il periodo di etichettatura contiene informazioni successive a tale data. Ciò ci consente di fornire al nostro modello i dati di addestramento e dirgli cosa è successo nel periodo futuro che sta imparando a predire. Dal momento che non stiamo lavorando con un singolo vettore di caratteristiche piatte, ma con un numero arbitrario di tabelle, dobbiamo fare attenzione a che la gestione del tempo sia la stessa in tutte le relazioni nel grafo di calcolo.

Problemi con approcci separati:

I passaggi sopra descritti verranno affrontati ogni volta che si costruiscono modelli su dati relazionali che non sono in un vettore di caratteristiche pronto per l’apprendimento automatico, il che avviene nella maggior parte dei casi. È vero che i feature store sono emersi come un’astrazione alcuni anni fa per risolvere gran parte di questo problema, ma adottano un approccio architetturale diverso rispetto a GraphReduce. Le particolarità delle differenze tra i feature store come feast, Tecton o Vertex AI feature store sono lasciate per un altro post del blog.

Astrazioni:

GraphReduce tratta le entità/tabelle come nodi e le relazioni tra di loro come archi in una struttura dati grafica. La libreria sottoclassifica networkx per sfruttare i primitive dei grafi e estendere l’interfaccia. GraphReduce fornisce un’astrazione per contenere i parametri del grafo di calcolo di alto livello:

  • Il nodo/genitore a cui ridurre i dati
  • La quantità di dati da includere nell’insieme di dati di addestramento storico
  • Una data di taglio per dividere tra il periodo di addestramento e il periodo di etichettatura
  • Parametro di backend di calcolo plug-in per l’utilizzo di Spark, Pandas o Dask
  • Parametro di formato dei dati
  • Se il grafo di calcolo sta generando etichette o meno

Anche l’oggetto GraphReduce di alto livello centralizza l’ordine delle operazioni che vengono mappate, tipicamente in modo depth-first, ai nodi nel grafo. L’oggetto GraphReduce centralizza l’orchestrazione delle operazioni di calcolo in tutto il grafo dei nodi e le operazioni di unione tra i nodi dopo le operazioni di riduzione. Il diagramma seguente illustra l’ordine delle operazioni.

L’astrazione del nodo in GraphReduce contiene le seguenti operazioni:

  • Ottenere i dati (ogni nodo è responsabile del caricamento delle proprie informazioni)
  • Filtrare i dati
  • Annotare i dati
  • Normalizzare i dati
  • Ridurre i dati
  • Preparare i dati per le caratteristiche effettuando un taglio sulla data di taglio
  • Preparare i dati per le etichette effettuando un taglio sulla data di taglio

Portando tutto insieme in questo esempio:

Istanziare l’oggetto GraphReduce con le specifiche per l’operazione di calcolo del grafo:

Istanziare i nodi su cui si sta effettuando il calcolo e aggiungerli a GraphReduce:

Esegui operazioni di calcolo

Utilizza un vettore di caratteristiche pronto per l’uso con l’apprendimento automatico e addestra un modello:

Alternativamente, potresti utilizzare SQL e fare qualcosa del genere, ma non te lo consiglio 🙂

Riassunto:

Abbiamo dimostrato un esempio di set di dati di e-commerce, problemi comuni nell’aggregazione di un vettore di caratteristiche pronto per l’apprendimento automatico da dati relazionali e astrazioni con GraphReduce. Abbiamo dimostrato che GraphReduce fornisce un’interfaccia unificata per le operazioni di calcolo su set di dati relazionali di cardinalità dinamica arbitrariamente grandi. Approfondirò ulteriormente durante il mio prossimo intervento al ODSC West.

Esempio di codice completo: https://github.com/wesmadrigal/GraphReduce/blob/master/examples/cust_order_demo.ipynb

Informazioni sull’autore:

Wes Madrigal è un esperto di apprendimento automatico con oltre un decennio di esperienza nel fornire valore aziendale con l’intelligenza artificiale. L’esperienza di Wes spazia su diverse industrie, ma con un focus su MLOps. Le sue aree di interesse recenti sono i grafi, il calcolo distribuito e i flussi di lavoro di ingegneria delle caratteristiche scalabili.