Coder Social home page Coder Social logo

orange_cb_recsys's People

Contributors

blackienbad avatar itsfrank98 avatar m-elio avatar m3ttiw avatar marcopoli avatar p4lmiotta avatar rbarile17 avatar silleellie avatar yukiroby avatar

Stargazers

 avatar  avatar

orange_cb_recsys's Issues

Restituire score vuoto anziché lanciare eccezione se condizioni di classificazione non soddisfatte

Come descritto in #30, i classificatori funzionano solo se sono presenti gli item valutati in locale e se ce n'è almeno uno negativo e uno positivo. Anziché lanciare eccezione però, restituire risultato vuoto se tali condizioni non vengono rispettate cosicché i fit della classe ReportEvalModel e RankingEvalModel funzionino e continuino.
Questa soluzione si basa su quella già adottata sul ranking_algorithm CentroidVector(), in quanto se non sono presenti item valutati in locale, viene restituito score vuoto.

Import verbosi

Dopo aver completato #84, procedere alla finale semplificazione dei vari import, per ridurre al minimo la loro verbosità

Numerose semplificazioni nella fase di configurazione

Nella fase di configurazione l'intero processo è stato snellito mantenendo salde la flessibilità del framework:

  • Ogni field di interesse dovrà essere specificato tenendo a mente la seguente impostazione. Viene mantenuta la possibilità di specificare più rappresentazioni per uno stesso field e specificare più preprocessor:
movies_ca_config.append_field_config(
    field_name='Plot'
    config_list = [
        FieldConfig(WhooshTfIdf(), NLTK(stemming=True), 'whooshtfidf'),  # id specificato, else automaticamente a 0
        FieldConfig(SkLearnTfIdf)  # id automatico a 1
        FieldConfig(SkLearnTfIdf, [NLTK(stemming=True), NLTK(lemmatization=True)])  # id automatico a 2
    ]
)
  • Alla stessa stregua, le eventuali rappresentazioni esogene dovranno essere specificate tenendo a mente il seguente schema. La possibilità di specificare più rappresentazioni esogene per uno stesso contenuto è mantenuto:
movies_ca_config.append_exo_config(
    exo_config_list = [
        ExogenousConfig(DBPedia(), 'dbpedia_exo')
        ExogenousConfig(PropertiesFromDataset()) # id automatico a 1
    ]
)
  • Rimossa attualmente la possibilità di specificare un memory processor aggiuntivo oltre l'indice creato automaticamente dalla tecnica di produzione SearchIndexing(). Non se ne vede l'utilità, seguirà aggiornamento dopo essersi interfacciati con il commitente

Cambiare progress bar per una migliore gestione dei log

La progress bar attualmente in uso in (poche parti del codice ancora) non permette un uso efficace dei log, in quanto se si vuole printare qualcosa a schermo mentre c'è la progress bar, è presente qualche glitch grafico.

Migliorare logging e fix log assente su Colab

Ridurre i messaggi rumorosi per l'utilizzatore del framework al minimo e migliorare in generale la fase di logging, soprattutto riguardante l'EvalModel, che per natura richiama i moduli del recsys più e più volte per i vari split, visualizzando dunque più e più volte anche i suoi vari messaggi di log.

Inoltre risolvere anche il problema per cui il logging negli ambienti IPython non risulta essere presente

Alcune query SPARQL di DBPediaMappingTechnique non sono corrette

