RDF・RDFS・OWL・Turtleの違いを整理して、ファイルで理解するオントロジー入門

RDF・RDFS・OWL・Turtleの違いを整理して、ファイルで理解するオントロジー入門

「オントロジーを勉強し始めたけれど、RDF、RDFS、OWL、Turtleの違いが分からない」

これは、たぶんオントロジー初心者が最初につまずきやすいポイントです。少なくとも、ぼくはこれらが出てきたときに思考が止まりました。。。 なので、これらだけをザックリ解説する記事になっております。

特に混乱しやすいのが、次のような疑問です。

  • RDFとOWLは別のファイル形式なのか
  • .ttlファイルはRDFなのかOWLなのか
  • ex:とは何を意味するのか
  • URIはどのように決めればよいのか
  • RDF/XMLでは、なぜURIの書き方が場所によって違うのか

この記事では、社員と会社を表す小さなサンプルを使いながら、これらの関係を順番に整理します。

最初はつらいですが、がんばって途中まで読んでみてください!なんとなく、わかった気になるはずです。

そして意外だったのは、オブジェクト指向プログラミング言語を触ったことがある方々は、理解しやすいかもですので、その観点でも読んでみていただけますと幸いです。

※途中で出てくるオントロジーのファイル(.ttl)を、グラフとして可視化しそのまま編集できる VSCode Extension を公開していますので、こちらも合わせて使っていただくと、よりイメージがわきやすいかもしれませんので、せひ使ってみてください!

Ontology Viewer — OWL & RDF Visual Editor - Visual Studio Marketplace
Extension for Visual Studio Code - Visualize and safely edit OWL, RDF, RDFS, and SKOS ontologies in VS Code with an interactive schema diagram.

全体像を理解する

まず、RDF、RDFS、OWL、Turtleは、すべて同じ種類のものではありません。

一言で整理すると、次のようになります。

RDF     :情報をグラフとして表すためのデータモデル
RDFS    :クラスや継承関係を定義する基本的なスキーマ
OWL     :より高度な意味や論理関係を定義するオントロジー言語
Turtle  :RDFグラフをテキストで書くための記法
.ttl    :Turtleで書かれたファイルの拡張子

RDFでは、情報を「主語・述語・目的語」の3要素で表します。これをトリプルと呼びます。

たとえば、

山田はABC社に勤務している

という情報は、次のように表せます。

山田 ── worksFor ──> ABC

Turtleでは、次のように書きます。

@prefix ex: <https://example.com/company#> .

ex:yamada ex:worksFor ex:abc .

ex:は省略記号です。

ex:yamada

は、実際には次のIRIを表します。

https://example.com/company#yamada

同様に、ex:worksForも次のIRIに展開されます。

https://example.com/company#worksFor

ここで重要なのは、Turtleはあくまで「書き方」だという点です。

同じRDFグラフを、RDF/XMLで書くこともできます。

<rdf:Description rdf:about="https://example.com/company#yamada">
  <ex:worksFor
      rdf:resource="https://example.com/company#abc"/>
</rdf:Description>

TurtleとRDF/XMLは見た目が異なりますが、どちらも同じRDFトリプルを表せます。

RDFSを使うと、クラスや継承関係を定義できます。

ex:Employee rdfs:subClassOf ex:Person .

これは、「EmployeeはPersonの一種である」という意味です。

OWLでは、さらに複雑な意味を表現できます。

ex:worksFor owl:inverseOf ex:hasEmployee .

これは、「山田がABCに勤務しているなら、ABCは山田を社員として持つ」という逆方向の関係を定義します。

したがって、全体の関係は次のようになります。

RDF
└─ 情報をトリプルとして表す

RDFS
└─ RDF上でクラスや継承を定義する

OWL
└─ RDF上でさらに高度な論理を定義する

Turtle
└─ それらをテキストファイルに書くための構文

つまり、.ttlファイルの中には、単純なRDFデータも、RDFSスキーマも、OWLオントロジーも書くことができます。

