知識表現(Knowledge Representation)入門 ― 意味ネットワーク・フレーム・意味プリミティブから知識グラフまで
意味ネットワーク・フレーム・意味プリミティブといった古典的な知識表現の手法をSwiftのサンプルコードで確認したうえで、現代のオントロジー・知識グラフ・OWLとの関係を整理します。
目次
- はじめに
- 1. 意味ネットワーク(Semantic Network)
- 2. フレームシステム(Frame System)
- 3. 意味プリミティブ(Semantic Primitives)
- 4. 現代への橋渡し:オントロジー・知識グラフ・OWL
- まとめ
- 注釈
- 参考資料
はじめに
知識表現(Knowledge Representation, KR)は、AIが推論に使える形で「世界についての知識」をコンピュータの中に表す方法を扱う分野です。1970〜80年代の記号主義AI(Symbolic AI)の時代に、意味ネットワーク・フレームシステム・意味プリミティブといった手法が生まれ、その考え方は形を変えながら現代のオントロジーや知識グラフにまで受け継がれています。
この記事では、これら古典的な手法の考え方をSwiftのサンプルコードで確認したうえで、現代のオントロジー/知識グラフ/OWLとの関係を整理します。Swiftを選んだ理由は、フレームの「スロット+デフォルト値+継承」という構造がオブジェクト指向のクラス継承とほぼ同じ発想であり、iOS/macOS開発者にとって最も直感的に理解できると考えたためです。
1. 意味ネットワーク(Semantic Network)
意味ネットワークは、概念をノード、概念間の関係を**ラベル付きの矢印(エッジ)**で表すグラフ構造です。代表的な関係が is-a(〜の一種である)で、これによって上位概念から下位概念へ属性を伝播させる「継承」が実現できます。
- 長所: ノードと矢印だけで表現できるため直感的で分かりやすい
- 短所: 答えを得るにはネットワーク全体をたどる必要があり、探索コストが高い。手続き(ロジック)を持たせにくい
古典的によく使われる例が「鳥は飛べるが、ペンギンは鳥なのに飛べない」というデフォルト推論と例外の問題です。下位ノードに個別の事実(ペンギンは泳ぐ)があれば、それを上位ノードのデフォルト値(鳥は飛ぶ)より優先させたい、というものです。
enum Relation: String {
case isA = "is-a"
case canDo = "can"
case hasProperty = "has"
}
final class ConceptNode {
let name: String
var edges: [(relation: Relation, target: String)] = []
init(name: String) { self.name = name }
func addEdge(_ relation: Relation, to target: String) {
edges.append((relation, target))
}
}
final class SemanticNetwork {
private var nodes: [String: ConceptNode] = [:]
func addNode(_ name: String) {
if nodes[name] == nil { nodes[name] = ConceptNode(name: name) }
}
func addRelation(from: String, relation: Relation, to: String) {
addNode(from); addNode(to)
nodes[from]?.addEdge(relation, to: to)
}
private func ancestors(of name: String) -> [String] {
var result: [String] = []
var current = name
while let node = nodes[current],
let parentEdge = node.edges.first(where: { $0.relation == .isA }) {
result.append(parentEdge.target)
current = parentEdge.target
}
return result
}
// 自分自身 → 祖先の順に探索し、最初に見つかった値を返す
// (下位ノードの値が上位のデフォルト値より優先される)
func query(_ name: String, relation: Relation) -> String? {
let chain = [name] + ancestors(of: name)
for concept in chain {
if let edge = nodes[concept]?.edges.first(where: { $0.relation == relation }) {
return edge.target
}
}
return nil
}
}
let net = SemanticNetwork()
net.addRelation(from: "Canary", relation: .isA, to: "Bird")
net.addRelation(from: "Penguin", relation: .isA, to: "Bird")
net.addRelation(from: "Bird", relation: .isA, to: "Animal")
net.addRelation(from: "Bird", relation: .canDo, to: "Fly")
net.addRelation(from: "Animal", relation: .canDo, to: "Move")
net.addRelation(from: "Penguin", relation: .canDo, to: "Swim")
net.query("Canary", relation: .canDo) // → "Fly"(Bird から継承)
net.query("Penguin", relation: .canDo) // → "Swim"(Penguin 自身の値が優先)
query は自分自身から is-a を親方向にたどり、最初に見つかった値を採用します。これにより「ペンギン自身に泳ぐという事実があればそれを使い、なければ鳥のデフォルトである飛ぶを使う」という、デフォルト推論と例外処理を単純な探索で実現しています。
2. フレームシステム(Frame System)
フレームは Marvin Minsky が1974年の論文 "A Framework for Representing Knowledge" で提唱した表現法で、「典型的な状況」をスロット(属性)とその値の組として構造化します。意味ネットワークの発展形にあたり、次の点が強化されています。
- スロットにデフォルト値を持たせられる
- スロットに**手続き(procedural attachment)**を埋め込める(=メソッド)
- 上位フレームから下位フレームへの継承
これはまさにオブジェクト指向の「クラス(デフォルト実装を持つ基底クラス)」「サブクラスでのオーバーライド」「メソッド」に対応しており、Swiftではほぼそのままの構文で書けます。実際、フレームは後年のオブジェクト指向言語のクラス/インスタンス概念の源流の一つとされています。
class VehicleFrame {
// スロット(デフォルト値)
var wheels: Int { 4 }
var maxSpeedKmh: Int { 120 }
var canFly: Bool { false }
// 手続き型スロット: 他のスロットの値を使って動的に組み立てる
func summary() -> String {
"\(type(of: self)): 車輪\(wheels)個 / 最高速度\(maxSpeedKmh)km/h / 飛行\(canFly ? "可" : "不可")"
}
}
final class CarFrame: VehicleFrame {
override var maxSpeedKmh: Int { 180 }
}
final class AirplaneFrame: VehicleFrame {
override var wheels: Int { 3 }
override var maxSpeedKmh: Int { 900 }
override var canFly: Bool { true }
}
let car = CarFrame()
let plane = AirplaneFrame()
print(car.summary()) // CarFrame: 車輪4個 / 最高速度180km/h / 飛行不可
print(plane.summary()) // AirplaneFrame: 車輪3個 / 最高速度900km/h / 飛行可
VehicleFrame のスロットはすべてデフォルト値を持ち、CarFrame や AirplaneFrame は必要なスロットだけを override で上書きしています。これは意味ネットワークの is-a 継承と同じ発想ですが、フレームでは値だけでなくsummary()のような手続きも一緒に継承・共有できる点が強みです。
3. 意味プリミティブ(Semantic Primitives)
意味プリミティブは、自然言語の意味をそれ以上分解できない少数の基本要素の組み合わせとして表す考え方です。代表的なのが Roger Schank の Conceptual Dependency(概念依存理論、1969年〜)で、文の意味を言語非依存の少数のプリミティブ行為(ATRANS=所有権の移動、PTRANS=物理的な移動、MTRANS=情報の伝達など)とケース役割(動作主・対象・起点・終点など)の組み合わせで表現します(注1)。
この手法の最大の特徴は、表層の単語が違っても意味が同じなら同一の内部表現に正規化される点です。
enum PrimitiveAct: String {
case atrans // 所有権の移動
case ptrans // 物理的な移動
case mtrans // 情報の伝達
}
struct ConceptualDependency: Equatable {
let actor: String
let act: PrimitiveAct
let object: String
let from: String
let to: String
}
let cdA = ConceptualDependency(actor: "太郎", act: .atrans, object: "本", from: "太郎", to: "花子") // 「あげた」
let cdB = ConceptualDependency(actor: "太郎", act: .atrans, object: "本", from: "太郎", to: "花子") // 「渡した」
cdA == cdB // true ―― 表層は異なるが同じ出来事として正規化される
「あげた」と「渡した」は表層の単語としては別物ですが、どちらも「所有権が太郎から花子に移った(ATRANS)」という同じ出来事なので、同一の構造体値になります。この正規化のしやすさから、機械翻訳や要約など「表現が違っても意味が同じものをまとめたい」タスクで有効とされました。
もう一つの代表例が Yorick Wilks のプリファレンス意味論(1975年)で、約70個の意味プリミティブを使い、単語同士の意味的な「好み(selectional preference)」に基づいて構文的な曖昧性を解消しました(注2)。
いずれの手法も、プリミティブの種類と粒度をどう設計するか(網羅性と再利用性のトレードオフ)が実装上の難所で、これが後に汎用的な意味プリミティブ集合の標準化を難しくした一因でもあります。
4. 現代への橋渡し:オントロジー・知識グラフ・OWL
ここまでの3手法はいずれも1970〜80年代のものですが、根底にある「ノードと関係」「属性値スロットと継承」という発想は、現代の技術にもそのまま引き継がれています。
| 古典 | 現代 | 変化点 |
|---|---|---|
| 意味ネットワーク | RDFグラフ/知識グラフ | 同じ「ノードと関係」の発想。トリプル構造とSPARQLというクエリ言語を獲得 |
| フレーム | OWLクラス+プロパティ | 同じ「属性値の集合+継承」の発想。Description Logic(DL)による厳密な意味論と自動推論(reasoner)を獲得 |
| 意味プリミティブ | 上位オントロジー(SUMOなど) | 直接の主流ではないが、共通語彙という発想は継続 |
Description Logic(DL)は1980年代、意味ネットワークやフレームに数学的に厳密な意味論がなく実装依存で曖昧だった問題を解決するために生まれました。**OWL(Web Ontology Language)**はこのDLを基盤にしたW3C標準で、あるドメインのクラス・プロパティ・制約を形式的に定義します(注3)。知識グラフは、この考え方を実務に適用したもので、エンティティと関係を「主語-述語-目的語」のRDFトリプルとして大量に蓄積し、SPARQLで問い合わせます(注4)。OWLの推論エンジン(reasoner)を使えば、明示的に書いていない事実も論理的に導出できます(例:「収益2億円の会社」+「収益1億円以上はPlatinum」というルールから自動的にPlatinum会社だと推論する)。
先ほどの意味ネットワークの例をRDFトリプル風に書き直すと、発想が地続きであることが分かります。
struct Triple: CustomStringConvertible {
let subject: String
let predicate: String
let object: String
var description: String { "(\(subject), \(predicate), \(object))" }
}
let triples: [Triple] = [
Triple(subject: "Canary", predicate: "rdf:type", object: "Bird"),
Triple(subject: "Penguin", predicate: "rdf:type", object: "Bird"),
Triple(subject: "Bird", predicate: "rdfs:subClassOf", object: "Animal"),
Triple(subject: "Bird", predicate: "canDo", object: "Fly"),
Triple(subject: "Penguin", predicate: "canDo", object: "Swim")
]
これは先ほどの ConceptNode の edges 配列を、より標準化された (subject, predicate, object) の3つ組として表しただけです。実運用ではこれをRDFストアに保存し、OWLでスキーマを定義し、SPARQLやreasonerで問い合わせる、という形になりますが、核となる考え方は意味ネットワークと変わりません。
まとめ
| 手法 | 単位 | 強み | 弱み |
|---|---|---|---|
| 意味ネットワーク | ノードと関係 | 直感的、可視化しやすい | 探索コストが高い、手続き知識が持てない |
| フレーム | スロット付き構造体 | デフォルト推論・手続き添付が可能、OOPの原型 | 設計者の恣意性が入りやすい |
| 意味プリミティブ | 言語非依存の基本要素 | 同義表現の正規化に有効 | プリミティブの網羅性・粒度の設計が難しい |
| オントロジー/知識グラフ(現代) | RDFトリプル+OWLスキーマ | 形式的な意味論、自動推論、標準化されたクエリ | 学習コストが高く、大規模化すると設計・保守が難しい |
意味ネットワーク・フレーム・意味プリミティブはいずれも、ノードと関係、属性とデフォルト値、そして継承という共通の骨格を持っています。現代のオントロジーや知識グラフは、この骨格に形式的な数学的基盤(Description Logic)と業界標準(RDF/OWL/SPARQL)を与えたものだと理解すると、両者のつながりが見えやすくなります。
注釈
- Roger Schank, Conceptual Dependency Theory(1969年〜)。11種の基本行為(ATRANS/PTRANS/MTRANSなど)とケース役割で文の意味を表現する。
- Yorick Wilks, Preference Semantics(1975年)。約70個の意味プリミティブによる曖昧性解消。
- Description Logic は1980年代、意味ネットワーク・フレームに形式的な意味論を与える目的で考案された。OWLはこれを基盤にしたW3C標準。
- 知識グラフはRDF(主語-述語-目的語のトリプル)とオントロジー(OWL/RDFS)を組み合わせ、SPARQLで問い合わせる。Googleのナレッジグラフや企業内ナレッジグラフ、RAG(検索拡張生成)の構造化知識層などに応用されている。
参考資料
- Knowledge Representation in AI: Ontologies, Frames & Semantic Nets - Sanfoundry
- Semantic Networks - John F. Sowa
- Conceptual dependency theory - Wikipedia
- Description logic - Wikipedia
- RDF Knowledge Graphs: Structure & Benefits - PuppyGraph
- Knowledge Graph vs Ontology: Know Differences - PuppyGraph
元記事(Bitz Notebook): https://www.bitz.co.jp/notebook/knowledge-representation-introduction.html