认知架构实战与CLARION:构建类人智能的计算框架
关键词
| 序号 | 关键词 | 英文对照 |
|---|---|---|
| 1 | 认知架构 | Cognitive Architecture |
| 2 | ACT-R | Adaptive Control of Thought-Rational |
| 3 | SOAR | State, Operator, And Result |
| 4 | CLARION | Connectionist Learning with Adaptive Rule Induction On-line |
| 5 | 物理符号系统 | Physical Symbol System |
| 6 | 双重过程 | Dual Process Theory |
| 7 | SPAUN | Semantic Pointer Architecture Unified Network |
| 8 | 神经符号AI | Neuro-symbolic AI |
一、什么是认知架构?
1.1 认知架构的定义
认知架构(Cognitive Architecture)是一个试图统一解释人类认知的计算框架。它不是某个具体的算法或模型,而是一整套关于”认知是如何工作的”核心假设和组件体系。
打个比方,如果你要建造一栋智能建筑,你需要的不只是砖头和水泥,而是一个完整的设计蓝图——包括地基、结构、管线、电路、通风系统等。认知架构就是这个蓝图的AI版本,它规定了:
- 认知系统由哪些基本组件构成
- 这些组件之间如何交互
- 信息是如何表示和加工的
- 学习是如何发生的
- 行为是如何选择的
好的认知架构应该具备三个特征:
- 完整性:能解释认知的各个方面(感知、记忆、注意、推理、行动等)
- 一致性:各组件之间逻辑自洽,不存在矛盾
- 可计算性:能用数学/计算语言精确描述,可以实现为程序
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虽然是最成熟的认知架构,但它确实有些”年代感”了:
- 表示能力有限:ACT-R的Chunk表示相对简单,难以处理复杂的模式识别任务
- 学习机制单一:主要依赖产生式规则和激活扩散,没有深度学习那样的表示学习能力
- 视觉处理薄弱:原生的ACT-R视觉模块比较初级
- 实时性挑战:在复杂场景下,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 核心要点
- 认知架构是统一的认知计算框架,目标是用计算模型解释和复现人类智能
- ACT-R是最成熟的认知架构,符号+子符号混合,跟神经科学有对应
- CLARION强调显式/隐式知识的区分,是双重过程理论的计算实现
- SPAUN展示了大规模脑模拟的可能性
- 神经符号AI是认知架构和深度学习融合的方向
8.2 未来趋势
- 大规模认知模拟:随着计算能力提升,模拟整个大脑成为可能
- 认知架构+LLM:用认知架构的思想来理解和改进LLM
- 具身认知:将身体和环境纳入认知模型
- 认知安全的AI:用认知架构来设计更安全、更可控的AI系统