從零開始學本體論 2:披薩本體論範例

從零開始學本體論 2:披薩本體論範例

上一篇提到史丹佛大學的 Noy & McGuinness 提出一個很實用的流程,被很多人當作本體論開發 101,你可以在這裡下載

七步驟如下:

  1. (Determine Domain and Scope)
  2. 考慮重複使用,不要從零開始 (Consider Reusing Existing Ontologies)
  3. 列出重要術語 (Enumerate Important Terms)
  4. 定義類別與階層的 is-a 關係 (Define Classes and the Class Hierarchy)
  5. 定義屬性 (Define Properties – Slots)
  6. 定義約束 (Define Facets of Slots)
  7. 建立實例 (Create Instances)

接下來就一步一步建構披薩本體。

七步建構披薩本體

1. 確定領域與範圍 (Determine the domain and scope)

在動手之前,先問自己:「這個本體論是用來解決什麼問題的?」這決定了複雜度邊界。

  • 領域 (Domain):披薩、配料、菜單分類。
  • 範圍 (Scope):
    • 要涵蓋:各種披薩的分類規則 (什麼是素食?什麼是辣味?)、配料的層級 (起司、肉、蔬菜)。
    • 不涵蓋:披薩的營養成分 (卡路里)、價格、庫存管理、外送路徑。
  • 關鍵問題 (Competency Questions):
    • 「這個披薩是素食的嗎?」
    • 「有哪些披薩有放莫扎瑞拉起司?」

2. 考慮重複使用現有本體論 (Consider reusing existing ontologies)

不要重新發明輪子。

  • 披薩案例:這是史丹佛大學的教學案例,所以作為學習者我們應該要從頭做起。但在真實世界中,你可能會引用「食物本體 (Food Ontology) 描述食材,或「計量單位本體論 (Units of Measure Ontology)」描述重量和尺寸。
  • 實作:假設需要描述「辣度」,我們可以引用外部定義好的「辛辣等級」標準,例如大辣、中辣或小辣,而不是自己發明一套。

3. 列出重要術語 (Enumerate important terms)

先撇開階層,把腦中想到的相關詞彙全部倒出來、列舉出來。

  • 清單:Pizza、Base (餅皮)、Topping (配料)、Cheese (起司)、Mozzarella (莫扎瑞拉)、Ham (火腿)、Pepperoni (義大利辣香腸)、Tomato、Spicy、Vegetarian、 American、Italian、Thin and Crispy (薄脆)…
  • 目的:確保沒有遺漏核心概念,這也是未來 Class 和 Property 的候選名單。

4. 定義類別與階層 (Define the classes and the class hierarchy)

這是骨架搭建的過程,通常採用 Top-down (由上而下) 的方法。

  • Top Level (頂層):Thing -> Pizza, PizzaBase, PizzaTopping
    這三個是互斥的 disjoint
  • Drill Down (向下細分):
    • PizzaTopping -> CheeseTopping, MeatTopping, VegetableTopping
    • CheeseTopping -> Mozzarella, Parmesan
    • MeatTopping -> Ham, Pepperoni

注意:確保 Mozzarella is-a CheeseTopping,邏輯必須通順。

5. 定義屬性 (Define the properties of classes – Slots)

類別只是名詞,屬性是讓它們產生關聯的動詞。在 OWL 中分為兩種主要屬性:

  • Object Properties (物件屬性。連接兩個類別):
    • hasTopping 連接 Pizza -> PizzaTopping
    • hasBase 連接 Pizza -> PizzaBase
    • isToppingOf 連接 PizzaTopping -> Pizza,這是 hasTopping 的反向屬性。
  • Data Properties (資料屬性。連接類別與數值):
    • 雖然披薩本體論較少用,但可以想像:hasCaloricValue 是整數,hasPrice 是浮點數。

6. 定義屬性的限制 (Define the facets of the slots)

這是最核心的邏輯定義層,也是讓機器能「推理」的關鍵。

  • Cardinality (數量限制):
    • 一個 Pizza 必須 剛好有 1 個 hasBase (Functional Property)。
  • Value Type (數值類型/範圍限制):
    • Existential (∃ some): Pizza 必須有 至少一個 hasBase 指向 PizzaBase
    • Universal (∀ only): VegetarianPizza hasTopping 必須全部都是 VegetarianTopping (或者是 Cheese/Fruit)。
  • Domain & Range:
    • hasTopping 的 Domain 是 Pizza,因為只有披薩能有配料;Range 是 PizzaTopping,因為配料只能是配料類別。

7. 建立實例 (Create instances)