I problemi riscontrati:

  • Se si vuole cercare una resource su DBPedia avente label con punteggiatura (si pensi ad esempio alla serie tv 11.22.63), la query viene creata "pulendo" il label da cercare togliendo la punteggiatura (seguendo l'esempio di prima avremmo 11 22 63), non facendo così hit con la resource cercata
  • Se vengono passati additional_filters, tali filtri non vengono trovati nelle proprietà di DBPedia nonostante invece esistano
  • Se vengono passati additional_filters e tali filtri non vengono trovati nelle proprietà di DBPedia, il programma crasha invece di continuare senza tener conto di tali filtri

Delegare la produzione di contenuto alla content_technique

Come da titolo, si preferisce far sì che l'istanziazione dei contenuti sia delegata alle tecniche di contenuto piuttosto che al ContentsProducer, in quanto ognuna necessita di una creazione del contenuto in maniera diversa, delegando la sua produzione al produttore di contenuti non si permette una corretta astrazione (if innestati e quant'altro).
Esso dovrà quindi essere eliminato poiché non ha più ragion d'essere, e la classe di controllo ContentAnalyzer nel metodo fit() dovrà invece sfruttare polimorficamente i metodi di produzione di contenuto definiti in ogni tecnica. In pseudo-codice:

for technique in config.technique_list:
    technique.produce_content()

Nello specifico, in pseudo-codice si illustra il funzionamento di produce_content() per ogni tecnica attualmente presente nel framework:

CollectionBasedTechnique

def produce_content():
    # eseguire preprocessing
    # fit
    for field di interesse specificato:
        # transformer()

SingleContentBasedTechnique

def produce_content():
    # eseguire preprocessing
    for field di interesse specificato:
        # transformer()

IndexBasedTechnique

def produce_content():
    # creazione indice
    # eseguire preprocessing
    for field di interesse specificato:
        # aggiungere il valore del field all'indice

Automatizzare e migliorare l'integrazione dell'EmbeddingLearner nel framework

La classe EmbeddingLearner permette l'addestramento di modelli di embedding (come quelli di Gensim) e il loro salvataggio in locale.
Tuttavia, questa classe è ad un livello di astrazione tale da poter essere considerata come un modulo a sè stante alla pari del modulo Content Analyzer (nonostante sia utile per una sola tecnica di produzione dei contenuti, ovvero quella che fa riferimento agli embedding). Un'ulteriore conseguenza di questa situazione, è la staticità dell'EmbeddingLearner, non vi è nessun modo di effettuare un addestramento automatico durante la fase di creazione dei contenuti.
Quello che si richiede, quindi, è il modificare l'EmbeddingLearner in modo tale da permettere l'addestramento dinamico ed automatizzato durante il processo di creazione dei contenuti, mantenendo però disponibile la possibilità, per utenti esperti, di utilizzare l'EmbeddingLearner autonomamente.
A questo fine, l'EmbeddingLearner dovrebbe essere integrato nell'EmbeddingSource in modo da avere un utilizzo comodo ed intuitivo direttamente legato alle EmbeddingTechnique.

Migliorare astrazione EmbeddingSource per supportare diverse granularità

Al momento, tutte le EmbeddingSource ragionano con granularità word.
Questo vale anche per le EmbeddingTechnique, sia SentenceEmbeddingTechnique che DocumentEmbeddingTechnique producono i loro EmbeddingField a partire dagli embedding delle parole e combinandoli.
Questo però è molto limitante, perchè significa che diventa infattibile utilizzare dei modelli di embedding che lavorano con una granularità diversa da word (un esempio è Sbert, un framework che permette di ottenere gli embedding delle frasi).
Si necessita quindi di modificare l'astrazione di EmbeddingSource per permettere l'aggiunta di classi che lavorano con granularità diverse da word, come ad esempio sentence e document, e di modificare EmbeddingTechnique in modo complementare a questi cambiamenti.

Realizzare una prima versione stabile della Feature Selection

