Skip to content

Duccioo/Advanced-Machine-Learning-Project

Repository files navigation

Advanced-Machine-Learning-Project

Progetto che consisterebbe nel realizzare una versione dei diffusion model che usa lo spazio latente. In pratica si trattrebbe di generare una rappresentare latente di un grafo, ad esempio usando graphVAE. Poi potremo provare a generare tale rappresentazione con un metodo a diffusione. Essendo lo stato latente un semplice vettore, la sua generazione è più semplice, ma il fatto che si debba comporre due metodi da vita ad una cosa un pò più complicata.

Models

Dataset

Per quanto riguarda il dataset (QM9), potete comodamente scaricarlo tramite il pacchetto pytorch_geometric, come spiegato a questo link:

  • QM9 DataSet

    E' sufficiente includere questa riga tra le importazioni: from pytorch_geometric.datasets import QM9

Il dataset QM9 preso da PyTorch Geometric è strutturato come un oggetto InMemoryDataset di PyTorch Geometric. L’oggetto contiene i seguenti attributi:

  • data.x: Matrice di features dei nodi (dimensione num_nodes x num_node_features)

  • data.edge_index: Matrice di adiacenza sparsa che rappresenta gli archi tra i nodi (dimensione 2 x num_edges)

  • data.edge_attr: Matrice di features degli archi (dimensione num_edges x num_edge_features)

  • data.y: Tensor contenente la proprietà target per ogni molecola nel dataset (dimensione num_molecules x num_targets)

Visualizzare il dataset:

https://github.com/chainer/chainer-chemistry/blob/master/examples/qm9/qm9_dataset_exploration.ipynb