這一步在披薩案例中有個特殊的陷阱。

  • 常見誤區:不少人以為「瑪格麗特披薩」是一個 Instance (實例)。
  • 本體論觀點:在菜單上,MargheritaPizza 其實是一個 Class (類別),因為它代表「一種」披薩,而不是你盤子上那塊「特定的」披薩。
  • 真正的實例 (Individuals):
    • MyOrder_001 (這是我週五晚上點的那片具體的披薩)。
    • 我們設定 MyOrder_001 MargheritaPizza 的一個 Instance。
    • 機器推理:因為 MyOrder_001 MargheritaPizza,且 MargheritaPizza 被定義為素食,所以推論出 MyOrder_001 也是素食的。

用 Markdown 描述披薩本體

用 Markdown 可以描述概念模型 (Conceptual Model) 與邏輯公理 (Logical Axioms)。


## **1\. 簡介與範圍 (Introduction & Scope)**

### **1.1 目的**
本本體論旨在描述各類披薩、其組成成分(配料、餅皮)以及基於成分的分類規則。其核心目標是支援自動化推理,以判斷披薩的類別(例如:自動識別某披薩是否為素食)。

### **1.2 涵蓋範圍 (Scope)**
* **包含:** 披薩種類、餅皮種類、配料種類(肉類、蔬菜、起司、海鮮)、辛辣程度分類、素食分類。  
* **不包含:** 價格、庫存量、營養成分(熱量、蛋白質)、烹飪時間。

### **1.3 關鍵提問 (Competency Questions)**
本體論構建完成後,必須能回答以下問題:
1. 這款披薩是素食披薩嗎?  
2. 這款披薩屬於辛辣披薩嗎?  
3. 瑪格麗特披薩(Margherita)包含哪些配料?

---

## **2\. 類別階層 (Class Hierarchy / Taxonomy)**

所有類別皆繼承自 `owl:Thing`。以下為主要的分類樹狀結構:
* **DomainConcept** (抽象層)
* **Pizza** (披薩本體)
* `NamedPizza` (如:Margherita, Americana...)
* `VegetarianPizza` (邏輯定義類別)
* `SpicyPizza` (邏輯定義類別)
* **PizzaBase** (餅皮)
* `ThinAndCrispyBase`
* `DeepPanBase`
* **PizzaTopping** (配料)
* `CheeseTopping`
* `MozzarellaTopping`
* `ParmesanTopping`
* `MeatTopping`
* `HamTopping`
* `PepperoniTopping`
* `SpicyBeefTopping`
* `VegetableTopping`
* `TomatoTopping`
* `MushroomTopping`
* `PepperTopping` (甜椒)
* `SeafoodTopping`
* `AnchoviesTopping`
**限制條件 (Disjoint Axioms):** `Pizza`, `PizzaBase`, `PizzaTopping` 彼此為 **Disjoint Classes (不相交)**。即一個實體不可能同時是披薩又是配料。

---

## **3\. 屬性定義 (Property Definitions)**

### **3.1 物件屬性 (Object Properties)**

描述類別之間的關係。
| 屬性名稱 (Label) | 定義域 (Domain) | 值域 (Range) | 特性 (Characteristics) | 描述 |
| :---- | :---- | :---- | :---- | :---- |
| **hasBase** | `Pizza` | `PizzaBase` | Functional | 披薩具有餅皮 |
| **isBaseOf** | `PizzaBase` | `Pizza` | Inverse of `hasBase` | 餅皮屬於披薩 |
| **hasTopping** | `Pizza` | `PizzaTopping` | \- | 披薩具有配料 |
| **isToppingOf** | `PizzaTopping` | `Pizza` | Inverse of `hasTopping` | 配料屬於披薩 |
| **hasIngredient** | `Pizza` | `Thing` | Transitive | 一般性的成分關係 (父屬性) |

### **3.2 資料屬性 (Data Properties)**

描述類別的數值特徵(本範疇較少使用,僅列範例)。
| 屬性名稱 | 定義域 | 值域 (Data Type) | 描述 |
| :---- | :---- | :---- | :---- |
| **hasSpicinessLevel** | `PizzaTopping` | `xsd:integer` | 辣度等級 (0-10) |

---

## **4\. 邏輯公理與限制 (Logical Axioms & Restrictions)**

此部分使用 **Manchester Syntax** 描述,這是讓推理機運作的核心規則。

### **4.1 基礎存在限制 (Existential Restrictions)**

描述一個合法的披薩必須具備的基本條件。
* **Class:** `Pizza`  
* **SubClassOf:** `hasBase` **some** `PizzaBase`  
* *(解釋:每一個披薩都必須至少有一個餅皮)*

