认知架构实战与CLARION:构建类人智能的计算框架

关键词

序号关键词英文对照
1认知架构Cognitive Architecture
2ACT-RAdaptive Control of Thought-Rational
3SOARState, Operator, And Result
4CLARIONConnectionist Learning with Adaptive Rule Induction On-line
5物理符号系统Physical Symbol System
6双重过程Dual Process Theory
7SPAUNSemantic Pointer Architecture Unified Network
8神经符号AINeuro-symbolic AI

一、什么是认知架构?

1.1 认知架构的定义

认知架构(Cognitive Architecture)是一个试图统一解释人类认知的计算框架。它不是某个具体的算法或模型,而是一整套关于”认知是如何工作的”核心假设和组件体系。

打个比方,如果你要建造一栋智能建筑,你需要的不只是砖头和水泥,而是一个完整的设计蓝图——包括地基、结构、管线、电路、通风系统等。认知架构就是这个蓝图的AI版本,它规定了:

  • 认知系统由哪些基本组件构成
  • 这些组件之间如何交互
  • 信息是如何表示和加工的
  • 学习是如何发生的
  • 行为是如何选择的

好的认知架构应该具备三个特征:

  1. 完整性:能解释认知的各个方面(感知、记忆、注意、推理、行动等)
  2. 一致性:各组件之间逻辑自洽,不存在矛盾
  3. 可计算性:能用数学/计算语言精确描述,可以实现为程序

1.2 为什么需要认知架构?

现在的深度学习系统其实挺”碎片化”的——搞视觉的、搞NLP的、搞强化学习的,各玩各的。一个图片识别模型和一个对话模型,虽然底层都是神经网络,但它们基本上是”独立进化”的,彼此之间没什么交流。

认知架构想要做的事,就是把这些碎片整合起来,构建一个统一的智能系统。这不是简单的模型堆叠,而是要解决一些根本性的问题:

  • 知识表示的统一:视觉信息、语言知识、动作技能,这些不同类型的知识能否用同一种形式表示?
  • 跨任务迁移:在一个任务上学到的东西,能否帮助完成另一个任务?
  • 持续学习:如何在不忘记旧知识的情况下学习新知识?
  • 可解释性:系统的决策过程能否被理解?

1.3 认知架构的理论基础

认知架构的发展汲取了多个学科的营养:

认知架构的理论来源:
│
├── 心理学
│   ├── 认知心理学(信息加工理论)
│   ├── 发展心理学(皮亚杰的认知发展阶段)
│   └── 神经心理学(大脑功能分区)
│
├── 计算机科学
│   ├── 人工智能(知识表示、推理)
│   ├── 机器学习(统计学习、深度学习)
│   └── 软件工程(模块化、架构设计)
│
├── 语言学
│   ├── 生成语法(乔姆斯基)
│   ├── 认知语言学( Lakoff, Langacker)
│   └── 话语分析
│
└── 哲学
    ├── 心灵哲学(心物问题、意识)
    ├── 现象学(具身认知)
    └── 认知科学哲学

正是这种跨学科的特性,让认知架构成为理解智能的一个独特视角。

二、300年认知架构简史

2.1 前身:从哲学思辨到实验科学

认知架构的思想渊源可以追溯到18世纪的哲学传统:

莱布尼茨的”心灵计算”思想:莱布尼茨提出了一个惊人预见——思维可以被计算。他设想了”通用特征”的符号系统,能够表达任何知识并进行逻辑推理。这比图灵机早了两百多年!

赫尔姆霍兹的”无意识推理”:19世纪的赫尔姆霍茨提出,感知不是被动的接收,而是一个主动的推理过程。大脑根据已有知识,对感官输入进行”无意识的推断”。这个观点至今仍是计算感知研究的核心。

20世纪初的行为主义:华生等人开创了行为主义,主张只研究可观察的行为,不研究内在心理过程。这为后来的认知革命埋下了伏笔。

2.2 符号主义时代(1956-1980s)

1956年被认为是”人工智能元年”,那一年达特茅斯会议召开,符号AI正式诞生。

物理符号系统假说

Newell和Simon提出了一个影响深远的假说:

物理符号系统具有产生智能行为的必要和充分手段。

简单来说,这个假说认为:智能等于符号操作。任何能进行符号操作的系统(不管是人类大脑还是计算机)都能表现出智能。

这一时期的代表成就:

  • ELIZA(1966):最早的聊天机器人,用模式匹配模拟心理治疗师
  • SHRDLU(1970):Winograd开发的对话系统,能理解积木世界的命令
  • 专家系统(1970s-80s):MYCIN、XCON等系统在医疗、配置等领域取得成功

局限性:纯粹的符号系统遇到了”符号接地”问题——符号如何与真实世界对应?如何处理模糊性和不确定性?

2.3 连接主义革命(1980s-2000s)

1986年Rumelhart和McClelland发表《并行分布处理》,掀起了连接主义(Connectionism)的浪潮。

连接主义的核心观点:

  • 知识不是存储在单个节点,而是分布式存储在整个网络中
  • 概念通过激活模式来表示,而非离散符号
  • 学习通过调整连接权重实现,而非显式编程

代表性工作

  • Hopfield网络(1982):联想记忆模型
  • 反向传播(1986):训练多层网络的关键算法
  • LeNet(1989):早期的手写数字识别卷积神经网络
  • LSTM(1997):处理序列数据的长短期记忆网络

局限性:连接主义擅长模式识别,但在逻辑推理、符号操作方面表现不佳。

