1. 这篇文章真正要解决的问题
当我们在谈论AI模型的优化时,最常听到的词是“准确性”、“效率”或“对齐”。但今天,我们要探讨一个听起来有些“不务正业”的优化目标:好奇心。这并非一个哲学讨论,而是一个正在前沿AI研究领域,特别是强化学习和探索型智能体中,被严肃对待的技术范式。
你可能会疑惑:好奇心不是人类才有的特质吗?把它作为AI的优化目标,到底能解决什么实际的技术问题?这正是本文要深入剖析的核心。简单来说,“以好奇心为优化目标”旨在解决AI智能体在稀疏奖励或未知环境中“动力不足”的问题。想象一下,让一个AI在复杂的《我的世界》游戏里学习建造,或者在没有任何明确分数提示的迷宫中寻找出口。如果只有最终成功(如找到宝藏)才给予奖励,AI在探索初期几乎接收不到任何有效反馈,很容易陷入“躺平”状态,什么也不做,因为“不做不错”。这就是经典的稀疏奖励难题。
而好奇心机制,为AI内置了一个“内在驱动力”。它不再仅仅为了外部奖励(如游戏得分)而行动,还会为了“降低自身对环境的预测误差”或“访问新颖的状态”而主动探索。这就像给AI装上了一颗“求知欲”引擎,驱动它去尝试那些未曾见过的按钮、走进未知的房间,从而更快地发现环境中隐藏的奖励结构和解决方案。
本文将带你从理论到实践,彻底理解“好奇心驱动学习”。我们不仅会解释其核心原理(如基于预测误差的好奇心),更会通过一个完整的代码示例,在经典的CartPole(车杆平衡)和更复杂的MountainCar(山地车)环境中,亲手实现一个带有好奇心模块的强化学习智能体。你会看到,在奖励极其稀疏的MountainCar环境中,普通智能体几乎学不会,而“好奇的”智能体如何一步步自己找到登顶的秘诀。对于研究者、算法工程师以及对AI探索机制感兴趣的开发者而言,理解好奇心优化是打开更通用、更自主AI智能体大门的一把关键钥匙。
2. 好奇心优化:从人类本能到AI算法
在深入代码之前,我们必须先厘清概念:在AI的语境下,“好奇心”究竟被如何定义和量化?它不是一个模糊的比喻,而是一个可以被精确计算并融入损失函数的数学模块。
目前主流的好奇心实现方式主要分为两大类:基于预测误差的好奇心和基于新颖性的好奇心。
2.1 基于预测误差的好奇心
这是最经典和直观的方法,其核心思想是:智能体因为无法完美预测其行动后果而感到“好奇”。
- 核心机制:智能体拥有一个额外的神经网络,我们称之为“好奇心模型”或“内在动机模型”。这个模型的任务是,根据当前的状态(
state)和将要执行的动作(action),预测下一个状态(next_state)的特征。 - 好奇心的量化:预测的
next_state与实际发生的next_state之间的差异(如均方误差MSE),就被定义为“好奇心奖励”。预测误差越大,说明这个(state, action)对智能体来说越“陌生”、越“意外”,因此获得的额外内在奖励就越高。 - 通俗理解:这好比一个婴儿摇晃拨浪鼓。他并不知道“摇晃”这个动作会带来“声音”和“视觉移动”的结果。当他第一次摇晃并观察到结果时,预测误差很大,好奇心奖励高,促使他重复这个动作来学习其中的因果关系。随着重复次数增多,他能越来越准地预测结果,预测误差减小,好奇心奖励也随之降低,他便可能转向其他新玩具。
2.2 基于新颖性的好奇心
这类方法更直接地衡量状态本身的“新鲜度”。
- 核心机制:系统会记录或建模智能体访问过的历史状态。当一个新状态出现时,通过计算它与历史状态的相似度(或直接使用计数)来判断其新颖性。越少见的状态,获得的内在奖励越高。
- 常见技术:包括状态计数、基于密度模型(如高斯混合模型)的新颖性评估,以及通过随机网络蒸馏(Random Network Distillation, RND)等方法学习一个状态的新颖性表征。
- 与预测误差的区别:预测误差关注的是动态过程(从A到B的转变是否难以预测),而新颖性关注的是状态本身(B这个点是否很少被访问)。两者常常结合使用。
2.3 好奇心解决了什么?又带来了什么?
解决的问题:
- 稀疏奖励:在奖励信号极少或延迟很长的环境中,提供持续的学习信号。
- 探索效率:引导智能体优先探索信息量大、不确定性高的区域,避免在已知区域无效徘徊。
- 局部最优:帮助智能体跳出局部最优策略,尝试风险更高但潜在收益更大的行为。
可能引入的新问题:
- “噪声电视”问题:如果环境中存在完全随机、不可预测的噪声(比如电视雪花屏),基于预测误差的好奇心会被其无限吸引,导致智能体“沉迷”于噪声而无法完成真正任务。
- 计算开销:需要额外训练一个预测模型,增加了计算和调参的复杂度。
- 奖励干扰:内在奖励如果设计不当,可能与外部奖励发生冲突,反而干扰最终任务的学习。
为了直观展示其威力,我们将在后续章节中,用代码对比同一个智能体在有无好奇心机制下的表现差异。你会发现,在有些环境中,好奇心不是“锦上添花”,而是“雪中送炭”。
3. 环境与工具准备
我们将使用Python生态中最流行的强化学习库之一——Stable-Baselines3 (SB3)来实现我们的好奇心智能体。同时,为了构建好奇心模块,我们会用到PyTorch。选择SB3是因为它封装了诸多经典算法(如PPO, A2C, DQN),接口统一,易于扩展。
3.1 前置条件与安装
请确保你的Python版本在3.7以上。我们通过pip安装必要的包:
# 创建虚拟环境(推荐) python -m venv curiosity_env source curiosity_env/bin/activate # Linux/Mac # curiosity_env\Scripts\activate # Windows # 安装核心依赖 pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu # 以CPU版本为例,可根据CUDA版本调整 pip install gymnasium==0.29.1 # OpenAI Gym的维护分支,API更稳定 pip install stable-baselines3==2.3.0 pip install imageio # 用于生成演示视频关键版本说明:
gymnasium:原gym库已不再维护,gymnasium是其官方继任者,API高度兼容但更优。本文代码基于此。stable-baselines3:一个可靠且维护良好的强化学习算法实现库。torch:我们使用PyTorch来构建自定义的好奇心神经网络模块。
3.2 测试基础环境
安装完成后,我们可以快速测试一个标准环境,确保一切正常。
import gymnasium as gym # 创建经典的CartPole环境 env = gym.make('CartPole-v1', render_mode='human') # render_mode='human'用于弹出窗口观看 observation, info = env.reset() for _ in range(100): action = env.action_space.sample() # 随机采取动作 observation, reward, terminated, truncated, info = env.step(action) if terminated or truncated: observation, info = env.reset() env.close() print("基础环境测试通过!")运行这段代码,你应该能看到一个窗口,一个小车上面顶着一根杆子,由于动作是随机的,杆子很快会倒下。这说明Gymnasium环境和可视化功能工作正常。
我们的实验将围绕两个环境展开:
- CartPole-v1:相对简单,奖励密集(每步保持平衡都有+1奖励)。我们将用它验证好奇心模块是否会影响一个本来就能学好的任务。
- MountainCar-v0:典型的稀疏奖励环境。小车位于两山之间,目标是通过左右加速冲到右侧山顶。只有在成功登顶时才会获得+100奖励,其余每步都是-1(惩罚时间消耗)。如果没有探索机制,智能体很难自学出有效的“摇摆”策略来积累动能。这是展示好奇心价值的绝佳舞台。
4. 构建好奇心模块:代码核心
我们将实现一个基于预测误差的好奇心模块。这个模块会作为一个“包装器”附加在原有的环境上,为每一步都计算一个额外的内在奖励。
4.1 好奇心模型定义
首先,我们用PyTorch定义一个前馈神经网络,用于预测下一状态的特征。
import torch import torch.nn as nn import torch.nn.functional as F class CuriosityModel(nn.Module): """ 好奇心驱动模型:根据当前状态和动作,预测下一状态。 输入:state, action 输出:predicted_next_state 损失:预测状态与实际下一状态的均方误差(MSE),此误差即内在奖励。 """ def __init__(self, state_dim, action_dim, hidden_dim=128): super(CuriosityModel, self).__init__() # 将状态和动作拼接起来作为输入 self.fc1 = nn.Linear(state_dim + action_dim, hidden_dim) self.fc2 = nn.Linear(hidden_dim, hidden_dim) self.fc3 = nn.Linear(hidden_dim, state_dim) # 输出维度与状态维度相同 def forward(self, state, action): # 确保action是float类型,并调整形状以匹配state if isinstance(action, int) or (isinstance(action, torch.Tensor) and action.dim() == 0): action = torch.tensor([action], dtype=torch.float32) action = action.view(-1, 1) if action.dim() == 1 else action # 拼接状态和动作 x = torch.cat([state, action], dim=-1) x = F.relu(self.fc1(x)) x = F.relu(self.fc2(x)) next_state_pred = self.fc3(x) # 预测的下一个状态 return next_state_pred关键点解析:
state_dim和action_dim:必须与环境观察空间和动作空间的维度匹配。例如,CartPole-v1的state_dim=4,action_dim=1(离散动作0或1)。- 网络结构:一个简单的三层MLP。输入是
state和action的拼接,输出是预测的next_state。 forward函数:接收当前状态和动作,返回预测的下一个状态。这里处理了action可能为整数或张量的情况,确保能正确拼接。
4.2 环境包装器:注入好奇心
接下来,我们创建一个Gymnasium的环境包装器。这个包装器在每一步环境交互后,调用好奇心模型计算内在奖励,并将其与外部环境奖励叠加。
from gymnasium import Wrapper import numpy as np class CuriosityWrapper(Wrapper): """ 环境包装器,为原始环境奖励添加好奇心驱动奖励。 """ def __init__(self, env, curiosity_model, curiosity_weight=0.01, lr=1e-3): super().__init__(env) self.model = curiosity_model self.optimizer = torch.optim.Adam(self.model.parameters(), lr=lr) self.curiosity_weight = curiosity_weight # 好奇心奖励的权重系数 self.last_state = None self.last_action = None def reset(self, **kwargs): self.last_state = None self.last_action = None return self.env.reset(**kwargs) def step(self, action): # 执行原始环境动作 next_state, extrinsic_reward, terminated, truncated, info = self.env.step(action) # 计算好奇心奖励 intrinsic_reward = 0.0 if self.last_state is not None: # 将numpy数组转换为torch张量 state_tensor = torch.FloatTensor(self.last_state).unsqueeze(0) action_tensor = torch.FloatTensor([self.last_action]).unsqueeze(0) next_state_tensor = torch.FloatTensor(next_state).unsqueeze(0) # 使用好奇心模型预测下一状态 predicted_next_state = self.model(state_tensor, action_tensor) # 计算预测误差(均方误差)作为内在奖励 prediction_error = F.mse_loss(predicted_next_state, next_state_tensor, reduction='none').mean().item() intrinsic_reward = prediction_error # 使用预测误差作为损失,更新好奇心模型 loss = F.mse_loss(predicted_next_state, next_state_tensor) self.optimizer.zero_grad() loss.backward() self.optimizer.step() # 更新上一个状态和动作 self.last_state = next_state.copy() self.last_action = action # 总奖励 = 外部奖励 + 权重 * 内在奖励 total_reward = extrinsic_reward + self.curiosity_weight * intrinsic_reward return next_state, total_reward, terminated, truncated, info关键点解析:
- 包装器模式:继承了
gymnasium.Wrapper,可以透明地包装任何Gymnasium环境,复用其所有方法。 - 奖励叠加:在每一步
step中,先获取环境原始的外部奖励extrinsic_reward,然后计算好奇心奖励intrinsic_reward,最后将两者加权求和作为返回给智能体的总奖励。curiosity_weight是一个超参数,控制好奇心奖励的强度。 - 模型更新:在计算预测误差的同时,我们立即用这个误差作为损失来更新好奇心模型。这意味着好奇心模型也在与环境交互的过程中不断学习,目标是更好地预测环境动态。当预测越来越准,好奇心奖励自然下降,智能体的探索重点就会转移。
- 状态跟踪:使用
last_state和last_action来记录上一步的信息,用于当前步的预测。
5. 完整训练流程与对比实验
现在,我们将使用Stable-Baselines3的PPO算法,分别在原始环境和好奇心增强环境下训练智能体,并进行对比。
5.1 训练脚本实现
import os from stable_baselines3 import PPO from stable_baselines3.common.monitor import Monitor from stable_baselines3.common.vec_env import DummyVecEnv from stable_baselines3.common.evaluation import evaluate_policy import time def train_and_evaluate(env_name, use_curiosity=False, total_timesteps=50000, seed=42): """ 训练和评估智能体 :param env_name: 环境名称,如 'CartPole-v1' :param use_curiosity: 是否使用好奇心包装器 :param total_timesteps: 总训练步数 :param seed: 随机种子,保证可复现性 """ print(f"\n=== 开始实验:环境={env_name}, 好奇心={use_curiosity} ===") # 1. 创建基础环境 env = gym.make(env_name) env.reset(seed=seed) # 2. 如果需要,添加好奇心包装 if use_curiosity: # 获取状态和动作维度 state_dim = env.observation_space.shape[0] if hasattr(env.action_space, 'n'): action_dim = 1 # 离散动作空间 else: action_dim = env.action_space.shape[0] # 连续动作空间 # 创建好奇心模型 curiosity_model = CuriosityModel(state_dim, action_dim) # 用好奇心包装器包裹原始环境 env = CuriosityWrapper(env, curiosity_model, curiosity_weight=0.1) # 权重设为0.1 # 3. 用Monitor包装环境以记录日志,并用DummyVecEnv包装以兼容SB3 env = Monitor(env) env = DummyVecEnv([lambda: env]) # 4. 创建PPO智能体 model = PPO('MlpPolicy', env, verbose=0, seed=seed, learning_rate=3e-4, n_steps=2048, batch_size=64) # 5. 训练模型 start_time = time.time() model.learn(total_timesteps=total_timesteps) training_time = time.time() - start_time print(f"训练完成,耗时: {training_time:.2f} 秒") # 6. 评估模型(在原始环境上,不包含好奇心包装) eval_env = gym.make(env_name) eval_env = Monitor(eval_env) eval_env = DummyVecEnv([lambda: eval_env]) mean_reward, std_reward = evaluate_policy(model, eval_env, n_eval_episodes=10, deterministic=True) print(f"评估结果 - 平均奖励: {mean_reward:.2f} +/- {std_reward:.2f}") # 7. 保存模型 model_save_path = f"models/ppo_{env_name}_{'with_curiosity' if use_curiosity else 'baseline'}" os.makedirs("models", exist_ok=True) model.save(model_save_path) print(f"模型已保存至: {model_save_path}") return model, mean_reward # 运行对比实验 if __name__ == "__main__": # 实验1: CartPole-v1 (密集奖励) print("\n" + "="*50) print("实验一:CartPole-v1 (密集奖励环境)") print("="*50) baseline_model_cartpole, baseline_reward_cartpole = train_and_evaluate('CartPole-v1', use_curiosity=False, total_timesteps=20000) curiosity_model_cartpole, curiosity_reward_cartpole = train_and_evaluate('CartPole-v1', use_curiosity=True, total_timesteps=20000) # 实验2: MountainCar-v0 (稀疏奖励) print("\n" + "="*50) print("实验二:MountainCar-v0 (稀疏奖励环境)") print("="*50) # MountainCar需要更多步数学习 baseline_model_mountain, baseline_reward_mountain = train_and_evaluate('MountainCar-v0', use_curiosity=False, total_timesteps=100000) curiosity_model_mountain, curiosity_reward_mountain = train_and_evaluate('MountainCar-v0', use_curiosity=True, total_timesteps=100000) # 打印总结 print("\n" + "="*50) print("实验总结") print("="*50) print(f"CartPole-v1 - 基线模型平均奖励: {baseline_reward_cartpole:.2f}") print(f"CartPole-v1 - 好奇心模型平均奖励: {curiosity_reward_cartpole:.2f}") print(f"MountainCar-v0 - 基线模型平均奖励: {baseline_reward_mountain:.2f}") print(f"MountainCar-v0 - 好奇心模型平均奖励: {curiosity_reward_mountain:.2f}")5.2 代码逻辑详解
- 环境创建与包装:函数
train_and_evaluate是实验的主体。它首先创建指定的Gymnasium环境。如果use_curiosity为真,则创建CuriosityModel并用CuriosityWrapper包装原始环境。 - 兼容性处理:Stable-Baselines3的算法通常需要向量化环境(
VecEnv)。我们使用DummyVecEnv进行包装。Monitor用于记录训练过程中的回报等数据。 - 智能体训练:使用PPO算法进行训练。我们设置了适中的超参数(学习率、步数等)。关键点在于,当环境被好奇心包装后,PPO智能体接收到的每一步奖励已经是外部奖励+好奇心奖励的混合体,它的策略优化目标也随之改变。
- 公平评估:评估模型性能时,我们重新创建了一个没有好奇心包装的原始环境。这是因为我们关心的是智能体在真实任务(仅靠外部奖励定义)上的表现,而不是在训练时混合奖励下的表现。这是一个重要的实验设计细节。
- 对比实验:我们分别在
CartPole-v1(密集奖励)和MountainCar-v0(稀疏奖励)上运行了基线(无好奇心)和好奇心增强的版本。
6. 运行结果分析与可视化
运行上述训练脚本后,观察控制台输出和训练结果。
6.1 预期结果分析
对于CartPole-v1:
- 基线模型:PPO算法本身就能很好地解决这个问题,在训练2万步后,评估平均奖励应该能接近或达到环境最大值(500)。
- 好奇心模型:表现应该与基线模型相当或略低。因为环境奖励已经很密集,额外的好奇心奖励可能会引入一些噪声,但通常不会破坏学习。有时好奇心甚至能帮助找到更鲁棒的策略。关键在于
curiosity_weight的设置,权重过大可能会干扰。
对于MountainCar-v0:
- 基线模型:这是一个严峻的挑战。在10万步的标准PPO训练下,智能体很可能无法学会有效的策略。评估平均奖励会非常低(远低于-100,甚至接近-200),因为它只会左右乱撞,无法积累足够的动能登顶。
- 好奇心模型:我们期望看到显著的性能提升。好奇心奖励会驱动智能体去尝试不同的速度和位置组合,即使这些尝试在初期不会带来外部奖励。通过探索,它更有可能偶然发现“摇摆”的节奏,从而成功登顶。评估平均奖励有望从极低的负值提升到一个相对较高的值(例如-150到-100之间,甚至更高,成功登顶的回合会获得+100奖励)。
6.2 结果可视化与演示
我们可以加载训练好的模型,并生成一段智能体运行时的视频,直观地观察其行为差异。
import imageio from stable_baselines3.common.vec_env import VecVideoRecorder def record_video(model, env_name, video_length=500, video_name="agent_video.mp4"): """录制智能体运行视频""" env = gym.make(env_name, render_mode='rgb_array') # 注意:这里为了录制,我们使用一个临时的不带好奇心的环境来评估 env = DummyVecEnv([lambda: env]) # 使用VecVideoRecorder包装环境来录制 env = VecVideoRecorder(env, "videos", record_video_trigger=lambda x: x == 0, video_length=video_length, name_prefix=video_name) obs = env.reset() for _ in range(video_length): action, _states = model.predict(obs, deterministic=True) obs, rewards, dones, info = env.step(action) if dones[0]: break env.close() print(f"视频已保存至: videos/{video_name}.mp4") # 录制MountainCar环境中好奇心模型的演示 if __name__ == "__main__": # 加载之前保存的好奇心模型 curiosity_model_path = "models/ppo_MountainCar-v0_with_curiosity" model = PPO.load(curiosity_model_path) # 录制视频 record_video(model, 'MountainCar-v0', video_length=1000, video_name="mountaincar_curious_agent")观察重点:
- 基线模型视频:小车可能只在谷底轻微左右移动,从未接近山顶。
- 好奇心模型视频:小车会表现出更积极的探索行为,左右摆动幅度更大,最终可能会展示出经典的“摇摆”策略:先向左后退积蓄势能,再向右冲刺上山。
通过对比这两个视频,你能最直观地感受到“好奇心”作为内在驱动力,如何改变了智能体的行为模式,使其在缺乏明确指引的环境中,依然能通过自主探索找到解决方案。
7. 常见问题与排查思路
在实现和运行好奇心驱动学习的过程中,你可能会遇到以下典型问题:
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| 训练不稳定,奖励曲线震荡剧烈 | 好奇心奖励权重(curiosity_weight)设置过大。 | 观察训练日志,分别打印外部奖励和内在奖励的曲线。如果内在奖励均值远高于外部奖励。 | 逐步调低curiosity_weight(如从0.1调到0.01,0.001),直到总奖励曲线趋于稳定。 |
| 智能体完全忽视外部任务,行为怪异 | 陷入了“噪声电视”问题,或好奇心模型过强主导了策略。 | 检查环境中是否存在完全随机、不可预测的噪声源。观察智能体是否沉迷于某个无意义的动作循环。 | 1. 对状态进行预处理,过滤掉无关噪声。2. 使用更稳定的好奇心形式,如RND。3. 进一步降低好奇心权重,或设置内在奖励的衰减机制。 |
| 好奇心奖励很快降为零,探索停止 | 好奇心模型学习过快,迅速拟合了环境动态。 | 在训练初期记录预测误差(内在奖励)的变化。如果误差在几百步内就快速收敛到接近零。 | 1. 降低好奇心模型的学习率(lr)。2. 使用更复杂/更深的网络作为好奇心模型,增加其学习难度。3. 引入随机性,如对好奇心模型的预测添加噪声。 |
| 代码报错:维度不匹配 | 环境的状态(state_dim)或动作(action_dim)维度获取错误,或张量拼接出错。 | 打印env.observation_space.shape和env.action_space。检查CuriosityModel.forward中输入张量的形状。 | 根据环境空间类型(Box连续空间或Discrete离散空间)正确获取维度。离散动作需转换为one-hot编码或整型处理。 |
| MountainCar环境中,有好奇心也学不会 | 训练步数(total_timesteps)可能仍然不足,或超参数(如PPO的learning_rate)不适用于当前环境+好奇心组合。 | 尝试大幅增加训练步数(如到50万步)。调整PPO或其他基础算法的超参数。 | 稀疏奖励环境本身难度高,需要耐心和更多的探索。可以尝试结合其他探索技术,如好奇心 + 熵奖励。 |
| 内存占用过大或训练极慢 | 好奇心模型每一步都进行反向传播更新,计算开销大。 | 使用nvidia-smi或任务管理器监控GPU/内存使用。 | 1. 增加CuriosityWrapper中更新模型的频率(如每N步更新一次)。2. 使用更小的好奇心网络。3. 在更简单的环境上验证原理后,再挑战复杂环境。 |
8. 最佳实践与进阶思考
在工程和研究中应用好奇心驱动学习时,以下几点建议可以帮助你走得更远:
- 始于简单环境:不要一开始就在
Atari或MuJoCo等复杂环境上尝试。从CartPole,MountainCar,GridWorld等经典环境开始,验证代码正确性并理解好奇心奖励的动态变化。 - 权重调参是关键:
curiosity_weight是平衡外部任务和内在探索的最重要超参数。建议从一个小值(如0.01)开始,根据训练过程中外部奖励和内在奖励的比例关系进行调节。一个经验法则是,在训练初期,内在奖励的均值不应超过外部奖励均值的10倍。 - 分离评估环境:正如我们代码中所做,评估时一定要使用原始环境。训练时使用好奇心增强的环境是为了提供探索激励,但最终评价标准是智能体在原始任务上的表现。
- 好奇心形式的多样性:本文实现的是最基础的基于预测误差的好奇心。在实践中,可以探索:
- 随机网络蒸馏(RND):通过一个固定随机初始化的“目标网络”和一个训练的“预测网络”之间的误差来衡量新颖性,对随机噪声更鲁棒。
- 基于计数的好奇心:直接估计状态被访问的频率,越罕见的状态奖励越高。
- 信息增益(Empowerment):衡量智能体行动影响未来状态的能力。
- 与现有算法结合:好奇心模块是一个通用插件,可以很容易地与大多数基于奖励的强化学习算法(如DQN, A2C, PPO, SAC)结合。只需像本文一样,在环境层面进行奖励重塑即可。
- 应对“噪声电视”:这是基于预测误差好奇心的致命弱点。除了使用RND,还可以考虑:
- 特征学习:训练一个编码器,将原始状态映射到对任务更有意义的特征空间,在这个空间计算预测误差。
- 忽略不可控部分:在预测模型中,只预测智能体动作可能影响的那部分状态变化。
- 记录与可视化:务必同时记录并可视化外部奖励、内在奖励和总奖励的曲线。这能帮助你诊断智能体是在学习任务,还是在盲目探索。
好奇心驱动学习将强化学习智能体从“唯奖励是图”的短视行为中解放出来,赋予其一种更接近生命体的、主动认识世界的内在动力。它不仅是解决稀疏奖励问题的利器,更是迈向通用人工智能探索机制的重要一步。通过亲手实现这个模块,并将其应用于经典难题,你已掌握了这一前沿概念的核心实践方法。下一步,你可以尝试将其移植到更复杂的自定义环境中,或者研究ICM、RND等更高级的论文实现,探索自主智能的更多可能性。