### **4.2 定義類別 (Defined Classes / Equivalent Classes)**

這是推理機自動分類的依據。

#### **A. 素食披薩 (VegetarianPizza)**
如何定義什麼是素食披薩?
Class: VegetarianPizza
EquivalentTo:
    Pizza
    AND (hasTopping ONLY (CheeseTopping OR VegetableTopping))
**注意:** 使用 `ONLY` (Universal Quantification) 來確保**除了**起司和蔬菜外,沒有其他類型的配料(如肉類)。

#### **B. 辣味披薩 (SpicyPizza)**
Class: SpicyPizza
EquivalentTo:
    Pizza
    AND (hasTopping SOME (SpicyBeefTopping OR PepperoniTopping))
**注意:** 只要有(SOME)一種配料是辣的,整塊披薩就是辣的。

### **4.3 命名披薩的定義 (Named Pizza Definitions)**
描述具體菜單上的披薩配方。**關鍵在於使用 Closure Axiom(封閉公理)**。

#### **A. 瑪格麗特披薩 (MargheritaPizza)**
Class: MargheritaPizza
SubClassOf:
    Pizza,
    hasTopping SOME MozzarellaTopping,
    hasTopping SOME TomatoTopping,
    hasTopping ONLY (MozzarellaTopping OR TomatoTopping)
**邏輯解析:**
1. 必須有莫扎瑞拉起司 (SOME)。  
2. 必須有番茄 (SOME)。  
3. **封閉公理 (Closure):** 配料**只能是** (ONLY) 莫扎瑞拉或番茄。如果不加這一行,在開放世界假設下,推理機無法確認它是否包含其他隱藏配料。

#### **B. 美式臘腸披薩 (AmericanaPizza)**
Class: AmericanaPizza
SubClassOf:
    Pizza,
    hasTopping SOME PepperoniTopping,
    hasTopping SOME MozzarellaTopping,
    hasTopping SOME TomatoTopping,
    hasTopping ONLY (PepperoniTopping OR MozzarellaTopping OR TomatoTopping)

---

## **5\. 實例範例 (Individuals / Instantiation)**

模擬真實世界的點餐資料。
* **Individual:** `MyOrder_Fri_001`  
* **Types:** `Pizza`  
* **Facts:**  
* `hasBase` \-\> `DeepPanBase_Instance`  
* `hasTopping` \-\> `Mozzarella_Instance`  
* `hasTopping` \-\> `Tomato_Instance`
**預期推理結果 (Expected Reasoning Result):** 當啟動推理機 (如 HermiT) 時,`MyOrder_Fri_001` 應該會被自動歸類為:
1. `MargheritaPizza` (因為成分符合定義)  
2. `VegetarianPizza` (因為成分皆為素食)  
3. **不會**是 `SpicyPizza`

---

## **6\. 版本歷程 (Version History)**
* **v1.0 (2025-09-24):** 初始草案,包含基本階層與素食邏輯定義。  
* **v0.9:** 僅包含類別階層 (Taxonomy),尚未加入屬性限制。

用 Semantic JSON Model 描述披薩本體

將本體論轉換為 JSON 結構,幫助軟體工程師理解如何結構化地儲存與交換「邏輯規則」。

個 JSON 結構完整對應了上述用 Markdown 制定的規格書,並將類別 (Classes)屬性 (Properties) 與邏輯規則(Axioms) 清楚地分開。