ここまで理解できれば、全体像はほぼつかめています。


ここから詳しく解説

1. RDFとは何か

RDFは、Resource Description Frameworkの略です。

名前だけを見ると難しそうですが、基本的な考え方はシンプルです。

RDFでは、すべての情報を次の3要素で表します。

主語 ── 述語 ──> 目的語

英語では、次のように呼びます。

Subject ── Predicate ──> Object

たとえば、

山田はABC社に勤務している

という情報は、次のトリプルになります。

主語   :山田
述語   :勤務している
目的語 :ABC社

RDF風に名前を付けると、次のようになります。

山田 ── worksFor ──> ABC

さらに、

山田の社員番号はE001である

という情報は、次のトリプルになります。

山田 ── employeeId ──> "E001"

RDFでは、こうしたトリプルをたくさん組み合わせて、情報のネットワークを作ります。

                 ┌── employeeId ──> "E001"
                 │
山田 ───────────┼── worksFor ────> ABC
                 │
                 └── manages ─────> 鈴木

この構造をRDFグラフと呼びます。


2. URIやIRIを使う理由

RDFでは、山田やABC、worksForなどを、単なる文字列ではなくIRIで識別します。

たとえば、次のIRIを使えます。

https://example.com/company#yamada
https://example.com/company#abc
https://example.com/company#worksFor

IRIは、世界中で名前が衝突しないようにするための識別子です。

たとえば、異なる会社がどちらもEmployeeという言葉を使っていたとしても、IRIが異なれば別の概念として区別できます。

https://company-a.example/vocab#Employee
https://company-b.example/vocab#Employee

RDFにおけるIRIは、データベースの主キーやプログラムの完全修飾名に近い役割を持ちます。


3. Turtleとは何か

Turtleは、RDFグラフを人間が比較的読みやすい形で記述するための構文です。

次のTurtleを見てみましょう。

@prefix ex: <https://example.com/company#> .

ex:yamada
    ex:worksFor ex:abc ;
    ex:employeeId "E001" ;
    ex:manages ex:suzuki .

このファイルには、次の3つのトリプルが書かれています。

ex:yamada ex:worksFor ex:abc .
ex:yamada ex:employeeId "E001" .
ex:yamada ex:manages ex:suzuki .

セミコロン;は、同じ主語を繰り返さないための省略記法です。

したがって、

ex:yamada
    ex:worksFor ex:abc ;
    ex:employeeId "E001" .

は、次と同じ意味です。

ex:yamada ex:worksFor ex:abc .
ex:yamada ex:employeeId "E001" .

4. @prefixex:の意味

Turtleファイルの先頭には、よく次の記述があります。

@prefix ex: <https://example.com/company#> .

これは、

ex:

を、

https://example.com/company#

の省略形として使う、という宣言です。

そのため、

ex:yamada

は次のIRIに展開されます。

https://example.com/company#yamada

また、

ex:worksFor

は次のIRIに展開されます。

https://example.com/company#worksFor

exという名前自体に特別な意味はありません。

次の3つは、対応する宣言があれば同じIRIを表します。

@prefix ex:      <https://example.com/company#> .
@prefix company: <https://example.com/company#> .
@prefix c:       <https://example.com/company#> .
ex:Employee
company:Employee
c:Employee

重要なのはexという省略名ではなく、展開先のIRIです。


5. 名前空間IRIはどのように決めるのか

サンプルでは、次のIRIを使用しています。

https://example.com/company#

example.comは、説明資料やサンプルコードで使用するためのドメインです。

本番環境では、原則として自社や自分が管理しているドメインを使用します。

たとえば、自社のドメインがmycompany.co.jpなら、次のような名前空間を考えられます。

@prefix company:
    <https://data.mycompany.co.jp/vocab/company#> .

実データ用のIRIは、語彙とは分けると管理しやすくなります。

@prefix company:
    <https://data.mycompany.co.jp/vocab/company#> .

@prefix resource:
    <https://data.mycompany.co.jp/resource/> .

