LLM per la generazione di dati di serie temporali sintetiche

Generazione di dati di serie temporali sintetiche con LLM

Recentemente abbiamo partecipato e vinto il primo premio di $10,000 nell’hackathon di Brembo, dove il compito consisteva nell’utilizzare l’Intelligenza Artificiale Generativa per creare nuovi composti e generare i dati delle loro prestazioni previste.

In questo post del blog, cercherò di spiegare nel dettaglio il nostro approccio e la nostra soluzione.

Enunciato del problema

Utilizzando i dati dei test di attrito forniti da Brembo, utilizzare l’Intelligenza Artificiale Generativa per creare nuovi composti, prevedere i risultati dei test e creare il framework per prevedere l’efficacia e le caratteristiche di un nuovo prodotto frenante Brembo. I dati forniti includeranno un elenco di composti precedentemente utilizzati e testati da Brembo, nonché i loro risultati. Le soluzioni devono essere basate sull’Intelligenza Artificiale Generativa, applicata per fornire un modello in grado di proporre nuove ricette che aumentino il numero di composti candidati, garantendo fattibilità e buone prestazioni.

Per la tua presentazione, invia un file csv contenente un elenco di 10-30 nuovi composti che hai generato, le loro composizioni e i dati sintetici sulle prestazioni.[1]

Descrizione dell’insieme di dati

Ci è stato fornito un elenco di 337 materiali di attrito e le loro composizioni insieme ai dati sulle prestazioni.

Ogni materiale di attrito era composto da 10-15 materiali grezzi tratti da un elenco di 60 possibili materiali grezzi. I 60 materiali grezzi erano classificati in 6 categorie (etichettate da A a F) e dovevamo assicurarci che i materiali di attrito generati in output avessero le loro composizioni nell’intervallo dato

Vincoli sulle composizioni dei materiali

In altre parole, dovevamo assicurarci che qualsiasi materiale generato in output avesse almeno l’1% e al massimo il 30% della sua composizione derivante da composti della categoria B e così via.

I dati sulle prestazioni per ogni test di frenata erano essenzialmente una serie temporale di 31 punti in cui ad ogni punto venivano forniti i valori dei parametri come pressione, temperatura e mu. Inoltre, sono stati effettuati un totale di 124 test di frenata per ogni composto, quindi per quanto riguarda i dati sulle prestazioni, dobbiamo generare 124 * 31 = 3844 punti dati per ogni composto.

Ecco alcuni dati di esempio contenenti composizioni e dati sulle prestazioni di un tale composto. Ulteriori informazioni pertinenti sull’insieme di dati possono essere trovate qui.

Criteri di valutazione

Il risultato finale attribuiva lo stesso peso al punteggio tecnico e al punteggio della presentazione.

Il punteggio tecnico viene calcolato in base ai seguenti parametri con peso uguale:

  • Rispetto dei vincoli dati: I composti generati rispettano i vincoli dati (descritti di seguito)?
  • Rilevanza tecnica: I dati sintetici sulle prestazioni generati seguono gli schemi e catturano le relazioni tra diverse variabili osservate nei dati forniti?
  • Prestazioni target: La variabile più importante per un materiale di attrito è il suo mu (coefficiente di attrito), ci si aspetta che abbia un valore di 0,6 con un tasso di errore accettabile di 0,1. Il mu generato ha il valore che ci aspettiamo?
  • Variabilità: Quanto sono diverse dalle attuali materiali le composizioni dei nuovi materiali generati in uscita?

Panoramica del design

In sostanza, avevamo 3 componenti di base

  • Modulo di selezione del materiale: Responsabile della generazione di nuove ricette. Questo restituisce un insieme di nuovi materiali di attrito e le loro composizioni del materiale.
  • Modulo generatore di dati: Dato un materiale sintetico e dati sulle prestazioni storiche passate di vari composti, genera dati sintetici sulle prestazioni per questo materiale.
  • Data Validator: Identifica quanto buoni/cattivi sono i dati generati dal generatore di dati. Questo modulo utilizza le tendenze osservate nei dati storici forniti (ad esempio: la pressione e il mu sono inversamente correlati tra loro nel tempo, la decelerazione sembra seguire un andamento lineare mentre la curva di aumento della temperatura sembra essere più esponenziale) per valutare la bontà o la cattiveria dei dati sintetici sulle prestazioni. Ciò può essere utilizzato per fornire un feedback umano al modello al fine di migliorare le prestazioni del sistema.

