ClassDef BaseSimulatedEnv
BaseSimulatedEnv: BaseSimulatedEnv类的功能是作为模拟环境的基础类,提供与强化学习环境交互的基本接口。
属性:
ensemble_models
: 用于评估的模型集合。env_task
: 环境任务的实例。observation_space
: 观察空间。action_space
: 动作空间。cum_reward
: 累计奖励。total_turn
: 总回合数。env_name
: 环境名称。predicted_mat
: 预测矩阵。MIN_R
: 预测奖励的最小值。MAX_R
: 预测奖励的最大值。cur_user
: 当前用户状态。
代码描述:
BaseSimulatedEnv类继承自gym.Env
,提供了与仿真环境交互的基本方法,包括初始化、重置环境、执行动作、渲染环境等。在初始化方法中,它接受模型集合、环境任务类、任务环境参数、任务名称和预测矩阵作为输入,初始化环境的基本属性,如观察空间、动作空间和累计奖励等。reset
方法用于重置环境到初始状态,step
方法用于在环境中执行一个动作并返回新的状态、奖励、是否终止等信息。此外,该类还提供了render
方法用于渲染环境,seed
方法用于设置随机种子,以及内部方法用于计算预测奖励、重置历史记录等。
从项目中的调用情况来看,BaseSimulatedEnv类被用作构建不同类型的模拟环境的基础,例如IntrinsicSimulatedEnv
、PenaltyEntExpSimulatedEnv
和PenaltyVarSimulatedEnv
等派生类。这些派生类通过继承BaseSimulatedEnv类并扩展或重写部分方法,实现了具有特定特性的模拟环境,如考虑项目相似性和流行度的内在奖励机制、基于曝光干预的奖励机制等。
注意:
- 在使用BaseSimulatedEnv类及其派生类时,需要确保传入的模型集合、环境任务类和任务环境参数等均符合预期的格式和要求。
- 在进行环境交互时,应注意调用
reset
方法初始化环境状态,并通过step
方法执行动作和获取环境反馈。
输出示例:
调用reset
方法可能返回的示例输出为:
(state, {'cum_reward': 0.0})
其中state
表示环境的初始状态,cum_reward
为累计奖励,初始值为0.0。
FunctionDef init(self, ensemble_models, env_task_class, task_env_param, task_name, predicted_mat)
init: 此函数用于初始化模拟环境的基础设置。
参数:
- ensemble_models: 用于预测的模型集合。
- env_task_class: 环境任务的类。
- task_env_param: 传递给环境任务类的参数,为字典类型。
- task_name: 环境任务的名称,为字符串类型。
- predicted_mat: 预测矩阵,可选参数。
代码描述:
此函数是BaseSimulatedEnv
类的构造函数,负责初始化模拟环境的各项基础设置。首先,通过调用ensemble_models.eval()
来获取模型集合的评估结果,并将其赋值给self.ensemble_models
。接着,使用env_task_class
和task_env_param
来创建环境任务实例,并将其赋值给self.env_task
。此外,从环境任务实例中获取观察空间和动作空间,分别赋值给self.observation_space
和self.action_space
。
初始化过程中还会设置累积奖励(self.cum_reward
)和总转数(self.total_turn
)为0,这两个变量用于在模拟过程中跟踪环境的性能。环境名称通过参数task_name
传入,并赋值给self.env_name
。如果提供了predicted_mat
参数,则将其赋值给self.predicted_mat
,并基于此矩阵计算最小和最大奖励值,分别赋值给self.MIN_R
和self.MAX_R
。
构造函数中调用了self._reset_history()
方法来重置环境的历史动作记录,这是为了确保每次实验开始时,环境处于干净的初始状态。最后,通过调用self.reset()
方法来重置环境到初始状态,准备开始新的模拟实验。
注意:
- 在使用此构造函数初始化模拟环境时,需要确保传入的
ensemble_models
已经是处于评估模式的模型集合,这是因为在模拟环境中通常需要使用模型的推断功能而非训练功能。 predicted_mat
参数是可选的,如果在某些场景中不需要使用预测矩阵,可以不传递此参数。- 构造函数内部会调用
reset
方法,该方法的作用是重置模拟环境到初始状态,具体行为包括重置累积奖励、总转数等,并根据环境名称处理当前用户信息,确保每次实验的独立性和一致性。
FunctionDef _construct_state(self, reward)
_construct_state: 此函数的功能是构建并返回模拟环境的当前状态。
参数:
- reward: 一个表示奖励的数值,用于在某些情况下与状态一起考虑,以便进行后续的处理和分析。
代码描述: _construct_state
函数是 BaseSimulatedEnv
类中的一个私有方法,它通过调用 env_task
的 state
方法来获取当前环境的状态,并将此状态作为结果返回。在这个过程中,env_task
是一个对 BaseEnv
或其子类的实例的引用,而 BaseEnv
类中的 state
方法负责生成并返回当前环境的状态,该状态通常是一个包含当前用户 (cur_user
) 和最近一次行动 (action
) 的 NumPy 数组。在 BaseSimulatedEnv
类的 step
方法中,_construct_state
被调用以获取模拟环境在执行了一个动作后的新状态。这个新状态随后被用于更新环境状态,并作为 step
方法的返回值之一,用于后续的决策或评估过程。
注意: _construct_state
方法的调用依赖于 env_task
的 state
方法正确实现,因此在使用 _construct_state
方法之前,需要确保 env_task
已经被正确初始化,并且其 state
方法能够反映环境的当前状态。此外,尽管 _construct_state
方法接受一个 reward
参数,但在当前实现中,这个参数并未被使用。开发者在未来的扩展或修改中,可以考虑如何结合奖励信息来优化状态的构建。
输出示例: 假设当前环境状态由当前用户 (cur_user
) 的值为 1 和最近一次的行动 (action
) 的值为 2 组成,则 _construct_state
方法的返回值可能如下:
array([1, 2])
这个输出示例反映了 env_task
的 state
方法的典型实现方式,即通过组合当前用户和最近一次的行动来构建环境状态。
FunctionDef seed(self, sd)
seed: 该函数用于设置随机数生成器的种子。
参数:
- sd: 种子值,默认为0。
代码描述:
seed
函数是BaseSimulatedEnv
类的一个方法,其主要作用是为PyTorch的随机数生成器设置一个固定的种子。通过调用torch.manual_seed(sd)
实现,其中sd
是一个整数,用作随机数生成的种子。设置种子是为了确保实验的可重复性,即在相同的种子和模型条件下,每次运行实验都能得到相同的结果。
注意:
- 在使用该函数时,应当注意
sd
参数的选择。不同的种子值会导致不同的随机数序列,进而可能影响模型训练和测试的结果。 - 该函数仅对使用PyTorch框架的环境有效。如果项目中使用了其他框架(如TensorFlow),则需要使用相应框架的种子设置方法。
FunctionDef reset(self)
reset: 此函数用于重置模拟环境到初始状态。
参数: 此函数不接受任何外部参数。
代码描述: reset
函数是 BaseSimulatedEnv
类的一个公共方法,负责将模拟环境重置到一个初始状态。该方法首先将累积奖励 (cum_reward
)、总转数 (total_turn
)、当前奖励 (reward
)、当前动作 (action
) 以及环境任务中的当前动作 (env_task.action
) 设置为其初始值。接着,调用环境任务的 reset
方法来获取初始状态 (state
) 和附加信息 (info
)。此外,通过调用 _reset_history
方法来重置环境的历史动作记录。
根据环境名称 (env_name
) 的不同,reset
方法会以不同的方式处理当前用户 (cur_user
)。如果环境名称为 "VirtualTB-v0",则当前用户信息从状态的最后三个元素之前获取;若环境名称为 "KuaiEnv-v0",则当前用户信息从状态的第一个元素获取。最后,函数返回环境的初始状态和一个包含累积奖励的字典。
在项目中,reset
方法在 BaseSimulatedEnv
类的构造函数 (__init__
) 中被调用,以确保每次创建环境实例时,环境都被初始化到一个干净的初始状态。此外,reset
方法可以在环境运行过程中被外部调用,以重新开始一个新的环境实例。
注意: 虽然 reset
方法不接受外部参数,但其行为受到环境名称 (env_name
) 的影响。因此,在使用此方法之前,应确保正确设置了环境名称。
输出示例: 假设环境的初始状态为 [0.5, 0.3, 0.2]
,则 reset
方法可能返回如下值:
([0.5, 0.3, 0.2], {'cum_reward': 0.0})
FunctionDef render(self, mode, close)
render: 此函数的功能是渲染环境的视图。
参数:
- mode: 渲染模式,默认为'human'。此参数决定了渲染的方式或目标,例如直接在屏幕上显示或者保存为文件等。
- close: 是否关闭渲染视图,默认为False。此参数用于控制在渲染后是否需要关闭或清理渲染产生的资源。
代码描述:
render
函数是BaseSimulatedEnv
类的一个方法,用于渲染模拟环境的当前状态。它接受两个参数:mode
和close
。mode
参数用于指定渲染的模式,而close
参数用于指示是否需要在渲染后关闭视图。在函数体内,通过调用self.env_task.render(mode)
方法来实现具体的渲染逻辑,其中self.env_task
是一个表示环境任务的对象,其具体的render
方法将根据传入的mode
参数来执行相应的渲染操作。
注意:
- 在使用
render
方法时,需要注意mode
参数的取值,不同的模式可能对应不同的渲染效果或目标。例如,某些模式可能会将渲染结果显示在屏幕上,而另一些模式可能会将结果保存到文件中。 - 如果在渲染过程中不需要关闭视图或释放资源,可以保持
close
参数的默认值False。如果需要在渲染完成后关闭视图或清理资源,应将close
参数设置为True。 - 在实际应用中,应根据环境任务的具体需求和特性来合理使用
render
方法,以达到预期的渲染效果。
FunctionDef _compute_pred_reward(self, action)
_compute_pred_reward: 该函数的功能是计算预测奖励。
参数:
- action: 执行的动作,用于计算预测奖励。
代码描述:
_compute_pred_reward
函数根据当前环境名称 (env_name
) 来决定如何计算预测奖励。如果环境名称为 "VirtualTB-v0",则使用用户模型来预测奖励;如果是其他环境(例如 "KuaiEnv-v0"),则通过查找预测矩阵来获取预测奖励。
对于 "VirtualTB-v0" 环境,函数首先将当前用户状态、奖励、总轮数和动作合并为一个特征向量,然后将该特征向量转换为张量并传递给用户模型以预测奖励。预测的奖励值会被限制在0到10之间。
对于其他环境,如 "KuaiEnv-v0",预测奖励是通过从预测矩阵中查找当前用户和动作对应的值,并减去最小奖励值 MIN_R
来获得的。
该函数在项目中被 step
函数调用,用于在每个步骤中计算预测奖励,并更新累计奖励和总轮数。这对于模拟环境中的决策过程是至关重要的,因为它影响了模拟环境的状态更新和信息反馈。
注意:
- 预测奖励的计算方法依赖于环境名称,因此在使用此函数时需要确保环境名称正确设置。
- 预测奖励值被限制在一个特定范围内(例如0到10),这可能需要根据具体应用场景进行调整。
输出示例:
假设在 "VirtualTB-v0" 环境中,给定一个动作,预测奖励可能为 5.3。如果是在 "KuaiEnv-v0" 环境中,给定相同的动作,预测奖励可能为 2(这取决于预测矩阵中的值和 MIN_R
)。
FunctionDef step(self, action)
step: 此函数的功能是执行一个动作并返回模拟环境的新状态及相关信息。
参数:
- action: FloatTensor类型,表示要在模拟环境中执行的动作。
代码描述:
step
函数是 BaseSimulatedEnv
类的核心方法之一,负责处理环境中的动作执行,状态转移,奖励计算,以及终止条件的判断。该函数首先通过调用 env_task
的 step
方法执行动作,并收集真实的状态转移信息,包括新的状态、奖励、是否终止等。接着,根据当前总轮数,如果小于环境任务允许的最大转数,会将动作添加到历史记录中,这一步骤通过调用 _add_action_to_history
方法实现。
随后,函数计算预测奖励,这是通过 _compute_pred_reward
方法完成的,该方法根据当前的动作和环境状态,使用预定义的用户模型或预测矩阵来估计奖励值。计算得到的预测奖励累加到累计奖励中,并更新总轮数。
最后,函数根据预测奖励构建新的环境状态,这一步通过 _construct_state
方法实现。同时,根据真实的终止条件设置模拟环境的终止标志,并构造返回的信息字典,其中包含累计奖励等信息。函数最终返回新的状态、预测奖励、终止标志、截断标志(此处始终为False),以及信息字典。
注意:
- 在调用
step
函数之前,确保env_task
已经被正确初始化,并且可以通过其step
方法获取真实的环境状态转移信息。 - 该函数的实现依赖于
_add_action_to_history
、_compute_pred_reward
和_construct_state
等方法,确保这些方法能够根据当前环境和策略正确执行。 step
函数的返回值中,terminated
和truncated
标志用于指示环境是否结束,其中terminated
表示环境是否自然结束,而truncated
在本实现中始终为False,表示环境是否因为达到最大步数而被截断。
输出示例:
假设执行一个动作后,预测奖励为5,累计奖励更新为15,环境未终止,那么 step
函数可能返回如下值:
(new_state, 5, False, False, {'cum_reward': 15})
其中 new_state
是根据预测奖励构建的新状态,5
是预测奖励,第一个 False
表示环境未终止,第二个 False
表示环境未被截断,字典中的 'cum_reward': 15
表示当前的累计奖励。
FunctionDef _reset_history(self)
_reset_history: 该函数用于重置环境历史动作记录。
参数: 此函数不接受任何外部参数。
代码描述: _reset_history
函数是 BaseSimulatedEnv
类的一个私有方法,用于在模拟环境中重置历史动作记录。根据环境名称 (env_name
) 的不同,此函数会以不同的方式初始化 history_action
属性。如果环境名称为 "VirtualTB-v0",则 history_action
被初始化为一个零矩阵,其形状由环境任务 (env_task
) 的最大转数 (max_turn
) 和动作空间的形状 (action_space.shape[0]
) 决定。对于其他环境名称(例如 "KuaiEnv-v0"),history_action
则被初始化为一个整型的零向量,其长度由环境任务的最大转数决定。此外,max_history
属性被设置为 0,表示当前没有历史动作记录。
在项目中,_reset_history
函数被 __init__
和 reset
方法调用。在 __init__
方法中,_reset_history
被调用以初始化环境的历史动作记录,这是创建 BaseSimulatedEnv
实例时的必要步骤之一。在 reset
方法中,每次环境重置时都会调用 _reset_history
,以确保在新的环境实例中不会保留上一次实验的历史动作记录。这对于模拟环境的正确运行至关重要,确保每次实验开始时环境状态是干净的。
注意: _reset_history
是一个内部方法,仅在 BaseSimulatedEnv
类的内部使用,不应直接从类外部调用。正确的使用方式是通过调用 reset
方法或在类的初始化过程中让其自动执行,以保证环境的历史动作记录被正确初始化或重置。
FunctionDef _add_action_to_history(self, t, action)
_add_action_to_history: 该函数的功能是将执行的动作添加到历史记录中。
参数:
- t: 当前时间步,表示动作发生的时间。
- action: 执行的动作,其具体类型和结构取决于环境。
代码描述:
_add_action_to_history
函数是BaseSimulatedEnv
类的一个私有方法,用于在模拟环境中跟踪每一步执行的动作。该函数首先检查环境名称(self.env_name
),以确定如何处理和存储动作。如果环境名称为"VirtualTB-v0",则会将动作扩展一个维度后存储;否则,直接存储动作。此外,该函数还断言当前的最大历史记录索引(self.max_history
)与传入的时间步t
相等,然后将最大历史记录索引加一,以便于后续动作的记录。
在项目中,_add_action_to_history
函数被step
方法调用。在step
方法中,首先通过环境任务(self.env_task
)执行动作并获取实际的状态转移信息,然后在满足条件的情况下(即当前时间步小于环境任务允许的最大转数),调用_add_action_to_history
函数记录这一动作。这样做的目的是为了在模拟环境中跟踪动作的执行历史,这对于后续的环境状态重构、奖励预测等操作至关重要。
注意:
- 确保在调用此函数之前,环境名称(
self.env_name
)已正确设置,因为不同的环境可能需要不同的动作处理方式。 - 该函数假设传入的时间步
t
与当前的最大历史记录索引self.max_history
相等。如果在实际使用中存在不一致的情况,可能会触发断言错误,因此在调用此函数前需要确保时间步的正确性。 - 由于该函数直接修改了类的内部状态(如历史动作记录和最大历史记录索引),在并发环境下使用时需要注意线程安全问题。