概念语义学详解

文档概述

本文档系统探讨概念语义学的核心理论体系与计算实现。从Roger Schank的概念依存理论出发,涵盖脚本理论、框架网络、原型理论及概念图等经典模型,阐述概念层面的语义表示方法及其在人工智能中的应用。

关键词速览

术语英文核心定义
概念依存Conceptual Dependency用 primitives 表示概念语义
脚本理论Script Theory典型情境的知识结构
框架Frame刻板情境的概念结构
FrameNetFrameNet框架语义学计算资源
原型Prototype范畴的最佳代表示例
概念图Conceptual Graph概念关系的图形表示
基本层次Basic Level概念分类的核心层级
意象图式Image Schema感知运动经验的抽象
范畴化Categorization将事物归入概念类别
隐喻映射Metaphor Mapping跨域概念转移

一、概念语义学的理论背景

1.1 什么是概念语义学

概念语义学(Conceptual Semantics)研究概念层面的语义表示,关注语言意义背后的认知结构和知识组织方式。

与形式语义学的对比

维度形式语义学概念语义学
研究层面语言表达式心理/认知表征
核心工具逻辑、λ演算概念结构、网络
处理单元句子情境、事件
关注点真值条件概念关系
应用推理验证理解生成

1.2 概念语义学的认知基础

概念语义学建立在认知科学的多项发现之上:

格式塔心理学 整体大于部分之和,概念结构具有系统性组织。

原型效应 某些成员比其他人更能代表其范畴。

基本层次优势 人类在中间层次(“狗”而非”动物”或”金毛”)上分类最快最准。

意象图式 感知运动经验形成的抽象结构,支撑概念组织。


二、概念依存理论(Conceptual Dependency Theory)

2.1 Roger Schank的理论框架

Roger Schank于1970年代提出概念依存理论,旨在建立一种独立于语言的概念表示系统。

2.1.1 核心思想

概念依存(CD)理论的基本假设:

  1. 概念原语:所有概念可分解为有限的基本单元
  2. 动作结构:事件由原语动作和参与者构成
  3. 因果链接:动作之间存在因果关系
  4. 状态变化:概念表示状态及其变化

2.1.2 概念原语分类

原语动作(Primitive Actions)

CD_PRIMITIVES = {
    # 十大原语动作 (Schank & Abelson)
    'PTRANS': '物理传输(物体位置变化)',
    'ATRANS': '属性传输(关系/所有权变化)',
    'MTRANS': '心理传输(信息传递)',
    'MBUILD': '心理构建(形成新观念)',
    'CONC': '关注(心理聚焦)',
    'SPEAK': '说话(产生语言)',
    'GRASP': '抓取(物理接触)',
    'INGEST': '摄入(进入生物体)',
    'EXPEL': '排出(离开生物体)',
    'MOVE': '移动(身体部位运动)',
    
    # 辅助原语
    'PRODUCE': '产生(创造新物体)',
    'CONSUME': '消耗(物体消失)',
    'BE': '存在(状态)',
    'BEHAVIOR': '行为(无特定原语的复杂行为)'
}

原语属性

class ConceptualDependency:
    """
    概念依存表示
    
    核心数据结构:动作 + 参与者 + 属性
    """
    
    def __init__(self, action, actors, objects, attributes=None):
        self.action = action           # 原语动作
        self.actors = actors           # 施事者列表
        self.objects = objects         # 宾语列表
        self.attributes = attributes or {}  # 附加属性
        self.instruments = []         # 工具
        self.source = None            # 起点
        self.goal = None              # 终点
        self.time = None              # 时间
        self.location = None          # 地点
    
    def to_cd_notation(self):
        """转换为CD表示法"""
        parts = [f"({self.action}"]
        
        if self.actors:
            parts.append(f":ACTOR ({self.actors[0]})")
        
        if self.objects:
            parts.append(f":OBJECT ({self.objects[0]})")
        
        for attr, value in self.attributes.items():
            parts.append(f":{attr} ({value})")
        
        parts.append(")")
        return " ".join(parts)
 
# 示例
cd_eat = ConceptualDependency(
    action='INGEST',
    actors=['JOHN'],
    objects=['APPLE'],
    attributes={'FROM': 'HAND', 'TO': 'STOMACH'}
)
print(cd_eat.to_cd_notation())
# 输出: (INGEST :ACTOR (JOHN) :OBJECT (APPLE) :FROM (HAND) :TO (STOMACH))

