Ricerca in Database Strutturati

Traduzione e Integrazione delle Lezioni a cura di Sandro Gallo

Home Alberi Decisionali OLAP


Spesso ci si trova a lavorare con tipi di dato particolarmente complessi e strutturati, tali da non poter essere descritti e immagazzinati in normali basi di dati. Un esempio eclatante è la rappresentazione dei dati in chimica, che avviene tramite graphi. Ed è ovvio pensare che esistano database di graphi sui quali effettuare ricerche strutturate.
Le motivazioni che hanno spinto alla costruzione di database strutturati sono da una parte inerenti il tipo di oggetti d'interesse, cioè molecole. Queste sono usualmente classificate in base alle caratteristiche strutturali presenti in piu’strutture o in base alla loro attivita’ biologica. Dall'altra parte riguardano l'utilizzo che se ne fa.
Cioè questi database di strutture chimiche in forma di grafi possono servire per predire funzioni di un nuovo composto naturale o sintetizzato in base ai suoi frammenti, o per ricercare la struttura 2D/3D di proteine. I campi d'applicazione, quindi, si estendono dalla biologia, bioinformatica, proteomica alla computer grafica(dai pixel ai grafi per riconoscere caratteri, o dalle immagini ai grafi per riconoscere regioni adiacenti). Dati due grafi, G=(V,E) e G'=(V',E'), G e G' sono isomorfi se esiste una biezione
image not found
cioè possiamo rietichettare i vertici di G per essere vertici di G', mantenendo la corrispondenza tra gli archi in G e G'. Dati due grafi, G=(V,E) e G'=(V',E'), allora G è sottografo omomorfo di G', se G è isomorfo a un sottografo di G'. G può essere sottografo isomorfo a diversi sottografi di G'. Un grado G = (V,E) è sottografo isomorfo di G' = (V',E') se esiste una iniezione
image not found
cioè noi possiamo rietichettare i vertici di G per essere vertici di G', mantenendo gli archi corrispondenti in G. Riguardo la complessità, l'isomorfismo tra grafi è difficile, ma ancora non è stato provato se è un problema NP-completo o meno. Invece è provato che il matching con sottografi è NP-completo.
Un'algoritmo bruto, rozzo che fa il matching tra grafi impiega tempo quasi esponenziale, infatti ci sono n! modi se il grafo ha n nodi di cercare un match. Alcuni modi per aumentare la velocità nel fare l'isomorfismo tra sottografi sono: l'uso di computer più veloci, lo sviluppo di trucchi che evitino quelle soluzioni che portano a fallimento, anticipare molti passi di computazione nella fase di pre-processing.
Un esempio di trucchi che evitano le soluzioni non corrette è il backtracking, cioè l'abbandono di soluzioni parziali quando possiamo affermare che portano ad un fallimento. Il backtracking procede così:

  1. Mappa un numero arbitrario di coppie di nodi
  2. Quindi mappa il loro contorno
  3. Se ottieni un successo, mappa il contorno del contorno, etc. etc.
  4. Altrimenti torna indietro di un passo, e prova un mapping differente
  5. L'algoritmo termina quando:
    1. tutti i nodi sono stati mappati, oppure
    2. quando tutte le alternative per il primo nodo da matchiare sono state provate e portano tutte a fallimento.
Al backtracking si può affiancare il partitioning che tenta di dividere i nodi in gruppi possibilmente corrispondenti. Se la lista delle corrispondenze possibili diventa vuota per un nodo query, allora nessun isomorfismo è possibile.
Un algoritmo per il matching esatto con sottografi è quello di Ullmann, l'algoritmo VF.
Siano
image not found
grafi da matchare. Sia M(s) ={(n,m) in V1xV2 tali che n è mappato in m nella soluzione parziale corrente corrispondente allo stato s}, e siano M1(s) e ( M2(s) ) gli insiemi dei primi ( rispettivamente secondi ) componenti delle coppie in M(s). Siano E1(s) e E2(s) gli insiemi di tutti gli archi che connettono i nodi in M1(s) e M2(s), rispettivamente. Siano
image not found.
Sia (n,m) una coppia candidata con
image not found.
La coppia (n,m) è aggiunta alla mappa se tutte le seguenti condizioni sono soddisfatte:
  1. image not found
  2. Il numero di nodi in T1(s) connessi a n è minore o uguale al numero di nodi in T2(s) connessi a m.
  3. Il numero di nodi connessi a n che non sono né in M1(s) né in T1(s) è minore o uguale al numero di nodi connessi a m che non sono né in M2(s) né in T2(s).