2.4 混合系统时代(2000s-至今)

新世纪见证了符号主义和连接主义走向融合的趋势:

认知架构的兴起

  • ACT-R(1980s至今):最成熟的认知架构,符号+子符号混合
  • SOAR(1980s至今):通用问题求解器
  • CLARION(1990s至今):强调显式/隐式知识区分
  • NARS(1990s至今):基于概率逻辑的统一智能系统
  • SPAUN(2012):能完成多种认知任务的脑模拟器

深度学习时代

  • 注意力机制(2014):Transformer的前身
  • Transformer(2017):彻底改变了NLP
  • 大型语言模型(2018至今):GPT系列、Claude等

三、ACT-R:最成熟的认知架构

3.1 ACT-R概述

ACT-R(Adaptive Control of Thought-Rational)是目前最成功、最有影响力的认知架构之一。它由卡内基梅隆大学的John Anderson教授开发,从1981年的第一个版本发展到今天的ACT-R 7。

ACT-R的名字本身就揭示了它的核心思想:

  • Adaptive:系统能适应不同任务和环境
  • Control:强调认知控制的重要性
  • Thought:高层次的思维过程
  • Rational:遵循”工具式学习”(Instrumental Learning)原则,最大化期望收益

ACT-R最厉害的地方在于,它不仅是一个理论框架,而且跟大量的人类行为实验数据进行了严格比对。换句话说,它不只是在”猜”大脑是怎么工作的,而是在预测人类的反应时间、错误率等行为指标。

3.2 ACT-R的核心组件

ACT-R是一个高度模块化的系统:

┌─────────────────────────────────────────────────┐
│                 目标模块 (Goal)                  │
│         当前任务目标、意图、状态监控              │
└─────────────────────────────────────────────────┘
                         ↓
┌─────────────────────────────────────────────────┐
│              视觉/听觉模块                        │
│         感知输入、注意力焦点                      │
└─────────────────────────────────────────────────┘
          ↓                        ↓
┌────────────────────┐    ┌────────────────────┐
│   陈述性记忆模块    │    │   程序性记忆模块    │
│   (Declarative)    │    │   (Procedural)     │
│   - 事实知识       │    │   - 技能规则       │
│   - Chunks         │    │   - Productions    │
└────────────────────┘    └────────────────────┘
          ↓                        ↓
┌─────────────────────────────────────────────────┐
│                 影像模块                          │
│         空间表征、心理模拟                         │
└─────────────────────────────────────────────────┘

陈述性记忆(Declarative Memory)

  • 存储”知道什么”类型的知识
  • 基本单元是 Chunk,类似于一个小型数据结构
  • Chunk之间通过联想链接连接,形成语义网络
; ACT-R中Chunk的示例
(chunk-type dog name species color breed)
; 定义一个"狗"的Chunk类型
 
(add-dm 
  (fido ISA dog 
     name Fido 
     species canine 
     color brown 
     breed golden-retriever)
  (fluffy ISA dog 
     name Fluffy 
     species feline 
     color white
     breed persian))
; 向工作记忆添加具体的Chunk实例

程序性记忆(Procedural Memory)

  • 存储”知道如何做”类型的知识
  • 基本单元是 Production(产生式规则)
  • 规则形式:IF 条件 THEN 动作
; ACT-R中Production的示例
(P check-if-dog
  ; 条件部分
  =goal>
     ISA dog-query
     species nil
  ?visual>
     state free
==>
  ; 动作部分
  +visual>
     cmd attend
     screen-pos first
  =goal>
     species canine
)
; 如果目标是查询狗的种类,且视觉系统空闲,
; 则将注意力转向屏幕上的第一个对象

工作记忆(Working Memory)

  • 当前激活的Chunks和状态
  • 容量有限,大约3-5个Chunks
  • 负责各模块之间的信息传递

视觉/听觉模块

  • 处理感知输入
  • 实现注意力机制(选择性地处理某些信息)

目标模块

  • 维护当前任务目标
  • 控制任务执行流程

3.3 ACT-R与神经科学的对应

ACT-R不仅跟行为数据匹配,还跟神经影像学研究对应:

ACT-R模块大脑区域功能
陈述性记忆海马体 + 颞叶皮层事实记忆、情景记忆
程序性记忆基底神经节 + 小脑技能学习、习惯形成
目标模块前额叶皮层规划、决策、执行控制
视觉模块枕叶皮层 + 顶叶视觉处理、空间注意
听觉模块颞叶语音处理、音乐感知
影像模块顶叶皮层空间表征、心象

这种对应不是偶然的——Anderson在设计ACT-R时,有意识地参考了神经科学的发现。ACT-R被称为”计算认知神经科学”的代表,就是这个原因。

3.4 用ACT-R模拟词汇检索实验

认知心理学中有一个经典实验范式——词汇检索(Word Naming)。实验者给被试一个提示词,要求他说出相关词(比如看到”面包”,说”黄油”)。这个实验可以用来研究语义记忆中词语之间的关联强度。

"""
使用ACT-R模拟词汇检索实验
基于ACT-R 7的Python接口(PyActR)
 
实验设计:
- 给被试呈现线索词(如"bread")
- 被试需要检索目标词(如"butter")
- 记录反应时间(RT)
- 比较不同关联强度条件下的RT差异
 
假设:
- 高关联词对检索更快
- 关联强度通过激活扩散(Spreading Activation)实现
"""
 
from pyactr import *
 
