Materiál k cvičení DBM2 týden #10, sezona 2025/2026

Linked Data - aktivní projekty

DBpedia

DBpedia je projekt, který vytváří strukturovaná data z Wikipedie. Primárně se zaměřuje na data z infoboxů (objekt v pravém sloupci článku), ale zpracovává i další informace z textu. Data jsou dostupná v RDF formátu a provázána na několik ontologií. Projekt vznikl spoluprací Free University of Berlin a Leipzig University v roce 2007.

Projekt poskytuje rozhraní pro vyhledání RDF entit a rozhraní pro dotazování se (SPARQL endpoint). Výhodou tohoto rozhraní je, že nejčastěji používané prefixy jsou automaticky doplňované a není třeba je v dotazu uvádět.

K datům se lze připojit z libovolného SPARQL klienta.

Příklad - Jaké programovací jazyky ovlivnily nejvíce jiných jazyků?

Na Wikipedii jsou obecně info boxy strukturované podle typu popisované entity. Např. u států bývají informace o jazyce, měně či vlajce; u osob pak datum narození, povolání nebo národnost. Pokud bychom se podívali na záznam o některém z programovacích jazyků, viděli bychom zde i informaci o vlivu na jiné jazyky. Tato informace v podstatě tvoří orientovaný graf, kde vrcholy jsou jazyky a hrany jsou vlivy.

Pokud bychom chtěli tato data zkoumat přímo z webu Wikipedie, bylo by potřeba traversovat všechny stránky a nějakým způsobem tuto informaci extrahovat. DBpedia ale toto již udělala za nás a výsledné data jsou dostupné v RDF formátu.

Základním problémem je, že neznáme URL adresu záznamu o programovacím jazyku a ani neznáme používané ontologie, abychom si pomohli dotazem například na všechny zdroje typu dbo:ProgrammingLanguage nebo wikidata:Q9143. Můžeme ale využít rozhraní pro vyhledávání entit, kde můžeme zadat název jazyka a získat URL adresu záznamu.

Nejprve zkusme vyhledat resource, který odpovídá nějakému programovacímu jazyku. Pro Java např.:

07javasearchpng Fig — Vyhledání zdroje odpovídajícího názvu Java. První nález se týká ostrova, třetí je kategorie článků o programovacím jazyku. Hledaný záznam je až čtvrtý.

Pokud zvolíte první položku, brzy zjistíte, že se jedná o záznam o ostrovu Java, nikoliv o programovacím jazyce. Je tedy potřeba se v nabídce trochu lépe zorientovat a možná i se štěstím dojít do popisu zdroje, který ve skutečnosti hledáme. Tím je záznam https://dbpedia.org/describe/?url=http%3A%2F%2Fdbpedia.org%2Fresource%2FJava_%28programming_language%29

Na daném odkaze se zobrazí facetový prohlížeč s informacemi o daném zdroji. Za zmínku stojí, že nejsou zobrazeny všechny údaje. Např. u jazykových řetězců jsou zobrazeny pouze hodnoty, které odpovídají místnímu nastavení prohlížeče (předpokládám na bázi HTTP hlavičky Accept-Language - v mém případě Accept-Language: en-US,en;q=0.9,ja;q=0.8,cs;q=0.7). V případě, že bychom chtěli získat všechny jazykové řetězce, museli bychom použít SPARQL dotaz.

07javafacetpng Fig — Zobrazení popisu zdroje Java.

Pro možná pohodlnější práci doporučuji podívat se i na alternativní pohled na zdroj, na která se lze navigovat skrze odkaz nahoře za About.

Všimněte si, že v záznamu se vyskytuje několik zajímavých metadat.

Co nás zajímá, je identifikace property popisující vliv na jiné jazyky. V tomto případě je to dbo:influenced a dbo:influencedBy.

SPARQL dotaz můžeme postavit díky znalosti názvu vlastnosti dbo:influenced a odhadnutím typu entity (vlastnost rdf:type), kterou by mohly používat obecně všechny programovací jazyky. Konkrétně Java má typ dbo:Software a dbo:Work. Ani jednoho z toho však nevrátí smyslupný výsledek. Trochou bádání a experimentování s jinými popisy jazyků ukáže, že všechny programovací jazyky mají často typ wd:Q9143

PREFIX dbo: <http://dbpedia.org/ontology/> PREFIX wd: <http://www.wikidata.org/entity/> SELECT ?lang1 ?lang2 WHERE { ?lang1 dbo:influenced ?lang2 . ?lang1 a wd:Q9143 . ?lang2 a wd:Q9143 . }

Pokud bychom chtěli vyfiltrovat pouze jazyky, které ovlivnily například C++, můžeme přidat filtrovací podmínku. Konkrétní adresu zdroje používám z předchozího výsledku dotazu.