2.2 概念依存的应用

2.2.1 自然语言理解

概念依存可用于自然语言理解系统:

class CDParser:
    """
    概念依存分析器
    
    将自然语言句子转换为CD表示
    """
    
    def __init__(self):
        self.verb_to_primitive = {
            'give': 'ATRANS',
            'take': 'ATRANS',
            'go': 'PTRANS',
            'move': 'PTRANS',
            'tell': 'MTRANS',
            'say': 'SPEAK',
            'see': 'CONC',
            'think': 'MBUILD',
            'eat': 'INGEST',
            'drink': 'INGEST',
            'walk': 'MOVE',
            'run': 'MOVE'
        }
    
    def parse(self, sentence):
        """
        将句子解析为CD表示
        
        示例: "John gave Mary a book."
        → (ATRANS :ACTOR (JOHN) :OBJECT (BOOK) 
           :FROM (JOHN) :TO (MARY))
        """
        tokens = sentence.lower().split()
        
        # 简化版本:基于关键词映射
        cd_representation = None
        
        # 识别动词和参与者
        for verb, primitive in self.verb_to_primitive.items():
            if verb in tokens:
                cd_representation = self.build_cd(primitive, tokens)
                break
        
        return cd_representation
    
    def build_cd(self, primitive, tokens):
        """构建CD结构"""
        actors = [t for t in tokens if t in ['john', 'mary', 'he', 'she']]
        objects = [t for t in tokens if t in ['book', 'apple', 'money']]
        
        return ConceptualDependency(
            action=primitive,
            actors=actors,
            objects=objects
        )

2.2.2 故事理解

概念依存特别适合表示故事结构:

class StoryAnalyzer:
    """
    基于CD的故事分析
    
    分析事件序列的因果关系
    """
    
    def __init__(self):
        self.events = []
        self.causal_links = []
    
    def analyze_story(self, story_text):
        """分析故事的CD表示和因果结构"""
        # 分句
        sentences = story_text.split('.')
        
        # 解析每个句子为CD
        parser = CDParser()
        for sent in sentences:
            if sent.strip():
                cd = parser.parse(sent.strip())
                if cd:
                    self.events.append(cd)
        
        # 构建因果链
        self.build_causal_links()
        
        return {
            'events': self.events,
            'causal_structure': self.causal_links
        }
    
    def build_causal_links(self):
        """构建事件间的因果链接"""
        # 简化:基于动作类型的因果关系
        for i in range(len(self.events) - 1):
            current = self.events[i]
            next_event = self.events[i + 1]
            
            # 检查因果关系
            if self.has_causal_relation(current, next_event):
                self.causal_links.append((i, i + 1, 'enables'))
    
    def has_causal_relation(self, event1, event2):
        """判断两个事件是否有因果关系"""
        # 简化规则
        enabling_pairs = [
            ('PTRANS', 'GRASP'),   # 移动后可能抓取
            ('MTRANS', 'MBUILD'),  # 信息接收后形成观念
        ]
        return (event1.action, event2.action) in enabling_pairs

三、脚本理论(Script Theory)

3.1 脚本的定义与结构

脚本(Script)是一种表示典型情境的知识结构,包含事件发生的标准序列。

3.1.1 脚本的组成

脚本结构:

┌─────────────────────────────────────────────┐
│ 脚本: 餐厅用餐                              │
├─────────────────────────────────────────────┤
│ 入口条件:                                   │
│   - 顾客饿了                                 │
│   - 顾客有钱                                │
├─────────────────────────────────────────────┤
│ 角色:                                       │
│   - 顾客 (Customer)                         │
│   - 服务员 (Waiter)                         │
│   - 厨师 (Chef)                            │
│   - 收银员 (Cashier)                        │
├─────────────────────────────────────────────┤
│ 道具:                                       │
│   - 桌子、椅子、菜单                        │
│   - 食物、饮料                              │
│   - 账单、收据                              │
├─────────────────────────────────────────────┤
│ 场景序列:                                   │
│   1. 进入餐厅 → 入座                       │
│   2. 看菜单 → 点菜                         │
│   3. 等候 → 上菜                           │
│   4. 吃饭 → 喝茶                           │
│   5. 结账 → 离开                           │
├─────────────────────────────────────────────┤
│ 结果:                                       │
│   - 顾客获得食物和满足感                    │
│   - 餐厅获得收入                            │
└─────────────────────────────────────────────┘