使用例は次のとおりです。

resource:yamada
    a company:Employee ;
    company:worksFor resource:abc ;
    company:employeeId "E001" .

ここでは、

company:Employee

が「社員という概念」を表し、

resource:yamada

が「具体的な山田という人物」を表します。

名前空間を決めるときは、次の点が重要です。

  • 自分たちが管理するドメインを使う
  • 長期間変更しなくて済む名前にする
  • 語彙と実データを必要に応じて分離する
  • 一度公開したIRIを安易に変更しない
  • 可能であれば、ブラウザでアクセスした際に説明を返せるようにする

IRIは単なるWebページのURLではなく、概念やリソースの識別子です。

そのため、Webサイトのデザインを変更したからといって、オントロジーのIRIまで変更するべきではありません。


6. #/はどう使い分けるのか

名前空間には、主にハッシュ形式とスラッシュ形式があります。

ハッシュ形式

@prefix ex: <https://example.com/company#> .

展開結果は次のようになります。

https://example.com/company#Employee
https://example.com/company#worksFor

比較的小規模な語彙を、1つの文書として管理するときに向いています。

スラッシュ形式

@prefix ex: <https://example.com/company/> .

展開結果は次のようになります。

https://example.com/company/Employee
https://example.com/company/worksFor

各用語を個別のURLとして管理したい場合に向いています。

どちらが絶対に正しいというわけではありません。

それよりも、一度決めたIRIを安定して使い続けることのほうが重要です。


7. TurtleはRDFそのものではない

ここは重要なポイントです。

RDF     :情報の構造
Turtle  :その構造を書く方法

たとえば、次のTurtleがあります。

ex:yamada ex:worksFor ex:abc .

この内容は、RDF/XMLでも表せます。

<rdf:Description
    rdf:about="https://example.com/company#yamada">

  <ex:worksFor
      rdf:resource="https://example.com/company#abc"/>

</rdf:Description>

見た目はまったく違いますが、どちらも次のトリプルを表しています。

主語:
https://example.com/company#yamada

述語:
https://example.com/company#worksFor

目的語:
https://example.com/company#abc

つまり、TurtleとRDF/XMLは、同じRDFグラフを異なる形式で表現しているだけです。

プログラムでたとえるなら、同じデータをJSONとXMLのどちらで表現するか、という違いに近いでしょう。


8. RDF/XMLにおけるex:の意味

RDF/XMLでは、ファイルの先頭に次のような名前空間宣言があります。

<rdf:RDF
    xmlns:rdf=
      "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns:ex=
      "https://example.com/company#">

ここで、

xmlns:ex="https://example.com/company#"

と宣言しています。

そのため、

<ex:worksFor>

は、次のIRIを表します。

https://example.com/company#worksFor

ex:worksForがそのまま文字列として保存されるわけではありません。

XMLの名前空間機能によって、正式なIRIへ展開されます。


9. なぜrdf:resourceには完全なIRIを書くのか

次のRDF/XMLを見てみましょう。

<ex:worksFor
    rdf:resource="https://example.com/company#abc"/>

ex:worksForはXML要素名です。

そのため、XML名前空間の仕組みにより、次のIRIへ展開されます。

https://example.com/company#worksFor

一方、

rdf:resource="https://example.com/company#abc"

の引用符の中は、XMLの要素名ではなく、単なる属性値です。

XML名前空間のプレフィックスは、通常、属性値の中までは展開してくれません。

そのため、次のようには書きません。

<ex:worksFor rdf:resource="ex:abc"/>

期待するIRIを確実に指定するため、完全なIRIを書きます。

<ex:worksFor
    rdf:resource="https://example.com/company#abc"/>

これはRDFの都合というより、XML名前空間の仕組みに由来する制約です。

Turtleでは、主語・述語・目的語のすべてに同じプレフィックス記法を使えます。

ex:yamada ex:worksFor ex:abc .

そのため、人間が直接読み書きする用途では、Turtleのほうが簡潔です。


