SISTEMI A RETI SEMANTICHE
Cronologia delle notazioni:
1889:
1896:
Logica del Primo Ordine (Peano)
Grafi Esistenziali (Peirce) – “la logica del futuro”
~1961:
Reti Semantiche introdotte in AI
Quale formalismo è migliore?
Fin dall’inizio si è avuto un dibattito fra i vari sostenitori… ma:
ogni rete semantica o sistema a frame è facilmente esprimibile
tramite formule della logica del prim’ordine
(gestendo opportunamente le eccezioni con qualche accortezza)
ogni formula della logica del prim’ordine si può esprimere
tramite reti semantiche
Motivi del successo delle reti semantiche:
formalismo grafico (usano diagrammi)
modello esecutivo molto semplice
(cf. Prolog vs. dimostratori di teoremi in logica del prim’ordine)
Pur programmando una rete molto vasta, è facile capire quali
interrogazioni saranno efficienti:
facilità di visualizzazione dei passi attraversati dalla procedura
di inferenza
semplicità del linguaggio di interrogazione, che non consente
interrogazioni troppo complesse
Per questo motivo, le reti semantiche furono usate dai primi ricercatori sull’ontologia
del buon senso per sviluppare le loro teorie.
SINTASSI E SEMANTICA
I linguaggi di rappresentazione hanno 2 componenti:
sintassi - marginale
Utile dal punto di vista della chiarezza e comprensibilità per un
lettore umano: alcune cose sono più semplici da comprendere in
notazione grafica, altre come stringhe di caratteri.
Traduzione semplice ed automatizzabile
semantica (& teoria della dimostrazione) - fondamentale
Qualunque sia il formalismo usato dal linguaggio (stringhe o nodi)
e il suo nome (rete semantica o logica), il suo significato o la sua
implementazione non variano.
Le reti semantiche si concentrano su
categorie di oggetti
relazioni fra di loro
Esempio.
Esprimiamo nei due formalismi il fatto che “I gatti sono mammiferi”:
Gatti →sottoinsieme Mammiferi
Gatti ⊂ Mammiferi o, più formalmente,
∀x gatto(x) ⇒ mammifero(x)
L’idea comune è che una formula logica non ammetta eccezioni
e che una rete semantica abbia un significato più blando
Alcuni sistemi usavano frecce “IsA” per indicare sia l’essere
sottoinsieme (“un gatto è un mammifero”) che l’appartenenza
(“Tom è un gatto”), il che può portare ad incoerenze.
(McDermott, 1976: “Artificial Intelligence Meets Natural Stupidity”)
Alcuni sistemi falliscono nella distinzione fra proprietà dei
membri di una categoria e della categoria nel suo insieme.
RETI SEMANTICHE & LOGICA
Esempio.
Una rete semantica con la corrispondente traduzione in logica del prim’ordine.
Animali
Vivo:
T
Vola:
F
rel(vivo, animali, true).
rel(vola, animali, false).
uccelli ⊂ animali
mammiferi ⊂ animali
rel(vola, uccelli, true).
rel(zampe, uccelli, 2).
rel(zampe, mammiferi, 4).
pinguini ⊂ uccelli
gatti ⊂ mammiferi
pipistrelli ⊂ mammiferi
rel(vola, pinguini, false).
rel(zampe, pipistrelli, 2).
rel(vola, pipistrelli, true).
opus ∈ pinguini
tom ∈ gatti
pat ∈ pipistrelli
nome(opus, ‘Opus’).
nome(tom, ‘Tom’).
amico(opus, tom).
amico(tom, opus).
nome(pat, ‘Pat’).
Sottoinsieme
Sottoinsieme
Uccelli
Zampe:
2
Vola:
T
Mammiferi
Zampe:
4
Sottoinsieme
Pinguini
Vola:
F
Membro
Opus
Nome: Opus
Amico:
Sottoinsieme
Gatti
Membro
Tom
Nome: Tom
Amico:
Sottoinsieme
Pipistrelli
Zampe:
2
Vola:
T
Membro
Pat
Nome:
Pat
Per rispondere alla domanda: “quante zampe ha Opus?”
bisogna seguire la catena di legami Membro e Sottoinsieme da Opus ai pinguini fino
agli uccelli, che hanno 2 zampe (Ereditarietà).
E se ci sono più catene che portano a quantità differenti di zampe?
EREDITARIETA’
L’ereditarietà consente di risalire alle proprietà di un oggetto
senza doverle esplicitamente elencare tutte per ogni singolo
oggetto, ma facendo in modo che:
ogni oggetto assuma implicitamente tutte le proprietà della
classe a cui appartiene immediatamente;
ogni classe a sua volta assuma implicitamente tutte le proprietà
delle classi più ampie di cui fa parte.
Questo meccanismo, sebbene comodo, non assicura di per sé che,
qualora un oggetto o una classe appartenga a sovraclassi diverse,
queste non gli attribuiscano valori differenti per una stessa
proprietà.
La semantica del linguaggio, ossia cosa succede in caso di
proprietà con valori diversi a seconda del percorso di ereditarietà
seguito, non è chiara: bisogna indurla basandosi sul
comportamento del programma che lo implementa.
Questo ha fatto sì che gli utenti delle reti semantiche pensino ad
esse al livello implementativo piuttosto che a quello logico o di
conoscenza.
La semantica di semplici reti semantiche si può definire tramite gli
equivalenti in logica del primo ordine per le asserzioni nel
linguaggio della rete
Iniziamo con una versione in cui le eccezioni non sono ammesse
EREDITARIETA’
Sono necessari 5 tipi di legami (ossia di relazioni):
1. Sottoinsieme
A →Sottoinsieme B
Esempio.
Gatti ⊂ Mammiferi
2. Membro
A →Membro B
Esempio.
A⊂B
A∈B
Tom ∈ Gatti
3. R vale fra due oggetti A e B
R(A,B)
A →R B
Esempio.
Tom →Età 12
Età(Tom,12)
4. R vale fra ogni elemento della classe A e un oggetto B
∀x x ∈ A ⇒ R(x,B)
A →R B
Essendo questo tipo molto comune, conveniamo di indicarlo
con
rel(R,A,B)
Esempio.
Uccelli →Zampe 2
rel(Zampe, Uccelli, 2)
5. R vale per ogni elemento di A e qualche elemento di B
∀x ∃y x ∈ A ⇒ y ∈ B ∧ R(x,y)
A →R B
Esempio.
Uccelli →Genitore Uccelli
N.B.: Un linguaggio di programmazione logica può usare la normale inferenza logica
per implementare l’ereditarietà a partire dalle traduzioni logiche dei legami.
Un sistema a rete semantica usa algoritmi dedicati per i legami e quindi può risultare
più veloce dell’inferenza logica (che è generale).
EREDITARIETA’ CON ECCEZIONI
I tipi naturali sono ricchi di eccezioni.
Esempio.
I mammiferi hanno 4 zampe, ma i pipistrelli (che sono mammiferi) solo 2.
Gli uccelli volano, ma i pinguini (che sono uccelli) no.
Secondo la semantica logica diretta, queste sono contraddizioni.
E’ necessario cambiare la traduzione semantica dei legami R da A
a B, per indicare che “ogni membro di A deve avere una relazione
R verso B a meno che non vi sia qualche A’ per cui rel(R,A’,B’)”.
In tal modo, nell’esempio degli animali, non c’è più ambiguità sul fatto che i
pipistrelli hanno solo 2 zampe.
rel(R,A,B) non significa più che ogni A è legata da R a B, ma che
B è un valore di default della relazione R per i membri di A, e che
quindi può essere sovrascritto da altra informazione.
Sebbene sia intuitivo pensare di gestire l’ereditarietà con eccezioni
seguendo le frecce nel diagramma, è anche possibile definire la
semantica in logica del primo ordine.
1. Reificare le relazioni (che diventano oggetti invece che
predicati). Quindi rel(R,A,B) è una frase atomica, non
un’abbreviazione di una formula.
Poiché R ora è un oggetto, non possiamo più usare R(x,B).
Usiamo:
vale(R,x,B) per indicare che l’equivalente di una relazione
R(x,B) è asserito esplicitamente nella rete semantica;
valido(R,x,B) per indicare che R(x,B) può essere inferito.
EREDITARIETA’ CON ECCEZIONI
2. Dobbiamo quindi definire questi nuovi predicati:
∀r, x, b
valido(r,x,b) ⇔
vale(r,x,b) ∨ (∃p x ∈ p ∧ rel(r,p,b) ∧ ¬rel_intermedia(x,p,r))
∀x, p, r
rel_intermedia(x,p,r) ⇔
∃i intermedia(x,i,p) ∧ ∃b’ rel(r,i,b’)
∀a, i, p
intermedia(x,i,p) ⇔ (x ∈ i) ∧ (i ⊂ p)
cioè valido è definito dicendo che una relazione r vale fra x e b
se vi è un predicato esplicito vale, o se vi è una r su qualche
classe genitrice p di cui x è un elemento, e non vi è una r in
nessuna classe intermedia i (ossia un sottoinsieme di p di cui x
è un elemento).
N.B.: il simbolo ⊂ indica un sottoinsieme proprio, ossia diverso da p stesso.
3. Infine, oltre a sapere quando valgono, vogliamo sapere anche
quando le relazioni rel e vale non valgono.
Se la base di conoscenza contiene solo atomi positivi rel,
possiamo usare l’Ipotesi del Mondo Chiuso. A tal fine, la
traduzione di una rete semantica deve esprimere il fatto che
solo le relazioni rel e vale esplicitamente asserite sono vere:
∀r, a, b rel(r,a,b)
⇔
[r,a,b] ∈ {[⋅,⋅,⋅],[⋅,⋅,⋅], …}
∀r, a, b vale(r,a,b)
⇔
[r,a,b] ∈ {[⋅,⋅,⋅],[⋅,⋅,⋅], …}
Esempio.
Cerchiamo un n che soddisfi valido(Zampe, Opus, n).
Sappiamo che rel(Zampe,Uccelli,2) e che Opus ∈ uccelli, ma la definizione di valido
non ci consente di inferire nulla a meno che dimostriamo che non esista
rel(Zampe,i,b) per i = Pinguini o per alcuna categoria intermedia.
La base di conoscenza contiene solo atomi positivi
rel(Zampe, uccelli, 2) ∧ rel(Vola, uccelli, true)
per cui senza queste ultime regole saremmo bloccati.
EREDITARIETA’ MULTIPLA
L’ereditarietà multipla, supportata da alcuni sistemi a reti
semantiche, consente che un oggetto possa appartenere a più di
una categoria e che quindi erediti proprietà lungo percorsi
differenti.
Spesso questo non causa problemi, in quanto le proprietà ereditate
lungo percorsi differenti non sono in conflitto.
Esempio.
Se una persona appartiene sia alla categoria dei miliardari che a quella dei tassisti, si
può inferire che è ricca e sa guidare un’automobile.
Ci sono tuttavia casi in cui le risposte date da due cammini di
ereditarietà differenti sono in conflitto.
Esempio. (Diamante di Nixon)
Richard Nixon era un quacchero, dunque un pacifista, ma era anche un repubblicano,
dunque non pacifista.
Sfruttando le traduzioni logiche date in precedenza si possono quindi inferire
entrambe le conclusioni, che disponendo di una sufficiente conoscenza di fondo si
rivelerebbero in contraddizione.
Essere
Umano
Sottoinsieme
Sottoinsieme
Non
Pacifista
Repubblicano
Quacchero
Ideale
Membro
Ideale
Pacifista
Membro
Richard
Nixon
Tali conflitti non possono essere risolti se non sfruttando
informazione aggiuntiva che espliciti un criterio di preferenza per
uno dei percorsi in conflitto.
EREDITARIETA’ E CAMBIAMENTO
L’utilità fondamentale di una base di conoscenza consiste nella
possibilità di essere espansa aggiungendo nuova informazione.
Nei sistemi basati sulla logica del prim’ordine, si usa la funzione
assert(KB,A)
per indicare che la base di conoscenza KB viene aumentata con
l’affermazione A.
La proprietà di monotonicità assicura che, se una conclusione C
segue logicamente da KB, allora continuerà a seguire anche dopo
aver aumentato KB con la nuova informazione A:
if KB  C then (KB ∧ A)  C
L’ereditarietà con eccezioni è non monotona.
Esempio.
Se aggiungessimo l’affermazione che i gatti hanno 3 zampe:
rel(Zampe, Gatti, 3)
seguirebbe che Tom ha 3 zampe, e non più 4 come in precedenza.
EREDITARIETA’ E CAMBIAMENTO
Ci sono 2 modi per risolvere questo problema
1. passare dalla logica del prim’ordine ad una logica non
monotona che tratta esplicitamente i valori di default.
Le logiche non monotone permettono di dire che una
proposizione P dovrebbe essere considerata vera fino a quando
qualche informazione aggiuntiva non consenta di dimostrare
che P è falsa.
C’è stato un grande lavoro teorico su questo punto, ma con un impatto minore sulle
applicazioni.
2. trattare l’aggiunta di enunciati facendo precedere la assert da
una retract, il che è possibile per come abbiamo definito rel.
Invece di fare molte affermazioni della forma
assert(KB,rel(R,A,B)), facciamo una grossa enunciazione di
equivalenza della forma
assert(KB, ∀r,a,b rel(r,a,b) ⇔ …)
dove … indicano tutte le possibili rel.
Dunque, per aggiungere rel(Zampe, Gatti, 3) dovremmo prima
rimuovere il vecchio enunciato di equivalenza sostituendolo
con uno nuovo.
Una volta alterata la base di conoscenza eliminando da essa
una frase (oltre che aggiungendone una nuova) la non
monotonicità dovrebbe essere facilmente comprensibile.
IMPLEMENTAZIONE DELLE RETI SEMANTICHE
Definita la semantica, si può pensare a come realizzare
effettivamente la rete:
dimostratore di teoremi
linguaggio di programmazione logica (spesso scelta migliore)
struttura dati (più diretta, per reti di piccole dimensioni)
Un nodo si può rappresentare come una struttura dati
con campi per le connessioni tassonomiche di base:
categorie di cui è membro: appartenenza
elementi che ne fanno parte: elementi
sovrainsiemi e sottoinsiemi diretti: sovrains, sottoins
e altri campi per altre relazioni in cui partecipa:
riferimenti ordinari (R): rel_in, rel_out
riferimenti R e R: tutte_rel_in e tutte_rel_out
Risulta la seguente definizione del tipo di dati per i nodi:
TipoDato
nodo_rete_sem
Componenti nome, appartenenza, elementi, sovrains, sottoins,
rel_in, rel_out, tutte_rel_in, tutte_rel_out
Ciascun campo ‘rel’ è organizzato come una tavola indicizzata
dalla relazione. Una funzione lookup(chiave, tabella) consente di
trovare il valore associato ad una chiave in una tavola.
Esempio.
Dati due riferimenti
Opus →Amico Tom
e
Opus →Amico Steve,
lookup(Amico, rel_out(Opus)) = {Tom, Steve}.
IMPLEMENTAZIONE DELLE RETI SEMANTICHE
L’interrogazione (ask) ad una rete circa quale relazione
(Sottoinsieme, Membro, …) vale fra due oggetti è realizzata dal
seguente codice:
function Membro?(elemento, categoria) returns boolean
for each c in appartenenza(elemento) do
if Sottoinsieme?(c, categoria) then return T
return F
function Sottoinsieme?(sotto, sovra) returns boolean
if sotto = sovra then return T
for each c in sovrains(sotto) do
if Sottoinsieme?(c, sovra) then return T
return F
function Legate?(sorgente, relazione, destinazione) returns boolean
if relazione appare in rel_out(sorgente) then
return Membro([relazione, destinazione], rel_out(sorgente))
else for each c in appartenenza(sorgente) do
if Tutte_legate?(c, relazione, destinazione) then return T
end
return F
function Tutte_legate?(sorgente, relazione, destinazione) returns boolean
if relazione appare in tutte_rel_out(sorgente) then
return Membro([relazione, destinazione], tutte_rel_out(sorgente))
else for each c in sovrains(categoria) do
if Tutte_legate?(c, relazione, destinazione) then return T
end
return F
N.B.: Membro? è una funzione che opera sui nodi della rete semantica;
Membro è un’utilità che opera su insiemi.
IMPLEMENTAZIONE DELLE RETI SEMANTICHE
Ciascuna funzione segue semplicemente i riferimenti appropriati
fino a trovare la risposta o fino alla fine dei riferimenti.
Il codice non gestisce i riferimenti R, né le eccezioni.
Inoltre il codice che asserisce (assert) nuove informazioni nella
rete è omesso, in quanto immediato.
Si possono aggiungere funzioni per rispondere ad altre domande.
Un problema di questo approccio è che è facile venire distratti
dalle strutture di dati e dimenticare la semantica alla base.
Esempio.
Definiamo una funzione numero_sottotipi che restituisce la lunghezza della lista
contenuta nel campo sottoins.
In base alla definizione precedente, numero_sottotipi(Animale) = 2.
Questa potrebbe essere la risposta che voleva l’utente, ma la sua situazione logica è
dubbia:
è probabile che vi siano specie di animali che non sono rappresentate nella base di
conoscenza
può accadere che alcuni nodi denotino lo stesso oggetto.
Magari Cane e Dog sono due nodi con un riferimento di uguaglianza fra di loro.
Questi contano come uno o due?
gatto_dalla_coda_nera o gatto_alla_stazione_stamattina sono tipi di animale? E’
facile rispondere a queste domande basandosi su ciò che è presente nella base di
conoscenza, ma è meglio avere una semantica chiara in modo tale da poter dare
una risposta che sia generale e non dipenda dallo stato corrente della
rappresentazione interna.
ESPRESSIVITA’ DELLE RETI SEMANTICHE
Le reti viste finora hanno un’espressività estremamente limitata,
non essendo in grado di esprimere costrutti che sono essenziali in
qualunque dominio, quali:
negazione
disgiunzioni
quantificazione
Come viene risolta questa limitazione?
Alcune reti semantiche estendono la notazione per consentire
l’utilizzo di tutti i costrutti della logica del prim’ordine (è il
caso dei grafi esistenziali originali).
Un approccio più comune riempie i buchi tramite aggiunte
procedurali, una tecnica per cui una funzione scritta in un
linguaggio di programmazione può essere immagazzinata come
valore di una qualche relazione ed utilizzata per rispondere a
chiamate ask sulla relazione (e talvolta anche a chiamate assert).
Qual è il vantaggio con cui le reti semantiche controbilanciano
questi compromessi?
possono catturare l’informazione di eredità in maniera modulare
sono facili da comprendere grazie alla loro semplicità
sono efficienti: poiché l’inferenza viene fatta seguendo
riferimenti, piuttosto che recuperando frasi da una base di
conoscenza tramite unificazioni, sono sufficienti pochi cicli di
macchina per ogni passo
In realtà, tuttavia, non vi è molta differenza col tipo di computazioni eseguite dai
programmi Prolog. Un programma Prolog compilato per un insieme di relazioni di
sottoinsieme e di appartenenza, combinate con proprietà generali di categoria, fa un
numero di calcoli praticamente pari a quello di una rete semantica.