3.2 脚本的表示与实现

class Script:
    """
    脚本知识表示
    
    表示典型情境的标准化事件序列
    """
    
    def __init__(self, name):
        self.name = name
        self.entry_conditions = []      # 入口条件
        self.roles = {}                  # 角色字典
        self.props = []                  # 道具列表
        self.scenes = []                 # 场景序列
        self.results = []                 # 结果
    
    def add_scene(self, scene):
        """添加场景"""
        self.scenes.append(scene)
    
    def is_applicable(self, context):
        """
        检查脚本是否适用于当前情境
        
        检查入口条件是否满足
        """
        for condition in self.entry_conditions:
            if not self.check_condition(condition, context):
                return False, condition
        return True, None
    
    def check_condition(self, condition, context):
        """检查单个条件"""
        return context.satisfies(condition)
    
    def execute(self, context):
        """
        执行脚本
        
        返回执行后的状态变化
        """
        # 检查适用性
        applicable, failed_condition = self.is_applicable(context)
        if not applicable:
            return {'error': 'unmet_condition', 'condition': failed_condition}
        
        # 按顺序执行场景
        execution_trace = []
        for scene in self.scenes:
            result = scene.execute(context)
            execution_trace.append(result)
            
            # 检查是否提前终止
            if result.get('terminal'):
                break
        
        return {
            'script': self.name,
            'execution': execution_trace,
            'final_state': context
        }
 
 
class Scene:
    """
    场景表示
    
    脚本中的单个场景
    """
    
    def __init__(self, name, actions=None):
        self.name = name
        self.actions = actions or []
        self.responses = {}  # 条件响应
    
    def add_action(self, action):
        """添加动作"""
        self.actions.append(action)
    
    def execute(self, context):
        """执行场景"""
        results = []
        for action in self.actions:
            result = action.perform(context)
            results.append(result)
            
            # 条件响应
            for condition, response in self.responses.items():
                if context.satisfies(condition):
                    response.execute(context)
        
        return {
            'scene': self.name,
            'actions': results
        }

3.3 脚本推理