10. rdf:resourceがある場合とない場合

次の2つを比較してみましょう。

<ex:worksFor
    rdf:resource="https://example.com/company#abc"/>
<ex:employeeId>E001</ex:employeeId>

違いは、目的語がリソースなのか値なのかです。

rdf:resourceがある場合

<ex:worksFor
    rdf:resource="https://example.com/company#abc"/>

この目的語は、ABCという別のリソースです。

山田 ── worksFor ──> ABC

Turtleでは次のようになります。

ex:yamada ex:worksFor ex:abc .

要素の中に値がある場合

<ex:employeeId>E001</ex:employeeId>

この目的語は、E001という文字列です。

山田 ── employeeId ──> "E001"

Turtleでは次のようになります。

ex:yamada ex:employeeId "E001" .

RDFでは、目的語にIRIで識別されるリソースを置くことも、文字列や数値などのリテラルを置くこともできます。


11. RDFSとは何か

RDFだけでもデータは表現できます。

しかし、RDFだけでは次のような構造を十分に説明できません。

  • EmployeeはPersonの一種である
  • ManagerはEmployeeの一種である
  • worksForの主語はEmployeeである
  • worksForの目的語はOrganizationである

こうした基本的なスキーマを表現するのがRDFSです。

たとえば、次のようにクラスを定義できます。

@prefix ex:
    <https://example.com/company#> .

@prefix rdfs:
    <http://www.w3.org/2000/01/rdf-schema#> .

ex:Employee
    a rdfs:Class ;
    rdfs:subClassOf ex:Person .

ex:Manager
    a rdfs:Class ;
    rdfs:subClassOf ex:Employee .

クラス階層は次のようになります。

Person
└─ Employee
   └─ Manager

ManagerがEmployeeのサブクラスで、EmployeeがPersonのサブクラスなら、ManagerはPersonでもあります。


12. rdfs:domainrdfs:range

RDFSでは、プロパティの主語と目的語の型を表現できます。

ex:worksFor
    rdfs:domain ex:Employee ;
    rdfs:range ex:Organization .

これは、次の意味です。

worksForの主語はEmployeeである
worksForの目的語はOrganizationである

たとえば、次のデータがあるとします。

ex:yamada ex:worksFor ex:abc .

RDFSの推論を行うと、次の型を導けます。

ex:yamada a ex:Employee .
ex:abc a ex:Organization .

ただし、domainrangeを入力チェックと考えてはいけません。

たとえば、次のデータがあったとします。

ex:invoice123 ex:worksFor ex:abc .

人間から見ると、「請求書が会社に勤務する」という不自然なデータです。

しかしRDFSは、このデータを単純にエラーにするのではなく、次のように推論します。

ex:invoice123 a ex:Employee .

つまり、RDFSのdomainは、

EmployeeだけがworksForを使用してよい

という入力制約ではなく、

worksForの主語になっているものはEmployeeである

という意味です。


13. OWLとは何か

OWLは、RDFSより高度な意味や論理関係を表現するためのオントロジー言語です。

RDFSで表現できる主な内容は、次のとおりです。

  • クラス
  • サブクラス
  • プロパティ
  • サブプロパティ
  • domain
  • range

OWLでは、さらに次のような内容を表現できます。

  • 2つのクラスが同じ意味である
  • 2つのクラスが同時には成立しない
  • 2つのプロパティが逆関係である
  • プロパティが推移的である
  • プロパティが対称的である
  • 個体同士が同一である
  • 特定の条件を満たすものをクラスとして定義する
  • キーを定義する
  • 値の個数に制約を付ける

14. OWLによる逆プロパティ

次のOWL定義を考えてみます。

ex:worksFor
    a owl:ObjectProperty ;
    owl:inverseOf ex:hasEmployee .

これは、worksForhasEmployeeが逆方向の関係であることを表します。

データに次の記述がある場合、

ex:yamada ex:worksFor ex:abc .

OWL Reasonerは、次の情報を推論できます。

ex:abc ex:hasEmployee ex:yamada .