PREFIX dbo: <http://dbpedia.org/ontology/> PREFIX wd: <http://www.wikidata.org/entity/> SELECT ?lang1 WHERE { ?lang1 dbo:influenced ?lang2 . ?lang1 a wd:Q9143 . ?lang2 a wd:Q9143 . FILTER(?lang2 = <http://dbpedia.org/resource/C++>) }

Pokud bychom chtěli získat agregované počty, resp. žebříček vlivnosti, můžeme použít upravený dotaz. Zároveň extrahujeme i informaci o datumu vzniku jazyka, je-li k dispozici a odkaz na zdrojovou stránku Wikipedie.

PREFIX dbo: <http://dbpedia.org/ontology/> PREFIX wd: <http://www.wikidata.org/entity/> SELECT ?lang1 (count(?lang2) as ?count) ?year ?link WHERE { ?lang1 dbo:influenced ?lang2 . ?lang1 rdf:type wd:Q9143. ?lang2 rdf:type wd:Q9143. OPTIONAL {?lang1 dbp:year ?year} OPTIONAL {?lang1 prov:wasDerivedFrom ?link} } GROUP BY ?lang1 ?year ?link ORDER BY desc(?count)

Q1: Věříte výsledkům? Jaké hodnoty se vyskytují ve sloupci s rokem vzniku?

Příklad - Knihy s největším počtem stran

Předchozí příklad byl do jisté míry úspěšný a tak lze směle pokračovat do jiného typy entit. Zajímavou informací by mohlo být, jaké evidujeme "nejtlustší", ve smyslu počtu stránek, knihy.

Postup bude obdobný, nejprve opět potřebujeme najít ukázkový záznam o knize, např. 1984. Zde se vyskytuje property dbo:numberOfPages nebo dbp:pages, která nám bude sloužit jako základ pro řazení. Zároveň můžeme využít i název knihy rdfs:label (bez jazykového určení, nebo v konkrétním jazyce) pro lepší identifikaci výsledků a získat informaci o vydání dbp:published. Všimněme si i RDF typu dbo:Book, který se zdá vhodný pro zúžení prohledávaného prostoru.

PREFIX dbo: <http://dbpedia.org/ontology/> PREFIX dbp: <http://dbpedia.org/property/> PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> SELECT ?link ?published ?label ?pages WHERE { ?s a dbo:Book . ?s dbo:numberOfPages ?pages . ?s prov:wasDerivedFrom ?link . OPTIONAL{?s dbp:published ?published} OPTIONAL{?s rdfs:label ?label . FILTER(LANG(?label) = "" || lang(?label) = "en") .} } ORDER BY desc(?pages) LIMIT 100

Q2: Jaké knihy se zdají být nejdelší a kolik mají stran? Jaká je kvalita dat v odpovědi?

Pozorování Hlavním problémem jsou nesmyslná čísla v počtu stránek a dále nesystematicky vyplňovaný údaj Published. Výsledky tedy v tomto případě nejsou použitelné a nelze jim věřit.

07hubbardpng

Podívejte se na některý ze záznamů v původní podobě na Wikipedii. Například pro L. Ron Hubbard je v infoboxu uveden počet stránek jako komplikovaný záznam s několika hodnotami pro různé roky. Parser tuto informaci pochopil jako 3 hodnoty 1987402, 1992460, 1995, což ani v jednom případě není správná hodnota.

Případně u The Tolkien Reader vidíte v datech

Příklad - Bitvy Třicetileté války

Zajímavé použití dat z Wikipedie by mohlo být k agregaci údajů z bitev v průběhu války, které typicky mají infobox s pevnou strukturou. Konkrétně vyzkoušíme získat informace o bitvách, které byly součástí Třicetileté války (1618-1648). Na stránce s válkou je rozklikávací seznam na významné bitvy a například na Obléhání Plzně lze pozorovat strukturovanou informaci o síle obou stran a ztrátách.

Stejně jako v předchozích případech, je potřeba učinit pozorování o struktuře dat v DBPedii. Při vyhledání Siege of Pilsen můžeme pozorovat, že je bitva kótovaná pomocí geolokačních údajů geo:lat a geo:long. Zároveň je zde informace o síle obou stran dbo:strength. Ztráty jsou uvedeny v dbo:casualties. Není rozlišováno v tomto ohledu mezi ztrátou "pravé" a "levé" strany konfliktu. Klíčovým poznatkem je existence vlastnosti dbo:wikiPageWikiLink obsahujícím odkaz na kategorii dbc:Battles_of_the_Thirty_Years'_War, ve které očekáváme i ostatní bitvy.

