小人的认知系统

07/25综合
这是一个很好的思路。RND 的核心——用"预测误差"度量新奇度,驱动探索——可以直接映射到校园小人的认知系统上,而且不需要真的跑神经网络。下面是方案讨论。
horizontal linehorizontal line

RND 思想到校园小人的映射

RND 原始结构 vs 校园简化版

RND 组件原始含义校园小人对应
目标网络(固定随机)为每个状态生成固定特征环境的客观快照:房间类型、物件数、人员密度、卫生度、当前时段
预测网络(可训练)学习预测目标网络输出小人的认知预期:他"以为"这个房间长什么样
预测误差内在奖励(好奇心)新奇度 / 惊讶度:实际观察和预期的差距
误差衰减反复访问后误差降低熟悉化:去多了就不再好奇

为什么不用真神经网络

当前引擎是纯 Lua 脚本,没有 GPU 训练管线。但 RND 的本质不是神经网络本身,而是:
用一个"我学不会的基准"减去"我正在学的模型",差值就是好奇心。
这可以用指数移动平均 + 特征距离完美模拟,计算量几乎为零。
horizontal linehorizontal line

具体方案:三层认知好奇心

第一层:状态特征向量(对应"目标网络输出")

每个可探索实体(房间、区域、物件聚集区)在每帧有一个客观特征快照
lua
-- 伪代码:环境为每个区域生成的"真实特征" feature = { roomTypeHash, -- 房间类型哈希(教室=1, 食堂=2...) objectCount, -- 区域内物件数 personDensity, -- 当前人员密度(0~1) hygieneLevel, -- 卫生度(0~1) timeSlot, -- 时段槽(早读=1, 上课=2...) eventFlag, -- 是否有异常事件(打闹、违规等) }
这些值是客观的、每帧可算的,相当于 RND 中固定随机网络的输出——小人无法改变它,只能观察。

第二层:认知预期模型(对应"预测网络")

每个小人对每个已知区域维护一个预期特征向量
lua
-- state.actorMinds[actorId].predictions[roomId] prediction = { expectedObjectCount = 0, expectedDensity = 0, expectedHygiene = 0.5, expectedTimeSlot = 0, visitCount = 0, lastVisitFrame = 0, }
更新规则(每次小人实际到达/观察该区域时):
lua
-- 指数移动平均,学习率 alpha 随 visitCount 衰减 local alpha = 1.0 / (1.0 + prediction.visitCount * 0.3) prediction.expectedObjectCount = lerp(prediction.expectedObjectCount, feature.objectCount, alpha) prediction.expectedDensity = lerp(prediction.expectedDensity, feature.personDensity, alpha) -- ...其他维度同理 prediction.visitCount = prediction.visitCount + 1
关键设计:
  • 学习率随访问次数衰减:第一次去,预期大幅修正;第 100 次去,几乎不修正。
  • 未访问过的区域:预期 = 类型默认值(如教室默认安静、食堂默认拥挤),或全零(完全未知)。

第三层:预测误差 → 好奇心(对应 RND 内在奖励)

lua
-- 预测误差 = 实际观察 vs 预期的距离 local error = 0 error = error + abs(feature.objectCount - prediction.expectedObjectCount) * 0.3 error = error + abs(feature.personDensity - prediction.expectedDensity) * 0.4 error = error + abs(feature.hygieneLevel - prediction.expectedHygiene) * 0.2 error = error + (feature.eventFlag and 1.0 or 0.0) * 0.5 -- 异常事件 = 高惊讶 -- 对完全未知的区域,给一个基础好奇心 bonus if prediction.visitCount == 0 then error = error + BASE_CURIOSITY -- 例如 0.8 end -- 归一化到 [0, 1] local curiosity = math.min(1.0, error)

决策融合(对应 RND 的"灵活结合内外奖励")

小人在 PickTarget() 选择下一个目标时:
lua
-- 总效用 = 任务驱动 + 好奇心驱动 local utility = alpha * taskPriority + beta * curiosity
其中:
  • alpha:任务权重,受日程、岗位、紧急事件控制
  • beta:好奇心权重,因角色性格而异
角色性格beta 值行为倾向
规矩学生0.1几乎不探索,只走日程路线
普通学生0.3偶尔偏离路线去没去过的地方
好奇学生0.6经常探索新区域,容易触发事件
调皮学生0.8强烈偏好未知和异常区域
保安/保洁0.05几乎纯任务驱动
horizontal linehorizontal line

与现有系统的集成点

1. 接入 state.actorMinds

当前 actorMinds[actorId] 已保存 beliefs[targetId] 认知层级。好奇心系统可以复用这个结构:
lua
actorMinds[id].predictions = actorMinds[id].predictions or {} actorMinds[id].predictions[roomId] = { ... }

2. 接入学生 AI 的 PickTarget()

当前 学生AI.PickTarget() 只考虑日程任务。改造为:
PickTarget()
  ├─ 读取当前日程任务优先级 → taskPriority
  ├─ 读取所有可达区域的好奇心 → curiosity[roomId]
  ├─ 计算 utility = alpha * taskPriority + beta * curiosity
  └─ 选 utility 最高的目标

3. 与探索服务的关系

当前探索服务(CampusDaily / Exploration)已有 ROOM_VISITED 事件。好奇心系统可以消费这个事件来更新预测模型,而不是另建一套探索逻辑。

4. 与行为观察的联动

高好奇心 → 更频繁偏离路线 → 更多机会出现在"不该出现的地方" → 触发观察/怀疑系统。这形成了一条自然的玩法因果链
好奇学生 → 探索禁区 → 被目击 → 怀疑累积 → 跟随/询问 → 识破
horizontal linehorizontal line

和 RND 的关键差异(诚实说明)

维度RND 原始校园简化版
特征空间高维像素 embedding6 维手工特征
预测网络3 层 MLP,梯度下降指数移动平均
目标网络随机初始化,永不更新环境客观快照,每帧重算
探索信号MSE 误差加权绝对差
训练在线策略梯度无需训练,规则驱动
简化版丢失了什么:
  • 无法发现"隐含结构":RND 的随机网络能捕捉像素中的隐含模式,手工特征做不到。
  • 无法泛化:RND 的预测误差对"视觉相似但语义不同"的状态有区分力,手工特征需要显式编码。
但在校园模拟中,这些损失可以接受,因为:
  • 状态空间本身就是结构化、低维的(房间类型、人数、卫生度等)。
  • 我们不需要从像素中学习,环境已经提供了语义标签。
horizontal linehorizontal line

建议实现顺序

  1. 最小版本:只加 visitCountBASE_CURIOSITY,让完全没去过的房间有固定好奇心 bonus。接入 PickTarget() 的 utility 计算。验证小人是否会偏离路线。
  2. 特征距离版:加入 3~4 维特征向量(类型、密度、卫生度),用指数移动平均更新预期,用加权绝对差算好奇心。验证小人是否对"变化"敏感(如房间被弄脏后重新好奇)。
  3. 性格分化:给不同学生分配不同 beta,观察行为多样性。
  4. 与观察系统联动:高好奇心学生的探索行为自然触发观察/怀疑链。
4