Question & Answer

  1. C'è differenza tra modelli GraphVAE e VGAE?

    GraphVAE e VGAE sono due modelli leggermente diversi, ma appartengono alla stessa classe (graph-based variational autoencoders) e sono del tutto intercambiabili, quindi usate pure quello che vi sembra meglio. Comunque, cambiando dataset, le matrici di adiacenza cambiano. Nella repository che vi ho passato, il file "train.py" carica le matrici di adiacenza dal dataset "enzymes", mentre a voi servono quelle di QM9. Il DataLoader di QM9 che trovate in pytorch_geometric carica i grafi di QM9, ognuno dei quali contiene la sua matrice di adiacenza. Tendenzialmente, il DataLoader di QM9 dovrebbe funzionare con GraphVAE e con VGAE. Se non fosse così, ci sarà da adattare la classe GraphAdjSampler che trovate in "data.py" al formato dati di QM9. GraphAdjSampler infatti è un DataLoader scritto dagli autori della repo (in poche righe di codice) appositamente per il dataset "Enzymes".

  1. Quali metriche conviene utilizzare per confrontare se il grafo generato è buono o no?

    Per capire se i grafi generati sono buoni o no si può procedere in due modi: valutare Validity, Uniqueness e Novelty, e controllare che le distribuzioni di probabilità siano simili a quelle del training set. Per adesso mi limiterei a Validity, Uniqueness, Novelty. La validity si può valutare col pacchetto python RdKit con una routine che permette di scartare i grafi che violano qualche regola della Chimica e di misurare la percentuale di grafi generati che sono validi. La Uniqueness viene calcolata comparando i grafi generati uno a uno e scartando i doppioni, misurando la percentuale di molecole che non sono copie di altre. Infine, la novelty viene misurata comparando tutti i grafi validi e unici generati con i grafi del training set, ottenendo la percentuale di materiale effettivamente "nuovo" generato dalla rete.

  2. Le features dei edge vanno inserite dentro il modello?

    Le edge features sono una delle matrici da passare in input al modello: il DataLoader di QM9, una volta integrato nel codice, dovrebbe automaticamente passarle al modello quando si chiama la funzione "train". Se i tipi di archi definiti da Enzymes e da QM9 non sono uguali (come sospetto), ci sta che vada aggiustato un parametro nel codice del modello per far funzionare GraphVAE sulla matrice di QM9.

  3. Ci siamo accorti, infine, che analizzando il dataset QM9 c'è qualcosa che non torna. Un esempio è la molecola numero 23 denominata "gdb_24" con una ground truth smiles = [H]CC#C[NH3+]. Se noi ci calcoliamo in base alle matrici e alle features presenti nella molecola 23 otteniamo uno smiles = [H]CC#CN.

    Il "problema" delle SMILES è che non sono rappresentazioni univoche: la stessa molecola può essere rappresentata da un sacco di diverse SMILES, a seconda dell'atomo da cui si inizia a scrivere la stringa SMILES e a seconda delle ramificazioni che scegliamo di espandere per prime durante la visita del grafo. Esiste un modo per rendere le SMILES "canoniche", seguendo delle regole che stabiliscono quali ramificazioni espandere per prime ecc..., ma anche in questo caso non si rende univoca la rappresentazione (spesso, esistono più SMILES canoniche per una molecola). Gli ioni possono essere riportati alla molecola con carica neutra corrispondente, per cui [H]CC#C[NH3+] = [H]CC#C[NH2]. Inoltre, gli atomi di idrogeno sono spesso superflui nell descrizione di una molecola organica, per cui [H]CC#C[NH3+] = [H]CC#C[NH2] = [H]CC#CN = CC#CN Spesso, anche i generatori di grafi ignorano gli atomi di idrogeno, soprattutto modelli come i GraphVAE che non sono invarianti alle permutazioni dell'ordinamento del grafo. Non considerando gli idrogeni, infatti, si riduce di più della metà il numero di atomi presenti in una molecola, riducendo drasticamente il numero di ordinamenti possibili per il grafo molecolare che la rappresenta. Anche l'addestramento del modello, in termini di memoria occupata e tempo di esecuzione, beneficia molto dell'assenza degli atomi di idrogeno. Se trovate degli idrogeni nei dati di QM9, vi conviene riscrivere il DataLoader in modo da eliminarli (sia dalla matrice delle features, che dalla matrice di adiacenza, eliminando poi anche le features degli archi che connettono gli atomi di idrogeno al resto del grafo). Penso però che il DataLoader di pytorch_geometric non carichi gli idrogeni. Potete controllare stampando la dimensione massima dei grafi che il DataLoader vi passa: se la dimensione massima è 29 ci sono gli idrogeni, se invece è 9 non ci sono.

  1. come faccio a far sì che la matrice adiacente e la matrice dei legami degli atomi siano correttamente matchate

  2. Per ottenere la generazione del vettore delle features dei nodi sia corretto aggiungere degli strati in più nel decoder della rete perchè di default il modello restituisce solo la matrice adiacente.

    Per quanto riguarda invece l'output, l'idea di aggiungere una parte che generi le features dei nodi mi sembra ottima. Potreste aggiungere un modulo anche piccolo che restituisca i vettori one-hot tramite softmax. Se poi il softmax non dovesse funzionare o dovesse comportarsi in modo troppo ripetitivo, potremo sostituirlo con un layer particolare che ha un'uscita stocastica (gumbel softmax).

  3. non siamo ancora sicuri di come aggiungere le features degli edges, avevamo pensato prima di tutto a concatenare direttamente le features degli edges a quelle dei nodi poi abbiamo pensato di modificare la matrice di adiacenza aggiungendo le features degli edges in modo da ottenere un tensore 3d dove ad ogni edge corrisponde la codifica one-hot del legame della molecola.

    Ho controllato la repo, e devo dire che la gestione delle features degli archi c'è, ma è effettivamente un po' intricata: viene definita una matrice "s" (non esattamente un nome esplicativo per una variabile) ottenuta cross-correlando le features degli archi tra di loro. La matrice "s" viene utilizzata dal metodo self.mpm(), che ripete alcune iterazioni di "message passing convoluzionale" tra i nodi del grafo. Questa procedura permette di incorporare le features degli archi all'interno delle "features rielaborate" in uscita dal processo di message passing, che vengono poi compresse nel vettore latente. Il message passing è quello descritto in questo articolo: https://arxiv.org/abs/1704.01212

    Secondo me conviene mantenere il metodo così com'è, almeno per adesso.

  4. Poi per quanto riguarda la loss abbiamo seguito il codice ovvero la somma della KL e la binary-cross-entropy tra la matrice adiacente vera e quella ricostruita dalla rete partendo dal vettore delle features dei nodi. E volevamo quindi sapere se era giusto lasciarla così oppure aggiungere un altro pezzo per considerare anche gli strati aggiunti in più nel decoder per ottenere il vettore di features dei nodi.

    problema risolto, usate 2 MSE loss una per la matrice delle features dei nodi e una per gli edges

  5. Come implementare il Latent Diffusion:

  • Allenare prima il VAE, staccare e salvarsi l'encoder

  • magari usare rumore normalizzato

  • quale loss utilizzare? quella del diffusion model o quella del graphVAE?

    vi avevo detto che vi avrei specificato meglio quale funzione errore va usata per addestrare la rete che fa la diffusione inversa sullo stato latente. Ho ricontrollato è si può usare un'errore quadratico (differenza fra il rumore predetto e quello effettivo). Tra l'altro questo dettaglio era già nelle slide del corso e non me lo ricordavo. Per spiegarlo, vi riallego le slide, L'algoritmo di addestramento è definito nella slide 14. Sostanzialmente è previsto che si prenda un immagine del dataset, un tempo t a caso e si applichi un rumore che, pixel per pixel, dipende dal valore iniziale del pixel e da un epsilon che è generato da una distribuzione normale. La formula da usare è quella di slide 8, dove gli alfa e i beta di t sono quelli definiti in slide 8 e slide 6. Come vedete in slide 6 si spiega come si calcolano i beta: sostanzialmente dipendono da un alpha e un beta inziale che ci dicono quanto è il rumore all'inizio. Poi i beta crescono (e di conseguenza il rumore) in maniera lineare rispetto a t. Sono stati provati altri andamenti (quadratico), ma io dire di usare quello di base lineare. In pratica, voi dovete prendere un immagine e un t a caso e applicargli un rumore secondo formula a slide 8. Poi date l ímmagine rumorosa e il t in ingresso alla rete che deve restituire il rumore. Calcolate il gradiente come un problema di regressione sul rumore.

