Exemple d’exploitation de requête SPARQL distribuée (federated query)

Ce billet présente un scénario d’utilisation de requête distribuée et montre la construction d’une requête associant un jeu de données qui nous est propre et dbpedia. Je crois qu’il peut être éclairant, même sans pouvoir directement utiliser les exemples.

pour tester les exemples: voir note à la fin de ce billet

I. Enrichissement d’un jeu de donnée à partir de DBPedia

     Réflexions autour du cas ‘Postimpressionnisme’

postimpressionnisme est un des tags présents dans un de nos jeux de données (http://givingsense.eu/onto/refCulture/refHistArts.rdf et http://www.data.gouv.fr/fr/dataset/ressources-pedagogiques-pour-l-enseignement-de-l-histoire-des-arts). Nous nous sommes demandés ce que nous pourrions tirer de dbpedia pour ce tag et avons cherché à généraliser la démarche.

La requête SPARQL

select distinct * where {
?s rdfs:label "Postimpressionnisme” .
} LIMIT 100

appliquée à fr.dbpedia.org/sparql ne donne rien

La requête

select distinct * where {
?s rdfs:label "Postimpressionnisme”@fr .
} LIMIT 100

appliquée à fr.dbpedia.org/sparql donne un résultat:

http://fr.dbpedia.org/resource/Postimpressionnisme

Les liens dbpedia-owl:wikiPageWikiLink qu’on y trouve suggèrent des pistes pour établir des relations avec d’autres ressources.

On trouve par exemple des liens avec

On a aussi les propriétés dcterms:subject

dcterms:subject

ou des backlinks ‘is dbpedia-owl:wikiPageWikiLink of’

Cela suggère, par exemple, la possibilité de requêtes permettant de trouver des musées en rapport avec un sujet.

Par exemple, la requête

select distinct * where {
?s rdfs:label "Postimpressionnisme"@fr .
?m dbpedia-owl:wikiPageWikiLink ?s .
?m prop-fr:nommusée ?p
} LIMIT 100

me donne neuf musées en rapport avec le Postimpressionnisme.

Je chercherais à vérifier systématiquement ce que nous pouvons tirer pour les tags qui sont un courant artistique, mais aussi avec d’autres tags. Je pense donc que sur ce modèle, je peux trouver les musées qui sont en rapport avec chacun des tags de mon jeu de données.

J’ai choisi quelques exemples à partir des programmes scolaires d’histoire pour lesquels nous avons des ontologies et des tags (voir par exemple https://ilot.wp.imt.fr/2014/01/16/publication-de-references-culturelles-dans-un-triple-store/).

Cherchons à le vérifier avec le tag ‘Première Guerre mondiale’. Je trouve 51 musées.

Cherchons à le vérifier avec le tag ‘Carolingiens’. Je trouve 4 musées.

D’autres comme ‘Femme’ ou ‘Taoïsme’ ne donnent rien.

Une recherche systématique va être intéressante.

Elle reposera probablement sur des requêtes dans Fuseki qui interrogeront simultanément notre jeu de données et dbpedia.

II. Une requête SPARQL distribuée

La requête suivante

PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX prop-fr: <http://fr.dbpedia.org/property/>
PREFIX refc: <http://givingsense.eu/onto/refCulture/refHistArts.rdf#>
PREFIX dbpedia-owl: <http://fr.dbpedia.org/ontology/>
SELECT  distinct ?vtag  ?s WHERE {
?fiche refc:tags ?tags .
?tags ?v ?vtag .
BIND (STRLANG(?vtag,"fr") AS ?tag) .
SERVICE <http://fr.dbpedia.org/sparql>
{
?s rdfs:label ?tag .
}
} LIMIT 100

 

nous montre que de nombreux tags de notre jeu de données sont associés à une ressource de DBPedia.

Cette requête conduit à trouver un ensemble de fiches de notre jeu de données. Les fiches ont pour propriétés un ensemble de tags; on trouve cette association avec cette partie de la requête

?fiche refc:tags ?tags

On trouve chaque tag d’un ensemble associé à une fiche avec cette partie

?tags ?v ?vtag .

Comme nous savons que nos tags n’ont pas d’attribut de langue -c’est un défaut de l’état actuel de notre jeu de données- nous en ajoutons un avec la ligne

       BIND (STRLANG(?vtag,"fr") AS ?tag) .

Ensuite, nous allons utiliser l’élément ?tag ainsi créé pour interroger dbpedia; nous signifions que nous interrogeons dbpedia en englobant le code concerné par

       SERVICE <http://fr.dbpedia.org/sparql>
       {
           <... ici les éléments de requête envoyés à dbpedia ...>
       }

La ligne que nous envoyons au dbpedia français

           ?s rdfs:label ?tag .

nous renvoie toutes les ressources de dbpedia associées aux tags présents dans notre jeu de données (ici, limité aux 100 premiers).

Ainsi, nous allons trouver toutes les associations, via le label, entre un tag de notre jeu de données et une ressource de dbpedia.

J’ai cherché à systématiser par la combinaison de cette requête avec la requête sur les musées présentée à la section précédente. L’idée étant d’arriver à une application qui permette pour chaque tag d’avoir des propositions de musées.

La combinaison donne quelque chose comme

PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX prop-fr: <http://fr.dbpedia.org/property/>
PREFIX refc: <http://givingsense.eu/onto/refCulture/refHistArts.rdf#>
PREFIX dbpedia-owl: <http://dbpedia.org/ontology/>
SELECT  distinct ?vtag  ?m WHERE {
       ?fiche refc:tags ?tags .
       ?tags ?v ?vtag .
       BIND (STRLANG(?vtag,"fr") AS ?tag) .
       SERVICE <http://fr.dbpedia.org/sparql>
       {
          ?s rdfs:label ?tag .
           ?m prop-fr:nomDuMusée ?p .
           ?m dbpedia-owl:wikiPageWikiLink ?s
       }
} LIMIT 20

qui marche bien.

On peut aussi remplacer la propriété

prop-fr:nomDuMusée

par prop-fr:nommusee.

(il y 69 ressources dans fr.dbpedia pour la première propriété, tandis qu’il y en a 1966 pour la deuxième)

Ainsi, grâce à notre formalisation des programmes scolaires dans des ontologies et à la mise en oeuvre assez simple des principes des Linked Data, nous pouvons proposer des associations entre tags décrivant certaines parties du programme scolaire et musées, par exemple pour aider des enseignants de différentes matières à aborder des domaines de l’Histoire des Arts, comme ils y sont tenus.

 _____

**pour tester les exemples: 

Ce billet suppose qu’un outil suivant les spécifications de SPARQL 1.1. est utilisé. Les exemples ont été testés avec Jena-Fuseki; pour tester ces exemples nous avons utilisé une installation locale de Fuseki sur une de nos machines. Notre serveur public (http://shadok.enst.fr:8890/sparql) est une version un peu ancienne de Virtuoso (paquet debian stable, basé sur une version de 2011 de Virtuoso); elle ne supporte pas des fonctionnalités dont nous avons besoin pour les exemples qui précédent; pour l’instant, nos services informatiques, devant faire face à de nombreuses attaques, s’opposent à l’installation d’une version plus à jour.

Le lecteur intéressé par tester les exemples ci-dessous devra installer Fuseki  (https://jena.apache.org/documentation/serving_data/index.html), y importer notre jeu de données disponible (http://givingsense.eu/onto/refCulture/refHistArts.rdf et  http://www.data.gouv.fr/fr/dataset/ressources-pedagogiques-pour-l-enseignement-de-l-histoire-des-arts)

 

 

Publié dans Cuisine OWL, DBPedia, Données publiques | Un commentaire

Exemple d’interaction Web basée sur une ontologie simple

bloomtree

Dans le cadre de nos travaux, nous avons identifié plusieurs ontologies sur lesquelles un mode de visualisation utile est l’affichage d’un arbre de concepts. En fait, dans beaucoup d’ontologies ou même d’ensemble de triplets RDF, une ‘vue’ possible est de traverser les données dans un parcours arborescent. Nous allons en voir un exemple qui préserve les liens ‘sémantiques’ d’origine.

Nous allons voir que cela est faisable avec quelques transformations et un peu de code simple.

Pour avancer sur cette idée, nous avons choisi l’ontologie de Bloom que nous avons créée dans le cadre du projet ILOT (voir cet article). Dans son état actuel, il s’agit principalement d’un thésaurus, qui aurait pu être représenté en SKOS, mais, qui, pour des raisons liées au déroulement du projet ILOT, a été réalisée sous forme d’une ontologie OWL, exploitant une partie du vocabulaire de SKOS. Clairement, il s’agit d’un arbre composant un vocabulaire avec des concepts/mots généraux et une hiérarchie de mots limitant le champs du concept. L’ontologie est disponible ici.

Pour l’affichage Web d’un arbre, nous avons rapidement identifié la librairie javascript d3.js comme étant fiable et facilement adaptable,offrant diverses possibilités pour l’affichage de données arborescentes.

d3.js offre des fonctionnalités intéressantes pour charger des données décrites dans une structure json et les afficher. Pour cela, on va partir d’un modèle d’affichage d’arbre avec un fonctionnement par défaut de l’objet tree, qui suppose une structure bien définie de l’objet json, mais qui repose sur des méthodes que l’on peut redéfinir. En première approche, il suffit de redéfinir deux méthodes:

  • children, qui partant d’un nœud renvoie une table de ses fils directs,
  • une fonction qui renvoie le label à afficher pour un nœud donné.

Nous y reviendrons une fois générée la structure JSON que nous allons utiliser.

 Transformer l’ontologie OWL en JSON-LD

Notre ontologie de Bloom peut-être facilement transformée en JSON-LD avec l’outil RDF-Translator. Il s’agit d’un outil en ligne, dont les sources sont disponibles, qui permet de convertir des fichiers d’une représentation de triplets RDF dans une autre. Il faut donner le format d’entrée -ici RDF/XML- et le format de sortie -ici JSON-LD.

JSON-LD est une récente spécification du W3C pour représenter en JSON des données RDF d’une façon organisée pour faciliter l’échange de données entre applications et entre sites web. Un prochain billet vous en dira plus sur JSON-LD.

Une fois récupéré le fichier json-ld, nous allons le rendre un peu plus facilement manipulable en javascript en y ajoutant un contexte. Un contexte est une sorte de série de templates ajouté au début du fichier, qui simplifient la présentation et l’exploitation dans du code en préservant le contenu. Pour cela, j’ai utilisé ‘json-ld playground‘ qui m’a permis d’ajouter le petit contexte ci-dessous au fichier json-ld précédemment généré:

{
    "subClassOf": "http://www.w3.org/2000/01/rdf-schema#subClassOf",
    "label": {
      "@id": "http://www.w3.org/2000/01/rdf-schema#label",
      "@container": "@language"
    },
    "prefLabel": {
      "@id": "http://www.w3.org/2004/02/skos/core#prefLabel",
      "@container": "@language"
    },
    "close": "http://www.w3.org/2004/02/skos/core#closeMatch",
    "bloom": {
      "@id": "http://givingsense.eu/frscol/FrBloom/Bloom_Taxonomy"
    },
    "scopeNote": {
      "@id": "http://www.w3.org/2004/02/skos/core#scopeNote",
      "@type": "http://www.w3.org/2001/XMLSchema#anyURI"
    }
  }

qui permet par exemple que la portion de json-ld suivante:

"http://www.w3.org/2004/02/skos/core#prefLabel": [
      {
        "@value": "detect",
        "@language": "en"
      },
      {
        "@value": "détecter ",
        "@language": "fr"
      }
    ],

 

prenne, via le filtre du contexte, la représentation suivante:

"prefLabel": {
        "en": [
          "compter ",
          "reckon"
        ]
      }

ce qui est plus commode à manipuler. Le fichier JSON-LD que nous utilisons ensuite est ici.

 Affichage avec d3

En partant de l’exemple ‘Indented Tree’ qui figure sur la page d’exemples d3, nous avons cherché comment exploiter une telle représentation avec notre fichier JSON-LD. La première étape est, bien sûr, de remplacer les données utilisées dans l’exemple par les nôtres:

d3.json("bloom/ontobloom.jsld", ...

Les points de suspension remplacent une fonction passée en paramètre et qui exploite les données json lues à partir du chemin qui constitue le premier paramètre.

Directement, cela ne donne rien. Comme évoqué plus haut, il faut indiquer à la fonction comment trouver la racine de l’arbre qui nous intéresse:

  flare["@id"] = "http://givingsense.eu/frscol/FrBloom/Bloom_Taxonomy";

où on donne l’id du nœud qui devra être cherché dans la fonction qui trouve les fils d’un nœud:

childrenFinder = function(node) {
            var j=0;
            var children = new Array();
            var id = node["@id"];
            if (id!==undefined) {
              root["@graph"].forEach(function(n, i) {
                if (n.subClassOf!==undefined)
                if ("@id" in n.subClassOf)
                if (n.subClassOf["@id"]===id){
                    children[j] = n; j++;
                }
                }
              );    
            }
            return children;
          };

Cette fonction est assez simple et évidemment dépendante des données fournies en entrée. Elle est appelée récursivement sur les nœuds fils et les fils des fils et ainsi de suite.

Une fois définie, elle est utilisée comme paramètre de la structure d’affichage de l’arbre:

// surcharge de la méthode standard de recherche des fils
tree.children( childrenFinder)
// construction de la structure visuelle de l'arbre
tree.nodes(root);

Un peu plus loin, on trouve le morceau de code qui insère le texte dans l’arbre et on modifie la fonction qui trouve le label associé à chaque nœud:

nodeEnter.append("text")
      .attr("dy", 3.5)
      .attr("dx", 5.5)
      .text(function(d) { 
          var label = (d.label!==undefined?d.label.fr:"?");
          return label; 
        });

Le résultat est visible ici.

Si vous regardez dans un debugger -par exemple, avec les outils de développement intégrés à Chrome-l’objet d que vous récupérez sur un clic souris dans l’arbre, vous verrez que cet objet est directement issu de la structure de l’ontologie d’origine; en particulier, il contient un champs « @id » dont la valeur est l’URI de l’élément de l’ontologie associé à l’élément cliqué dans l’arbre; par exemple:

@id: "http://givingsense.eu/frscol/FrBloom/abstract"

Ainsi, à peu de frais, vous avez une interface utilisateur ‘sémantique’: elle est prête pour établir des liens avec le reste du merveilleux monde des données liées et du web sémantique.

 

Publié dans Cuisine OWL, Visualisation | Marqué avec , , , , , | 2 commentaires

Ré-utilisation de données publiques: ressources pédagogiques

Notre équipe a entrepris la réutilisation de données publiques, notamment dans le domaine de la culture. Pour cela, nous traitons des données publiques disponibles sur data.gouv.fr afin d’en améliorer leur utilisation dans le cadre du web sémantique et du LOD (Linked Open Data).

Le premier jeu de données publiées est celui intitulé

Ressources pédagogiques pour l’enseignement de l’histoire des arts

publié par le Ministère de la culture et de la communication français, sous licence ‘Licence Ouverte‘.

Le fichier initial est un fichier CSV, qui contient la description d’environ 5000 fiches pédagogiques. Ce fichier a plusieurs colonnes avec des valeurs multiples séparées par des ‘,’ ou des ‘;’. Nous avons amélioré la structuration de ces données en séparant ces valeurs pour qu’elles puissent aisément être reconnues pour des utilisations dans le cadre du web sémantique, et, en particulier avec des requêtes SPARQL. A ce sujet, voir https://ilot.wp.imt.fr/2014/01/16/publication-de-references-culturelles-dans-un-triple-store/, sur l’intégration en cours dans le cadre du projet ILOT.

Pour cela le fichier a été transformé en RDF/XML. Il est disponible à l’adresse suivante http://givingsense.eu/onto/refCulture/refHistArts.rdf. Il est publié sous licence Creative Commons Share Alike.

Nos données RDF ont été annoncées sur data.gouv.fr ici:

https://www.data.gouv.fr/fr/dataset/ressources-pedagogiques-pour-l-enseignement-de-l-histoire-des-arts

Les évolutions futures de notre travail devraient conduire à enrichir ces données avec:

  • des liens avec des données externes (par exemple avec DBPedia pour les personnes et les lieux, des liens avec geonames pour les lieux)
  • des liens vers une description enrichie pour tous les tags et mots-clés utilisés dans ce fichier.

N’hésitez pas à utiliser cette ressource. Merci de nous tenir informé si vous utilisez ou améliorez celle-ci.

 

Publié dans Cuisine OWL, Données publiques | Marqué avec , , , , | 2 commentaires

Ontologies, propriétés et héritages de caractéristiques

Je sais que je vais choquer certains spécialistes des ontologies en parlant d’héritages de caractéristiques de propriétés.

Mais laissez-moi raconter une petite histoire.

Je suis plutôt enthousiaste pour utiliser des ontologies dans mes projets mais j’étais encore un débutant dans le domaine il y a peu. Je fais des progrès rapides :).

J’ai eu un besoin qui me parait assez commun et simple, mais je suis resté coincé dessus pendant un temps long par rapport à cette simplicité.

Mon besoin:

  • J’ai un arbre virtuellement défini dans mon ontologie
  • Les nœuds ont un ancêtre direct (parent) et des ancêtres indirects
  • hasParent est une propriété qui relie un nœud à un autre, par un lien indiquant un ancêtre direct dans l’arbre,
  • hasAncestor est une propriété qui relie un nœud à un autre, qui est quelque part entre le nœud et la racine de l’arbre,
  • hasAncestor doit être transitive,
  • hasParent n’est pas transitive

Je veux que la règle suivante s’applique :

si
a :hasParent  b
alors
a :hasAncestor b

J’ai parcouru pas mal de documents et j’ai eu du mal à comprendre comment signifier cette règle dans OWL  (directement dans une représentation de l’ontologie ou interactivement avec Protégé).

Le solution était si simple et implicite qu’elle n’apparaissait pas clairement; la voilà exprimée avec la syntaxe Turtle:

:hasParent rdfs:subPropertyOf :hasAncestor.

Ma cécité était due à mon incapacité à penser qu’une subProperty ne partage pas certaines caractéristiques de sa super-propriété.

Affirmé

:hasParent rdfs:subClassOf :hasAncestor
et
:hasAncestor rdf:type owl:TransitiveProperty

ne signifie pas que :hasParent est aussi transitive.

La transitivité n’est pas ‘héritée’ dans la hiérarchie des propriétés, de sorte qu’il est possible d’avoir une sous-propriété non transitive d’une super-propriété transitive.

Dès que j’ai compris cela, j’ai cherché où j’avais raté quelque chose.

En premier lieu, je pense instinctivement qu’une sous-propriété hérite des ‘comportements’ de sa super-propriété.

De bons spécialistes -comme Dave Reynolds- considèrent que pour les ontologies OWL, et la logique sous-jacente, utiliser des termes comme ‘héritage’ ne peut que vous induire en erreur. En particulier quand il s’agit des axiomes et du raisonnement sur les propriétés. Dans la façon de penser avec RDF/OWL, une propriété est juste associée à un ensemble de paires de choses qui sont reliées par cette propriété. De sorte que de dire

:hasParent rdfs:subPropertyOf :hasAncestor

signifie seulement que l’ensemble des paires d’objets reliés par :hasParent est aussi relié par :hasAncestor.

Nous ne pouvons pas supposer que des caractéristiques de la propriété :hasAncestor sont transmises à la propriété :hasParent. Certaines caractéristiques ont des telles propriétés logiques qu’on va pouvoir déduire qu’elles s’appliquent aussi à la sous-propriété (comme la nature fonctionnelle d’une propriété); certaines ne se prêtent pas à de telles déductions (comme la transitivité et la symétrie). Et, assurément, penser à cela en terme d’héritage et pas de déduction logique ne peut qu’apporter de la confusion.

Certaines caractéristiques de propriétés  OWL sont héritables. D’autre non. Par exemple:

(a subPropertyOf b) et (b inverseOf c) n'implique pas (a inverseOf c)
(a subPropertyOf b) et (b equivalentPropertyOf c) n'implique pas (a equivalentPropertyOf c)
(a subPropertyOf b) et (b type SymetricProperty) n'implique pas (a type SymetricProperty)
(a subPropertyOf b) et (b type TransitiveProperty) n'implique pas (a type TransitiveProperty)

Où peut-on trouver des commentaires à ce sujet?

Aidan Hogan suggère que « si vous voulez une introduction pas trop technique des caractéristiques de OWL, par exemple en utilisant  SI — ALORS — (donc avec des règles) qui donne un bonne vision, même si elle est incomplète[…] étudier les règles dans  OWL 2 RL/RDF est un très bon point de départ pour quiconque voulant découvrir quelque peu ce que sont les notions clés d’OWL (2) caractéristiques (sans avoir besoin d’entrer dans des définitions de sémantique formelle):

http://www.w3.org/TR/owl2-profiles/#Reasoning_in_OWL_2_RL_and_RDF_Graphs_using_Rules

Les caractéristiques d’OWL permettent d’exprimer bien plus de choses que ce qui est indiqué dans ces règles, mais si vous comprenez ces règles, alors vous aurez acquis une connaissance opérationnelle d’OWL. »

Publié dans Cuisine OWL | Laisser un commentaire

OnSem, Objets Numériques et Sémantique

Au sein de Telecom ParisTech, dans le département de Traitement du Signal et des Images, nous sommes plusieurs membres de l’équipe Multimedia -qui travaille sur les technologies du multimédia-, à entreprendre des travaux de recherche mettant en oeuvre des représentations sémantiques: descriptions sémantiques de web services multimédia, utilisation de la sémantique dans des interfaces multimodales, exploration des technologies du web sémantique en liaison avec la cartographie et les représentations visuelles, technologies du web sémantique dans l’éducation.

Actuellement, les travaux les plus actifs portent sur ce dernier point et sont l’objet d’un blog spécifique: ILOT.

Dans OnSem, nous publierons des articles plus généraux sur les technologies du web sémantiques, les bonnes pratiques et les ‘recettes’, ainsi que des articles portant sur des domaines pour lesquels n’avons pas encore assez de matière pour en faire un sujet de blog à part entière.

Publié dans Uncategorized | Laisser un commentaire