class ScriptReasoner:
    """
    脚本推理器
    
    基于脚本进行理解和推理
    """
    
    def __init__(self):
        self.scripts = {}
        self.context = None
    
    def register_script(self, script):
        """注册脚本"""
        self.scripts[script.name] = script
    
    def understand_action(self, action_sequence):
        """
        理解动作序列
        
        识别匹配的脚本
        """
        best_match = None
        best_score = 0
        
        for name, script in self.scripts.items():
            score = self.match_score(script, action_sequence)
            if score > best_score:
                best_score = score
                best_match = script
        
        return {
            'script': best_match,
            'confidence': best_score,
            'missing_elements': self.find_missing(best_match, action_sequence)
        }
    
    def match_score(self, script, actions):
        """计算脚本与动作序列的匹配分数"""
        if not actions:
            return 0
        
        matched = 0
        for action in actions:
            for scene in script.scenes:
                for script_action in scene.actions:
                    if self.action_similar(action, script_action):
                        matched += 1
                        break
        
        return matched / len(actions)
    
    def action_similar(self, action1, action2):
        """判断两个动作是否相似"""
        # 简化的相似度判断
        return action1.type == action2.type
    
    def predict_next_action(self, script, current_actions):
        """
        预测下一步动作
        
        基于脚本预测可能的下一个动作
        """
        # 找到当前执行的场景位置
        current_scene_index = self.find_scene_position(script, current_actions)
        
        if current_scene_index < len(script.scenes) - 1:
            next_scene = script.scenes[current_scene_index + 1]
            return {
                'predicted_scene': next_scene.name,
                'possible_actions': [a.description for a in next_scene.actions]
            }
        
        return {'end_of_script': True}
    
    def find_scene_position(self, script, actions):
        """找到当前动作在脚本中的位置"""
        # 简化:返回已匹配场景的数量
        return min(len(script.scenes) - 1, len(actions) // 2)

3.4 脚本理论的局限性

  1. 情境变化:现实情境往往偏离脚本
  2. 文化差异:不同文化的脚本不同
  3. 动态更新:脚本需要适应新情境
  4. 层级嵌套:简单脚本难以处理复杂嵌套

四、框架网络(FrameNet)

4.1 框架语义学回顾

框架语义学(Frame Semantics)由Charles Fillmore提出,认为理解词义需要激活相关概念框架。

4.1.1 框架的定义

框架是关于某种情境的概念结构,包含该情境中的参与者和属性:

商业交易框架 (Commerce_buy):

参与者角色:
├── Buyer (买方): 购买商品的主体
├── Seller (卖方): 出售商品的主体
├── Goods (商品): 被购买的物品
├── Money (货币): 支付的对价
└── Theme (主题): 交易的焦点

框架元素:
├── 触发词: buy, purchase, acquire, shop for...
├── 必需角色: Buyer, Goods, Seller
└── 可选角色: Money, Time, Location

4.2 FrameNet项目

FrameNet是框架语义学的计算实现:

class FrameNetResource:
    """
    FrameNet资源
    
    提供框架语义学的标注数据
    """
    
    def __init__(self):
        self.frames = {}
        self.lexical_units = {}
    
    def load_frame(self, frame_name):
        """加载框架定义"""
        # FrameNet包含1000+框架
        # 每个框架包含:
        # - 框架定义
        # - 框架元素定义
        # - 词汇单元
        pass
    
    def find_frame(self, word):
        """查找词激活的框架"""
        return self.lexical_units.get(word.lower(), [])
    
    def get_frame_elements(self, frame_name):
        """获取框架的元素定义"""
        frame = self.frames.get(frame_name)
        return frame.elements if frame else []
    
    def annotate_sentence(self, sentence):
        """
        句子标注
        
        识别框架和框架元素
        """
        annotations = []
        tokens = sentence.split()
        
        for token in tokens:
            frames = self.find_frame(token)
            for frame in frames:
                annotation = {
                    'token': token,
                    'frame': frame.name,
                    'elements': self.extract_elements(sentence, frame)
                }
                annotations.append(annotation)
        
        return annotations
 
 
# 示例:餐厅场景框架
restaurant_frames = {
    'Restaurant_generic': {
        'definition': 'Generic frame for restaurant scenarios',
        'core_elements': {
            'Customer': 'Person who orders food',
            'Server': 'Person who serves food',
            'Food': 'Food being ordered/consumed'
        },
        'non_core_elements': {
            'Time': 'When the event occurs',
            'Location': 'Where the restaurant is'
        },
        'lexical_units': [
            'dine.v', 'eat.v', 'order.v', 'pay.v', 
            'restaurant.n', 'waiter.n', 'menu.n'
        ]
    }
}

4.3 基于框架的理解系统

class FrameBasedUnderstanding:
    """
    基于框架的自然语言理解
    
    使用框架进行语义分析
    """
    
    def __init__(self, frame_repository):
        self.frames = frame_repository
    
    def understand(self, utterance):
        """
        理解话语
        
        流程:
        1. 词法分析 → 识别触发词
        2. 框架激活 → 选择合适框架
        3. 元素填充 → 从句子提取框架元素
        4. 推理验证 → 检验情境一致性
        """
        # 1. 触发词识别
        triggers = self.identify_triggers(utterance)
        
        # 2. 框架选择
        selected_frames = []
        for trigger in triggers:
            frames = self.frames.find_frame(trigger)
            selected_frames.extend(frames)
        
        # 3. 元素填充
        interpretations = []
        for frame in selected_frames:
            elements = self.fill_elements(frame, utterance)
            interpretations.append({
                'frame': frame,
                'elements': elements,
                'confidence': self.compute_confidence(frame, elements)
            })
        
        # 4. 选择最佳解释
        best = max(interpretations, key=lambda x: x['confidence'])
        
        return best
    
    def identify_triggers(self, text):
        """识别框架触发词"""
        triggers = []
        for word in text.lower().split():
            if self.frames.is_trigger(word):
                triggers.append(word)
        return triggers
    
    def fill_elements(self, frame, text):
        """填充框架元素"""
        elements = {}
        
        # 根据框架类型选择填充策略
        if frame.type == 'Commerce':
            elements = self.fill_commerce_elements(frame, text)
        elif frame.type == 'Motion':
            elements = self.fill_motion_elements(frame, text)
        # ... 其他框架类型
        
        return elements
    
    def fill_commerce_elements(self, frame, text):
        """填充商业框架元素"""
        elements = {}
        
        # 提取买方
        buyer_patterns = ['I', 'customer', 'buyer', 'he', 'she', 'we']
        for pattern in buyer_patterns:
            if pattern in text:
                elements['Buyer'] = pattern
                break
        
        # 提取卖方
        seller_patterns = ['store', 'seller', 'shop', 'vendor']
        for pattern in seller_patterns:
            if pattern in text:
                elements['Seller'] = pattern
                break
        
        # 提取商品
        goods_patterns = ['buy', 'purchase', 'get']
        if any(p in text for p in goods_patterns):
            elements['Goods'] = self.extract_goods(text)
        
        return elements

五、原型理论(Prototype Theory)

5.1 Eleanor Rosch的原型研究

Eleanor Rosch在1970年代提出原型理论,挑战了经典的范畴观。

5.1.1 经典范畴观 vs 原型范畴观

经典范畴观

  • 范畴由充分必要条件定义
  • 范畴边界清晰
  • 所有成员地位平等

原型范畴观

  • 范畴围绕原型组织
  • 范畴边界模糊
  • 成员有典型性差异
经典范畴观:              原型范畴观:

      成员 / 非成员           核心(原型) ←→ 边缘(非典型)
        ↓                      ↓
    ┌────────┐            ┌─────────────────┐
    │Member  │            │  ● ● ● ● ●     │
    │Member  │    vs     │   ● ● ●       │
    │Member  │            │      ● ● ●    │
    └────────┘            └─────────────────┘
    (清晰边界)            (模糊边界,梯度分布)

5.1.2 原型效应

基本层次效应

class BasicLevelAnalyzer:
    """
    基本层次分析
    
    识别概念分类的基本层次
    """
    
    def __init__(self):
        self.ontology = {}
    
    def analyze_basic_level(self, concept):
        """
        分析概念的基本层次
        
        基本层次特征:
        - 感知信息最丰富 (形状意象)
        - 行为反应最一致 (运动原型)
        - 认知效率最高 (最短分类时间)
        - 跨文化一致性最强
        """
        # 在概念层次树中找到基本层次
        ancestors = self.get_ancestors(concept)
        descendants = self.get_descendants(concept)
        
        # 基本层次通常是中间的、拥有丰富感知特征的层次
        if ancestors and descendants:
            return {
                'concept': concept,
                'level': 'basic',
                'parent': ancestors[0],  # 上位层次
                'children': descendants   # 下位层次
            }
        elif ancestors:
            return {'concept': concept, 'level': 'superordinate'}
        else:
            return {'concept': concept, 'level': 'subordinate'}
    
    def get_ancestors(self, concept):
        """获取上位概念"""
        return self.ontology.get(concept, {}).get('ancestors', [])
    
    def get_descendants(self, concept):
        """获取下位概念"""
        return self.ontology.get(concept, {}).get('descendants', [])

5.2 原型表示

class PrototypeRepresentation:
    """
    原型表示
    
    使用特征向量表示原型
    """
    
    def __init__(self, category, features):
        self.category = category
        self.features = features  # 特征值字典
        self.typicality_scores = {}  # 各成员典型性
    
    def compute_typicality(self, instance, feature_weights=None):
        """
        计算实例的典型性得分
        
        与原型的相似度
        """
        if feature_weights is None:
            feature_weights = {f: 1.0 for f in self.features}
        
        similarity = 0
        total_weight = 0
        
        for feature, prototype_value in self.features.items():
            instance_value = instance.get(feature)
            weight = feature_weights.get(feature, 1.0)
            
            # 计算特征相似度
            feature_sim = self.feature_similarity(prototype_value, instance_value)
            
            similarity += weight * feature_sim
            total_weight += weight
        
        return similarity / total_weight if total_weight > 0 else 0
    
    def feature_similarity(self, val1, val2):
        """计算特征级相似度"""
        if isinstance(val1, (int, float)) and isinstance(val2, (int, float)):
            # 数值特征:归一化差异
            return 1 - abs(val1 - val2)
        elif isinstance(val1, list) and isinstance(val2, list):
            # 集合特征:Jaccard相似度
            intersection = len(set(val1) & set(val2))
            union = len(set(val1) | set(val2))
            return intersection / union if union > 0 else 0
        else:
            # 标称特征:相等为1,不等为0
            return 1 if val1 == val2 else 0
 
 
# 示例:鸟类原型
bird_prototype = PrototypeRepresentation(
    category='鸟',
    features={
        'has_feathers': 1.0,      # 羽毛
        'has_wings': 1.0,         # 翅膀
        'can_fly': 0.8,           # 能飞
        'has_beak': 1.0,          # 喙
        'lays_eggs': 1.0,         # 卵生
        'size': 'small',          # 体型小
        'migrates': 0.5           # 迁徙
    }
)
 
# 计算典型性
sparrow = {'has_feathers': 1, 'has_wings': 1, 'can_fly': 1, 
           'has_beak': 1, 'lays_eggs': 1, 'size': 'small', 'migrates': 0.3}
penguin = {'has_feathers': 1, 'has_wings': 0.3, 'can_fly': 0, 
           'has_beak': 1, 'lays_eggs': 1, 'size': 'medium', 'migrates': 1}
 
print(f"麻雀典型性: {bird_prototype.compute_typicality(sparrow):.3f}")
print(f"企鹅典型性: {bird_prototype.compute_typicality(penguin):.3f}")
# 麻雀典型性 > 企鹅典型性

5.3 原型理论的应用

5.3.1 范畴化决策

class PrototypeBasedCategorization:
    """
    基于原型的范畴化
    
    使用原型进行分类决策
    """
    
    def __init__(self):
        self.categories = {}
    
    def add_category(self, name, prototype):
        """添加类别及其原型"""
        self.categories[name] = prototype
    
    def categorize(self, instance):
        """
        将实例分类到最近的类别
        
        基于与各类原型的相似度
        """
        best_category = None
        best_typicality = -1
        
        for category_name, prototype in self.categories.items():
            typicality = prototype.compute_typicality(instance)
            
            if typicality > best_typicality:
                best_typicality = typicality
                best_category = category_name
        
        return {
            'category': best_category,
            'typicality': best_typicality,
            'all_scores': {
                name: proto.compute_typicality(instance) 
                for name, proto in self.categories.items()
            }
        }
    
    def graded_membership(self, instance, category):
        """
        渐进成员资格
        
        返回实例属于某类别的程度(0-1)
        """
        prototype = self.categories[category]
        return prototype.compute_typicality(instance)

5.3.2 语义相似度计算

class PrototypeSimilarity:
    """
    基于原型的语义相似度
    
    利用原型结构计算词语相似度
    """
    
    def __init__(self, prototype_repository):
        self.prototypes = prototype_repository
    
    def similarity(self, word1, word2):
        """
        计算两词的语义相似度
        
        基于特征重叠和原型距离
        """
        proto1 = self.prototypes.get(word1)
        proto2 = self.prototypes.get(word2)
        
        if not proto1 or not proto2:
            return 0.0
        
        # 特征重叠度
        common_features = set(proto1.features.keys()) & set(proto2.features.keys())
        
        if not common_features:
            return 0.0
        
        # 计算特征级相似度
        feature_sims = []
        for feature in common_features:
            sim = self.feature_similarity(
                proto1.features[feature],
                proto2.features[feature]
            )
            feature_sims.append(sim)
        
        return sum(feature_sims) / len(feature_sims)

六、概念图(Conceptual Graphs)

6.1 Sowa的概念图

John Sowa于1984年提出概念图,作为知识表示的形式系统。

6.1.1 概念图的基本结构

概念图是二分有向图:

  • 概念节点:表示实体、动作、属性
  • 关系节点:表示概念间的关系
概念图示例: "John gives Mary a book"

        ┌─────────┐
        │ Agent:  │
        │  John   │
        └────┬────┘
             │
             ↓
        ┌─────────┐
        │ Action: │
        │  GIVE   │
        └────┬────┘
        ┌────┴────┐
        ↓         ↓
   ┌────────┐ ┌────────┐
   │Recipient│ │ Object │
   │  Mary  │ │  Book  │
   └────────┘ └────────┘

6.2 概念图的表示与操作

class ConceptualGraph:
    """
    概念图
    
    Sowa概念图的Python实现
    """
    
    def __init__(self):
        self.concepts = {}  # 概念节点
        self.relations = []  # 关系节点和边
        self.next_id = 0
    
    def add_concept(self, concept_type, instance=None):
        """添加概念节点"""
        node_id = f"C{self.next_id}"
        self.next_id += 1
        
        self.concepts[node_id] = {
            'type': concept_type,
            'instance': instance,
            'attributes': {}
        }
        
        return node_id
    
    def add_relation(self, relation_type, source, targets):
        """
        添加关系节点
        
        Args:
            relation_type: 关系类型 (AGENT, THEME, etc.)
            source: 源概念节点ID
            targets: 目标概念节点ID列表
        """
        node_id = f"R{self.next_id}"
        self.next_id += 1
        
        self.relations.append({
            'id': node_id,
            'type': relation_type,
            'source': source,
            'targets': targets
        })
        
        return node_id
    
    def to_graphviz(self):
        """导出为Graphviz格式"""
        lines = ["digraph ConceptualGraph {"]
        
        for node_id, concept in self.concepts.items():
            label = f"{concept['type']}"
            if concept['instance']:
                label += f": {concept['instance']}"
            lines.append(f'  {node_id} [label="{label}", shape=box];')
        
        for rel in self.relations:
            for target in rel['targets']:
                lines.append(f'  {rel["source"]} -> {target} [label="{rel["type"]}"];')
        
        lines.append("}")
        return "\n".join(lines)
    
    def to_cgif(self):
        """
        导出为CGIF格式
        
        概念图交换格式
        """
        lines = []
        
        # 概念
        for node_id, concept in self.concepts.items():
            instance = concept['instance'] or '*'
            lines.append(f"[{node_id} {concept['type']}: {instance}]")
        
        # 关系
        for rel in self.relations:
            targets_str = " ".join(rel['targets'])
            lines.append(f"[{rel['id']} {rel['type']} -> {targets_str}]")
        
        return "\n".join(lines)
 
 
def create_giving_graph():
    """创建"John给Mary一本书"的概念图"""
    cg = ConceptualGraph()
    
    # 添加概念
    john = cg.add_concept('Person', 'John')
    mary = cg.add_concept('Person', 'Mary')
    book = cg.add_concept('Book', 'book')
    give_action = cg.add_concept('Give')
    
    # 添加关系
    cg.add_relation('Agent', give_action, [john])
    cg.add_relation('Recipient', give_action, [mary])
    cg.add_relation('Theme', give_action, [book])
    
    return cg
 
# 使用示例
cg = create_giving_graph()
print(cg.to_cgif())
# 输出:
# [C0 Person: John]
# [C1 Person: Mary]
# [C2 Book: book]
# [C3 Give]
# [R0 Agent -> C3 C0]
# [R1 Recipient -> C3 C1]
# [R2 Theme -> C3 C2]

6.3 概念图推理

class ConceptualGraphReasoner:
    """
    概念图推理器
    
    基于概念图进行逻辑推理
    """
    
    def __init__(self):
        self.graphs = []
    
    def add_graph(self, cg):
        """添加概念图"""
        self.graphs.append(cg)
    
    def join(self, cg1, cg2):
        """
        连接两个概念图
        
        通过匹配相同概念
        """
        # 查找匹配的概念
        matches = self.find_matching_concepts(cg1, cg2)
        
        if not matches:
            return None
        
        # 合并图
        merged = self.merge_graphs(cg1, cg2, matches)
        return merged
    
    def find_matching_concepts(self, cg1, cg2):
        """查找可匹配的概念"""
        matches = []
        
        for id1, concept1 in cg1.concepts.items():
            for id2, concept2 in cg2.concepts.items():
                if self.concepts_match(concept1, concept2):
                    matches.append((id1, id2))
        
        return matches
    
    def concepts_match(self, c1, c2):
        """判断两概念是否匹配"""
        # 类型匹配
        if c1['type'] != c2['type']:
            return False
        
        # 实例匹配(如果都有实例)
        if c1['instance'] and c2['instance']:
            return c1['instance'] == c2['instance']
        
        return True
    
    def merge_graphs(self, cg1, cg2, matches):
        """合并两个概念图"""
        merged = ConceptualGraph()
        
        # 复制第一个图
        merged.concepts = cg1.concepts.copy()
        merged.relations = cg1.relations.copy()
        merged.next_id = max(
            int(n[1:]) for n in list(merged.concepts.keys()) + ['R0']
        ) + 1
        
        # 添加第二个图的概念(不重复的)
        matched_ids1 = {m[0] for m in matches}
        for id2, concept2 in cg2.concepts.items():
            if id2 not in matched_ids1:
                new_id = merged.add_concept(concept2['type'], concept2['instance'])
                # 记录ID映射
        
        # 添加第二个图的关系
        for rel in cg2.relations:
            merged.relations.append(rel.copy())
        
        return merged
    
    def project(self, cg, target_type):
        """
        投影
        
        提取特定类型的概念
        """
        projected = ConceptualGraph()
        
        for node_id, concept in cg.concepts.items():
            if concept['type'] == target_type:
                projected.add_concept(concept['type'], concept['instance'])
        
        return projected

6.4 概念图与一阶逻辑

概念图与一阶逻辑有对应关系:

def cg_to_fol(cg):
    """
    将概念图转换为一阶逻辑
    
    对应规则:
    - 概念 → 常量或变量
    - 关系 → 谓词
    - 图结构 → 合取式
    """
    formulas = []
    
    # 概念表示
    for node_id, concept in cg.concepts.items():
        if concept['instance']:
            # 实例概念 → 常量
            formulas.append(f"{concept['type']}({concept['instance']})")
        else:
            # 类型概念 → 变量
            formulas.append(f"{concept['type']}(x_{node_id})")
    
    # 关系表示
    for rel in cg.relations:
        # 简化版本
        rel_predicate = rel['type'].lower()
        args = [rel['source']]
        args.extend(rel['targets'])
        formulas.append(f"{rel_predicate}({', '.join(args)})")
    
    return " ∧ ".join(formulas)

七、概念语义学的现代发展

7.1 认知语言学视角

概念隐喻理论(Lakoff & Johnson)

class ConceptualMetaphorTheory:
    """
    概念隐喻理论
    
    隐喻是跨域的概念映射
    """
    
    def __init__(self):
        self.mappings = {}
    
    def add_metaphor(self, source_domain, target_domain, mappings):
        """
        添加隐喻映射
        
        例如: 隐喻 "ARGUMENT IS WAR"
        - 源域(战争): 攻击、防守、输赢
        - 目标域(争论): 批评、辩护、成败
        """
        key = f"{source_domain}_IS_{target_domain}"
        self.mappings[key] = {
            'source': source_domain,
            'target': target_domain,
            'mappings': mappings
        }
    
    def map_concept(self, metaphor, source_concept):
        """
        跨域映射概念
        
        从源域映射到目标域
        """
        meta = self.mappings.get(metaphor)
        if not meta:
            return None
        
        for mapping in meta['mappings']:
            if mapping['source'] == source_concept:
                return mapping['target']
        
        return None
 
 
# 示例隐喻
cmt = ConceptualMetaphorTheory()
cmt.add_metaphor(
    source_domain='Time',
    target_domain='Money',
    mappings=[
        {'source': 'spending', 'target': 'spending'},
        {'source': 'saving', 'target': 'saving'},
        {'source': 'wasting', 'target': 'wasting'}
    ]
)

7.2 与深度学习的融合

现代NLP中,概念语义学的思想与深度学习融合:

class NeuroSymbolicConceptual:
    """
    神经符号概念系统
    
    结合神经网络与概念结构
    """
    
    def __init__(self):
        self.embedder = None  # 神经网络嵌入器
        self.concept_graph = None  # 概念图
    
    def align_embeddings_to_concepts(self, embeddings, concepts):
        """
        将词嵌入与概念结构对齐
        
        使嵌入空间反映概念关系
        """
        # 目标函数
        # 1. 保持语义相似性
        # 2. 保持概念层级关系
        # 3. 保持原型效应
        pass
    
    def use_concepts_to_guide_generation(self, concept_sequence):
        """
        使用概念结构引导文本生成
        
        确保生成内容符合概念语义
        """
        pass

参考文献与推荐阅读

  1. Schank, R. C., & Abelson, R. P. (1977). Scripts, Plans, Goals, and Understanding. Lawrence Erlbaum.
  2. Fillmore, C. J. (1976). Frame semantics and the nature of language. Annals of the New York Academy of Sciences, 280(1), 20-32.
  3. Lakoff, G., & Johnson, M. (1980). Metaphors We Live By. University of Chicago Press.
  4. Rosch, E. (1975). Cognitive representations of semantic categories. Journal of Experimental Psychology: General, 104(3), 192-233.
  5. Sowa, J. F. (1984). Conceptual Structures: Information Processing in Mind and Machine. Addison-Wesley.
  6. Minsky, M. (1974). A framework for representing knowledge. MIT AI Laboratory Memo.

关联文档