Lo pseudo-codice della procedura VF è il seguente:
PROCEDURE Match(s)
INPUT: stato s; per lo stato iniziale so, M(so)= 0
OUTPUT: la mappatura
IF M(s) copre tutti i nodi THEN
OUTPUT M(s)
ELSE
Calcola P(s) di tutte le coppie candidate per l’inclusione in M(s)
FOREACH p in P(s)
IF Le regole per includere p in M(s) hanno successo THEN
Calcola lo stato s’ ottenuto in modo da aggiungere p a M(s)
CALL Match(s’)
END IF
END FOREACH
END IF
END PROCEDURE


Per iniziare a parlare di algoritmi di matching inesatto, dobbiamo innanzitutto definire una funzione distanza. La distanza tra Ga e Gb è il costo di trasformare Ga in Gb, cioè dell'isomorfismo. Invece per isomorfismo tra sottografi, è il costo di trasformare Ga in una parte di Gb. Il nostro scopo è trovare tutti i match di Ga con Gb tali che d(Ga, Gb) < threshold. Esempi di funzioni distanza sono: rietichettatura dei nodi, delete-insert di archi, delete-insert di nodi, con il relativo costo associato ad ogni operazione.
Se l'algoritmo di Ullmann è utile per eseguire un match esatto tra due grafi, per il matching inesatto abbiamo l'algorimo di Nilsson. Lavoreremo non più sul confronto tra due grafi, ma sul confronto di un grafo query con un database di grafi:
image not found
Studieremo il GraphBlast, i cui passi sono:
  1. Filtering, cioè l'indicizzazione per trovare i grafi candidati e i sottograi candidati.
  2. Query Specification, cioè la formulazione di una query.
  3. Matching, usando VF o combinando i path.
  4. Data Storing.
Nel GraphBlast un grafo è un insieme di cammini, ed è in questo modo che viene memorizzato nel database. Il database usato è il Berkeley DB. Per filtrare il database usiamo i fingerprint, che sono indici costruiti con hash, associati ad ogni grafo nel database, usati per compare le strutture, per cercare similarità. Dopo aver filtrato il database costruendo un database di fingerprint da cui prendere una query fingerprint per quanto concerne i grafi candidati, e aver filtrato i sottografi candidati decomponendoli in pattern, si mettono insieme i due risultati e si processa la query. Quindi si passa a fare il match con il grafo query in ingresso o usando VF, matching grafo-grafo sui sottografi, o usando SQL come algebra per combinare i cammini dei sottografi candidati.
GraphBlast definisce GLIDE per le query approssimate, cioe’ non completamente specificate, cioe’ contenenti wildcards. È un query graph language per rappresentare testualmente i grafi.

In molti ambiti gli oggetti di un dataset vengono rappresentati mediante strutture dati complesse, come i grafi. Anche sui grafi applicheremo le tecniche di data mining, infatti possiamo fare le seguenti associazioni tra il mondo dei grafi e il mondo delle transazioni/dati:
image not found
Gli algoritmi per il graph mining si dividono in due classi:
  1. Quelli basati su tecniche Apriori:
    1. AGM/AcGM
    2. FSG
    3. PATH#
    4. FFSM
  2. E quello basati sulla crescita dei pattern:
    1. MoFa
    2. gSpan
    3. Gaston