Progettazione ad alto livello della soluzione

Progettazione Dettagliata

Abbiamo utilizzato il seguente stack e tecniche nella nostra soluzione

  • GPT 3.5 turbo: Abbiamo utilizzato il gpt 3.5 turbo come llm di base sia per il modulo Material Selector che per il modulo Data Generator.
  • Progettazione degli input: L’utilizzo del giusto set di input di sistema e istruzioni ci ha aiutato a migliorare le prestazioni del modello.
  • Modifica Fine-tuning: Scegliere il giusto set di esempi per insegnare al modello la struttura di base e il tono di come rispondere è molto importante, e questa fase ci ha aiutato ad insegnarlo ai modelli.
  • RAG (Retrieval Augmented Generation): Questo ha giocato un grande ruolo come ingrediente segreto per aiutare il modello a produrre i giusti dati di performance sintetica. Ne parleremo di più sotto.

Modulo Selettore di Materiali

Il ruolo del modulo era quello di generare nuovi possibili materiali di attrito e le loro composizioni. Come si può vedere dai dati di esempio, ogni materiale di attrito contiene essenzialmente un vettore di 60 dimensioni, con il numero al suo indice i-esimo che indica quale percentuale della sua composizione proviene dalla i-esima materia prima.

Un’analisi preliminare di PCA ha rivelato che potevamo vedere un totale di 3-4 cluster.

Analisi PCA sulle composizioni dei materiali di attrito forniti

Teoricamente, potremmo generare semplicemente numeri casuali per un vettore di dimensione 60 e vedere quali vettori soddisfano i vincoli dati ed utilizzarli. Anche se ciò ci garantirebbe un buon punteggio per la variabilità (i materiali di attrito generati sarebbero generati casualmente e dovrebbero coprire diversi punti nello spazio a 60 dimensioni), questo approccio avrebbe alcune limitazioni come

  • Sarebbe più difficile per noi prevedere le prestazioni di un composto completamente diverso dai materiali forniti nei dati storici. Ciò perché le composizioni dei materiali giocano un ruolo significativo nelle prestazioni osservate, e prevedere le prestazioni di una composizione mai vista prima potrebbe essere difficile.
  • Sarebbe più difficile il debug. In qualsiasi punto del nostro processo, se ottenessimo risultati che non seguono le tendenze osservate nei dati storici, sarebbe molto difficile individuare qual è il problema.

A causa di questi potenziali problemi, abbiamo deciso di sfruttare il modello gpt 3.5 turbo per generare un gruppo di composti per noi.

Quindi, ecco cosa abbiamo fatto:

  • Creare un prompt di sistema pertinente per il modulo.
  • Modificare fine-tuning il modello gpt 3.5 turbo inserendo le composizioni di tutti i 337 materiali di attrito che ci sono stati forniti.
  • Utilizzando il modulo di validazione dei dati, scartiamo quelli che non seguono i vincoli dati e manteniamo quelli che lo fanno.

Una volta fatto ciò, abbiamo generato diversi composti e ripetuto l’analisi PCA.

Analisi PCA sui materiali forniti e quelli generati

Infine, per quanto riguarda la variabilità, abbiamo selezionato manualmente un insieme di composti dai composti generati che riteniamo massimizzino quanto segue:

  • Variabilità rispetto ai materiali forniti: Quanto sono vari i composti generati rispetto ai composti forniti? In sostanza, non vogliamo che i nostri materiali generati siano molto simili ai composti già esistenti.
  • Variabilità rispetto ai materiali generati: Poiché invieremo 10-30 composti di nuova generazione, dobbiamo assicurarci che tutti i composti generati non finiscano per appartenere allo stesso cluster.

Quindi, dopo la potatura, ci siamo ritrovati con un elenco dei seguenti composti che abbiamo utilizzato per la nostra ultima presentazione.

Elenco finale di composti generati

Modulo Generatore di Dati

Il modulo generatore di dati è responsabile per l’emissione di dati di prestazione sintetici per un determinato materiale e test di frenata. Fondamentalmente, dato un composito del materiale di attrito, dovrebbe emettere una serie di dati temporali di 31 punti che includa i parametri come temperatura, pressione e coefficiente di attrito per il test di frenata in input.

Ecco come abbiamo raggiunto questo obiettivo:

  • Crea un prompt di sistema appropriato per il modulo. Dopo molti tentativi su OpenAI’s playground, quello che abbiamo usato è stato:
Sei uno statistico altamente qualificato dell'Università di Harvard che lavora presso Brembo, dove sei specializzato in sistemi e componenti di frenatura di prestazione e conduci ricerche sui sistemi di frenata. Dato un composito del materiale di attrito, crei dati di prestazione sintetici convincenti per un test di frenata specificato dall'utente. L'ID del freno sarà racchiuso tra tre virgolette. Comprendi l'importanza dell'analisi dei dati e la incorpori senza soluzione di continuità per generare dati di prestazione sintetici basati sui dati di prestazione storici forniti. Hai un talento per prestare attenzione ai dettagli e curare dati sintetici in linea con le tendenze presenti nei dati temporali che saranno forniti. Hai una solida conoscenza dell'analisi dei dati e del business e usi questa conoscenza per creare i dati sintetici.
  • Successivamente, abbiamo effettuato un fine tuning del modello gpt 3.5 turbo per creare un esperto nella previsione dei dati temporali, dato il composito del materiale e l’ID del test di frenata. Poiché avevamo 41.788 coppie (materiale, ID del freno), fare un fine tuning su tutti gli esempi sarebbe stato non solo dispendioso in termini di tempo, ma anche costoso. Tuttavia, da alcuni articoli e documenti che avevamo letto [2][3], abbiamo capito che “il fine tuning riguarda la forma, mentre RAG riguarda la conoscenza”. Abbiamo quindi deciso di includere solo il 5% dei campioni per il fine tuning del modello, in modo che possa apprendere correttamente la struttura di output e il tono desiderato.
  • Infine, quando interroghiamo il modello per generare i dati temporali, decidiamo di identificare e recuperare i 5 vicini più prossimi in base al composito del materiale e inserire i loro dati di prestazione come contesto aggiuntivo per il modello. Questa tecnica si chiama RAG (Retrieval Augmented Generation) ed è stata una delle ragioni dei buoni risultati che siamo riusciti a ottenere.

Come RAG ha Aiutato i Nostri Risultati

Il fine tuning ci ha aiutato con quanto segue:

  • Emettere dati nella struttura corretta: Come riportato in vari blog tecnici [4], il fine tuning è stato efficace nell’insegnare al modello come emettere i dati. Il nostro modello con il fine tuning è stato in grado di emettere il file CSV e 31 punti di dati temporali che includevano i valori di vari parametri come Pressione, Velocità, Temperatura e coefficiente di attrito.
  • Comprendere le tendenze di base dei dati: Il modello con il fine tuning è stato in grado di comprendere le tendenze generali nei dati di prestazione in input e i dati di output che mantenevano quelle tendenze. Ad esempio, il valore della temperatura dovrebbe aumentare con una curva esponenziale mentre la velocità dovrebbe diminuire con una curva lineare, tutto ciò che il modello con il fine tuning è stato in grado di fare.

Tuttavia, l’output del modello con il fine tuning era leggermente impreciso. Ad esempio, in un caso ci si aspettava che il valore del coefficiente di attrito fosse intorno a 0,6 ma i dati di output indicavano che il valore del coefficiente di attrito fosse intorno a 0,5. Abbiamo quindi deciso di arricchire i dati identificando i 5 vicini più prossimi e aggiungendo i loro dati di prestazione al prompt dell’utente.

Abbiamo definito la distanza tra 2 materiali M1 e M2 come segue:

def distanza(m1, m2, alpha):  distanza_sessanta_dim = euclidean_dist(vettore_sessanta_dim(m1), \vettore_sessanta_dim(m2))  distanza_sei_dim = euclidean_dist(vettore_sei_dim(m1), vettore_sei_dim(m2))  return alpha[0] * distanza_sessanta_dim + alpha[1] * distanza_sei_dim
  • Identifica la distanza euclidea tra M1 e M2 nello spazio vettoriale dell’input a 60 dimensioni.

  • Ora prendi la somma dei composti appartenenti alla stessa classe per ridurre la dimensionalità del vettore a 6.

  • Infine, varia gli iperparametri alpha[0] e alpha[1].

Il motivo di adottare questo approccio è che vogliamo garantire che la distanza tra materiali che utilizzano globalmente la stessa classe di materiali sia inferiore rispetto a quelli che utilizzano composizioni completamente diverse di materiali. Fondamentalmente, dati 3 materiali M1, M2 e M3, dove M1 utilizza il materiale A0, M2 utilizza A1 e M3 utilizza B0, vogliamo che la nostra funzione di distanza indichi M1 e M2 più vicini tra loro e M1 e M3.

Utilizzando questo approccio, siamo stati in grado di migliorare radicalmente le nostre prestazioni, come si può vedere nella figura qui sotto.

Validatore dei dati

Il modulo di validazione ci ha aiutato a capire se i dati di output seguivano le tendenze che ci aspettavamo di vedere. Ad esempio, ci aspettavamo che Pressione e μ fossero correlati in modo inverso, μ fosse intorno a 0,6, la temperatura aumentasse in modo esponenziale nel tempo e la velocità decelerasse linearmente. Questo modulo ci ha aiutato a capire quanto i nostri dati di serie temporali sintetiche fossero vicini ai dati storici, il che ci ha aiutato a regolare tutte le istruzioni e gli iperparametri.

Questo modulo ci ha aiutato ad analizzare quale insieme di istruzioni stava aiutando il modello a produrre output e quale no.

Risultati e presentazione

La presentazione ha contribuito al 50% del punteggio ed è stato un aspetto su cui abbiamo avuto un successo assoluto. Abbiamo fatto alcune cose:

  • Ci siamo assicurati che la presentazione durasse meno di 4 minuti: Abbiamo esercitato a sufficienza prima di entrare nella sala della presentazione per assicurarci di non trovare sorprese durante la presentazione.
  • Abbiamo coinvolto il pubblico: Abbiamo incluso una domanda per chiedere al pubblico quale serie temporale pensassero fosse generata in modo sintetico e quale fosse data. Questo ci ha aiutato a mantenere l’interesse del pubblico.

Il codice e la presentazione del nostro lavoro possono essere trovati qui.