PREFIX dcterms: <http://purl.org/dc/terms/> PREFIX dbo: <http://dbpedia.org/ontology/> PREFIX dbp: <http://dbpedia.org/property/> PREFIX geo: <http://www.w3.org/2003/01/geo/wgs84_pos#> SELECT ?link (SUM(?casualty) as ?totalCasualty) ?lat ?long (MAX(?date) as ?mdate) (SAMPLE(?label) as ?mlabel) WHERE { ?battle dbo:wikiPageWikiLink <http://dbpedia.org/resource/Category:Battles_of_the_Thirty_Years'_War> . ?battle prov:wasDerivedFrom ?link . ?battle dbo:date ?date . OPTIONAL{ ?battle rdfs:label ?label FILTER(lang(?label) = "en")} . OPTIONAL{ ?battle dbp:casualties ?casualty } . OPTIONAL{ ?battle geo:lat ?lat} . OPTIONAL{ ?battle geo:long ?long} . } GROUP BY ?link ?lat ?long ORDER BY ?link

Q3: Dávají výsledky smysl? Jsou geolokace správné?

Výsledky se na první pohled zdají správné. Mapová vizualizace např. pomocí Map Maker vysází piny na očekávaná místa. Nicméně intuitivně lze očekávat, že možná některé bitvy nebyly zahrnuty v seznamu (některé ani nemají stránku na anglické Wikipedii, viz box u Třicetileté války). Celkový počet obětí 356438 by také mohl být v uvěřitelném rozsahu, pokud jde pouze o bojové ztráty (v učebnicích se většinou mluví o celkových ztrátách v milionech).

Nicméně podstatné chyby v datech jsou. Prozkoumejte například záznam Battle of Breitenfeld (1631). DBpedia odpověděla souhrnně 30200 ztrát, nicméně přečtením infoboxu snadno odhalíme problém. Na Wikipedii jsou ztráty uváděné jako 5,100 dead | 2,100 Swedes, 3,000 Saxons, tedy 2100 + 3000 = 5100. V druhém sloupci 16,000 | 7,000 dead, 9,000 captured, tedy 7000 + 9000 = 16000 a navíc captured by asi neměli spadat do ztrát, jelikož nejsou vyčíslení vpravo. Číslo 30200 se zdá být složeno jako 5100 + 2100 + 16000 + 7000.

V jiném případě (který v době psaní nemohu dohledat) došlo k situaci, kdy ztráty na obou stranách byly stejné a tedy do RDF modelu, kde predikát nemůže nabývat dvou stejných hodnot, byla zapsána hodnota jen jednou.


Wikidata

Kromě DBpedia existuje i projekt Wikidata, který je součástí Wikimedia Foundation. Wikidata je kolekce strukturovaných dat, která jsou využívána v jiných projektech (Wikipedia, Wiktionary, Wikibooks, ...). Data jsou dostupná v RDF formátu a jsou provázána na několik ontologií.

Wikidata je v podstatě obdoba DBpedie, ale s tím rozdílem, že data jsou vytvářena přímo pro účely Wikidat a nejsou získávána z Wikipedie. Výhodou je, že data jsou vytvářena systematicky a mají charakter primárních údajů, nikoliv scrapována a extrahována z textů článků.

Dotazovací rozhraní je na adrese https://query.wikidata.org/. Grafické rozhraní obsahuje kolekci předpřipravených dotazů. Další příklady lze najít na WikiData:SPARQL_query_service/queries/examples.

Portál otevřených dat (CZ)

V České republice existuje projekt Portál otevřených dat, kde jsou publikována otevřená data z různých zdrojů. Data jsou dostupná v různých formátech, nejčastěji CSV, XML, JSON. Samotný katalog je vedený v RDF a má kromě webového rozhraní i SPARQL endpoint. Případně je možné katalog stáhnout jako RDF soubor.

Při otevření některé z publikovaných datových sad se lze podívat na facetový pohled na RDF zdroj ikonou vedle názvu sady.

Q4: Prozkoumejte RDF záznam některé datové sady. Jaké informace jsou dostupné? Lze tato data využít pro nějaké další zpracování?

Getty ULAN a další slovníky

Dalším použitím Linked Data jsou slovníky, které se snaží definovat jednotně pojmy, které následně mohou jiné datasety využívat. Jedním z takových slovníků je Getty Union List of Artist Names, který definuje pojmy pro umělce a další osoby.

Rozhraní pro procházení dat je přístupné skrze https://vocab.getty.edu/. Případně je k dispozici i SPARQL endpoint.

Q5: Podívejte se na záznam vybraného umělce v RDF a porovnejte s výpisem na jeho profilové stránce. Jakým způsobem je ve slovníku uchovávána informace o alternativách v zápisu jména umělce?

Linked Data - Inference