class WordRetrievalSimulation(ACTR):
    """词汇检索任务的认知模拟"""
    
    def __init__(self, word_pairs):
        super().__init__()
        self.word_pairs = word_pairs
        
        # 目标模块:维护当前检索任务
        self.goal = Buffer()
        
        # 视觉模块:处理输入词
        self.visual = VisualSearchEffort()
        
        # 陈述性记忆
        self.declarativememory = DeclarativeMemory(
            latency_factor=0.045,  # 检索延迟因子
            maximum_activation=1.0,
            activation_noise=0.04  # 激活噪声
        )
        
        # 程序性记忆:检索规则
        self.productiongroups = SEMANTICNETWORK()
        self.productions = self._create_retrieval_rules()
    
    def _create_retrieval_rules(self):
        """创建检索产生式规则"""
        return [
            # 规则1:看到线索词,开始检索
            {
                "condition": lambda self: (
                    self.goal.chunk_type == "retrieve" and
                    self.goal.cue is not None and
                    self.goal.retrieved is None
                ),
                "action": lambda self: self.declarativememory.request(
                    lambda x: x.cue == self.goal.cue
                )
            },
            # 规则2:检索成功,输出目标词
            {
                "condition": lambda self: (
                    self.goal.chunk_type == "retrieve" and
                    self.goal.retrieved is not None
                ),
                "action": lambda self: self._emit_response(self.goal.retrieved)
            },
        ]
    
    def _emit_response(self, word):
        """模拟语音输出"""
        # 记录反应时间
        self.response_time = self.simulation_time - self.start_time
        self.response = word
    
    def setup_memory(self, association_strengths):
        """
        设置词汇记忆及其关联强度
        
        association_strengths: dict
            键为(cue, target)元组
            值为关联强度(0-1)
        """
        for (cue, target), strength in association_strengths.items():
            # 创建词汇Chunk
            self.declarativememory.add(
                Chunk(
                    chunk_type="word",
                    name=target,
                    meaning=f"word:{target}",
                    activation=1.0
                )
            )
            
            # 创建关联
            # 关联强度影响激活扩散的速度
            if strength > 0:
                self.declarativememory.add(
                    Chunk(
                        chunk_type="association",
                        cue=cue,
                        target=target,
                        strength=strength,
                        activation=strength
                    )
                )
 
 
def run_experiment():
    """运行词汇检索实验模拟"""
    
    # 实验材料:高关联 vs 低关联词对
    word_pairs = {
        "high_association": [
            ("bread", "butter"),
            ("doctor", "nurse"),
            ("salt", "pepper"),
            ("hammer", "nail"),
        ],
        "low_association": [
            ("bread", "chair"),
            ("doctor", "river"),
            ("salt", "window"),
            ("hammer", "cloud"),
        ]
    }
    
    # 设置关联强度
    high_strengths = {pair: 0.95 for pair in word_pairs["high_association"]}
    low_strengths = {pair: 0.30 for pair in word_pairs["low_association"]}
    
    results = {"high": [], "low": []}
    
    # 模拟高关联条件
    for cue, target in word_pairs["high_association"]:
        sim = WordRetrievalSimulation(word_pairs)
        sim.setup_memory({(cue, target): 0.95})
        sim.goal.add(chunk_type="retrieve", cue=cue, retrieved=None)
        sim.start_time = 0
        sim.run(times=5)  # 运行5秒模拟
        
        results["high"].append({
            "cue": cue,
            "target": target,
            "rt": sim.response_time if hasattr(sim, 'response_time') else None
        })
    
    # 模拟低关联条件
    for cue, target in word_pairs["low_association"]:
        sim = WordRetrievalSimulation(word_pairs)
        sim.setup_memory({(cue, target): 0.30})
        sim.goal.add(chunk_type="retrieve", cue=cue, retrieved=None)
        sim.start_time = 0
        sim.run(times=5)
        
        results["low"].append({
            "cue": cue,
            "target": target,
            "rt": sim.response_time if hasattr(sim, 'response_time') else None
        })
    
    # 打印结果
    print("=" * 50)
    print("词汇检索实验模拟结果")
    print("=" * 50)
    print("\n高关联条件:")
    for r in results["high"]:
        print(f"  {r['cue']} -> {r['target']}: RT = {r['rt']:.3f}s" if r['rt'] else f"  {r['cue']} -> {r['target']}: 未完成")
    
    print("\n低关联条件:")
    for r in results["low"]:
        print(f"  {r['cue']} -> {r['target']}: RT = {r['rt']:.3f}s" if r['rt'] else f"  {r['cue']} -> {r['target']}: 未完成")
    
    # 计算平均RT
    valid_high = [r for r in results["high"] if r["rt"] is not None]
    valid_low = [r for r in results["low"] if r["rt"] is not None]
    
    if valid_high and valid_low:
        avg_high = sum(r["rt"] for r in valid_high) / len(valid_high)
        avg_low = sum(r["rt"] for r in valid_low) / len(valid_low)
        print(f"\n平均反应时间:")
        print(f"  高关联: {avg_high:.3f}s")
        print(f"  低关联: {avg_low:.3f}s")
        print(f"  差异: {avg_low - avg_high:.3f}s")
 
 
if __name__ == "__main__":
    run_experiment()

运行这个模拟,你会看到高关联词对的反应时间明显短于低关联词对——这跟真实的人类行为实验结果是一致的!

四、CLARION:双重过程架构

4.1 CLARION的设计理念

CLARION(Connectionist Learning with Adaptive Rule Induction On-line)是由加拿大滑铁卢大学的John鸣教授开发的认知架构。它的核心创新在于显式知识和隐式知识的区分