人間が両方向を手動で登録しなくても、片方の情報からもう片方を導けるのです。


15. OWLによるクラスの条件定義

OWLでは、クラスを単に名前で宣言するだけでなく、条件によって定義できます。

たとえば、Managerを次のように定義できます。

Managerとは、
Employeeであり、
少なくとも1人のEmployeeを管理しているもの

OWLでは、次のように記述できます。

ex:Manager
    owl:equivalentClass [
        a owl:Class ;
        owl:intersectionOf (
            ex:Employee
            [
                a owl:Restriction ;
                owl:onProperty ex:manages ;
                owl:someValuesFrom ex:Employee
            ]
        )
    ] .

データに次の記述があるとします。

ex:yamada ex:manages ex:suzuki .

山田がEmployeeで、鈴木もEmployeeであることが分かれば、Reasonerは次を推論できます。

ex:yamada a ex:Manager .

つまり、Managerという型を明示的に書かなくても、条件から分類できます。


16. OWLの排他関係と不整合

OWLでは、2つのクラスが同時には成立しないことを表現できます。

ex:Organization
    owl:disjointWith ex:Person .

これは、OrganizationとPersonが排他的であることを意味します。

もし、あるリソースに次の両方の型が付いた場合、

ex:abc a ex:Organization .
ex:abc a ex:Person .

オントロジーは論理的に不整合となります。

OWL Reasonerは、単に1行の入力ミスを探すのではありません。

オントロジー全体について、すべての条件を同時に満たせるかどうかを検証します。


17. OWLは入力バリデーションではない

OWLは強力ですが、データベースの入力チェックとは考え方が異なります。

OWLでは、一般にオープンワールド仮定が使われます。

たとえば、鈴木の勤務先がデータに書かれていない場合、OWLは次のようには判断しません。

鈴木には勤務先が存在しない

代わりに、次のように考えます。

鈴木の勤務先は、まだ分かっていない

つまり、情報が書かれていないことと、その情報が存在しないことは別です。

そのため、次のような検証にはOWLだけでは向かない場合があります。

  • employeeIdは必須
  • employeeIdは必ず1つ
  • 年齢は0以上
  • メールアドレスは特定の形式
  • 必須プロパティが欠けていないか確認する

こうした入力データの検証には、SHACLという技術がよく使われます。

役割を整理すると、次のようになります。

RDFS・OWL
    データが何を意味するかを定義する

SHACL
    データが期待する形になっているかを検証する

18. RDFパーサーとReasonerの違い

Turtleファイルを読み込んだからといって、自動的にすべての推論が行われるわけではありません。

パーサーとReasonerは別の役割を持ちます。

RDFパーサー

TurtleやRDF/XMLを読み込み、
明示的に書かれたRDFトリプルを取り出す

Reasoner

RDFSやOWLの意味論を使い、
明示されていない情報を推論する

たとえば、次のデータがあるとします。

ex:yamada ex:manages ex:suzuki .

単純なRDFパーサーは、このトリプルを読み込むだけです。

しかし、RDFSやOWLの定義があり、Reasonerを使用すると、次のような型が推論される可能性があります。

ex:yamada a ex:Manager .
ex:yamada a ex:Employee .
ex:yamada a ex:Person .

ex:suzuki a ex:Employee .
ex:suzuki a ex:Person .

使用するReasonerや設定によって、どの範囲まで推論されるかは異なります。


19. .ttl.rdf.owlの違い

ファイル拡張子と、内部で使われる意味論は分けて考える必要があります。

.ttl

Turtle構文で書かれたRDFファイルです。

中身は、単純なデータの場合もあれば、RDFSやOWLの定義の場合もあります。

data.ttl
schema.ttl
ontology.ttl

いずれもTurtle形式で記述できます。

.rdf

RDF/XML形式のファイルであることが多い拡張子です。

.owl

OWLオントロジーに使用されることが多い拡張子です。

ただし、.owlという拡張子だけでは、内部構文が必ずRDF/XMLであるとは限りません。