V souvislosti s Linked Data lze narazit na termín inference. Jedná se o způsob, jakým lze získat nové informace z dostupných dat. Kromě samotných datových trojic je k tomu použita i ontologie, která pro definované koncepty může uvádět další meta-informace jako např. příslušnost do určitých množin, definiční obory či obory hodnot u predikátů, vztahy mezi koncepty, ...

Pokud tedy máme v datech trojice

ex:A a ex:Zaměstnanec . ex:A ex:na_projektu_s ex:B .

a dále máme k dispozici ontologii, která definuje, že ex:Zaměstnanec je podmnožinou ex:Osoba, můžeme z toho usoudit, že ex:A je ex:Osoba. Tato trojice není explicitně v datech, a pokud bychom se dotazovali obyčejného SPARQL endpointu na ?s a ex:Osoba, nebyl by nalezen žádný výsledek. Pokud by na serveru byla podporována inference, byl by ex:A součástí výsledku.

Podobně by v ontologii mohlo být definováno, že ex:na_projektu_s má jako obor hodnot a definiční obor ex:Osoba. Z toho by inferenční systém mohl usoudit, že ex:B je také ex:Osoba.

Vlastnost ex:na_projektu_s by zároveň pravděpodobně byla definována jako symetrická, tedy pokud ex:A ex:na_projektu_s ex:B, pak ex:B ex:na_projektu_s ex:A.

Za určité situace lze tedy data obohatit o další trojice, které vyplývají z nějaké logiky a souvislostí mezi slovníkovými pojmy.

Triviální příklad v Jena Fuseki

Pro vyzkoušení inference využijeme Apache Jena Fuseki, který byl představen v předmětu KIV/DB2.

Verze fuseki výše potřebuje Java 11 nebo vyšší.

📝 Datový zdroj: ex1-data.ttl - jednoduchá data, ex1-vocab.ttl - ontologický popis

Q6: Prozkoumejte oba datové zdroje v textovém editoru. Co lze říci o entitě :x a entitě :y?

V ontologickém zápisu je možné pozorovat, že se užívají pojmy s prefixem rdfs. Jedná se o standardní ontologii, která je součástí RDF specifikace. Druhou často používanou základní ontologií je owl, která vychází z OWL specifikace.

Spusťte fuseki server příkazem (Windows):

fuseki-server.bat --file ex1-data.ttl --rdfs ex1-vocab.ttl /mem1

, který vytvoří /mem1 endpoint obsahující data z ex1-data.ttl obohacené o poznatky z ex1-vocab.ttl.

Pokud nyní skrze webové rozhraní na adrese http://localhost:3030/ použijeme dotaz SELECT * WHERE {?s ?p ?o} na endpoint /mem1, získáme 15 záznamů (oproti 3 v původním datasetu). Všimněte si, že data z přiložené ontologie nejsou v odpovědi obsažena - byla použita pouze k jednorázovému odvození nových trojic.

Příklad z DBPedia

DBpedia má vlastní ontologický popis používaných vlastností a tříd. K samotnému souboru je poměrně krkolomné se dostat, jelikož přirozený odkaz vede pouze na webové zobrazení.

Verzovaná ontologie lze stáhnout z Archivu. Pro účely tohoto cvičení použiji verzi 2023.11.30-100000 v ttl formátu.

Jako datový zdroj použiji popis záznamu knihy 1984, který přes webové rozhraní stáhnu v ttl verzi.

Stejným postupem jako v předchozím případě lze načíst obohacená data do modelu ve Fuseki.

📝 Datový zdroj: ex2-1984.ttl, dbpedia-onto.ttl

fuseki-server.bat --file ex2-1984.ttl --rdfs dbpedia-onto.ttl /mem1

Následně lze do pomocného modelu, například pojmenovaného /mem2, načíst pouze původní data z ex2-1984.ttl a porovnat, jaké trojice byly odvozeny

SELECT * WHERE{ ?s ?p ?o . MINUS{ SERVICE<http://localhost:3030/mem2/sparql>{ SELECT * WHERE{?s ?p ?o} } } } ORDER BY ?s ?p ?o

Dotaz je zaslán na rozhraní /mem1. Operace MINUS provede množinový rozdíl, tedy odstraní z výsledku záznamy, které jsou výsledkem poddotazu.

Q7: Jaké nové trojice byly odvozeny? Komentujte vybrané příklady.

Tento způsob práce s inferencí je zřejmě nepraktický. Fuseki umožňuje přes konfiguraci nastavit Resoner nad datasetem a tím mít možnost do datasetu průběžně přidávat nová data a ontologické záznamy během běhu serveru. Viz Apache Jena Fuseki - Adding reasoning and full-text search capabilities to a dataset .


Pro pohled, jak aplikovat Rule mining nad Linked daty doporučuji disertační práci Zeman, Václav - Rule mining over linked data a jeden z artefaktů RDFRules - demo