CLARION认为,人类认知涉及两个层次的处理:

层次类型特征
高层(Explicit)显式/符号可用语言描述、可反思、有意识访问
低层(Implicit)隐式/连接难以言传、自动化、快速、依赖经验

这种区分跟心理学中的双重过程理论(Dual Process Theory)高度一致。心理学家Evans和Stanovich提出,人类认知有两条并行的路径:

  • 类型1处理(System 1):快速、自动、无意识的直觉式处理
  • 类型2处理(System 2):缓慢、受控、有意识的反思式处理

CLARION试图用计算模型来形式化这两种处理方式。

4.2 CLARION的核心组件

CLARION架构:
┌─────────────────────────────────────────────────────────────┐
│                        行动选择系统                          │
│    ┌─────────────────────────────────────────────────┐     │
│    │              元认知控制层                         │     │
│    │    决定使用高层规则还是低层关联                    │     │
│    └─────────────────────────────────────────────────┘     │
└─────────────────────────────────────────────────────────────┘
              ↓                              ↑
┌────────────────────────┐    ┌────────────────────────┐
│       高层系统          │    │       低层系统          │
│   (Explicit Processing) │    │  (Implicit Processing) │
│                        │    │                        │
│  ┌──────────────────┐  │    │  ┌──────────────────┐  │
│  │   动作规则网络    │  │    │  │    神经网络       │  │
│  │   (Action Rules) │  │    │  │   (Neural Net)   │  │
│  │   Q-学习更新      │  │    │  │   BP更新         │  │
│  └──────────────────┘  │    │  └──────────────────┘  │
│                        │    │                        │
│  符号式表示             │    │  分布式表示             │
│  可解释                 │    │  快速但难解释           │
└────────────────────────┘    └────────────────────────┘
              ↓                              ↑
┌─────────────────────────────────────────────────────────────┐
│                      经验存储系统                            │
│   高层: episodic memory(情景记忆)                         │
│   低层: implicit learning(内隐学习)                       │
└─────────────────────────────────────────────────────────────┘

4.3 用Python实现简化版CLARION

"""
简化版CLARION双重过程框架实现
 
核心特点:
1. 高层系统:基于规则的符号推理,可解释
2. 低层系统:神经网络式的模式识别,快速
3. 元认知控制:动态选择使用哪个系统
"""
 
import numpy as np
from dataclasses import dataclass
from typing import Dict, List, Any, Optional, Callable
from enum import Enum
 
class ProcessingLevel(Enum):
    """处理层级"""
    HIGH = "high"  # 显式/符号
    LOW = "low"    # 隐式/神经网络
    HYBRID = "hybrid"  # 混合
 
 
@dataclass
class State:
    """环境状态"""
    features: Dict[str, float]
    
    def __hash__(self):
        return hash(tuple(sorted(self.features.items())))
    
    def to_vector(self, feature_names: List[str]) -> np.ndarray:
        """转换为特征向量"""
        return np.array([self.features.get(name, 0.0) for name in feature_names])
 
 
class Rule:
    """高层规则"""
    def __init__(self, condition: Callable, action: str, weight: float = 1.0):
        self.condition = condition
        self.action = action
        self.weight = weight
        self.match_count = 0
        self.success_count = 0
    
    def matches(self, state: State, context: Dict) -> bool:
        """检查规则是否匹配"""
        return self.condition(state, context)
    
    def update(self, success: bool):
        """更新规则权重(RL风格)"""
        self.match_count += 1
        if success:
            self.success_count += 1
        # 简化版:直接用成功率作为权重
        if self.match_count > 0:
            self.weight = self.success_count / self.match_count
 
 
class NeuralModule:
    """低层神经网络模块(简化版)"""
    
    def __init__(self, input_dim: int, hidden_dim: int = 32, output_dim: int = 1):
        self.input_dim = input_dim
        self.hidden_dim = hidden_dim
        self.feature_names = None
        
        # 初始化权重(简化版,没有复杂的初始化)
        np.random.seed(42)
        self.W1 = np.random.randn(input_dim, hidden_dim) * 0.1
        self.b1 = np.zeros(hidden_dim)
        self.W2 = np.random.randn(hidden_dim, output_dim) * 0.1
        self.b2 = np.zeros(output_dim)
        
        # Q值存储(用于Q-learning更新)
        self.q_table: Dict[State, np.ndarray] = {}
    
    def forward(self, x: np.ndarray) -> np.ndarray:
        """前向传播"""
        x = x.reshape(-1, self.input_dim)
        h = np.tanh(x @ self.W1 + self.b1)
        q = h @ self.W2 + self.b2
        return q
    
    def update(self, state: State, action: str, reward: float, 
               next_state: State, actions: List[str], alpha=0.1, gamma=0.9):
        """Q-learning更新"""
        if state not in self.q_table:
            self.q_table[state] = np.zeros(len(actions))
        if next_state not in self.q_table:
            self.q_table[next_state] = np.zeros(len(actions))
        
        action_idx = actions.index(action)
        
        # TD更新
        current_q = self.q_table[state][action_idx]
        max_next_q = np.max(self.q_table[next_state])
        td_target = reward + gamma * max_next_q
        td_error = td_target - current_q
        
        # 简化的梯度更新
        self.W2 += alpha * td_error * 0.01
        self.b2 += alpha * td_error * 0.01
    
    def get_q_values(self, state: State, actions: List[str]) -> np.ndarray:
        """获取Q值"""
        if state not in self.q_table:
            self.q_table[state] = np.zeros(len(actions))
        return self.q_table[state]
 
 
