Sistemi informativi Questa guida raccoglie appunti sul corso di sistemi informativi in preparazione all'esame. Sono presenti alcune annotazioni per agevolare l'apprendimento o rendere più esplicito alcune parti. Attenzione: Indica un concetto particolarmente importante o che presenta determinate criticità. Nota: Focalizza l'attenzione su un aspetto che richiede un approfondimanto. Problema: Definisce un problema da risolvere. Soluzione: Propone una soluzione ad un problema. Davide Mottin Indice Sistemi informativi Indice Argomenti trattati Dati strutturati Object oriented model Tipi di dato Chiavi Esercizi possibili Object-relational model User defined types (UDT) References (puntatori) Dereferenziare puntatori Inserimento e ordinamento Introduzione ai dati semistrutturati XML Principali caratteristiche di XML La sintassi Namespace DTD Sintassi DTD Attributi Definizioni ricorsive Usare i DTD nei documenti XML Esercizi possibili Query su documenti XML XPath Espressioni XPath Condizioni nelle espressioni XPath XPath (esteso) XQuery Sintassi di XQuery Join Eliminazione dei duplicati Test su insiemi di nodi Aggregazione Condizioni if Ordinamento XML Schema Sintassi di XML Schema Tipi semplici Tipi complessi Sequenze Attributi Altri tipi e restrizioni Chiavi e chiavi esportate Estensioni ai tipi Substitutions groups XQuery con tipi XSLT value-of apply-templates for-each if Data integration e mining Data integration Federated databases Data warehouse Mediatori Adornments Esercizi possibili Entity resolution Algoritmo per entity resolution Data mining Frequent itemset mining Trovare oggetti simili Min-hashing Locality Sensitive Hashing Clustering Clustering agglomerativo Distanza/unione di cluster Condizioni di stop Point assignment clustering k-means Algoritmo BFR OLAP Data cube Schema a stella Slicing e dicing Data cube formale Internet Rispondere a query PageRank Teleporting Altri modelli alternativi al PageRank Risolvere il problema dei link spam Pubblicizzare prodotti Ranking Adwords Un semplice algoritmo greedy Balance algorithm Argomenti trattati Due principali argomenti verranno approfonditi nel corso: dati strutturati e data integration and mining Dati Strutturati 1. Object oriented model 2. Object relational e linguaggi usati per Object-relational 3. Semi-structured data (senza schema) 4. XML Cos'è, come è fatto, a cosa serve Schema models: DTD e XSD Linguaggi per fare queries: XPath, XQuery e XSLT Data integration and mining 1. Data integration Come integrare diversi tipi di dato Come identificare oggetti (entità) simili o uguali anche se rappresentati in modo diverso 2. Introduzione al data mining: ricerca di strutture ricorrenti nei dati Frequent items Clustering Oggetti simili in pagine web (minhash) OLAP e datawarehousing Ricerca nel web Dati strutturati Object oriented model Definisce oggetti invece di relazioni (da tabelle a classi). Se vogliamo per esempio definire un film, possiamo creare la classe Movie: class Movie { attribute string title; attribute integer year; attribute integer length; attribute enum Genres {drama, comedy, sciFi, teen} genre; } Genres è di tipo enumerato, ovvero dichiara i possibili valori che può avere. Un attributo Address invece può essere definito come Struct, in questo caso rappresenta un tipo composto: attribute Struct Addr {string street, string city} address; Per aggiungere relazioni si usa la parola relationship, che nell'esempio permettono di definire insiemi di classi. relationship Set<Star> stars; (in Movie) relationship Set<Movie> starredIn; (in Star) Si possono esplicitamente definire relazioni inverse: relationship Set<Star> stars inverse Star::starredIn o riutilizzare tipi di dato definiti altrove: attribute Star::Addr address; Una classe può inoltre generalizzare (cioè estendere) un'altra con la parola chiave extends class HistoricalMovie extends Movie { attribute integer period; }; Tipi di dato Dati base: integer, real, string, character Enumerazioni: enum {} Classi e struct: per definire tipi e relazioni Collezioni (insiemi): Set: insiemi di oggetti senza ripetizioni Bag: insiemi di oggetti con ripetizioni List: oggetti ordinati Array: i oggetti di tipo T Dictionary: oggetti associativi, simili alle hash map Chiavi Per definire chiavi (come nel modello relazionale) su determinati attributi si usa la parola key dopo il nome della classe: class Movie (key (title, year)) { ... Esercizi possibili 1. Rappresentare in ODL una base di dati, poi in XML. 2. Per la base di dati in ODL: tradurla in relazionale (prerequisito) [slide 28-36]. Object-relational model Sostanzialmente si tratta di un compromesso che accetta Oggetti + Tabelle. Caratteristiche principali: * Attributi solo strutturati * Metodi di classe * Identificatori per le singole tuple * Riferimenti La caratteristica principale è la possibilità di definire Nested relations: le relazioni annidate sono tabelle nel modello relazionale. Per esempio: se si definisce Star si possono definire relazioni annidate Address e Movie per ogni attore. Problema: duplicazione di tabelle e di valori. Soluzione: definire puntatori (riferimenti) ad una relazione R e le sue tuple con sintassi ∗R. Movies(title, year, length) Stars(name, address(street, city), birthdate, movies ({*Movies}) Nota: in questo modo, però, gli id delle tuple nella tabella Stars divengono visibili perché sono riferimenti a tuple nella tabella Movies. User defined types (UDT) È possibile creare nomi alternativi (alias) a tipi già definiti per sollevare errori di type check (ovvero confrontare tipi di dato diversi non è possibile). CREATE TYPE T AS <primitive type>; Inoltre si possono definire tipi di dato complessi: CREATE TYPE street AddressType AS ( street CHAR(50), city CHAR(20) ); Si possono anche creare relazioni (TABLE) di UDT: CREATE TABLE MovieStar OF StarType ( PRIMARY KEY (name) ); References (puntatori) Per poter referenziare una tabella T si usa la sintassi REF(T); inoltre, se due tabelle hanno lo stesso tipo, si può definire uno scope per restringere il riferimento ad una sola di esse. CREATE TYPE StarType AS ( name CHAR(30), address AddressType, bestMovie REF(MovieType) SCOPE Movies ) È possibile riferirsi esplicitamente all'id di una tabella (o di una tupla) utilizzando la sintassi: REF IS <campo id> SYSTEM GENERATED alla crezione della tabella stessa. Il campo può essere SYSTEM GENERATED o DERIVED (ovvero la chiave primaria viene usata come id). Dereferenziare puntatori Ma a cosa punta effettivamente un puntatore? Sia dato un puntatore x ad una tupla t di tipo T . Allora il costrutto DEREF(x) restituisce t e x->a restituisce l'attributo a di t. Ecco un esempio di dereferenziazione: SELECT DEREF(movie) FROM StarsIn WHERE star-­‐>name=Brad Pitt; Dimenticare il DEREF significa non lavorare con l'oggetto, ma solo con i suoi riferimenti. Per accedere al valore di un campo x in una tupla t si usa estrazione del valore x al tipo (come un metodo getter). t. x() , che in pratica applica il metodo di SELECT m.year() FROM Movies m WHERE m.title()=’KingKong’; Nota: Una caratteristica fondamentale dei database object-relational è che non richiedono JOIN, in quanto basta utilizzare relazioni annidate e dereferenziare puntatori. Inserimento e ordinamento Per inserire un nuovo oggetto bisogna prima crearne uno vuoto e poi popolarlo. L'ordinamento deve essere esplicitamente dichiarato attraverso il costrutto: CREATE ORDERING for <type name> <details> dove <details> è: * EQUALS ONLY BY STATE: definisce l'uguaglianza se gli attributi sono uguali * FULL BY RELATIVE WITH F definisce un determinato ordine con F. CREATE ORDERING FOR StarType EQUALS ONLY BY STATE; Attenzione: se l'oggetto contiene altri tipi, l'uguaglianza deve essere definita per ogni tipo annidato. Introduzione ai dati semistrutturati I dati semistrutturati: * Non hanno uno schema fissato, ma viene inferito dai dati stessi. * Sono utilizzati per data integration o per interscambio di dati. * Possono essere prodotti da tecnologie diverse. * Possono essere utilizzati per creare "wrappers" che convertano query in diversi linguaggi. * Maggiore flessibilità ↔ , difficile ottimizzazione delle query. * Vengono rappresentati come nodi e archi. * Il modello prevede: * Un nodo radice (root). * Nodi intermedi senza etichetta (rappresentano classi). * Etichette sugli archi: nomi degli attributi. * I dati memorizzati sulle foglie. XML XML è lo pseudonimo di eXtensible Markup Language, nato per presentare documenti. Si è evoluto come standard per la descrizione di dati in maniera semistrutturata. Attenzione: XML non richiede uno schema di dato, perciò in molti casi può risultare ambiguo o difficile da interpretare. HTML è progenitore di XML, seppure sia meno flessibile. HTML viene utilizzato per la presentazione del contenuto di pagine web. Le regole di presentazione di HTML sono molto libere, a differenza di XML (vedi sotto), e perciò non risulta adatto a descrivere dati. Principali caratteristiche di XML Vediamo un esempio di XML: <?xml version="1.0" encoding="ISO-­‐8859-­‐1"?> <?xml-­‐stylesheet type="text/xsl" href="books.xsl"?> <books> <book title="Learning XML"> <authors> <author>Erik Ray</author> </authors> <publisher>O’Reilly</publisher> </book> <book title="XQuery"> <authors> <author>Priscilla Walmsley</author> </authors> <publisher>O’Reilly</publisher> </book> </books> I tag possono essere definiti dall'utente ed esprimono una struttura logica. Il documento XML è rappresentato ad albero. HTML può essere rappresentato in XML. Lo schema non obbligatorio viene definito nel DTD o XML Schema. Si possono applicare trasformazioni al file XML per convertirlo in un qualsiasi altro formato. Le trasformazioni XML sono chiamate anche XSL(t). XML viene utilizzato per l'interscambio di dati. Essendo un file di testo, può essere letto e interpretato da diverse piattaforme software e librerie di programmazione. Lo standard XML è definito dal World Wide Web Consortium (W3C)1. Lo standard XML è definito dal World Wide Web Consortium (W3C)1. La sintassi Risulta importante considerare due concetti fondamentali: 1. Elementi: può essere una qualsiasi cosa racchiusa in tag (come book nell'esempio in alto). 2. Attributi: definiscono caratteristiche di un tag (come title nell'esempio in alto). Un documento XML si dice well-formed se: 1. Ogni elemento è circondato da < ... >. 2. Esiste un solo elemento radice. 3. Ogni elemento aperto deve essere chiuso, dove la chiusura di un elemento <tag> si indica con </tag>. 4. Gli elementi possono essere innestati: <tag><nestedtag><\nestedtag><\tag> e i tag più interni vanno chiusi per primi. 5. I tag possono avere attributi: <tag attribute="value">. 6. Elementi senza contenuto (nessun tag/testo al loro interno) possono essere chiusi con <tag />. 7. Un elemento può contenere testo. 8. I nomi degli attributi in un elemento sono univoci. Un documento XML si dice valido se rispetta lo schema (vedremo DTD e XML schema). Nota: Il documento XML rappresenta quasi fedelmente l'albero in memoria. Quasi perché l'ordine dei tag non viene catturato dall'albero (a meno di particolari istruzioni) e perché gli spazi bianchi ed altri caratteri vengono ignorati. Se non si vuole che una particolare sezione di testo venga interpretata come XML, deve essere inclusa in un blocco CDATA <![CDATA[ Tags in XML are delimited by "<" and ">". ]]> Altrimenti per rappresentare < e > bisogna usare caratteri di escape &lt; e &gt;. Namespace Per evitare di definire più volte lo stesso tag si possono usare i namespace (analoghi ai package nei linguaggi di programmazione) inserendo prefissi definiti attraverso speciali attributi nei tag o all'inizio del documento XML nella root. Ecco un esempio per una tabella: <xh:table xmlns:xh="http://www.w3.org/1999/xhtml"> <xh:tr> <xh:td>Apples</xh:td><xh:td>Bananas</xh:td> </xh:tr> </xh:table> DTD Il Documento delle Definizioni di Tipi (DTD) serve per definire una struttura agli elementi di un documento XML. Il DTD è basato sulle espressioni regolari (regexp o regular expressions). Nota: definire un DTD (come XML schema d'altronde) significa dare delle regole per dire quando un particolare documento è valido, inducendo regole di struttura. Attenzione: come vedremo il DTD è poco espressivo, perciò è stato introdotto XSchema. Sintassi DTD I tag definiscono gli elementi (che sono, di fatto, tipi complessi). A parte gli elementi, non ci sono altri tipi base (interi, booleani, ...): tutto è una stringa (indicata con #PCDATA). In DTD, oltre agli elementi (tag) che possono contenere altri tag, si possono definire i seguenti contenuti: #PCDATA: indica sequenze di caratteri (parsed, ovvero interpretabili dal parser). EMPTY: nessun contenuto. ANY: qualsiasi contenuto. (e): un gruppo di espressioni (di solito serve per riferirsi al particolare gruppo con un nome o un numero e non doverlo riscrivere ogni volta). Un documento DTD inizia con !DOCTYPE, seguito dal nome della radice del documento XML Ecco un esempio per definire Stars: <!DOCTYPE Stars [ <!ELEMENT Stars (Star*)> <!ELEMENT Star (Name, Address+, Movies)> <!ELEMENT Name (#PCDATA)> <!ELEMENT Address (Street, City)> <!ELEMENT Street (#PCDATA)> <!ELEMENT City (#PCDATA)> <!ELEMENT Movies (Movie*)> <!ELEMENT Movie(Title, Year)> <!ELEMENT Title (#PCDATA)> <!ELEMENT Year (#PCDATA)> ]> Come si nota, gli elementi (come Movie) possono essere definiti da altri elementi o da espressioni regolari (cfr. Stars (Star*)). Per esempio: Stars (Star*) definisce che Stars (l'elemento radice) contiene 0 o più elementi Star. Se un elemento non contiene altri elementi allora è una foglia e, come Name nell'esempio precedente, può contenere solo testo o essere vuoto. Attributi Gli attributi degli elementi XML in DTD sono indicati con <!ATTLIST>. Gli attributi possono essere: Stringhe: indicate con CDATA. Enumerazioni: indicate con (valore1 | valore2 | ...). Chiavi: indicate con ID. Chiavi esportate: indicate con IDREF (chiavi che sono definite in altri elementi). Liste di chiavi esportate: indicate con IDREFS. Possono inoltre avere un valore: Di default, se l'attributo è opzionale ed assume un valore fisso (per esempio età=10). #REQUIRED: se l'attributo è obbligatorio. #IMPLIED: se è opzionale. #FIXED value: se assume un valore fisso. Nota: Se un attributo è dichiarato come ID, allora i suoi valori devono essere univoci. Nota: Un elemento può non avere nessuna chiave (a differenza del modello relazionale). Esempio: <!ELEMENT height (#PCDATA)> <!ATTLIST height dimension (cm|in) #REQUIRED accuracy CDATA #IMPLIED resizable CDATA #FIXED "yes" > Attenzione: Gli attributi non possono essere definiti una volta sola. Definizioni ricorsive Un elemento può essere definito in termini di se stesso. Per esempio, una persona può essere definita da due altre persone (genitori). <!DOCTYPE Person [ <!ELEMENT Person (Person?, Person?)> <!ATTLIST name #CDATA> ]> Attenzione: le definizioni ricorsive devono avere un modo per definire un caso base (nel caso sopra, una persona non ha nessun figlio). Usare i DTD nei documenti XML Per importare un DTD e definire la validità dell'XML si usano le seguenti direttive: <?xml version="1.0" encoding="utf-­‐8" standalone="no"?> <!DOCTYPE Stars SYSTEM "star.dtd"> dove standalone="no" indica che il documento ha un DTD (nello stesso file o in uno esterno). Il sistema controlla che il documento XML sia valido, quindi conforme al DTD. Attenzione: un DTD deve essere deterministico, il che vuol dire che non è possibile generare le stesse strutture in due (o più) pattern ugualmente validi. Esercizi possibili 1. Riconoscere quando un DTD è ambiguo. 2. Generare un DTD per un determinato XML . 3. Riconoscere se una struttura è valida per un DTD. 4. Generare un DTD ricorsivo per determinate strutture. Query su documenti XML Tra i diversi linguaggi, solo XQuery è un linguaggio per interrogazioni2 su documenti XML, mentre XPath definisce un linguaggio per navigare l'albero XML e XSL trasformazioni tra i documenti. XPath XPath3 è un linguaggio navigazionale che produce documenti XML come output, perché restituisce tutti i nodi che rispettano particolari condizioni. Nota: La navigazione del documento può partire da un punto qualsiasi, anche se solitamente si parte dalla radice, indicata con "/". Espressioni XPath Sono concatenazioni di tag e "selettori" su di esse, separate da "/", il che significa "considera il livello dell'albero sottostante al corrente". XPath permette di specificare attributi, valori e restringere i nodi da restituire. L'espressione: /T1/T2/ ... /Tn significa che, partendo dalla radice, si selezionano tutti i tag Tn figli della sequenza di elementi fino a T1. Per selezionare l'attributo att si usa @att. /StarMovieData/Star/@StarID. Assi: Si può navigare da padre a figlio e da figlio a padre usando ".." per risalire l'albero. Il selettore "." restituisce il nodo corrente. Il selettore "//" restituisce tutti i discendenti di un nodo (esempio //City). Wildcard: * significa "qualsiasi tag/elemento". @* significa "qualsiasi attributo". Attenzione: se si scrive un'espressione non valida o sbagliata, XPath non segnala un errore, ma restituisce una lista vuota. Condizioni nelle espressioni XPath Una condizione viene espressa con p[c], dove p è un tag e c una condizione booleana (uguaglianza, disuguglianza, ...). /StarMovieData/Star[name="Fisher"] (star con nome "Fisher") /StarMovieData/Star[.//City="Malibu"] (star che hanno almeno una casa a "Malibu") //religions[@percentage > 30]/..[name="Germany"]/name (filtri su attributi -­‐ nomi delle religioni in Germania con una percentuale di fedeli di almeno 30%) Attenzione: scrivere //City e .//City è profondamente diverso, in quanto la prima espressione parte dalla radice, la seconda dal nodo corrente. La condizione [i] restituisce l'i-esimo nodo, mentre [name] seleziona i nodi con un determinato figlio. /Movies/Movie/Version[1]/@year (anno della prima versione del film) /Movies/Movie/Version[Star] (film di cui esiste almeno una star) XPath (esteso) [nelle slide] XQuery XQuery è un linguaggio che permette di fare interrogazioni ad un documento XML utilizzando una sintassi paragonabile all'SQL per i database relazionali. XQuery utilizza i costrutti principali for, let, where, return. Nota: ulteriori informazioni e esempi su XQuery si possono trovare nella pagina del W3C4 Sintassi di XQuery Una query inizia con "for" (iterazione) o "let" (assegnamento di variabile), con, a seguire, un "where" opzionale e termina con un "return". La query: return <Greeting>Hello World</Greeting> restituisce un nuovo documento XML. I costrutti principali di XQuery sono: let: dichiara una nuova variabile che contiene la valutazione di un'espressione (un insieme di nodi). Sintassi: let variabile := espressione let $stars := doc("stars.xml") for: itera su una lista di nodi, rappresentata da un'espressione. Sintassi: for variabile in espressione let $movies := doc("movies.xml") for $m in $movies/Movies/Movie dove la variabile $m conterrà, ad ogni iterazione, un singolo nodo che corrisponde all'espressione $movies/Movies/Movie. where: come il "where" in SQL, ma applicato ai nodi di un documento XML. return: aggiunge elementi ai risultati, non interrompe il ciclo! let $movies := doc("movies.xml") for $m in $movies/Movies/Movie return $m/Version/Star Data la caratteristica "costruttiva" di return, è possibile costruire nuovi elementi/attributi che non appartengono al documento XML, per esempio la sintassi: return <Movie title="{$m/@title}">{$m/Version/Star}</Movie> costruisce un nuovo film con titolo come attributo e l'insieme delle star. Attenzione: non bisogna dimenticare le { ... } nei selettori di "return", altrimenti non vengono interpretate come espressioni XPath, ma copiate senza interpretazione in output!!! Nota: è possibile dichiarare una variabile che contenga la valutazione di un'espressione XQuery intera, come per esempio nel caso seguente: let $starSeq := ( let $movies := doc("movies.xml") for $m in $movies/Movies/Movie return $m/Version/Star ) Join Il confronto in XML è definito sull'identità dei nodi dell'albero, mentre l'operazione di join avviene sui valori. Per poter confrontare valori si usa la funzione data(E), che estrae i dati da un nodo. Usando un ciclo annidato è possibile effettuare join sui valori dei nodi. for $sl in $movies/Movies/Movie/Version/Star, $s2 in $stars/Stars/Star where data($sl)=data($s2/Name) Attenzione: se si scorre lo stesso tag più volte per esempio for $o1 in $doc//Order, $o2 in $doc//Order ricordarsi di includere una clausula where nel quale si eviti di fare il confronto più volte where $o1 << $o2 Attenzione: l'uguaglianza con "=" controlla l'esistenza di almeno un nodo che verifichi l'espressione in input, per testare, infatti, ogni singolo nodo, è necessario usare "eq". Ad esempio, in questo caso: let $stars := doc("stars.xml") for $s in $stars/Stars/Star where $s/Address/Street eq "123 Maple St." and $s/Address/City eq "Malibu" return $s/Name se si usasse "=" invece di eq, la condizione sarebbe vera se esistesse almeno una star con indirizzo "123 Maple St." a "Malibu". Eliminazione dei duplicati Per eliminare i duplicati è possibile utilizzare il costrutto distinct-values prima di restituire i risultati (e/o memorizzarli in una variabile). Test su insiemi di nodi Esiste (∃): some variable in expression1 satisfies expression2 Per ogni ( ∀): every variable in expression1 satisfies expression2 Esempio: ~~~xml let stars := doc(" stars. xml ")f or s in stars//Starwhereevery c in s//Citysatisf ies c="Hollywood" return $s/Name ~~~ Aggregazione Stessi operatori di SQL: count, max, min, avg, sum La somma di stringhe converte la stringa prima in numero (se possibile), poi calcola la somma dei risultati. Condizioni if Hanno la stessa semantica e sintassi di un normale linguaggio di programmazione. Sintassi: if (expression1) then expression2 else expression3 Attenzione: il ramo else è obbligatorio, ma può essere vuoto. Ordinamento Come in SQL, esiste il costrutto order by, che può essere utilizzato per scorrere gli elementi di un ciclo for in maniera ordinata. Sintassi: for ... order by attribute1,...,attributeN XML Schema XML Schema è un linguaggio (un dialetto XML, per la precisione) che definisce lo schema di un documento XML, proprio come DTD, ma più espressivo e verboso. Alcune caratteristiche principali: * I tag sono separati dal tipo: è infatti possibile definire lo stesso tag più volte. * I tipi base sono già definiti. * XSchema è un documento XML! ⟹ non si deve imparare una nuova sintassi. Nota: Dato che XML Schema è analogo a XML, per disambiguare i tag definiti dall'utente da quelli definiti dallo standard si usano i namespace (vedi sezione corrispondente). Di solito si indica il namespace di XML Schema con xs, per esempio xs:element. Sintassi di XML Schema Tipi semplici Il tag xs:element definisce la struttura di un nodo XML del documento. <xs:element name="[nome elemento]" type="[tipo elemento]"[vincoli o informazioni struttu rali] /> Per esempio, si può definire il tag Year di tipo intero, ma in questo modo se si indica all'anno un tipo diverso in fase di validazione, verrà segnalato un errore. <xs:element name="Year" type="xs:integer" /> Tipi complessi Si possono definire anche tag ed elementi più complessi, come insiemi di elementi semplici (per esempio Movie è un elemento complesso). <xs:complexType name="[nome dell'elemento]"> <xs:sequence> [Lista di definizioni di elementi] </xs:sequence> </xs:complexType> Nota: Si possono definire tipi complessi senza nomi, detti tipi anonimi. Nota: se vogliamo elementi con nodi e test mescolati, si può usare mixed="true" Sequenze Serie di elementi che definiscono i figli di un tag attraverso <xs:sequence>. Possono avere una cardinalità espressa con gli attributi minOccurs e maxOccurs, con valore intero OPPURE "unbounded" (se infinito). Attenzione: le sequenze definiscono elementi figli, ma nel caso si voglia vincolarne il numero si usa xs:all per dire di volere esattamente una occorrenza di ogni elemento, oppure xs:choice per dire che uno solo degli elementi nella sequenza deve essere presente (in maniera esclusiva). Attributi Gli attributi vengono definiti con xs:attribute attraverso la sintassi: <xs:attribute name="[nome attributo]" type="[tipo attributo]" [altre informazioni] /> Per esempio: ~~~xml ~~~ definisce l'attributo year di tipo intero con valore di default (se non è presente l'attributo) a 0 ⟹ l'attributo è in questo caso opzionale. Per definire un attributo obbligatorio si deve usare la sintassi use="required". Altre definizioni utili <xs:attribute name="country" type="xs:NMTOKEN" fixed="US"/> xs:NMTOKEN modella stringhe senza spazi e caratteri speciali. fixed significa che quando l'attributo country è presente, ha il valore "US". xs:date rappresenta date. <xs:attribute name="orderDate" type="xs:date"/> ref modella attributi definiti altrove. <xs:element ref="comment" minOccurs="0"/> Altri tipi e restrizioni I valori sugli elementi possono essere condizionati definendo una restrizione che vincoli il valore minimo e massimo (con minInclusive e maxInclusive), oppure attraverso una serie di valori (per creare un enumerazione). Restrizione sui valori <xs:simpleType name="movieYearType"> <xs:restriction base="xs:integer"> <xs:minInclusive value="1915" /> </xs:restriction> </xs:simpleType> Enumerazioni: definiscono possibili valori accettati dal tipo <xs:simpleType name="genreType"> <xs:restriction base="xs:string"> <xs:enumeration value="comedy" /> <xs:enumeration value="drama" /> <xs:enumeration value="sciFi" /> <xs:enumeration value="teen" /> </xs:restriction> </xs:simpleType> Pattern: servono a specificare restrizioni sulle stringhe accettate attraverso la sintassi <xs:pattern value="pattern" />. I pattern sono definiti dalla sintassi delle espressioni regolari (vedi sotto): <xs:simpleType name="SKU"> <xs:restriction base="xs:string"> <xs:pattern value="\d{3}-­‐[A-­‐Z]{2}"/> </xs:restriction> </xs:simpleType> Nota: la sintassi dei pattern è la seguente: Nota: la sintassi dei pattern è la seguente: Liste: è possibile definire anche elementi di tipo lista e restrizioni nella dimensione (separati da spazio). <xs:simpleType name="USStateList"> <xs:list itemType="USState"/> </xs:simpleType> <xs:simpleType name="SixUSStates"> <xs:restriction base="USStateList"> <xs:length value="6"/> </xs:restriction> </xs:simpleType> Unioni: tipi che devono essere ristretti a uno tra una lista di tipi: <xs:simpleType name="zipUnion"> <xs:union memberTypes="USState listOfMyIntType"/> </xs:simpleType> la quale modella i seguenti elementi validi: <zips>CA</zips> <zips>95630 95977 95945</zips> <zips>AK</zips> Attenzione: Solo i tipi complessi possono avere attributi. Per avere attributi su un tipo semplice, si definisce un tipo complesso con un contenuto semplice (tag simpleContent). <xs:element name="internationalPrice"> <xs:complexType> <xs:simpleContent> <xs:extension base="xs:decimal"> <xs:attribute name="currency" type="xs:string"/> </xs:extension> </xs:simpleContent> </xs:complexType> </xs:element> Attenzione: per avere un tag "vuoto" (cioè senza contenuto, ma con attributi) si può costruire un complexType con un complexContent, ma con restrizione xs:anyType e descrizione degli attributi, oppure più semplicemente: <xs:element name="internationalPrice"> <xs:complexType> <xs:attribute name="currency" type="xs:string"/> <xs:attribute name="value" type="xs:decimal"/> </xs:complexType> </xs:element> Chiavi e chiavi esportate In XML schema ci sono due tipi di chiavi: selettori e campi. * I selettori: identificano l'elemento a cui applicare una chiave attraverso XPath. * I campi: identificano i campi usati come chiave attraverso XPath. <xs:key name="[nome chiave]" > <xs:selector xpath="[espressione xpath]" /> <xs:field xpath="[espressione xpath]" /> </xs:key> Nota: ci può essere più di un selettore per lo stesso elemento. Nota: si può usare xs:unique invece di xs:key, con la differenza che per key "xs:field" deve sempre esistere, invece per unique no. <xs:key name="movieKey"> <xs:selector xpath="Movie" /> <xs:field xpath="Title" /> <xs:field xpath="Year" /> </xs:key> Allo stesso modo si possono definire le chiavi esportate, con la seguente sintassi: <xs:keyref name="[nome chiave esportata]" refer="[nome chiave a cui si riferisce]" > <xs:selector xpath="[espressione xpath]" /> <xs:field xpath="[espressione xpath]" /> </xs:keyref> Estensioni ai tipi Una volta definito un tipo è possibile estenderlo, che significa aggiungere altri elementi ad un tipo già esistente. Si deve usare il tag <extension>. <extension base="[tipo esistente]"> [elementi aggiunti al tipo] </extension> Per esempio, definito un tipo Address è possibile definire un tipo USAddress in questo modo: <complexType name="USAddress"> <complexContent> <extension base="Address"> <sequence> <element name="state" type="USState"/><!-­‐-­‐ USState è un tipo già definito altrov e -­‐-­‐> <element name="zip" type="positiveInteger"/> </sequence> </extension> </complexContent> </complexType> Substitutions groups Gli elementi in un "gruppo di sostituzione" (traduzione dall'inglese) possono essere usati in un qualsiasi posto in cui l'elemento che sostituiscono sia stato usato. Attenzione: se un elemento usa elementi che sono sostituzioni, allora sarà richiesto lo specifico tag da essi definito (applicando una restrizione al tipo che sostituisce, non al sostituito). <element name="comment" type="string"/> ... <element name="shipComment" type="string" substitutionGroup="ipo:comment"/> <element name="customerComment" type="string" substitutionGroup="ipo:comment"/> XQuery con tipi Per fare una query ristretta ad un particolare tipo si può usare la sintassi: instance of element(tag, tipo) Per esempio: count( doc("ipo.xml")//shipTo[. instance of element(*, ipo:UKAddress)]) Nota: In questo modo si possono costruire funzioni che controllano solo particolari tag e particolari tipi e che effettuano operazioni su di esse. XSLT XSLT è l'acronimo di Extensible Stylesheet Language for Transformation ed è un linguaggio che permette di trasformare un documento XML in qualsiasi altro formato attraverso XQuery e XPath. XSLT è (nuovamente) un documento XML definito attraverso un preciso schema5. Un documento XSLT è così strutturato: <? xml version = "1.0" encoding = "utf-­‐8" ?> <xsl:stylesheet xmlns:xsl="http ://www.w3.org/1999/XSL/Transform"> [elenco trasformazioni] </xsl:stylesheet> Un XSLT è un insieme di template che, attraverso espressioni XPath, matchano parti di documento ed effettuano opportune trasformazioni. <xsl:template match="[espressione XPath]"> Ora descriviamo i principali costrutti di XSLT: value-of Seleziona il valore di una particolare espressione e lo stampa in output <xsl:value-­‐of select="[espressione]"/> Per esempio, se volessimo l'attributo title di ogni film: <? xml version="1.0" encoding="utf-­‐8" ?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/Movies/Movie"> <xsl:value-­‐of select="@title" /> <br/> </xsl:template> </xsl:stylesheet> apply-templates È possibile applicare ricorsivamente template una volta definiti. Per esempio, per ogni elemento corrispondente ad un'espressione è possibile applicare un template di trasformazione. <xsl:apply-­‐templates select="[espressione]" /> Per esempio: <xsl:template match="/Movies"> <Movies> <xsl:apply-­‐templates /> </Movies> </xsl:template> Nota: l'assenza di un select dopo apply-templates significa: "applica tutti i template che matchano tutti i figli" (nel caso dell'esempio, da solo non produce nessun output). for-each Si può eseguire la trasformazione per ognuno dei tag corrispondenti. <xsl:for-­‐each select="[espressione]" /> Per esempio si può iterare ogni Star e produrre una lista di nomi: <ol> <xsl:for-­‐each select = "Stars/Star"> <li> <xsl:value-­‐of select = "Name"> </li> </xsl:for-­‐each> </ol> if La trasformazione entro il tag si attiva ad un particolare condizione booleana. Attenzione: non c'è nessun else. <xsl:if test="[espressione booleana]" /> Data integration e mining L'importanza di gestire, integrare e analizzare i dati è vitale in molte applicazioni. In questo capitolo verranno introdotti i seguenti argomenti: Integrazione di dati Data mining OLAP Trovare informazioni nel web Data integration Problema: abbiamo diverse basi di dati eterogenee che contengono cose simili ma con schemi diversi, tipi di dato diversi, rappresentazioni diverse. Come troviamo le informazioni da cercare in maniera trasparente? Assumiamo che i dati abbiano lo stesso schema, ma valori leggermente diversi negli attributi. Esistono tre approcci: 1. Federated databases: database indipendenti, ma ognuno in grado di chiamare/spedire informazioni all'altro. 2. Warehousing: integrazione dei dati in un unico grande database (esempio, OLAP). 3. Mediation: crea un'interfaccia comune di accesso ai vari dati e converte le query per ognuno dei database. Federated databases Supponiamo di avere n database con informazioni diverse e indipendenti. Un approccio potrebbe essere che ogni database effettua una query su ogni altro database. Problema: Approccio troppo dispendioso dato il numero di query da fare, ossia tutte le possibili coppie: (n2 ) Soluzione: Scrivere una query diversa per ogni database. Problema: Difficile costruire una query del genere. Data warehouse Un'unico grande database che combina i dati di n database indipendenti. I dati vengono integrati e aggiornati periodicamente nella warehouse. Vengono utilizzate soprattutto per calcolare aggregati e per questo non devono essere necessariamente aggiornati in tempo reale. Vantaggio: dobbiamo scrivere una sola query. Problema: Come mappare tanti dati in un'unico database? Come mantenere i dati aggiornati? Soluzione: Integrare i dati in maniera manuale producendo tabelle e mediatori per ogni database, in modo tale da tradurre i dati in un'unica tabella (si ricorda che i campi dei singoli database possono avere nomi diversi). Attenzione: mentre inserimenti e interrogazioni alla data warehouse sono abbastanza automatici, la cancellazione è più complicata, in quanto cancellare un dato nella tabella integrata potrebbe voler dire cancellarlo in multiple tabelle (se è un dato replicato) oppure in una sola. Il problema è che se il dato è più complesso non si può sapere se si debba preservare o no in un database. Mediatori I mediatori sono delle viste (view in SQL) virtuali di un insieme di database. I mediatori non memorizzano nessun dato. Ogni database ha un "wrapper" o un mapping tra campi mediati e campi nel singolo database, in modo da "tradurre" le query nei diversi database. Per tradurre una query in un database in una query utente si possono usare template per wrapper (si ricorda che un wrapper è un pezzo di software che effettua la traduzione degli attributi). Ecco un esempio dove AutosMed è lo schema del mediatore: SELECT * FROM AutosMed WHERE color = $c; => SELECT serialNo, model, color, autoTrans, "dealer1" FROM Cars WHERE color = $c; Problema: le query possono diventare molto complesse ed in molti casi è impossibile trovare un Problema: le query possono diventare molto complesse ed in molti casi è impossibile trovare un mapping. Soluzione: restringere il problema a determinate classi di query e costruire un wrapper generator. Problema: non è possibile costruire un template per ogni query. Si immagini di volere macchine di un certo colore e di un certo modello (condizioni in AND su attributi). Soluzione: creare dei template meno rigidi che restituiscano meno risultati (per esempio solo vincolati al colore), per poi restringere la query in un secondo momento. Problema: non è sempre possibile scrivere una query più generica (privacy, costo computazionale o di rete). Soluzione: definire un modello che descriva quali query si possano fare o sono vietate → adornments Adornments È una sorta di linguaggio che specifica le possibilità su un database. f (free): l'attributo può essere specificato. b (bound): dobbiamo specificare un valore per l'attributo. u (unspecified): l'attributo non può essere specificato. c[S] (choice from set S): un valore deve essere specificato entro l'insieme S. o[S] (optional, from S): se specificato deve avere un valore in S. f': l'attributo non può essere parte dell'output. L'insieme degli adornments definisce le capabilities specification. Cars(serialNo, model, color, autoTrans, navi) Cars(ubbo[yes,no]o[yes,no]) Sono specificati modello e colore e, opzionalmente, trasmissione automatica e navi gatore. Il mediatore semplicemente analizza le specifiche e decide la miglior strategia (ha una sorta di cost model interno). Esercizi possibili 1. Scrivere una soluzione di integrazione per diversi database (e.g. 3 database). 2. Scrivere adornments per un particolare sistema. 3. Dato un'insieme di specifiche con adornments verificare se possono rispondere a determinate query o costruire un plan di esecuzione di una query. Entity resolution Molte volte alla stessa entità (oggetto, persona, stato ...) ci si può riferire in modi diversi. Questo problema si verifica spesso in database diversi e ancor più spesso nel web a causa del linguaggio naturale. Problema: come capire che due espressioni si riferiscono alla stessa entità? Soluzione: Edit distance: approssimare le stringhe con la stringa più "vicina", cioè quella che è ottenuta trasformando (inserendo, cancellando o modificando) il minor numero di caratteri possibili. Attraverso l'edit distance è possibile definire una somiglianza tra stringhe: le stringhe che hanno una distanza minore di τ fissato sono considerate simili. Attenzione: la similarità non è transitiva. Algoritmo per entity resolution Problema: dato un database, unire (merge) tuple simili. Soluzione: un algoritmo che unisca tuple simili, ma solo nel caso che l'operazione di merge rispetti alcune proprietà. Sia ⊕ un'operazione di merge che rispetta le seguenti proprietà: t ⊕ t (riflessività). t ⊕ s = s ⊕ t (commutatività). (r ⊕ s) ⊕ t = r ⊕ (s ⊕ t) (associatività). mentre la relazione di similarità ≈ deve essere tale che: r ≈ r (riflessività). r ≈ s iff s ≈ r (simmetria). if r ≈ s then r ≈ (s ⊕ t) (rappresentabilità). Input: un insieme I di record, similarità ≈, una funzione di merge ⊕. Ouptut: un insieme O ⊆ I. Procedura: L'algoritmo parte dall'insieme dei risultati, inizialmente vuoto, e cerca di aggiungere tuple dal database che non sono simili a nessuno dei risultati già aggiunti. Questo è lo pseudocodice: O := emptyset; WHILE I is not empty DO BEGIN let r be any record in I; find, if possible, some record s in O that is similar to r; IF no record s exists THEN move r from I to O ELSE BEGIN delete r from I; delete s from O; add the merger of r and s to I; END; END; Attenzione: per utilizzare l'algoritmo bisogna dimostrare le proprietà per ≈ e ⊕. Problema: se la funzione ⊕ non rispetta le proprietà? Soluzione: si definisce una dominance relation r (contiene) e perciò si può ignorare r . ≤ s nella quale s contiene tutte le informazioni di r Data mining Molte volte si hanno a disposizione dati non strutturati o per i quali si hanno poche informazioni preliminari (prior), ma si vogliono fare delle analisi per scoprire importanti relazioni o inferire nuove informazioni. Il data-mining si occupa di questo. Frequent itemset mining Problema: Abbiamo un insieme di oggetti venduti da un negozio e una serie di transazioni, ossia oggetti comperati da utenti in un singolo acquisto. È possibile trovare quali oggetti vengono comperati insieme più frequentemente? Questo problema è detto association rule mining. Assumiamo di avere un insieme di oggetti e uno B di transazioni. Vogliamo trovare tutte le regole del tipo I ⇒ i , dove i ∈ e I ⊆ . Definiamo una nozione di "frequenza" basata sul supporto, che misura quante volte un sottoinsieme di oggetti compare nelle transazioni degli utenti. Diciamo che un insieme di oggetti è frequente se ha un supporto maggiore di un s fissato. Definiamo inoltre la confidenza di una regola I contengono I. ⇒ i come la probabilità di trovare i negli insiemi che Problema: come trovare efficientemente tutte le regole che abbiano un minimo supporto confidenza c? Soluzione: s e una minima Soluzione naive SELECT I.item, J.item, C0UNT(I.basket) FROM Baskets I, Baskets J WHERE I.basket = J.basket AND I.item < J.item GROUP BY I.item, J.item HAVING COUNT(I.basket) >= s; Chiaramente richiede troppe comparazioni e potrebbe generare regole poco interessanti. Algoritmo A-priori Sfrutta il risultato teorico che la frequenza è antimonotona, ovvero: i sottoinsiemi di un insieme frequente sono insiemi frequenti. Ecco lo pseudo-pseudo codice (nelle slide ne è presente uno più formale): 1. Sia C1 l'insieme degli itemset frequenti con un item. 2. i=1 3. Per ogni (a, b) 1. 4. ∈ Ci Ci+1 contiene tutti gli a ∪ b frequenti, i = i + 1 e riparti da 3. finché Ci+1 ≠ ∅ Nota: A livello di implementazione l'algoritmo può essere ottimizzato con strutture dati intelligenti. Attenzione: L'algoritmo genera itemset frequenti, non regole frequenti. Per generare regole frequenti bisogna aggiungere anche una confidenza minima e considerare le sole regole che hanno una confidenza minima. L'algoritmo si può ottimizzare utilizzando hashing: una funzione di hash viene sfruttata per produrre dei bucket tra coppie di oggetti negli item frequenti. Si mantiene un unico contatore di frequenza nel bucket. Se il contatore è sotto una soglia allora gli item non sono frequenti e possiamo eliminarli, altrimenti non possiamo concludere nulla. Per trovare gli itemset frequenti possiamo eseguire A-priori sugli insiemi di item già ridotti dopo hashing. Trovare oggetti simili Una semplice metrica per definire la similarità tra insiemi di oggetti è Jaccard, che rappresenta la percentuale di oggetti condivisi. Siano dati due insiemi S, T : Jaccard(S, T) = |S ∩ T| |S ∪ T| La misura Jaccard per quanto semplice è utile per: 1. Suggerire oggetti da acquistare ad utenti trovando oggetti, o utenti simili (recommending systems). 2. Se rappresentati come insiemi di parole o insiemi di n-grammi, trovare documenti simili. 3. Trovare la distanza semantica tra due ricerche su un motore di ricerca confrontando i risultati. Problema: computare Jaccard per insiemi grandi è computazionalmente costoso. Soluzione: approssimare Jaccard con un hash "furbo": min-hashing o locality sensitive hashing. Min-hashing n elementi e si prenda una permutazione casuale ma fissa dei suoi elementi. Il minhash di un insieme S è definito come il primo elemento degli elementi permutati che è membro di S. Sia dato un insieme di Per esempio, sia {1, 2, 3, 4, 5 } l'insieme di elementi e (2, 5, 1, 4, 3 ) una sua permutazione fissa. * Il minhash di {5,2,3} è 2 (primo elemento nella permutazione presente nell'insieme) Nota: di per sé è una soluzione debole, ma se si effettuano m permutazioni si possono prendere i primi m numeri in ogni permutazione come firma dell'insieme, aumentandone quindi il potere espressivo. Perché funziona? Se la permutazione è casuale calcolare il min-hash è come selezionare un sottoinsieme a caso di due insiemi e confrontarlo. Il sotto-insieme nel min-hash è generato però in entrambi gli insiemi dallo stesso insieme di permutazione. Queste tecniche randomizzate infatti funzionano perché il valore atteso si avvicina al valore statistico da misurare (ossia Jaccard in questo caso). Se prendiamo una permutazione casuale, la probabilità che produca lo stesso minhash per due insiemi diversi è uguale a Jaccard. Quindi possiamo approssimare Jaccard con min-hash! Problema: anche calcolare una permutazione è dispendioso. Soluzione: utilizzare un insieme di funzioni di hash h con B bucket per calcolare un'approssimazione delle permutazioni e risolvere le collisioni (una collisione è una coppia di elementi h(x) = h(x′ ) in qualche modo). x ≠ x′ tali che Algoritmo min-hash Sia dato un insieme S di n elementi, una funzione di hash h e un numero M > n. L'idea è di iterare per tutti gli elementi e trovare l'elemento S con hash minimo. V := M; for i := 1 to n do if h(ai) < V then V := h(ai); Nota: si può ripetere la stessa idea per diverse funzioni di hash. Nota: si può ripetere la stessa idea per m diverse funzioni di hash. Nota: L'hash approssima una permutazione. Locality Sensitive Hashing Si sfrutta un'hashing function tale per cui coppie di documenti simili finiscano nello stesso bucket con alta probabilità. Una volta computati i min-hash di ogni insieme (tupla) si possono dividere in b bande di uguale dimensione, ognuna contenente r valori. Sia s la distanza di Jaccard tra due insiemi, con un'analisi teorica si può calcolare che la probabilità che i documenti concordino su tutte le righe di almeno una banda è 1 − (1 − sr )b . Clustering Metodi per trovare e raggruppare oggetti simili. Sono basati su nozioni di distanza in spazi n dimensionali, ogni punto dello spazio rappresenta un oggetto6. Due approcci principali al clustering: * Agglomerativo o gerarchico: dato un insieme di cluster si tenta di unire (merge) cluster di oggetti simili * Point assignemnt: dopo aver assegnato i punti ad un insieme di cluster si tenta di assegnarli al cluster più vicino in modo tale da aumentare la qualità dei raggruppamenti. Gli algoritmi di clustering dipendono dalla misura di distanza. Dati due oggetti qualsiasi x e y una funzione di distanza d(x, y) deve soddisfare: * d(x, y) ≥ 0 : non negatività * d(x, y) = 0 se e soltanto se x = y : assioma di coincidenza * d(x, y) = d(y, x) : simmetria * d(x, y) ≤ d(x, z) + d(z, y) per ogni x, y, z : disuguaglianza triangolare Un'importante misura di distanza è la Lr -norm, definita come d(x, y) = n ∣xi − yi∣ r ∑ ( ) 1/r i=1 da cui derivano la Manhattan distance (L1-norm) e la euclidian distance (L2-norm). Un'altra importante misura è la distanza di Jaccard (è facile provare che è una metrica): d(x, y) = 1 − J(x, y) Nell'ambito dell'information retrieval una misura particolarmente interessante è la cosine distance che misura l'angolo tra due vettori (è massima quando l'angolo tra di loro è di 90º). La distanza coseno è definita come: d(x, y) = 1 − x⋅y d(x, y) = 1 − dove x ⋅ y è il prodotto scalare tra x e y e x⋅y ‖x‖‖y‖ ‖x‖ indica la norma del vettore x. Altre misure: Edit distance (stringhe), Hamming distance (booleani). Attenzione: gli oggetti sono tipicamente rappresentati da vettori in uno spazio multidimensionale. Se il numero di dimensioni è elevato (e tende ad infinito) allora la media delle distanze tra due oggetti a caso tende a 1. Questo fenomeno è conosciuto col nome di "curse of dimensionality". Clustering agglomerativo Famiglia di algoritmi molto semplici: 1. Si parte da un iniziale assegnamento dei punti a cluster 2. Finché non si raggiunge la condizione di stop 1. Unire i due cluster più vicini Nota: il risultato del clustering agglomerativo, molte volte è un albero ottenuto dall'unione di cluster. Distanza/unione di cluster Si può definire in molti modi minimo tra le distanze dei punti tra due cluster distanza media tra i punti dei cluster n punti è il punto ottenuto dalla media delle coordinate di ogni punto. Sia per esempio A = (x1 , y 1 ) e B = (x2 , y 2 ), allora il centroide sarà C = ((x1 + x2 )/2, (y1 + y2 )/2) distanza tra i centroidi, dove il centroide di definito il raggio di un Cluster come la distanza del punto più distante dal centroide, si uniscono i due cluster che risultano nel raggio minimo definito diametro come la distanza massima tra due punti di un cluster, si uniscono i due cluster che risultano nel diametro minimo Condizioni di stop In base alla distanza si possono definire molte condizioni di stop. * Dato in input k , ci si ferma quando si ottengono k cluster. * Si continua finché non si ottiene un singolo cluster * La coesione (distanza media tra i punti) del cluster non è maggiore di una certa soglia. * Il diametro del cluster ottenuto dall'unione supera una determinata soglia. * Fermarsi quando la densità del cluster unione (il migliore) è sotto una certa soglia. La densità può essere definita come il numero di punti diviso una certa potenza del raggio. Problema: Cosa succede se lo spazio non è euclideo e quindi non possiamo trovare un centroide per il cluster? Soluzione: Possiamo prendere il punto del cluster che minimizzi la somma/massimo/somma quadratica Soluzione: Possiamo prendere il punto del cluster che minimizzi la somma/massimo/somma quadratica delle distanze da sé stesso. Questo punto si chiama clustroide. Point assignment clustering k-means k-means è il più famoso algoritmo per clustering a punti, dove k è il numero di clustering che deve essere prodotto (è un parametro in input). 1. Scegli k punti iniziali come cluster 2. Assegna i centroidi ai punti scelti in 1. 3. Finche i centroidi cambiano * per ogni altro punto p * trova il centroide c del cluster più vicino * aggiungi p a c * ricalcola il centroide del cluster Attenzione: la qualità dei cluster in alcuni casi dipende dalla scelta dei punti d'inizio. Inizializzare i cluster Un modo per inizializzare i cluster è di scegliere punti che sono il più distante possibile tra loro. Ecco un possibile algoritmo per la scelta dei punti 1. Scegli il primo punto a random 2. Finché non sono stati scelti k punti * Scegli il punto il quale ha distanza minima con i punti già scelti massima. Alternativamente si può fare clustering di un campione di punti tale per cui ci siano k cluster e prendere i punti tra di loro più vicini al centroide del cluster. Problema: k deve essere conosciuto in anticipo. Soluzione: Adottare una misura per la qualità dei cluster (per esempio il diametro medio) e fare ripetute prove con k = 1, 2, 4, . . . finché non si trova il miglior k Algoritmo BFR Problema: I dati non riescono ad essere caricati tutti in memoria Soluzione: partizionare e caricare i dati in memoria e mantenere statistiche dei cluster e degli altri dati. Nota: si assumono dati distribuiti normalmente (e quindi si deve conoscere media e varianza) 1. Seleziona k punti iniziali 2. Leggi i dati in memoria in chunk (partizioni) 3. Mantieni statistiche dei dati e dei cluster 4. I punti sono divisi in: Discard set: punti già assegnati ad un cluster che non richiedono di essere in memoria Compressed set: punti vicini ad altri che si credono appartenere allo stesso cluster, ma non vicini abbastanza al centroide (rappresentati come statistiche) Retained set: non sono vicini a nessun altro punto (stanno in memoria) Dato che bisogna calcolare media e varianza, per ogni set bisogna mantenere: 1. Il numero di punti 2. La somma per componente (ricordati che siamo in uno spazio multidimensionale) di ogni punto. Per esempio se si hanno due punti (x1, y1) e (x2, y2) si memorizza (x1 + x2, y1 + y2) 3. La somma per componente dei quadrati (per il calcolo della varianza). Nota: per calcolare i centroidi basta usare la statistica al punto 2. e dividere per il numero di punti! OLAP OLAP significa (On-Line Analytic Processing) e si intende un insieme di tecniche per esaminare dati alla ricerca di pattern o trend. OLAP richiede query molto complesse (esempio, join multipli) e aggregati (avg, max, min) per poter calcolare statistiche ecco perché si mantiene copie dei dati nelle data warehouse che vengono aggiornate tipicamente una volta al giorno (di notte). Considera la seguente query su tre tabelle diverse: se i dati sono tanti potrebbe impiegare molto tempo in quanto analizza la gran parte del database. SELECT state, AVG(price) FROM Sales,Dealers WHERE Sales.dealer = Dealers.name AND date >= "2006-­‐01-­‐04" GROUP BY state; Data cube Immaginiamo di avere i dati organizzati in uno spazio multi-dimensionale (un cubo per semplicità). Ogni punto rappresenta una tupla ottenuta attraverso tutte le join delle tabelle di un database. La tabella che contiene i punti si chiama fact table. Immagina una vendita nell'esempio precedente rappresentata dalla tripla (macchina, dealer, data). Due tipi di data cube: * raw data cube: un modo per visualizzare i dati originali in modo diverso, nessun dato o ottimizzazione viene memorizzata * formal data cube: i punti potrebbero già rappresentare un'aggregazione di dati (vendite totali o modello) e vengono materializzati in un cubo vero e proprio. Schema a stella Al centro della stella c'è la fact table collegata a delle dimension tables che rappresentano una un attributo o un aggregato. Le dimensioni possono essere il numero di macchine vendute, il metodo di pagamento e così via. Ci possono essere alcuni attributi dipendenti che rappresentano dei valori vincolati alla scelta delle dimensioni (per esempio il costo). Per esempio Fact table: Sales(serialNo, date, dealer, price) Dimensioni: serialNo, date, dealer (sono chiavi esportate per una dimension table) Attributo dipendente: price Dimesion tables: Autos(serialNo, model, color), Dealers(name, city, state, phone) e date? Per date si immagina una tabella virtuale Date(day, weerk, month, year) Slicing e dicing SELECT e GROUP BY si focalizzano su parti del cubo (dice) attraverso la proiezioni di dati nelle diverse dimensioni (per esempio il modello di macchina, il colore). Nota: Si può dividere il cubo i cubi più piccoli e calcolare degli aggregati. Slicing si riferisce alla clausola WHERE che restringe e partiziona i dati. La forma generale di query "slicing and dicing" è la seguente: SELECT <grouping attributes and aggregations> FROM <fact table joined with some dimension tables> WHERE <certain attributes are constant> GROUP BY <grouping attributes > ; Un esempio: ~~~sql SELECT color, month, SUM(price) FROM (Sales NATURAL JOIN Autos) JOIN Days ON date = day WHERE model = "Gobi" GROUP BY color, month; ~~~ queste query permettono analisi dei dati in profondità, come chiedersi se alcuni modelli di macchine particolari non sono state vendute e perché. Data cube formale Si memorizzano dati riguardanti gli aggregati di determinate dimensioni o valori. Non è richiesta genericamente troppa memoria fisica. Nell'esempio delle macchine, invece di rappresentare il numero seriale, si può memorizzare il modello e il numero di vendite totali per modello. CUBE(F): è un operatore sulla fact table F che aggiunge un "*" a ogni dimensione. Vuol dire proiettare i valori del data cube su una particolare "faccia" o spigolo per poter costruire fisicamente il cubo. Prendiamo per esempio: ~~~ Sales(model, color, date, dealer, value, count) ~~~ dove value è la somma di tutti i prezzi per un dato modello, colore, data e dealer; count è il numero di auto vendute. CUBE(Sales) contiene esattamente tutte le tuple che hanno lo schema della fact table. Nota: con value e count possiamo calcolare la media dei valori! La tupla ~~~ (Gobi, *, 2001-05-21, Friendly Fred, 152000, 7) ~~~ rappresenta la somma e il valore delle macchine vendute di tipo Gobi, in data 2001-05-21, dal venditore Friendly Fred ⇒ un'aggregazione in Sales è divenuta una semplice SELECT (notare che è molto semplice da scrivere) su CUBE(Sales). In SQL attraverso la sintassi GROUP BY ... WITH CUBE CREATE MATERIALIZED VIEW SalesCube AS SELECT model, color, date, dealer, SUM(val), SUM(cnt) FROM Sales GROUP BY model, color, date, dealer WITH CUBE; Internet Il web contiene enormi quantità di informazioni che devono essere indicizzate e ordinate da motori di ricerca (quali Google), che hanno bisogno di costruire statistiche e ordinamenti sui documenti memorizzati. Un motore di ricerca deve essere in grado di rispondere a query in linguaggio naturale (e quindi ambiguo) in tempi rapidi e con alta precisione. Tutto questo è reso possibile da programmi detti crawler che ritrovano, spezzano e indicizzano le informazioni nei documenti contenuti in siti web aventi particolari indirizzi (URL). Dato un insieme S di URL da analizzare, per produrre un repository R di pagine, un crawler: ~~~ 1. Sceglie una pagina p dall'insieme S. 2. Scarica la pagina p e controlla se è già in R. 3. Se p non è in R: 1. Aggiunge p a R. 2. Aggiunge ad S i link uscenti di p se non sono già in R o S. 3. Ripete 1. ~~~ Problema: Per costruire un crawler servono diversi accorgimenti. * Come terminare la ricerca: limite sulle pagine da analizzare oppure limite sulla profondità. * Come trovare pagine già presenti in S o R: si può usare hashing sulle pagine anche in forma efficiente (min-hash con locality sensitive hashing). * Selezionare la pagina p da analizzare: - random oppure - con una coda (breadth first search sul grafo web), - stima dell'importanza della pagina. * Velocizzare il crawling: parallelizzazione in diverse macchine. Rispondere a query Problema: le query sono in linguaggio naturale e non in SQL. Soluzione: Indicizzazione: usare uno speciale indice inverso (per ogni parola, la lista dei documenti che la contiene). Problema: come ordinare i risultati? Soluzione: Ranking functions che prendono in considerazione diversi fattori come: la presenza delle parole chiave della query, presenza delle parole in parti importanti della pagina, autorevolezza della pagina, attualità della pagina ... PageRank Algoritmo creato da S. Brin e L. Page, ha rivoluzionato il modo di assegnare valori di importanza alle pagine e ha influenzato enormemente la qualità dei motori di ricerca. È basato sul concetto di link: più pagine importanti si riferiscono (attraverso un link) ad una pagina, più la pagina a sua volta sarà importante. In qualche modo la definizione è ricorsiva. PageRank: è un numero che rappresenta l'importanza di una pagina. Il Web viene rappresentato come un grafo diretto: i nodi sono le pagine e un arco da una pagina ad un'altra indica un link tra di esse. Immaginiamo un random walker che sta navigando su pagine web, partendo da un punto e muovendosi seguendo solamente i link che trova nelle varie pagine. Supponiamo di ripetere questo processo moltissime volte e di calcolare la frequenza con cui il walker si è trovato su una pagina. Questo valore (normalizzato per trasformarlo in probabilità) rappresenta il PageRank. Formalmente: * Il web è rappresentato da un grafo diretto in una matrice di transizione. * n pagine numerate da 1 a n. * La matrice di transizione è una matrice M n × n tale per cui la cella: * mij pagina j è collegata i e a r ≥ 1 pagine in totale. * mij = 0, altrimenti. = 1 r se j la Nota: per definizione la somma dei valori di una singola colonna è sempre 1. Algoritmo (sketch) Supponiamo che il walker parta da una qualsiasi delle pagine con equi-probabilità (cioè 1/n ). Il vettore del PageRank iniziale v 0 avrà quindi ogni componente assegnato a 1/n . Dopo ogni passo la distribuzione del walker sarà M ⋅ v 0 , in quanto con probabilità proporzionale ai link uscenti compirà un passo nel grafo. Al passo t il vettore sarà uguale a M t ⋅ v0 . Si può dimostrare che questo processo converge sotto particolari condizioni dei processi di Markov ad un vettore stazionario v M. La soluzione = M ⋅ v . Si può notare come questo vettore sia un autovettore della matrice v di questa equazione è il PageRank. Problema: calcoli su matrici gigantesche, quale quella del Web, sono troppo dispendiosi. Soluzione: parallelizzare la computazione e calcolare un'approssimazione dividendo la matrice in Soluzione: parallelizzare la computazione e calcolare un'approssimazione dividendo la matrice in sottomatrici (componenti connesse o fortemente connesse del grafo oppure clique) e calcolando il pagerank nelle sottomatrici. Altre soluzioni usano "Map/Reduce" per fare la moltiplicazione di matrici riga × colonna in maniera parallela e poi unire i risultati. Nota: Il web è caratterizzato da una componente fortemente connessa e da pagine che entrano in questa (ma non raggiungibili da esse) e pagine che escono e non possono tornarvi. Se un walker esce dalla componente, allora le pagine in essa avranno PageRank 0, in quanto non potrà più tornare, queste sono le famose "spider-traps" e "dead-ends" Problema: Come risolvere il problema delle spider-traps? Soluzione: (1) togliere i dead-ends dal grafo ricorsivamente (non ideale) (2) cambiare il modello di movimento del random walker (teleporting). Teleporting Il random walker può occasionalmente saltare ad una pagina a caso. v = βM ⋅ v + (1 − β)e/n β è una costante tra 0.8 e 0.9 (0.85 genericamente accettato). e è un vettore di n elementi tutti uguali a 1 (in realtà può essere anche utilizzato come vettore di partenza o di personalizzazione). (1 − β)e/n è la probabilità di tornare a una delle pagine che sono settate a 1 nel vettore (in buona sostanza è un modo per evitare le trappole). Altri modelli alternativi al PageRank Per argomento: il page rank può essere calcolato per pagine di un determinato argomento (si può usare il vettore di personalizzazione e e porre a 1 le sole pagine di un argomento). Trust-rank: introdurre un concetto di "pagine fidate" nel modello. Hubs-Authorities: ci sono pagine che parlano di un argomento (authorities) e pagine che contengono link per le pagine che parlano di argomento (hubs). Una pagina è un buon hub se è collegato a buone authorities ed è una buona authority se è raggiungibile da un buon hub. Risolvere il problema dei link spam Problema: Un potenziale spammer è in grado di costruire pagine collegate a pagine "oneste" le quali pagine sono collegate a soli link di spam. La target page t è una pagina costruita ad-hoc dallo spammer e viene linkata da siti noti (ad esempio forum di discussione) e collegata a m altre pagine di spam. Le pagine collegate a t sono collegate solo ad essa. Se si assume y il PageRank della pagina t allora si ottiene (risolvendo per y e omettendo i passaggi: y= x 1 − β2 +c m n il che potrebbe essere una frazione significativa anche solo con β c= β 1+β = .85 , infatti 1/(1 − β2 ) = 3.6 e = .45 . Significa che y dipende al 360% (3.6) dal valore delle pagine esterne (perché moltiplica x) e al 45% dal rapporto di pagine interne! Questo è un problema. Soluzione: riconoscere e rimuovere le spam farm, adattare il PageRank a questa minaccia (attraverso pagine fidate) oppure calcolare la massa di spam data dal PageRank r e dal TrustRank t nella formula (r − t)/r . Pubblicizzare prodotti Banner, link sponsorizzati, pubblicità nei siti sono importanti metodi per pubblicizzare la propria azienda o i propri prodotti. Problema: come presentare il banner in base alle informazioni nella pagina o ad una particolare ricerca dell'utente? Nota: effettuare il ranking dei link di pubblicità è difficile perché non si può usare PageRank (link non presenti). Ranking Ordinare i più recenti per primi. Attractiveness: metrica basata sul numero di click (però ads più rari saranno sempre più bassi in classifica e quindi mai clickati). Gli algoritmi per ranking possono essere on-line e off-line anche se poche informazioni possono essere calcolate in anticipo (off-line). Attenzione: gli algoritmi offline sono spesso inutilizzabili praticamente perché bisogna avere a disposizione i bid (puntate) di ogni advertiser per ogni query e calcolare il guadagno massimo e il numero di volte che l'annuncio è mostrato. Questi algoritmi producono la soluzione ottima ma sono inutilizzabili. Gli algoritmi online producono invece risultati in base alla query dell'utente e in base ad informazioni passate e click (personalizzazione), cercando di predire il funzionamento dell'algoritmo offline. Gli algoritmi online sono perlopiù greedy e quindi compiono una scelta "localmente" ottima. Possono ogni volta selezionare l'oggetto con il più alto competitive ratio (il rapporto tra il risultato di un algoritmo rispetto al migliore algoritmo off-line). Adwords Dopo il 2000, è nato il concetto di bid sulle parole. Ad ogni parola usata nelle query i venditori possono fare una sorta di puntata, in questo modo l'annuncio pubblicitario può venire pubblicato e se viene cliccato il venditore deve pagare. Formalmente: Un insieme di bid per ogni advertiser per particolari query. Il numero di click alla pubblicità per ogni query. Un budget per ogni advertiser. Un limite al numero di annunci visualizzabili. Problema: trovare l'insieme di annunci massimo (in base al limite) tale per cui il budget per advertiser sia massimo e sia massimizzata la puntata (bid). Soluzione: Si misura: * la revenue, ossia il valore totale degli annunci selezionati. * il valore dato dal prodotto del numero di click e dalla puntata. * il merito, che è la somma mensile della revenue. Si tenta di massimizzare la competitive ratio data dal revenue minimo dell'algoritmo per una sequenza di query, diviso il valore ottimo dell'algoritmo off-line. Un semplice algoritmo greedy Semplifichiamo: un solo annuncio mostrato, tutti gli advertiser con lo stesso budget, il numero di click è uguale, le puntate sono 0 o 1. L'algoritmo prende, per ogni query, un qualsiasi advertiser che ha bid a 1 per quella query. Attenzione: Il competitive ratio è 1/2 in quanto un algoritmo del genere non si cura di fare la scelta in base a ciò che condizionerà nel futuro. Se due bidder hanno budget 2, ma il primo ha bid su una query, il secondo su una query e un'altra, è possibile che il secondo advertiser consumi il budget sulla prima query e quando arriva la seconda nessuna dei due può rispondere. Balance algorithm Questo algoritmo assegna ad una query all'advertiser che ha bid sulla query e ha il budget rimanente massimo (in questo modo si previene il problema precedente, in parte). Questo algoritmo, nel modello semplificato, ha un competitive ratio di 3/4. L'algoritmo può essere generalizzato se i bid non sono solo 0 e 1 in questo modo: * prediligiamo sempre bid più alti. * siamo più flessibili sul budget considerando la parte del budget rimanente per ogni advertiser. Supponiamo che un particolare advertiser A ha una puntata x su una query q e che f sia la parte di budget non spesa di A. x(1 − f) Assegnamo la query q all'advertiser A che massimizza x(1 − ef ) . 1 Competitive ratio: si può dimostrare un competitive ratio di 1 − e ≈ 0.63 . 1. W3C XML Recommendation ↩ 2. Verranno usati alla stessa maniera query e interrogazione, anche se il termine inglese ha un'accezione più specifica e tecnica. ↩ 3. W3C XPath Recommendation ↩ 4. W3C XQuery casi d'uso ↩ 5. W3C XSLT Recommendation ↩ 6. I gruppi sono detti anche cluster. ↩