Jupyter中循环执行与重复运行单元格时Gymnasium对象行为差异
问题分析与解决办法
问题现象
- 单循环单元格重复执行:每次运行都会输出随机终止步数,符合环境内部随机性的预期
- 嵌套循环执行:首次循环输出随机步数,后续所有循环均以达到
max_steps=1000终止,环境自身的随机终止条件不再触发 - 环境仅实例化一次,无默认可变参数类错误,两种执行模式的结果稳定可复现
可能原因
自定义环境
reset()方法未完全重置状态:
你的BasicInfusion-v0环境可能在reset()时,遗漏了部分影响终止条件的状态变量重置。比如某些与随机性相关的内部状态仅在首次初始化时设置,后续reset()未更新,导致终止条件无法触发,只能走到max_steps。Jupyter执行上下文与Gymnasium随机数生成器的交互问题:
Jupyter的全局执行上下文可能保留了随机数生成器的状态,当在嵌套循环中连续调用reset()时,Gymnasium封装的np_random生成器未正确重新初始化,导致环境失去随机性,无法触发提前终止。
解决办法
方法1:显式为每次reset()传入动态随机种子
在每次调用reset()时传入不同的随机种子,强制重置随机数生成器状态:
import random for loopv in range(20): j = 0 # 每次重置时传入新的随机种子 be.reset(seed=random.randint(0, 100000)) while True: t = be.step((1, 1)) j += 1 if t[2]: print('Terminating after {}\n\n'.format(j)) break
方法2:检查并修复自定义环境的reset()方法
确认BasicInfusion-v0的reset()方法完全重置了所有必要状态:
- 重置所有与环境动态变化相关的变量(如当前速度、体积等)
- 确保调用父类的
reset(seed=seed)方法,保证np_random生成器正确初始化 - 检查终止条件依赖的所有变量是否在
reset()时被重置
示例修复后的reset()方法:
class BasicInfusionEnv(gymnasium.Env): def reset(self, seed=None, options=None): # 调用父类reset,确保随机数生成器正确初始化 super().reset(seed=seed) # 重置自定义状态变量 self.current_speed = 0 self.current_volume = 0 # ...其他需要重置的状态 return observation, info
方法3:嵌套循环内重新初始化环境(临时验证方案)
如果上述方法无效,可以在每次循环中重新创建环境实例,验证问题是否来自状态残留:
kwargs = {'width':10,'length':10,'max_speed':12,'max_volume':200,'back_upper_bound':10,'back_limit':5, 'ksp':1,'kpv':0.1,'kvl':0.5,'kbp':1,'kds':1,'kss':500,'vid_frequency':1,'max_steps':1000} for loopv in range(20): j = 0 # 每次循环重新创建环境 be = gymnasium.make('BasicInfusion-v0', render_mode='rgb_array', **kwargs) be.reset() while True: t = be.step((1, 1)) j += 1 if t[2]: print('Terminating after {}\n\n'.format(j)) be.close() break
内容的提问来源于stack exchange,提问作者TimNewman
相关产品推荐
相关产品推荐