Il canonical labeling aiuta alla comparazione veloce tra grafi e nell'ordinamento completo e deterministico per insiemi di grafi. Le canonical label usate sono:
  1. Concatenazione di righe o colonne della matrice di adiacenza=> non univoco!
  2. Tra tutte le possibili permutazioni dei nodi, scelta del codice maggiore o minore.
  3. Utilizzo di vertex invariants per il partizionamento in classi di nodi.
Definiamo il problema del mining dei grafi nel seguente modo:
Frequent Subgraph Discovery:
Input: L'obiettivo è trovare tutti i sottografi non orientati e connessi presenti in almeno ns grafi del dataset D.
L'algortimo Apriori largamente usato nei modelli market/basket è lo schema base per alcuni algoritmi di ricerca di sottografi. Lo pseudo-codice dell'algoritmo è il seguente:
image not found
Tra i tanti algoritmi elencati sopra vedremo FSG e gSpan. In FSG, basato su Apriori, si osserva l'incremento della dimensione dei sottografi frequenti mediante aggiunta di un arco alla volta. Utilizza il canonical labeling e ottimizza la generazione dei candidati e il conteggio degli insiemi frequenti.
Fsg(D, s)
{
1: F1 = tutti i sottografi frequenti di dimensione 1 in D
2: F2 = tutti i sottografi frequenti di dimensione 2 in D
3: k = 3
4: while image not found do
5: Ck = fsg-gen(Fk-1)
6: for each candidate image not found do
7: Gk.count = 0
8: for each transaction image not found do
9: if Gk è in T then
10: Gk.count = Gk.count + 1
11: image not found
12: k = k+1
13: return {F1, F2, ..., Fk-2}
}


Al rigo 1 e 2 si ha la generazione di tutti i sottografi frequenti di dimensione 1 e 2. Nelle righe 4-6 vi è la generazione dei sottografi candidati di dim. K mediante fusione dei sottografi frequenti di dim. k-1. Alle righe 8-10 si fa il conto dei grafi frequenti. Nel rigo 13 c'è la selezione dei candidati che soddisfano il vincolo di supporto.
La join avviene tra sottografi di dimensione K che condividono lo stesso (k-1)-subgraph (core). Il risultato potrebbe non essere un unico (k+1)-sottografo.

image not found

image not found


Al rigo 2 vi è la generazione di tutti i core condivisi per ogni coppia di sottografi frequenti. Al rigo 4 vi è la generazione di tutti i possibili candidati mediante fusione di ogni coppia di sottografi frequenti, per ogni core condiviso. E al rigo 7 inizia il False test.