{
  "ontology_meta": {
    "uri": "http://www.example.org/ontologies/pizza",
    "version": "1.0",
    "description": "A pizza ontology for learning OWL reasoning."
  },
  
  "schema_definitions": {
    "classes": [
      {
        "id": "Pizza",
        "parent": "Thing",
        "disjoint_with": ["PizzaBase", "PizzaTopping"],
        "description": "The main concept representing a pizza."
      },
      {
        "id": "PizzaBase",
        "parent": "Thing",
        "subclasses": ["ThinAndCrispyBase", "DeepPanBase"],
        "disjoint_with": ["Pizza", "PizzaTopping"]
      },
      {
        "id": "PizzaTopping",
        "parent": "Thing",
        "subclasses": [
          { "id": "CheeseTopping", "subclasses": ["MozzarellaTopping", "ParmesanTopping"] },
          { "id": "MeatTopping", "subclasses": ["HamTopping", "PepperoniTopping"] },
          { "id": "VegetableTopping", "subclasses": ["TomatoTopping", "MushroomTopping"] }
        ],
        "disjoint_with": ["Pizza", "PizzaBase"]
      }
    ],

    "object_properties": [
      {
        "id": "hasBase",
        "domain": "Pizza",
        "range": "PizzaBase",
        "type": "Functional",
        "description": "Every pizza must have exactly one base."
      },
      {
        "id": "hasTopping",
        "domain": "Pizza",
        "range": "PizzaTopping",
        "inverse_of": "isToppingOf",
        "description": "Relationship linking a pizza to its ingredients."
      }
    ]
  },

  "logical_rules": {
    "restrictions": {
      "note": "These rules define the requirements for a valid Pizza instance.",
      "definitions": [
        {
          "class": "Pizza",
          "constraint": {
            "property": "hasBase",
            "quantifier": "some", 
            "target": "PizzaBase"
          }
        }
      ]
    },

    "defined_classes": {
      "note": "Classes defined by logical conditions (Reasoning targets).",
      "definitions": [
        {
          "id": "VegetarianPizza",
          "equivalent_to": {
            "intersection_of": [
              "Pizza",
              {
                "property": "hasTopping",
                "quantifier": "only",
                "target": ["CheeseTopping", "VegetableTopping"],
                "comment": "Universal Quantification (∀): If it has toppings, they must ALL be cheese or veg."
              }
            ]
          }
        },
        {
          "id": "SpicyPizza",
          "equivalent_to": {
            "intersection_of": [
              "Pizza",
              {
                "property": "hasTopping",
                "quantifier": "some",
                "target": ["SpicyBeefTopping", "PepperoniTopping"],
                "comment": "Existential Quantification (∃): At least one topping must be spicy."
              }
            ]
          }
        }
      ]
    },

    "named_pizza_definitions": {
      "note": "Recipes for specific pizzas using Closure Axioms.",
      "definitions": [
        {
          "id": "MargheritaPizza",
          "subclass_of": "Pizza",
          "requirements": [
            { "property": "hasTopping", "quantifier": "some", "target": "MozzarellaTopping" },
            { "property": "hasTopping", "quantifier": "some", "target": "TomatoTopping" }
          ],
          "closure_axiom": {
            "property": "hasTopping",
            "quantifier": "only",
            "target": ["MozzarellaTopping", "TomatoTopping"],
            "comment": "This closes the world. No other toppings are allowed."
          }
        }
      ]
    }
  },

  "individuals_data": [
    {
      "id": "MyOrder_Fri_001",
      "declared_type": "Pizza",
      "relations": {
        "hasBase": "DeepPanBase_Instance_01",
        "hasTopping": [
          "Mozzarella_Instance_01",
          "Tomato_Instance_01"
        ]
      },
      "expected_inference": ["MargheritaPizza", "VegetarianPizza"]
    }
  ]
}

JSON 結構解析:對應本體論概念

這份 JSON 的設計邏輯是為了對應 OWL (Web Ontology Language)。以下說明:

  • schema_definitions (對應 TBox – Terminology Box)
    這是定義詞彙的地方。
    • Nested Subclasses:巢狀結構展示繼承關係 (例如,CheeseTopping PizzaTopping 之下)。
    • Disjoint With:標記 Pizza PizzaTopping 是互斥的,這在資料庫 schema 中很少見,但在本體論中非常重要。
  • logical_rules (邏輯公理)
    模擬推理機的規則。
    • quantifier: "some" (∃): 對應 OWL 的 someValuesFrom。例如 SpicyPizza 的定義中,只要有一個配料是辣的,它就是辣味披薩。
    • quantifier: "only" (∀): 對應 OWL 的 allValuesFrom。例如 VegetarianPizza 的配料集合必須只包含素食類。
  • named_pizza_definitions (封閉公理)
    例如 MargheritaPizza 中的 closure_axiom 欄位。
    • 這模擬了:「除此之外,沒有其他東西了」。
    • 如果沒有這一段 JSON 描述,推理機就無法斷定這是一塊素食披薩,因為它會懷疑「也許還有隱藏的火腿」。
  • individuals_data (對應 ABox – Assertion Box)
    這是實際的資料數據。
    • 我們只宣告它是 Pizza
    • 但透過 expected_inference 欄位,我們預期系統能根據上面的規則,自動把它標記為 VegetarianPizza

結語

學習描述披薩本體,不需要額外專業知識就能理解,很適合當作第一個練習題。在跟 LLM 對話的過程中,它一直要給我 OWL 和 Python 程式碼,但是都被我制止,我還是先從 Markdown 和 JSON 的描述性語言讓你看見這個結構,之後再繼續擴展。

下一篇,我繼續再用另一個範例重新走過這七個步驟,然後再進入 OWL 和 Python。同時,我也會繼續探索 Anthropic Agent Skills 和 Ontology 的組合拳應用模式。

Similar Posts

發表迴響