appunti e domande 19/02:

  • chiedere come calcolare la matrice di similarità tra le matrici di adiacenza e i vettori delle features degli edges

  • chidere se è necessario modificare la loss dopo aver aggiunto i nuovi strati per le features dei nodi/edges

    • aggiungere la MSE per i node features e gli edge features e controllare il numero di edge
  • problema del match tra la matrice adiacente e quella delle features degli edge: il numero di edges nella matrice adiacente è diverso da quello del edges features:

    • aggiungere il numero di edge dal calcolo del numero massimo dei nodi
  • fare il one-hot encoding dell'uscita delle features dei nodi

  • eliminare le molecole formate da un solo atomo

  • Dimezzare le dimensioni delle features degli edge poichè si ripetono 2 volte?

  • Sulla codifica della matrice adiacente: ha senso fare la predizione anche della diagonale se tanto i self-loop non ci sono?

    • in caso affermativo ridurre la dimensione di output della vae e aggiunstare la ricostruzione della matrice adiacente da quella codificata
  • Salvare il modello dell'encoder

  • Generazione:

    • Sistemare l'uscita in modo tale che la matrice delle features degli edges sia sensata con il numero di edges

    • aggiungere la softmax sull'uscita delle features dei nodi (solo GENERAZIONE)

    • quando creo lo smiles ha senso fare la Sanitizzazione della molecola prima di convertirla?

    • Durante la generazione otteniamo valori della matrice adiancente molto bassi, tutti sotto 0.5.

      • quindi quando decidiamo se fare o meno un edge il valore con un round() semplice viene sempre 0 ovvero quel edge non viene preso
      • solito discorso sulla diagonale dove i valori sono ancor più piccoli, intorno a 0.10/0.20.
      • conviene diminuire la trashold?

meeting 04/04

  • stampare le loss separate e vedere dove va

    • plotting della loss sia sul training che nel validation
  • allenare con 2 distinti loss, prendere l'optimization solo sui parametri (quando istanzio l'optimization separo i 2 parametri)

  • nel diffusion abbassare il learning_rate a 1e-5

    • risultato:
  • aggiunto un peso alla kl divergence loss, sperando di migliorare l'addestramento del decoder

Resurces

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages