RecList 2.0 Test sistematico open-source dei modelli di ML
RecList 2.0 - Test open-source dei modelli di ML
Una nuova RecList per fornire maggiore flessibilità e un migliore supporto per la valutazione

Introduzione
La valutazione è una questione complessa. Spesso è difficile gestire i diversi componenti coinvolti nella scrittura delle pipeline di valutazione: devi avere il tuo modello da qualche parte, devi caricarlo, ottenere il test, eseguire i test, e così via.
E poi? Beh, devi salvare i risultati da qualche parte e magari registrare gli output online in modo da poter tenerne traccia.
Dato che questa è sempre una procedura difficile, di recente abbiamo cercato di fornire un modo più strutturato per effettuare i test. In questo post del blog, presentiamo e mostriamo come utilizzare RecList beta, il nostro pacchetto open-source per la valutazione; RecList è un approccio generale plug-and-play per scalare i test, con un’interfaccia facile da estendere per casi d’uso personalizzati. RecList è un progetto open-source liberamente disponibile su GitHub.
RecList ti permette di separare la parte di valutazione del tuo codice e di incapsularla in una classe che gestisce automaticamente diverse altre cose (ad esempio, l’archiviazione e la registrazione).
- Un’opinione sull’Intelligenza Artificiale ispirata al cervello. Da dove andiamo da qui?
- Implementare e Allenare una CNN da Zero con PyTorch Lightning
- Miglioramento delle pipeline RAG in Haystack Introduzione di DiversityRanker e LostInTheMiddleRanker

Abbiamo iniziato a lavorare su RecList un paio di anni fa e la versione alpha di RecList è uscita poco più di un anno fa. Da allora, RecList ha raccolto oltre 400 stelle su GitHub.
Abbiamo utilizzato RecList e lo abbiamo sottoposto a test di stress per organizzare una sfida RecSys al CIKM nel 2022 e attualmente ci stiamo preparando per una prossima sfida al KDD 2023. RecList ci ha permesso di sistematizzare la valutazione per tutti i partecipanti. L’idea è che, una volta che a tutti viene fornita la stessa RecList, confrontare diverse valutazioni diventa facile. Un riassunto della nostra esperienza appare nel nostro commento su Nature Machine Intelligence.
RecList è stato originariamente presentato in un articolo accademico, ma abbiamo anche una panoramica generale che è stata presentata in una pubblicazione di Towards Data Science che puoi leggere qui:
NDCG non è tutto ciò di cui hai bisogno
Testing comportamentale per recSys con RecList
towardsdatascience.com
Chia, P. J., Tagliabue, J., Bianchi, F., He, C., & Ko, B. (2022, aprile). Oltre l’nDCG: Testing comportamentale dei sistemi di raccomandazione con RecList. Nei Companion Proceedings del Web Conference 2022 (pp. 99–104).
Anche se RecList è stato originariamente progettato per il testing dei sistemi di raccomandazione, nulla impedisce di utilizzarlo per il testing di altri modelli di apprendimento automatico. Quindi, perché c’è un nuovo post sul blog? Beh, dopo aver sviluppato la prima versione ci siamo resi conto che aveva bisogno di alcuni aggiornamenti.
Cosa abbiamo imparato: Ripensare a un’API
Spesso è solo dopo aver costruito qualcosa che si capisce come migliorarla.
Per coloro che hanno utilizzato RecList 1.0, abbiamo apportato importanti aggiornamenti all’API di RecList. Originariamente, avevamo vincoli più rigidi sulla struttura del codice e sulle coppie di input/output.
Infatti, quando abbiamo implementato RecList, volevamo fornire un’API più generale per la valutazione dei sistemi di raccomandazione che offrisse diverse funzionalità già pronte all’uso. Tuttavia, per fare ciò abbiamo dovuto creare diverse interfacce astratte che gli utenti dovevano implementare.
Ad esempio, la versione originale di RecList 1.0 richiedeva agli utenti di incapsulare i propri modelli e set di dati in classi astratte predefinite (ad esempio, RecModel e RecDataset). Questo ci ha permesso di implementare un insieme comune di comportamenti che erano collegati da queste astrazioni. Tuttavia, presto ci siamo resi conto che questo poteva spesso complicare i flussi e richiedeva molto lavoro aggiuntivo che a alcune persone potrebbe non piacere.
In RecList 2.0 abbiamo deciso di rendere facoltativi questi vincoli: abbiamo reso i test molto più flessibili. Gli utenti definiscono il proprio caso di valutazione, lo avvolgono con un comodo decorator e ottengono già implementata la memorizzazione dei metadati e il logging. Gli utenti possono quindi condividere l’interfaccia di test con altre persone e possono eseguire esperimenti identici.
Riepilogo: abbiamo capito quanto sia importante la flessibilità quando costruiamo software che altre persone devono utilizzare.
RecList 2.0 In Azione
Ora, esploriamo un caso d’uso semplice su come utilizzare RecList per scrivere ed eseguire una pipeline di valutazione. Utilizzeremo modelli molto semplici che restituiscono numeri casuali per ridurre la complessità coinvolta nella realizzazione di un progetto di machine learning.
Un Caso D’uso Semplice
Creiamo un caso d’uso molto semplice con un dataset molto semplice. Supponiamo di avere una sequenza target di interi, ognuno con una categoria associata. Semplicemente genereremo alcuni dati casuali.
n = 10000target = [randint(0, 1) for _ in range(n)]metadata = {"categories": [choice(["rosso", "blu", "giallo"]) for _ in range(n)]}
Il nostro dataset molto semplice dovrebbe apparire più o meno così:
>>> target[0, 1, 0, 1, 1, 0]>>> metadata{"categories" : ["rosso", "blu", "giallo", "blu", "giallo", "giallo"]}
Un Modello Semplice
Supponiamo ora di avere un DummyModel che restituisce interi casuali. Ovviamente, come abbiamo detto, questo non è un modello “buono”, ma è una buona astrazione che possiamo utilizzare per vedere un’intera pipeline di valutazione.
class DummyModel: def __init__(self, n): self.n = n def predict(self): from random import randint return [randint(0, 1) for _ in range(self.n)]simple_model = DummyModel(n)# facciamo alcune previsionipredictions = simple_model.predict()
Ora, come eseguiamo le valutazioni?
Una RecList Semplice
Una RecList è una classe Python che eredita funzionalità dalla nostra classe astratta RecList. RecList implementa RecTests, semplici astrazioni che ti permettono di sistematizzare la valutazione. Ad esempio, questo potrebbe essere un possibile test di accuratezza.
@rec_test(test_type="Accuratezza", display_type=CHART_TYPE.SCALAR)def accuratezza(self): """ Calcola l'accuratezza """ from sklearn.metrics import accuracy_score return accuracy_score(self.target, self.predictions)
Stiamo prendendo la metrica di accuratezza di sklearn e la stiamo incapsulando in un altro metodo. Cosa rende diverso questo da una semplice funzione di accuratezza? beh, il decorator ci permette di avere alcune funzionalità aggiuntive: ad esempio, il rectest memorizzerà automaticamente le informazioni in una cartella locale. Inoltre, definire un tipo di grafico ci permette di creare alcune visualizzazioni per questi risultati.
Cosa succede se vogliamo un test più sofisticato? Ad esempio, se vogliamo vedere quanto stabile è la nostra accuratezza tra le diverse categorie (ad esempio, l’accuratezza calcolata sugli oggetti rossi è maggiore rispetto agli oggetti gialli?)
@rec_test(test_type="AccuratezzaPerCategoria", display_type=CHART_TYPE.SCALAR)def accuratezza_per_categoria(self): """ Calcola l'accuratezza per categoria """ from reclist.metrics.standard_metrics import accuracy_per_slice return accuracy_per_slice( self.target, self.predictions, self.metadata["categories"])
Ora, vediamo un esempio di una RecList completa!
class BasicRecList(RecList): def __init__(self, target, metadata, predictions, model_name, **kwargs): super().__init__(model_name, **kwargs) self.target = target self.metadata = metadata self.predictions = predictions @rec_test(test_type="AccuratezzaPerCategoria", display_type=CHART_TYPE.SCALAR) def accuratezza_per_categoria(self): """ Calcola l'accuratezza per categoria """ from reclist.metrics.standard_metrics import accuracy_per_slice return accuracy_per_slice( self.target, self.predictions, self.metadata["categories"] ) @rec_test(test_type="Accuratezza", display_type=CHART_TYPE.SCALAR) def accuratezza(self): """ Calcola l'accuratezza """ from sklearn.metrics import accuracy_score return accuracy_score(self.target, self.predictions) @rec_test(test_type="AccuratezzaPerPaese", display_type=CHART_TYPE.BARS) def accuratezza_per_paese(self): """ Calcola l'accuratezza per paese """ # TODO: nota che questo è un test statico, # utilizzato per mostrare la visualizzazione a barre from random import randint return {"US": randint(0, 100), "CA": randint(0, 100), "FR": randint(0, 100)}
Pochissime righe di codice sono necessarie per mettere tutto ciò di cui abbiamo bisogno in un unico posto. Possiamo riutilizzare questo pezzo di codice per nuovi modelli, o aggiungere test e eseguire nuovi modelli passati.
Fintanto che le tue metriche restituiscono dei valori, puoi implementarle nel modo che preferisci. Ad esempio, questa BasicRecList valuta un modello specifico in un contesto specifico. Ma nulla ti impedisce di generare altre reclist specifiche per il modello (ad esempio, GPT-RecList) o specifiche per il dataset (ad esempio, IMDB-Reclist). Se vuoi vedere un esempio di un modello profondo su RecList, puoi controllare questo colab.
Esecuzione e Ottenimento degli Output
Eseguiamo la RecList. Abbiamo bisogno dei nostri dati target, dei metadati e delle previsioni. Possiamo anche specificare un logger e un metadata store.
rlist = BasicRecList( target=target, metadata=metadata, predictions=predictions, model_name="myRandomModel",)# esegui reclistrlist(verbose=True)
Cosa otteniamo con questa procedura? Ciò che vedremo nella nostra riga di comando è il seguente insieme di risultati: per ogni test, abbiamo un punteggio effettivo.
Le metriche vengono anche automaticamente rappresentate graficamente. Ad esempio, l’AccuracyByCountry dovrebbe mostrare qualcosa di simile a questo:

