响应曲线 ============================================= 什么是响应曲线 ---------------------------- 响应曲线是描述系统或过程中输入与输出关系的图形表现。 通常在二维图上绘制,输入变量在横轴 (x 轴) 上,输出变量在纵轴 (y 轴) 上。输入变量可以是任何可测量的参数,例如频率、时间、电压或温度等。 输出变量可以是任何受输入影响的参数,例如幅度、相位、功率或电阻等。 在许多领域,响应曲线被用于分析和优化系统或过程的性能。 例如,在音频工程中,扬声器的频率响应曲线显示了其对不同频率声音的输出水平变化。 通过分析这条曲线,工程师可以确定扬声器的频率范围、灵敏度和失真特性,并根据需要进行设计调整。 同样,在电子学中,响应曲线可用于分析电路或设备的性能:例如,晶体管的电流电压 (I-V) 曲线显示了其输出电流随输入电压变化的情况。 通过分析这条曲线,工程师可以确定晶体管的工作区域、增益和线性度,并为不同应用优化其性能。 响应曲线也可用于比较不同系统或过程。 例如,对比不同音频扬声器或电子设备的响应曲线,可以帮助工程师选择最适合特定应用的选项。 总之,响应曲线是分析和优化许多领域中系统和过程性能的重要工具。 通过提供输入和输出变量之间关系的图形表现,它们帮助工程师和科学家了解系统或过程的特性,并做出有根据的决策来改进它们。 用 REVIVE SDK 绘制响应曲线 ---------------------------- REVIVE SDK 也提供了绘制响应曲线的功能。有以下两种方式调用响应曲线的绘制: 1. 在 ``config.json`` 文件中 ``base_config`` 域下配置 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ``default`` 中 ``true`` 即为开启响应曲线绘制, ``false`` 关闭。 .. code:: json { "base_config": [ ... { "name": "plt_response_curve", "abbreviation": "prc", "description": "Whether to plot response curve at the end of venv training.", "type": "bool", "default": true }, ... ], ... } } 这样 REVIVE 会在环境训练结束时自动绘制双环境(训练环境与验证环境)的响应曲线, 路径位于 ``logs//venv_train/response_curve``。 以冰箱温控为例,生成的文件目录结构如下:: response_curve |-- action | `-- action_on_temperature.png `-- next_temperature |-- next_temperature_on_action.png |-- next_temperature_on_door_open.png `-- next_temperature_on_temperature.png 该目录下每个文件夹对应决策流图中一个网络节点,比如这里 ``action`` 与 ``next_temperature`` 是网络节点,他们作为输出变量。 每个文件夹中有若干图片,分别代表不同输入对这个输出的响应曲线,比如 ``action_on_temperature.png`` 代表 ``action`` 对 ``temperature`` 的响应曲线。 如下所示: .. image:: images/action_on_temperature.png :align: center 可以看到有 16 幅子图,这是从数据集中随机采样 16 个数据点所绘而成。 x 轴代表了自变量 ``temperature`` 的变化范围,y 轴代表因变量 ``action`` 的变化趋势。 红线代表训练环境的预测值,蓝线代表验证环境的预测值。 从图中可以看到:随着 ``temperature`` 逐渐升高,冰箱电机的功率(``action``)逐渐增大,使得冰箱内温度稳定在目标温度 -2 度左右。 并且其中训练环境与验证环境的趋势基本一致,表明两个环境的一致性还挺好。 我们还可以计算 2 个环境之间的 ``MAE`` 以及 ``Spearman Correlation`` 系数,我们可以在每个16宫格的小标题处看到这些信息。 需要说明的是 ``MAE`` 以及 ``Correlation`` 系数是在 16 个子图中,以及每个 ``action`` 上做了平均。 高维数据请看下面的例子: 2. 通过调用 REVIVE SDK 提供的脚本绘制 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. code:: python import pickle from revive.data.dataset import OfflineDataset from revive.utils.common_utils import load_data, response_curve if __name__ == "__main__": dataset_path = "data/halfcheetah-medium-v2.npz" # 替换为对应数据集路径 yaml_path = "data/halfcheetah-medium-v2.yaml" # 替换为对应 yaml 文件路径 dataset = OfflineDataset(dataset_path, yaml_path).data venv = pickle.load(open("logs/revive/env.pkl", 'rb'), encoding='utf-8') # 换成对应环境的路径 save_path = "./response" # 设置保存路径 response_curve(save_path, venv, dataset) 以 HalfCheetah 为例,生成的文件目录结构如下:: response |-- action | `-- action_on_obs.png |-- delta_x | |-- delta_x_on_action.png | `-- delta_x_on_obs.png `-- next_obs |-- next_obs_on_action.png |-- next_obs_on_delta_x.png `-- next_obs_on_obs.png 比如 ``next_obs_on_action.png`` 代表 ``next_obs`` 对 ``action`` 的响应曲线。 如下所示: .. image:: images/next_obs_on_action.png :align: center 下面我们详细解释 response curve 是如何生成。假定我们的数据有以下形式定义: ================= ==================== ==================== obs Continuous(17,) :math:`S^i = [s^i_0, s^i_1, ..., s^i_{16}]` action Continuous(6,) :math:`A^i = [a^i_0, a^i_1, ..., a^i_5]` next_obs Continuous(17,) :math:`{NS}^i = [ns^i_0, ns^i_1, ..., ns^i_{16}]` ================= ==================== ==================== 首先,我们从数据集中采样 16 个数据点::math:`, , ..., `, 比如宫格 (``next_obs_dim: t`` , ``action_dim: k``) 中有 16 个子图, 它们代表:我们对 :math:`a^i_k` 取遍 action 第 k 维的数据范围,也即 [-1, 1] 中取遍每一个值。 同时观察 :math:`ns^i_t` 的变化情况。 就是说,在给定 :math:`S^i` 的情况下,观察 :math:`ns^i_t` 对 :math:`a^i_k` 的响应情况。 这里 :math:`i \in [0, 15], t \in [0, 17], k \in [0, 5]`。