silleellie / orange_cb_recsys Goto Github PK
View Code? Open in Web Editor NEWContent-Based Recommender System Framework in python
License: GNU General Public License v3.0
Content-Based Recommender System Framework in python
License: GNU General Public License v3.0
Per migliorare l'interoperabilità con altri framework, sarebbe opportuno dare la possibilità di serializzare i contenuti come dei file csv e non solo come Content (classe propria del framework), così che le rappresentazioni complesse create per i contenuti possano essere sfruttate in altri modi
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.
Dopo aver completato #84, procedere alla finale semplificazione dei vari import, per ridurre al minimo la loro verbosità
centroid_vector.py
non restituiva risultato in un caso ma restituiva eccezione (facendo terminare programma prematuramente) quando invece dovrebbe ritornare semplicemente un DataFrame
vuoto.
Nella fase di configurazione l'intero processo è stato snellito mantenendo salde la flessibilità del framework:
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
]
)
movies_ca_config.append_exo_config(
exo_config_list = [
ExogenousConfig(DBPedia(), 'dbpedia_exo')
ExogenousConfig(PropertiesFromDataset()) # id automatico a 1
]
)
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 commitenteCome da titolo: si potrebbe pensare di far sì che il workflow si crei l'immagine docker in locale senza eseguire il push se il login a docker hub fallisce, così si risolverebbe anche il fallimento del workflow quando viene eseguito un pull da un fork esterno
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.
Abilitare il test disabilitato (e revisionarlo se necessario), mentre crearne uno per la classe SynsetDocumentFrequency
Come da titolo. Questo perché nella pipeline di sklearn viene eseguita in ogni caso la trasformazione delle rated_features_bag_list
e quindi della X da un dizionario ad un vettore, dando ovviamente errore quando lo è già
Come da titolo. Si potrebbe prevedere che quando viene istanziato un oggetto FieldRepresentationPipeline, se viene passato come parametro content_technique = None, allora non dev'essere effettuata nessuna rappresentazione complessa per il campo.
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
I problemi riscontrati:
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 cercataadditional_filters
, tali filtri non vengono trovati nelle proprietà di DBPedia nonostante invece esistanoadditional_filters
e tali filtri non vengono trovati nelle proprietà di DBPedia, il programma crasha invece di continuare senza tener conto di tali filtriCome da titolo. Se viene specificato ad esempio:
preprocessor_list = [NLTK(lemmatization=True), NLTK(stemming=True)]
Il programma termina prematuramente
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
Come da titolo. Perché molto probabilmente vorrebbe dire che la WORKDIR della Dockerfile è stata settata male, quindi andrebbe corretta prima di poter effettuare il merge
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.
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.
Questo perché fa singole query all'endpoint SPARQL per ogni contenuto, si potrebbe fixare il tutto facendo fare una singola query per tutti i contenuti.
In teoria indicando di volere un pagerank personalizzato significa dare maggior peso all'interno del grafo agli item che la persona di cui si sta calcolando il rank ha votato. Tuttavia qualsiasi dataset viene utilizzato, viene restituito un rank con tutti i valori a 0
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)
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.
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.
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.
Nel setup vanno aggiunte alcune dipendenze mancanti (come per esempio networkx
)
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
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)
Come da titolo, EmbeddingSource.load()
anziché restituire una matrice dove ogni riga è il vettore che rappresenta ogni parola, restituisce una matrice avente dimensioni sbagliate, dove le prime righe sono sì i vettori delle parole, ma le altre sono righe non inizializzate.
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.
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.
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'))
Entrambi i classificatori hanno problemi con pochi rating, in quanto:
rated_item
inferiore, viene lanciata un'eccezionePer 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
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
Come da titolo. Su Ubuntu è necessario:
sudo apt-get install python3-dev default-libmysqlclient-dev build-essential
Su Windows vanno installati i C++ Build Tools, come indicato qui
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
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
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
Come da titolo, verificare che non vengano inseriti neanche i caratteri speciale per TAB \t
e il CARRIAGE RETURN \r
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:
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
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.
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
La classe PropertiesFromDataset
da exogenous_properties_retrieval.py
presenta numerosi bug:
'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 avvaloratifield_name_list
avente numero di elementi minore rispetto ai field della raw_source
, il programma crashafield_name_list
avente un elemento non presente nei field della raw_source
, il programma crashaCome da titolo. Basterà dare la possibilità di passare come parametro una lista di utenti, va perciò cambiata leggermente la logica e aggiornati i casi di test
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.)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.is_exogenous_properties()
non funziona: dichiara proprietà esogena, qualsiasi cosa che non sia nodo from o nodo to.
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)is_from_node()
ma dato che viene scansionato il source frame per dare risposta, quest'ultimo non conterrà né a né b e darà risultato negativo nonostante a sia a tutti gli effetti un from_nodeCome 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
Errore nell'installazione del framework nella Docker image, quando si va ad usarlo dà (modulenotfounderror)
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
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
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.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.