Un automorfismo di un grafo G è l'isomorfismo di un grafo con se stesso; cioè una mappa dai vertici di G ai vertici di G tale che il grafo risultante è isomorfo a G. Il canonical labeling rappresenta un punto critico dell’algoritmo. Viene massicciamente impiegato nei test di ridondanza (candidati già generati durante la join) e nei False test per la verifica di sottografi frequenti. Per questioni di efficienza, l’algoritmo di CL utilizzato fa uso di vertex invariants, prevedendone tre versioni differenti: Partition ordering, Neighbor list, Iterative partitioning.
Nella generazione dei candidati ci sono tre step computazionalmente costosi, cioè la generazione di core ( e automorfismi), join, eliminazione candidati infrequenti. Le possibili ottimizzazioni da fare sono 3: Ogni k-subgraph frequente mantiene le canonical label dei suoi (k-1)-subgraph frequenti; Inverted indexing scheme; Caching degli automorfismi dei cores precedenti; Uso di canonical labeling per la verifica di ridondanze e sottografi infrequenti (test veloci e ricerca binaria).
Il frequency counting di FSG ha un costo elevato, pari a nxmk (n=|D|, mk=# di candidati al passo k). Il costo computazionale è ridotto dall’uso di transaction identifier (TID) lists:
  1. Ogni sottografo frequente mantiene la lista di TID delle transazioni nelle quali è contenuto.
  2. Per il calcolo della frequenza di un (k+1)-subgraph si considera l’intersezione delle liste di TID dei suoi k-subgraph frequenti.
  3. Se la dimensione della lista è minore del supporto minimo, il candidato viene scartato, altrimenti viene valutata la frequenza sulle sole transazioni della lista.
I vantaggi di fsg sono la ricerca di sottografi generali e le numerose ottimizzazioni. Gli svantaggi sono la Candidate generation che è comunque costosa nonostante ottimizzazioni (false test e join ridondante), e la complessità spaziale elevata (a causa di BFS).


Gspan è un altro algoritmo per il graph mining basato sulla crescita di pattern. Le sue caratteristiche sono: l'uso di Depth-first search (DFS) invece di breadth-first search, l'incremento della dimensione dei sottografi frequenti mediante aggiunta di un arco alla volta; lo spazio di ricerca è un albero gerarchicamente basato sul DFS code; la join è sostituita dalla meno onerosa extension e i false test sono eliminati.
Quando si usa DFS si costruisce un DFS-tree. A questo corrisponde la generazione di una sequenza lineare di vertici, che vengono etichettati con i DFS-subscript. Il grafo risultante si indica con GT. Chiamiamo il vertice v0 la radice (root) e vn il vertice più a destra (right-most vertex). Il cammino da v0 a vn è chiamato rightmost path. Dato GT il forward edge set Ef,T è l'insieme degli archi nel DFS-tree, mentre il backward edge set Eb,T è l'insieme degli archi non presenti nel DFS-tree. Per semplicità scriviamo così i due insiemi:
image not found

Definiamo quindi:
  1. ordinamento forward:
    image not found
  2. Ordinamento backward:
  3. Ordinamento forward-backward:
    image not found
  4. ordinamento totale:
    image not found

Dato un DFS-tree per un grafo G, se una sequenza di archi (ei) può essere costruita usando l'ordinamento totale definito sopra, allora (ei) è chiamato DFS-code per G, e si indica con code(G,T).
Un ordinamento lessicografico può essere definito usando il DFS-code. Sia Z = {code(G,T) | T è un DFS-tree di G}, cioè Z è un insieme contenente tutti i DFS-code per G.
Sia a = code(Ga, Ta) = (a0, a1, ..., am) , b = code(Gb, Tb) = (b0, b1, ..., bn), a, b sono in Z. Allora l'ordinamento lessicografico DFS è definito così:
image not found
se e solo se: image not found
Il minimum DFS code di un grafo G è il DFS code minimo in base all’ordinamento lessicografico DFS e costituisce il canonical label di G.
Lo spazio di ricerca di GSPAN è rappresentato dal DFS-code tree, che è un albero che in ogni nodo contiene un DFS-code. L'operazione di extension per la costruzione dei figli di ogni nodo consta nell'aggiunta di archi per i soli nodi del rightmost path. La relazione tra fratelli segue l'ordinamento lessicografico.
Alcuni teoremi sullo spazio di ricerca in Gspan:
  1. DFS Code Tree Covering: Il DFS-code tree contiene i minimum DFS-code di tutti i grafi (completa enumerazione)
  2. DFS Code Growth: Il minimum DFS-code di un grafo G, durante la DFS, è incontrato prima di qualsiasi altro DFS-code non minimum rappresentante G.
  3. DFS Code Pruning: La discendenza di un nodo con DFS-code non minimum non darà vita ad alcun nodo con DFS code minimum.

L'algoritmo di Gspan è il seguente:

image not found

I vantaggi con Gspan sono i seguenti: La Join in candidate generation è sostituita da extension (minore complessità e ridondanze); Vengono eliminate i false test in candidate generation. La complessità spaziale è ridotta (grazie a DFS), come ridotte sono le transazioni del dataset ad ogni macropasso. In generale le prestazioni sono superiori ad FSG.
Gli svantaggi sono la necessità dei pruning test per la possibilità di DFS code duplicati, e che la risoluzione di subgraph isomorphism problems, anche se in quantità ridotta, è comunque presente.

Home Alberi Decisionali OLAP