In aggiunta a questo, RecList salva un file JSON che contiene tutte le informazioni degli esperimenti appena eseguiti:
{ "metadata": { "model_name": "myRandomModel", "reclist": "BasicRecList", "tests": [ "sliced_accuracy", "accuracy", "accuracy_by_country" ] }, "data": [ { "name": "SlicedAccuracy", "description": "Calcola l'accuratezza per slice", "result": 0.00107123176804103, "display_type": "CHART_TYPE.SCALAR" },...}
La cosa interessante è che con poche righe di codice aggiuntive, la maggior parte del logging viene gestita automaticamente!
Utilizzo di Loggers e Metadata Storage Online
Di default, il runner di RecList utilizzerà il seguente setup per il logger e i metadati.
logger=LOGGER.LOCAL,metadata_store= METADATA_STORE.LOCAL,
Tuttavia, nulla ci impedisce di utilizzare soluzioni online e cloud. Ad esempio, abbiamo incluso il supporto per le API di CometML e Neptune in modo da poterle utilizzare direttamente nel tuo pipeline di valutazione. Offriamo anche il supporto per l’archiviazione dei dati su S3.
Ad esempio, aggiungendo un paio di parametri alla BasicReclist ci permetterà di registrare informazioni su Neptune (offriamo un supporto simile per Comet.ml)!
rlist = BasicRecList( target=target, model_name="myRandomModel", predictions=predictions, metadata=metadata, logger=LOGGER.NEPTUNE, metadata_store= METADATA_STORE.LOCAL, NEPTUNE_KEY=os.environ["NEPTUNE_KEY"], NEPTUNE_PROJECT_NAME=os.environ["NEPTUNE_PROJECT_NAME"],)# esegui reclistrlist(verbose=True)
In modo molto simile, aggiungendo il seguente:
bucket=os.environ["S3_BUCKET"]
ci permetterà di utilizzare un Bucket S3 per archiviare i metadati (ovviamente, dovrai impostare alcune chiavi di ambiente anche per questo).
Conclusioni
Ecco tutto! Abbiamo creato RecList per rendere la valutazione nei Sistemi di Raccomandazione più sistematica e organizzata. Speriamo che questa grande ristrutturazione dell’API possa aiutare le persone a costruire pipeline di valutazione più affidabili!
Ringraziamenti
Tra giugno e dicembre 2022, lo sviluppo della nostra versione beta è stato supportato dagli incredibili collaboratori di Comet, Neptune, Gantry e sviluppato con l’aiuto di Unnati Patel.