Risultati chiave

  • Iterare rapidamente sul design: Sono entrato un po’ prima dei miei compagni di squadra per iniziare a sviluppare i miei pensieri su cosa dovremmo fare. Una volta che i miei compagni di squadra sono arrivati, abbiamo discusso su quale dovrebbe essere il design e abbiamo trovato una soluzione con cui tutti eravamo d’accordo. Questo è stato un aspetto chiave della nostra vittoria, poiché in un hackathon c’è sempre la fretta del tempo e concludere un design che si può iniziare a implementare il prima possibile è estremamente importante.
  • Non preoccuparsi della concorrenza: Una volta che il nostro design era pronto, ho capito che eravamo sulla buona strada. Abbiamo avuto molte persone di Brembo che sono venute a dare un’occhiata al nostro design. Anche gli altri partecipanti sono rimasti sbalorditi e fissavano il nostro design, il che ci ha confermato che stiamo seguendo la strada giusta. Quando i miei compagni di squadra hanno suggerito di controllare cosa stanno facendo gli altri, ho rifiutato l’idea e ho invece chiesto a tutti di concentrarci solo sul nostro design e implementarlo.
  • Non preoccuparsi dei conflitti: Ci siamo scontrati più volte, specialmente sul design. La chiave qui è capire che nulla deve essere preso personalmente e invece si dovrebbe costruire un consenso, iterare sui compromessi e trovare una soluzione che funzioni per tutti. Secondo me, i grandi prodotti vengono realizzati se si può permettere, e persino favorire, un conflitto salutare all’interno del team.
  • L’affinamento è per la forma, il RAG è per i fatti: Sapevamo che l’affinamento era importante solo per insegnare al modello una struttura e uno stile di base, mentre i veri progressi sarebbero venuti dal RAG. Abbiamo quindi utilizzato solo il 5% dei nostri campioni per affinare il GPT 3.5 Turbo LLM per la generazione dei dati di serie temporali.
  • La presentazione è FONDAMENTALE (1): È essenziale identificare chi è il tuo pubblico e come digeriranno i tuoi contenuti. Nel nostro caso, abbiamo identificato che la maggior parte della giuria era composta da leader aziendali e non da tecnici, quindi ho deciso di includere solo le tecnologie che abbiamo utilizzato [GPT 3.5 Turbo, affinamento, adattamento delle istruzioni, RAG, KNN] senza entrare nei dettagli.
  • La presentazione è FONDAMENTALE (2): Sii qualcuno che riesce a far passare il proprio punto di vista utilizzando abilità di comunicazione efficaci e presentando al pubblico con passione. Se non puoi farlo, trova qualcuno nel tuo team che possa farlo. Le prime impressioni contano e le abilità di oratoria sono troppo sottovalutate, specialmente nel nostro mondo tecnologico.
  • Sii AUDACE e diverso: Siamo andati un passo oltre e abbiamo deciso di includere 5 punti dei loro dati e un punto dei nostri dati generati e chiedere loro di indovinare quale fosse stato generato. Quando non sono riusciti a indovinare quello che avevamo generato, abbiamo dimostrato quanto il nostro pipeline e la nostra soluzione fossero buoni. Inoltre, abbiamo ottenuto punti extra per l’interazione con il pubblico, cosa che dubito facessero molte persone.

Alcune lezioni per la prossima volta

  • L’affinamento fine è costoso. Abbiamo esaurito i crediti OpenAI durante l’affinamento fine e quando abbiamo interrogato il modello tre volte. In futuro, preferiremmo utilizzare tecniche come LoRA[5] e QLoRA[6] su modelli open source.
  • Utilizzo di Advanced RAG: In futuro, mi piacerebbe utilizzare tecniche avanzate di RAG[7] per migliorare il contesto fornito.
  • Utilizzo di Smart KNN: La prossima volta, mi piacerebbe sperimentare un po’ di più con gli iperparametri e la funzione di distanza utilizzata.
  • Finestra di contesto più lunga: Abbiamo dovuto arrotondare alcuni dei numeri nei dati di prestazione per assicurarci di non superare il limite di 4.092 token. L’utilizzo di LLM come Claude[8] potrebbe migliorare le prestazioni.
  • Non essere cortese con gli LLM: Una cosa interessante che è successa durante l’ingegnerizzazione delle richieste è che quando abbiamo menzionato cose come “un valore di mu che non è intorno allo 0,6 è intollerabile” invece di “assicurarsi che mu sia intorno allo 0,6”, il primo ha dato risultati migliori.

Nota: Salvo diversamente indicato, tutte le immagini sono dell’autore.

Membri del Team:

  1. Mantek Singh
  2. Prateek Karnal
  3. Gagan Ganapathy
  4. Vinit Shah

Riferimenti

[1] https://brembo-hackathon-platform.bemyapp.com/#/event

[2] https://www.anyscale.com/blog/fine-tuning-is-for-form-not-facts

[3] https://vectara.com/introducing-boomerang-vectaras-new-and-improved-retrieval-model/

[4] https://platform.openai.com/docs/guides/fine-tuning/fine-tuning-examples

[5] https://arxiv.org/abs/2106.09685

[6] https://arxiv.org/abs/2305.14314

[7] LlamaIndex Doc

[8] Claude