Al momento, la Feature Selection all'interno del framework è in uno stato molto basilare e non sembra restituire dei risultati attendibili. Si vuole quindi andare a migliorare la Feature Selection sia da un punto di vista progettuale (migliorandone l'astrazione) sia da un punto di vista implementativo (migliorando il funzionamento dell'algoritmo di Feature Selection).

Si sottolinea che l'obiettivo è arrivare ad una versione stabile e funzionante (eventuali ulteriori miglioramenti potranno essere portati a compimento in futuro)

Classificatore SVM esegue necessariamente la cross-validation, lanciando eccezione in molti casi

Come da titolo. Il classificatore SVM viene calibrato attraverso CalibratedClassifierCV() di sklearn, che prevede l'esecuzione della cross validation. Tuttavia ciò non è sempre possibile, ed è stata già proposta una soluzione in #27:
in base a quanti rated_items sono disponibili, viene abbassato dinamicamente il numero di fold fino ad un minimo di 2.

Tuttavia anche effettuare la cross validation con 2 fold in molti casi non è possibile, quindi si può pensare di non effettuare questa calibrazione aggiuntiva in tali casi.

Pulire stdout

La console è molto densa di testo non molto significativo. Iniziare a pulirla inserendo ad esempio una progress bar quando vengono caricati gli item, e eliminare messaggi di "element not found" poiché non rilevanti e comunque gestiti nel codice.

Refactor di classifier.py

Il modulo in oggetto presenta alcune problematiche di codice che suggeriscono un refactor quantomento parziale. Alcune criticità sono:

  • Parametri del costruttore di ClassifierRecommender eccessivamente verbosi. Esempio:
    Per specificare di voler usare più campi sia il campo Plot che il campo Year, bisogna passare a ClassifierRecommender() _item_fields=["Plot", "Year"], inoltre va passata la rappresentazione per ognuno di essi
    _fields_representations={"Plot": ["0"], "Year": ["0"]}. Ma basterebbe quest'ultima informazione per derivare la prima. Poi nelle rappresentazioni nonostante volessimo passare solo una rappresentazione per campo, bisogna passarla racchiusa in una lista, cosa poco intuitiva. Se invece volessimo passare solo un field, va passato il parametro item_field="Plot" e rappresentazione dell'item field_representation="0" facendo salire così a 4 il numero di parametri che è possibile specificare con uno. Il sunto è: fare controlli da codice e non delegare all'utente quest'eccessiva verbosità.

  • Prevedere classi e modularizzare l'uso dei classificatori. Ora come ora per specificare il classificatore da voler usare si deve passare una stringa al costruttore di ClassifierRecommender ("svm" ad esempio). Si può pensare di passare invece un oggetto del tipo SVM(). Questo permetterebbe un'ulteriore modularizzazione del metodo predict, molto denso di codice.

Migliorare astrazione tecniche di produzione che utilizzano l'indice

Attualmente l'unica tecnica adibita alla creazione dei contenuti con l'indice è la classe SearchIndexing, che tuttavia non è astratta e non prevede una possibile estensione di altre tecniche che utilizzino l'indice. Si potrebbe pensare ad esempio di avere già allo stadio attuale del framework una classe che codifichi all'interno dell'indice i contenuti nel loro stato originale (OriginalIndexing) ed una classe che invece codifichi all'interno dell'indice i contenuti preprocessati tramite tecniche di preprocessing, cosa che attualmente il framework già fa (PreprocessedIndexing). Il tutto per una migliore semantica e usabilità. In pseudo codice:

class IndexingTechnique(FieldContentProductionTechnique):

    def __init__(self):
        super().__init__()
        self.index: InformationInterface = None

    @abstractmethod
    def create_index(self, index_path: str):
        raise NotImplementedError


class OriginalIndexing(IndexingTechnique):

    def create_index(self, index_path: str):
        self.index = IndexInterface(index_path)
        self.index.init_writing()

    def produce_content(self, field_name: str, preprocessor_list: list, config: ContentAnalyzerConfig):
        # process

class PreprocessedIndexing(IndexingTechnique):

    def create_index(self, index_path: str):
        self.index = IndexInterface(index_path)
        self.index.init_writing()

    def produce_content(self, field_name: str, preprocessor_list: list, config: ContentAnalyzerConfig):
        # process

Astrarre correttamente i diversi tipi di RecSys

Attualmente è possibile specificare una sola tipologia di RecSys, ossia quelli basati interamente sul contenuto. Tuttavia sono già presenti all'interno del framework altre tipologie di recsys, come quelli basati sul grafo (graph based recommendation) che allo stato attuale è impossibile usare come veri e propri recommender system (e quindi è impossibile valutarli nel modulo di valutazione).

Inoltre, astraendo sulla configurazione, si prepara il framework ad un'eventuale estensione con altre tipologie di RecSys (ad esempio quelle collaborative)

Separazione ContentAnalyzerConfig per User e per Item

Attualmente nella classe ContentAnalyzerConfig è possibile specificare l'attributo content_type, di tipo stringa, attraverso il quale si determina se i contenuti da creare sono 'user' oppure 'item'.
Tale separazione però è debole in quanto si dà troppa libertà all'utente che potrebbe scrivere 'users' anziché 'user', 'items' anziché 'item'.
La soluzione trovata è quella di creare la sottoclasse UserAnalyzerConfig e ItemAnalyzerConfig che derivano dalla classe ContentAnalyzerConfig che dovrà essere astratta, e l'utente specificherà quale tipo di contenuto dovrà essere creato tramite la relativa classe.

Fornire un metodo per eseguire query sull'indice in IndexInterface

Al momento, utilizzando IndexInterface, è possibile recuperare diverse informazioni da un indice (per un field di un contenuto è possibile sia recuperare il data serializzato sia generare la bag of words tf-idf), ma non è possibile effettuare query complesse.

Fornendo questo metodo, gli algoritmi di recommending potranno effettuare tutte le operazioni necessarie sull'indice direttamente da IndexInterface, in questo modo non dovranno caricare i contenuti dalla memoria per generare raccomandazioni e potranno invece lavorare direttamente sull'indice.

Migliorare astrazione EmbeddingTechnique

Al momento, nel framework, la classe EmbeddingTechnique (sottoclasse di FieldContentProductionTechnique che lavora sui vettori di embedding) incapsula il comportamento sia per la granularità word, sia sentence, sia document.
Per specificare una EmbeddingTechnique con granularità "word" è necessario fare quanto segue:

EmbeddingTechnique(Centroid(), GensimDownloader('glove-twitter-25'), granularity="word")

Questo è ovviamente scomodo sia per l'utente (che dovrà dare in input una stringa) sia per il programmatore (logica poco estendibile). La classe EmbeddingTechnique dovrebbe essere resa astratta e il funzionamento delle diverse granularità delegato a delle sottoclassi che la estendono. Quindi, riprendendo l'esempio precedente, si vuole arrivare ad una situazione in cui si ha quanto segue:

WordEmbeddingTechnique(Centroid(), GensimDownloader('glove-twitter-25'))

Classificatore SVM e KNN non funzionano con pochi rating

Entrambi i classificatori hanno problemi con pochi rating, in quanto:

  • SVM ha come numero di fold di default pari a 5, e se ci sono elementi di numero inferiore oppure almeno una tra le classi ha meno di 5 elementi, viene lanciata un'eccezione
  • KNN ha come numero di neighbors pari a 3 di default, se ci sono quindi un numero di rated_item inferiore, viene lanciata un'eccezione

Additional filters e prevedere estrazione mapping con DBPedia su campi aventi più valori

  • Per la tecnica di estrazione esogena da dbpedia, attualmente il risultato che si ottiene per ogni campo è il primo nel caso di duplicati. Si potrebbe pensare di inserire un parametro additional_filters che permette di dare ulteriori filtri oltre il 'label' (come ad esempio il budget, director, etc.) per permettere di dare maggiore flessibilità e potenza alla ricerca.

  • Inoltre si potrebbe prevedere nella raw_source un campo avente come valore una lista di elementi su cui fare mapping:
    ad esempio invece che avere solo campi del tipo {"genre": "Action, Adventure"}, ma un mapping per questo campo non farà mai hit perché il codice cerca un elemento che abbia come genere il valore "Action, Adventure", mentre su DBPedia sono due valori separati.
    Se invece si prevede una lista di valori {"genre": ["Action", "Adventure"]}, allora sarebbe possibile modificare la query in modo da fare hit anche con questo tipo di proprietà su DBPedia

Includere la graph-based recommendation nella pipeline del modulo RecSys

Attualmente la parte dei grafi del framework, compreso algoritmo di PageRank, è slegata dal modulo RecSys: è cioè impossibile istanziare un recommender system che usi la rappresentazione a grafo. Prevedere ciò in quanto allo stato attuale liste di raccomandazioni create usando il PageRank non possono essere valutate tramite il modulo di valutazione del framework

Refactor RatingImporter

Come da titolo. Il modulo che fa l'import dei rating è forse l'unico ancora intoccato rispetto alla versione iniziale del framework (precedente al completo refactoring).

Migliorarlo e semplificarlo, come del resto fatto per ogni altro modulo che compone il framework

Eseguire il mock dei test di cui risultato dipende da internet

Effettuare il mock di quei test cui il risultato dipende dalla connessione ad internet, per rendere così i test correttamente indipendenti e autosufficienti.
Le classi di test che dipendono da internet sono quelle relative ai modelli di embedding e al ritrovamento delle prop. esogene da DBPedia

Fix dipendenze 'wordnet'

Il modulo pywsd==1.0.4 non permette di eseguire import name 'WordNet' from 'wn'.
Va downgradato il modulo wn alla versione 0.0.23 tramite installazione pip

Integrare Dockerfile e migrazione da Travis CI a Github Action

Come da titolo. E' necessario migrare verso le Github Action in quanto meglio integrate con Github e permettono maggiore flessibilità di Travis nonché maggiore sicurezza:

  • Flessibilità perché bisogna prevedere un potenziale rebuild della Docker Image, ma solo quando viene modificata la Dockerfile. Con le Github Action è possibile controllare ciò;
  • Sicurezza perché l'eventuale Docker Image buildata va caricata sul Docker hub, e quindi bisogna usare user e password dell' utente che ha il repository, ma Travis salvava le credenziali in forma 'plain text' rendendo poco sicuro il tutto.

Far sì che sia possibile passare al metodo fit una X e Y esplicita

Attualmente il framework ha un metodo di fusione personalizzato delle eventuali rappresentazioni multiple degli item, ma per dare maggiore libertà all'utilizzatore bisognerebbe far sì che sia possibile scegliere se usare il metodo fornito dal framework oppure manipolare a proprio piacimento le feature dei contenuti per poi darle esplicitamente ai vari metodi come fit e predict

Rendere l'utilizzo del modulo wikipedia2vec dinamico

Dato che per installare il modulo wikipedia2vec su Windows è necessario un passo aggiuntivo che comporta download di dimensioni considerevoli (maggiori di 4GB), se possibile, rendere l'utilizzo e installazione del modulo in oggetto dinamica.

Individuare un corretto refactor per il modulo EvalModel

In seguito al refactoring approfondito svolto in queste ultime settimane che ha investito gli altri due moduli del framework, ContentAnalyzer e RecSys, bisogna adattare le modifiche al terzo ed ultimo macro modulo del framework, il modulo di valutazione.
Individuare dunque un refactor corretto per esso, cercando non solo di adattarlo alle modifiche compiute ma anche di migliorarlo in ogni sua parte

Lettura delle proprietà da un dataset locale ha numerosi problemi

La classe PropertiesFromDataset da exogenous_properties_retrieval.py presenta numerosi bug:

  • Se la modalità è 'only_retrieved_evaluated' dovrebbe restituire dizionario avente campi i soli campi della raw_source che sono avvalorati, e come valore tale valore, invece funziona esattamente al contrario, cioè restituisce dizionario con campi che non sono avvalorati
  • Se viene passata una lista field_name_list avente numero di elementi minore rispetto ai field della raw_source, il programma crasha
  • Se viene passata una lista field_name_list avente un elemento non presente nei field della raw_source, il programma crasha

Creazione di full_graphs con proprietà esogene presentano diversi problemi

  • Contraddizione tra parametri passati e manipolazione:
    • Per aggiungere informazioni esogene agli item o agli user, va passata una lista contenente quali proprietà estrapolare, tra quelle
      codificate nel contenuto. Tuttavia nel contenuto possono essere presenti più rappresentazioni esogene, quindi in realtà va passata una lista contenente l'indice della rappresentazione esogena dalla quale verranno estrapolate TUTTE le proprietà esogene presenti in essa. Oltre che poco intuitivo, non permette all'utente la libertà di scegliere quali parametri estrapolare tra tutti quelli codificati nel contenuto.
  • Il metodo add_tree() funziona in maniera analoga alla creazione del grafo, quindi presenta gli stessi problemi. (Va indicata la rappresentazione dalla quale estrapolare le prop. esogene, non permette l'estrapolazione di solo alcune, ecc.)
  • il metodo query_frame() restituisce anche il numero di riga, oltre che la riga, non permettendo la corretta esecuzione di altri metodi che invece si aspettano solo il contenuto della riga.
  • il metodo is_exogenous_properties() non funziona: dichiara proprietà esogena, qualsiasi cosa che non sia nodo from o nodo to.
    • (1 lo dichiara prop esogena, 'prova' lo dichiara come prop. esogena, ['a', 'b', 'c'] lo dichiara come prop. esogena, ecc.)
  • get_voted_contents() e get_properties() non funzionano e sono codificati esattamente alla stessa maniera, nonostante siano due metodi con compiti diversi (il primo restituisce gli elementi votati da un nodo, il secondo restituisce le proprietà di un dato nodo)
  • Viene mantenuto come riferimento il source frame usato per creare tutto il grafo, tuttavia quando il grafo viene aggiornato, il source frame rimane immutato:
    • ES. Inserisco nel grafo un nodo a, un nodo b, e un arco che va da a a b. Voglio sapere se a è un from_node, uso il metodo appropriato is_from_node() ma dato che viene scansionato il source frame per dare risposta, quest'ultimo non conterrà né ab e darà risultato negativo nonostante a sia a tutti gli effetti un from_node

Page Rank non restituisce risultati in ordine decrescente

Come da titolo, è importante che siano in ordine decrescente perché una volta che viene effettuato il page rank, viene effettuato su tutto il grafo, dopodiché la lista contenente i vari rank viene tagliata al numero x di raccomandazioni passato come parametro, e se le raccomandazioni non sono in ordine è possibile che vengano tagliati item con rank molto alto ma che si trovano al di là del cut

Travis CI error

Travis CI non builda, probabilmente per problema di dipendenze come evidenziato in #1.
In ogni caso Travis fa riferimento ad una build di Docker vecchia, quindi va buildata una nuova immagine con i fix alle dipendenze

Far sfruttare la flessibilità del framework ad ogni algoritmo contenutistico

La flessibilità del framework permette di codificare più field di un contenuto, e per ogni field creare più rappresentazioni. Tale flessibilità non è però sfruttata dagli algoritmi contenutistici tolti i classificatori.
Prevedere dunque di poter sfruttare e fondere più rappresentazioni codificate di un contenuto per ogni algoritmo contenutistico

Aggiornare il file di script e renderlo più dinamico

Si vuole aggiornare la gestione del file di script in modo tale che funzioni con le modifiche che sono state apportate al framework (quindi, ad esempio, far funzionare in modo appropriato il nuovo EvalModel quando utilizzato dal file di script).

Inoltre, si vuole ottenere una versione più dinamica della gestione del file di script, in modo da rimuovere il dizionario di alias presente in runnable_instances.py. Grazie ad una gestione più dinamica dovrebbe risultare più diretto l'utilizzo del file di script sia per l'utente che per il programmatore.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.