実際のファイル形式は、内容やContent-Type、使用ツールの設定を確認する必要があります。


20. 一つの.ttlファイルにRDF・RDFS・OWLを書ける

次のようなTurtleファイルを考えてみましょう。

@prefix ex:
    <https://example.com/company#> .

@prefix rdf:
    <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .

@prefix rdfs:
    <http://www.w3.org/2000/01/rdf-schema#> .

@prefix owl:
    <http://www.w3.org/2002/07/owl#> .

ex:Employee
    a owl:Class ;
    rdfs:subClassOf ex:Person .

ex:worksFor
    a owl:ObjectProperty ;
    rdfs:domain ex:Employee ;
    rdfs:range ex:Organization ;
    owl:inverseOf ex:hasEmployee .

ex:yamada
    a ex:Employee ;
    ex:worksFor ex:abc .

この1つのファイルには、次の内容が混在しています。

RDFデータ
    ex:yamada ex:worksFor ex:abc

RDFS
    rdfs:subClassOf
    rdfs:domain
    rdfs:range

OWL
    owl:Class
    owl:ObjectProperty
    owl:inverseOf

Turtle
    ファイル全体の記述構文

したがって、

このファイルはRDFなのか、RDFSなのか、OWLなのか

という二者択一で考える必要はありません。

すべてRDFグラフであり、その中でRDFSやOWLの語彙を使用しています。


21. 実務での使い分け

目的ごとに整理すると、次のようになります。

やりたいこと使用する技術
情報をグラフとして表したいRDF
人間が読みやすい形式で保存したいTurtle
クラスや継承関係を定義したいRDFS
同値・排他・逆関係・制約を定義したいOWL
データの必須項目や形式を検証したいSHACL
RDFデータを検索したいSPARQL

実務では、次の組み合わせで使うことが多いでしょう。

データモデル        RDF
ファイル形式        Turtle
基本スキーマ        RDFS
高度な意味論        OWL
データ検証          SHACL
検索                SPARQL

まとめ

最後に、最も重要な関係をもう一度整理します。

RDF
    情報を主語・述語・目的語のトリプルとして表す

RDFS
    RDF上でクラス、継承、domain、rangeを定義する

OWL
    RDF上で、同値、排他、逆関係、制約などを定義する

Turtle
    RDFグラフを読みやすいテキストとして書く構文

.ttl
    Turtle形式のファイルに使われる拡張子

そのため、次の表現はすべて正しいものです。

RDFデータをTurtleで書く
RDFSスキーマをTurtleで書く
OWLオントロジーをTurtleで書く

また、

@prefix ex: <https://example.com/company#> .

ex:は、IRIを短く書くための省略名です。

ex:yamada
ex:worksFor
ex:abc

は、それぞれ次のIRIに展開されます。

https://example.com/company#yamada
https://example.com/company#worksFor
https://example.com/company#abc

本番環境で名前空間を設計する場合は、自社が管理するドメインを使用し、長期間変更せずに使えるIRIを選ぶことが重要です。

オントロジーを学ぶときは、最初からOWLの複雑な制約をすべて理解しようとする必要はありません。

まずは、次の順番で学ぶと理解しやすくなります。

1. RDFのトリプルを理解する
2. Turtleでトリプルを書いてみる
3. RDFSでクラスと継承を定義する
4. OWLで逆関係や排他関係を試す
5. Reasonerによる推論結果を確認する
6. 必要に応じてSHACLやSPARQLを学ぶ

RDF、RDFS、OWL、Turtleは別々の技術に見えますが、すべては「意味を持ったグラフデータを表現し、共有し、推論する」という一つの目的につながっています。

ここまで読んだ方はすごいです!!!

改めましてですが、上記オントロジーのファイル(.ttl)を、グラフとして可視化しそのまま編集できる VSCode Extension を公開していますので、こちらも合わせて使っていただくと、よりイメージがわきやすいかもしれませんので、せひ使ってみてください!

以上、やがさきからでした。