class CLARIONAgent:
    """简化版CLARION Agent"""
    
    def __init__(self, feature_names: List[str], actions: List[str]):
        self.feature_names = feature_names
        self.actions = actions
        
        # 高层系统
        self.rules: List[Rule] = []
        
        # 低层系统
        input_dim = len(feature_names)
        self.neural_module = NeuralModule(input_dim, hidden_dim=32, output_dim=1)
        
        # 元认知参数
        self.confidence_threshold = 0.7  # 置信度阈值
        self.rule_confidence_threshold = 0.6  # 规则置信度阈值
        
        # 学习历史
        self.history: List[Dict] = []
    
    def add_rule(self, condition: Callable, action: str):
        """添加高层规则"""
        rule = Rule(condition, action)
        self.rules.append(rule)
        return rule
    
    def select_rule(self, state: State, context: Dict) -> Optional[Rule]:
        """选择匹配的规则(如果有)"""
        matching_rules = [r for r in self.rules if r.matches(state, context)]
        
        if not matching_rules:
            return None
        
        # 选择权重最高的规则
        best_rule = max(matching_rules, key=lambda r: r.weight)
        
        # 检查是否达到置信度阈值
        if best_rule.weight >= self.rule_confidence_threshold:
            return best_rule
        
        return None
    
    def neural_q_learning(self, state: State, context: Dict) -> str:
        """使用神经网络进行Q-learning"""
        state_vector = state.to_vector(self.feature_names)
        q_values = self.neural_module.get_q_values(state, self.actions)
        
        # ε-greedy选择
        epsilon = 0.1
        if np.random.rand() < epsilon:
            return np.random.choice(self.actions)
        
        return self.actions[np.argmax(q_values)]
    
    def choose_action(self, state: State, context: Dict = None) -> tuple[str, ProcessingLevel]:
        """
        行动选择:决定使用高层还是低层系统
        
        策略:
        1. 先尝试高层规则系统
        2. 如果没有匹配的规则或规则置信度不够,使用低层神经网络
        """
        context = context or {}
        
        # 尝试高层系统
        selected_rule = self.select_rule(state, context)
        
        if selected_rule is not None and selected_rule.weight >= self.confidence_threshold:
            return selected_rule.action, ProcessingLevel.HIGH
        
        # 回退到低层系统
        action = self.neural_q_learning(state, context)
        
        return action, ProcessingLevel.LOW
    
    def learn(self, state: State, action: str, reward: float, 
              next_state: State, used_high_level: bool):
        """
        学习:更新两个系统
        
        关键洞察:
        - 如果高层规则导致了好的结果,强化这条规则
        - 如果高层规则导致了坏的结果,弱化这条规则
        - 低层系统总是通过Q-learning更新
        """
        # 更新低层神经网络
        self.neural_module.update(state, action, reward, next_state, self.actions)
        
        # 如果使用了高层规则,更新该规则
        if used_high_level:
            for rule in self.rules:
                if rule.action == action:
                    rule.update(reward > 0)
                    break
        
        # 记录历史
        self.history.append({
            "state": state,
            "action": action,
            "reward": reward,
            "used_high_level": used_high_level
        })
    
    def explain_decision(self, state: State, action: str, 
                        processing_level: ProcessingLevel) -> str:
        """生成决策解释"""
        if processing_level == ProcessingLevel.HIGH:
            # 找到对应的规则
            for rule in self.rules:
                if rule.action == action:
                    return f"使用高层规则:{rule.action} (置信度: {rule.weight:.2f})"
            return f"使用高层系统执行动作: {action}"
        else:
            state_vector = state.to_vector(self.feature_names)
            q_values = self.neural_module.get_q_values(state, self.actions)
            action_idx = self.actions.index(action)
            return f"使用神经网络决策:{action} (Q值: {q_values[action_idx]:.3f})"
 
 
# 使用示例:模拟简单决策任务
def demo_clarion():
    """
    演示CLARION Agent在简单环境中的学习
    """
    
    # 定义状态特征
    feature_names = ["danger_level", "opportunity_level", "energy_level"]
    
    # 定义可用动作
    actions = ["explore", "rest", "retreat"]
    
    # 创建Agent
    agent = CLARIONAgent(feature_names, actions)
    
    # 添加高层规则
    # 规则1:危险高时撤退
    agent.add_rule(
        condition=lambda s, ctx: s.features.get("danger_level", 0) > 0.7,
        action="retreat"
    )
    
    # 规则2:机会高且能量足时探索
    agent.add_rule(
        condition=lambda s, ctx: (
            s.features.get("opportunity_level", 0) > 0.6 and 
            s.features.get("energy_level", 0) > 0.5
        ),
        action="explore"
    )
    
    # 规则3:能量低时休息
    agent.add_rule(
        condition=lambda s, ctx: s.features.get("energy_level", 0) < 0.3,
        action="rest"
    )
    
    # 模拟学习过程
    print("=" * 60)
    print("CLARION Agent 学习演示")
    print("=" * 60)
    
    for episode in range(20):
        # 随机生成状态
        state = State(features={
            "danger_level": np.random.rand(),
            "opportunity_level": np.random.rand(),
            "energy_level": np.random.rand()
        })
        
        # 选择动作
        action, level = agent.choose_action(state)
        
        # 模拟奖励
        reward = 0
        if action == "retreat" and state.features["danger_level"] > 0.7:
            reward = 1.0  # 危险时撤退,正确
        elif action == "explore" and state.features["opportunity_level"] > 0.6:
            reward = 0.8  # 机会好时探索,有收益
        elif action == "rest" and state.features["energy_level"] < 0.3:
            reward = 0.6  # 能量低时休息,合理
        else:
            reward = -0.2  # 其他情况,略有惩罚
        
        # 生成下一个状态(简化)
        next_state = State(features={
            "danger_level": np.random.rand(),
            "opportunity_level": np.random.rand(),
            "energy_level": np.random.rand()
        })
        
        # 学习
        agent.learn(state, action, reward, next_state, 
                   used_high_level=(level == ProcessingLevel.HIGH))
        
        # 打印前几轮和后几轮
        if episode < 3 or episode >= 17:
            print(f"\nEpisode {episode + 1}:")
            print(f"  状态: {state.features}")
            print(f"  选择: {action} ({level.value})")
            print(f"  奖励: {reward:.2f}")
            print(f"  解释: {agent.explain_decision(state, action, level)}")
    
    # 打印规则学习后的权重
    print("\n" + "=" * 60)
    print("学习后的规则权重:")
    for rule in agent.rules:
        print(f"  动作 {rule.action}: 权重={rule.weight:.3f}, "
              f"匹配次数={rule.match_count}, 成功次数={rule.success_count}")
 
 
if __name__ == "__main__":
    demo_clarion()

这个简化版的CLARION展示了双重过程架构的核心思想:高层的规则系统负责可解释的决策,低层的神经网络负责快速模式识别,元认知控制层决定使用哪个系统。

五、ACT-R太老了吗?SPAUN的启示

5.1 ACT-R的局限性

不得不承认,ACT-R虽然是最成熟的认知架构,但它确实有些”年代感”了:

  1. 表示能力有限:ACT-R的Chunk表示相对简单,难以处理复杂的模式识别任务
  2. 学习机制单一:主要依赖产生式规则和激活扩散,没有深度学习那样的表示学习能力
  3. 视觉处理薄弱:原生的ACT-R视觉模块比较初级
  4. 实时性挑战:在复杂场景下,ACT-R的推理速度可能不够快

5.2 SPAUN:脑模拟器的突破

2012年,加拿大滑铁卢大学的Chris Eliasmith团队发布了SPAUN(Semantic Pointer Architecture Unified Network),这是一个真正能够完成多种认知任务的脑模拟器。

SPAUN的关键创新:

语义指针(Semantic Pointers)

  • 一种压缩的信息表示方式
  • 类似于神经科学中的”种群编码”
  • 能够表示复杂的概念结构

神经工程框架(NEF)

  • 将计算映射到神经网络的系统方法
  • 可以将任意函数表示为神经活动模式
  • 支持学习、记忆、注意等多种功能

SPAUN能做的事情相当惊艳:

任务描述性能
视觉识别识别手写数字、字母接近人类水平
工作记忆记住数字序列约7个项目的容量
数数数图像中的物体数量准确率>90%
序列生成按规则生成数字序列正确执行规则
问题求解解决简单代数问题基本正确

5.3 认知架构 vs 深度学习

这是一个经常被问到的问题:既然深度学习已经这么强大了,还需要认知架构吗?

我的看法是:两者是互补的,不是替代的

维度认知架构深度学习
目标理解认知原理优化任务性能
解释性高(规则、Chunk)低(黑箱)
数据效率高(先验知识)低(需要大量数据)
泛化能力依赖知识表示数据驱动
灵活性可解释地调整需要重新训练
认知 plausibility中等

深度学习更像是一个”万能的学习者”,但缺乏结构化的先验知识。认知架构则更像是一个”结构化的推理者”,但学习能力相对有限。

最好的方向是两者的融合:用认知架构提供结构,用深度学习提供学习能力。这就是”神经符号AI”的核心思想。

六、代码实战:用CLARION处理分类任务

"""
使用CLARION双重过程框架处理分类任务
 
演示:
1. 高层系统:基于规则的分类(可解释)
2. 低层系统:神经网络分类(快速)
3. 元认知控制:根据置信度动态选择
"""
 
import numpy as np
from typing import List, Tuple, Dict
from collections import Counter
 
class HybridClassifier:
    """
    混合分类器:CLARION风格
    - 高层:决策规则
    - 低层:神经网络
    - 元认知:选择机制
    """
    
    def __init__(self, n_features: int, classes: List[str]):
        self.n_features = n_features
        self.classes = classes
        self.n_classes = len(classes)
        
        # 高层规则系统
        self.rules: List[Dict] = []
        self.rule_weights: Dict[int, float] = {}
        
        # 低层神经网络
        self._init_neural_net()
        
        # 元认知参数
        self.rule_confidence_threshold = 0.65
        self.neural_confidence_threshold = 0.70
        
        # 统计信息
        self.stats = {
            "high_level_uses": 0,
            "low_level_uses": 0,
            "high_level_correct": 0,
            "low_level_correct": 0,
        }
    
    def _init_neural_net(self):
        """初始化神经网络"""
        np.random.seed(42)
        
        # 简化的单层神经网络
        hidden_size = 64
        self.W1 = np.random.randn(self.n_features, hidden_size) * 0.1
        self.b1 = np.zeros(hidden_size)
        self.W2 = np.random.randn(hidden_size, self.n_classes) * 0.1
        self.b2 = np.zeros(self.n_classes)
        
        # 训练状态
        self.training_data: List[Tuple[np.ndarray, int]] = []
    
    def _relu(self, x):
        return np.maximum(0, x)
    
    def _softmax(self, x):
        exp_x = np.exp(x - np.max(x))
        return exp_x / exp_x.sum()
    
    def forward_neural(self, x: np.ndarray) -> Tuple[np.ndarray, float]:
        """神经网络前向传播"""
        x = x.reshape(1, -1)
        
        h = self._relu(x @ self.W1 + self.b1)
        logits = h @ self.W2 + self.b2
        probs = self._softmax(logits)
        
        confidence = probs.max()
        return probs.flatten(), confidence
    
    def train_neural(self, X: np.ndarray, y: np.ndarray, 
                    epochs: int = 100, lr: float = 0.01):
        """训练神经网络"""
        for epoch in range(epochs):
            for i in range(len(X)):
                x, label = X[i], y[i]
                
                # 前向传播
                probs, _ = self.forward_neural(x)
                
                # 交叉熵梯度(简化)
                grad = probs.copy()
                grad[label] -= 1
                
                # 简化梯度更新
                self.W2 -= lr * np.outer(self._relu(x @ self.W1 + self.b1), grad) * 0.001
                self.b2 -= lr * grad * 0.01
    
    def add_rule(self, condition_fn: callable, predicted_class: str):
        """添加高层规则"""
        rule_id = len(self.rules)
        self.rules.append({
            "id": rule_id,
            "condition": condition_fn,
            "predicted_class": predicted_class,
            "match_count": 0,
            "correct_count": 0
        })
        self.rule_weights[rule_id] = 1.0
    
    def apply_rules(self, x: np.ndarray) -> Tuple[Optional[str], float]:
        """应用高层规则"""
        matching_rules = []
        
        for rule in self.rules:
            try:
                if rule["condition"](x):
                    matching_rules.append(rule)
                    rule["match_count"] += 1
            except:
                pass
        
        if not matching_rules:
            return None, 0.0
        
        # 选择权重最高的规则
        best_rule = max(matching_rules, key=lambda r: self.rule_weights[r["id"]])
        confidence = self.rule_weights[best_rule["id"]]
        
        return best_rule["predicted_class"], confidence
    
    def predict(self, x: np.ndarray, return_explanation: bool = False) -> Dict:
        """
        预测:CLARION风格的元认知选择
        """
        # 第一步:尝试高层规则系统
        rule_class, rule_confidence = self.apply_rules(x)
        
        result = {
            "using_high_level": False,
            "using_low_level": False,
            "predicted_class": None,
            "confidence": 0.0,
            "explanation": ""
        }
        
        # 第二步:低层神经网络预测
        neural_probs, neural_confidence = self.forward_neural(x)
        neural_class = self.classes[np.argmax(neural_probs)]
        
        # 第三步:元认知选择
        if rule_class is not None and rule_confidence >= self.rule_confidence_threshold:
            # 使用高层规则
            result["using_high_level"] = True
            result["predicted_class"] = rule_class
            result["confidence"] = rule_confidence
            result["explanation"] = f"使用规则 '{rule_class}' (置信度: {rule_confidence:.2f})"
            result["rule_confidence"] = rule_confidence
            result["neural_confidence"] = neural_confidence
            result["neural_prediction"] = neural_class
            self.stats["high_level_uses"] += 1
            
        elif neural_confidence >= self.neural_confidence_threshold:
            # 使用神经网络
            result["using_low_level"] = True
            result["predicted_class"] = neural_class
            result["confidence"] = neural_confidence
            result["explanation"] = f"使用神经网络 (置信度: {neural_confidence:.2f})"
            result["neural_probs"] = dict(zip(self.classes, neural_probs))
            self.stats["low_level_uses"] += 1
            
        else:
            # 两者置信度都不够,结合使用
            # 如果规则和神经网络一致,更可信
            if rule_class == neural_class and rule_class is not None:
                result["predicted_class"] = rule_class
                result["confidence"] = (rule_confidence + neural_confidence) / 2
                result["explanation"] = f"规则和神经网络一致: {rule_class}"
            else:
                # 选择神经网络(通常更可靠)
                result["using_low_level"] = True
                result["predicted_class"] = neural_class
                result["confidence"] = neural_confidence
                result["explanation"] = f"神经网络为主,规则为辅"
                self.stats["low_level_uses"] += 1
        
        return result
    
    def update(self, x: np.ndarray, true_class: str):
        """更新模型(事后学习)"""
        # 更新匹配的规则
        for rule in self.rules:
            try:
                if rule["condition"](x):
                    if rule["predicted_class"] == true_class:
                        rule["correct_count"] += 1
                    # 更新规则权重
                    if rule["match_count"] > 0:
                        self.rule_weights[rule["id"]] = (
                            rule["correct_count"] / rule["match_count"]
                        )
            except:
                pass
        
        # 添加到训练数据
        label = self.classes.index(true_class)
        self.training_data.append((x, label))
        
        # 增量训练神经网络(简化)
        if len(self.training_data) > 10:
            self.train_neural(
                np.array([t[0] for t in self.training_data[-100:]]),
                np.array([t[1] for t in self.training_data[-100:]]),
                epochs=10
            )
    
    def print_stats(self):
        """打印统计信息"""
        print("\n" + "=" * 50)
        print("CLARION 混合分类器统计")
        print("=" * 50)
        print(f"高层规则使用次数: {self.stats['high_level_uses']}")
        print(f"低层神经网络使用次数: {self.stats['low_level_uses']}")
        print(f"总规则数: {len(self.rules)}")
        print("\n规则详情:")
        for rule in self.rules:
            if rule["match_count"] > 0:
                accuracy = rule["correct_count"] / rule["match_count"]
                print(f"  规则{rule['id']}: {rule['predicted_class']} "
                      f"(匹配{rule['match_count']}次, 准确率{accuracy:.2f})")
 
 
def demo_classification():
    """分类任务演示"""
    
    # 模拟一个二分类问题:判断用户是否会购买
    # 特征:[年龄, 收入水平(0-1), 网站停留时间(分钟), 历史购买次数]
    
    np.random.seed(42)
    
    # 生成训练数据
    n_samples = 500
    
    # 类别0:不购买
    class_0 = []
    for _ in range(n_samples // 2):
        age = np.random.normal(30, 10)
        income = np.random.uniform(0, 0.4)
        time = np.random.exponential(2)
        purchases = np.random.randint(0, 3)
        class_0.append([age, income, time, purchases])
    
    # 类别1:购买
    class_1 = []
    for _ in range(n_samples // 2):
        age = np.random.normal(35, 8)
        income = np.random.uniform(0.6, 1.0)
        time = np.random.exponential(8)
        purchases = np.random.randint(3, 10)
        class_1.append([age, income, time, purchases])
    
    X = np.array(class_0 + class_1)
    y = np.array([0] * (n_samples // 2) + [1] * (n_samples // 2))
    
    # 创建分类器
    classes = ["不购买", "购买"]
    classifier = HybridClassifier(n_features=4, classes=classes)
    
    # 添加高层规则(基于领域知识)
    # 规则1:高收入 + 长停留时间 → 购买
    classifier.add_rule(
        condition_fn=lambda x: x[1] > 0.7 and x[2] > 5,
        predicted_class="购买"
    )
    
    # 规则2:低收入 + 短停留时间 → 不购买
    classifier.add_rule(
        condition_fn=lambda x: x[1] < 0.3 and x[2] < 3,
        predicted_class="不购买"
    )
    
    # 规则3:购买次数超过5次 → 购买
    classifier.add_rule(
        condition_fn=lambda x: x[3] > 5,
        predicted_class="购买"
    )
    
    # 训练神经网络组件
    print("训练神经网络组件...")
    classifier.train_neural(X, y, epochs=200)
    
    # 测试
    print("\n" + "=" * 50)
    print("测试结果")
    print("=" * 50)
    
    test_cases = [
        np.array([25, 0.8, 10, 7]),   # 高收入长停留
        np.array([45, 0.2, 2, 1]),    # 低收入短停留
        np.array([35, 0.5, 5, 4]),    # 中等收入
        np.array([28, 0.9, 3, 2]),    # 高收入但短停留
    ]
    
    for i, x in enumerate(test_cases):
        result = classifier.predict(x, return_explanation=True)
        print(f"\n测试案例 {i + 1}:")
        print(f"  特征: 年龄={x[0]:.1f}, 收入={x[1]:.2f}, "
              f"停留={x[2]:.1f}分钟, 购买={x[3]}次")
        print(f"  预测: {result['predicted_class']}")
        print(f"  置信度: {result['confidence']:.2f}")
        print(f"  说明: {result['explanation']}")
        if result.get('neural_probs'):
            print(f"  神经网络概率: {result['neural_probs']}")
    
    # 打印统计
    classifier.print_stats()
 
 
if __name__ == "__main__":
    demo_classification()

七、认知架构评估:与人类行为数据对比

7.1 评估维度

认知架构的评估比普通机器学习模型复杂得多,因为我们不仅要问”准确率多少”,还要问”是否符合人类的认知规律”。

评估维度描述典型指标
行为拟合预测人类行为的能力反应时间、错误率
认知合理性是否符合心理学理论组件对应、过程合理性
预测性预测新情境的能力迁移准确率
可解释性决策是否可理解规则提取、轨迹可视化
计算效率资源消耗是否合理运行时间、内存使用

7.2 经典行为实验范式

认知架构研究者通常用以下实验范式来验证模型:

Stroop任务:展示颜色词(如”红”),但用不同颜色书写,要求命名颜色。经典发现是颜色和词的冲突会减慢反应时间。

N-back任务:呈现一系列刺激,要求报告n个刺激之前的是什么。用于评估工作记忆容量。

切换成本范式:在两种任务之间切换,测量任务切换带来的”成本”(反应时间增加)。

Bartlett的系列位置曲线:记忆一串项目时,开头和结尾的项目比中间记得更好。

这些范式之所以重要,是因为它们有大量的人类行为数据可以作为”ground truth”。一个好的认知架构应该能复现这些经典发现。

八、总结与展望

8.1 核心要点

  1. 认知架构是统一的认知计算框架,目标是用计算模型解释和复现人类智能
  2. ACT-R是最成熟的认知架构,符号+子符号混合,跟神经科学有对应
  3. CLARION强调显式/隐式知识的区分,是双重过程理论的计算实现
  4. SPAUN展示了大规模脑模拟的可能性
  5. 神经符号AI是认知架构和深度学习融合的方向

8.2 未来趋势

  • 大规模认知模拟:随着计算能力提升,模拟整个大脑成为可能
  • 认知架构+LLM:用认知架构的思想来理解和改进LLM
  • 具身认知:将身体和环境纳入认知模型
  • 认知安全的AI:用认知架构来设计更安全、更可控的AI系统

相关文档:元认知与执行功能 | 神经符号AI | 工作记忆模型 | 深度学习与认知科学