跳转到内容

响应曲线分析

什么是响应曲线

响应曲线是描述系统或过程中输入与输出关系的图形表现。通常在二维图上绘制,输入变量在横轴 (x 轴) 上,输出变量在纵轴 (y 轴) 上。输入变量可以是任何可测量的参数,例如频率、时间、电压或温度等。输出变量可以是任何受输入影响的参数,例如幅度、相位、功率或电阻等。

在许多领域,响应曲线被用于分析和优化系统或过程的性能。例如,在音频工程中,扬声器的频率响应曲线显示了其对不同频率声音的输出水平变化。通过分析这条曲线,工程师可以确定扬声器的频率范围、灵敏度和失真特性,并根据需要进行设计调整。同样,在电子学中,响应曲线可用于分析电路或设备的性能:例如,晶体管的电流电压(I-V) 曲线显示了其输出电流随输入电压变化的情况。通过分析这条曲线,工程师可以确定晶体管的工作区域、增益和线性度,并为不同应用优化其性能。响应曲线也可用于比较不同系统或过程。例如,对比不同音频扬声器或电子设备的响应曲线,可以帮助工程师选择最适合特定应用的选项。总之,响应曲线是分析和优化许多领域中系统和过程性能的重要工具。通过提供输入和输出变量之间关系的图形表现,它们帮助工程师和科学家了解系统或过程的特性,并做出有根据的决策来改进它们。

REVIVE也提供了绘制响应曲线的功能。有以下两种方式调用响应曲线的绘制:

自动绘制

config.json 文件中 base_config 域下配置 defaulttrue 即为开启响应曲线绘制, false 关闭。

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/<run_id>/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

该目录下每个文件夹对应决策流图中一个网络节点,比如这里 actionnext_temperature 是网络节点,他们作为输出变量。每个文件夹中有若干图片,分别代表不同输入对这个输出的响应曲线,比如 action_on_temperature.png 代表 actiontemperature 的响应曲线。

如下所示:

image

可以看到有 16 幅子图,这是从数据集中随机采样 16 个数据点所绘而成。 x 轴代表了自变量 temperature 的变化范围,y 轴代表因变量 action 的变化趋势。 红线代表训练环境的预测值,蓝线代表验证环境的预测值。从图中可以看到:随着 temperature 逐渐升高,冰箱电机的功率(action)逐渐增大,使得冰箱内温度稳定在目标温度 -2 度左右。并且其中训练环境与验证环境的趋势基本一致,表明两个环境的一致性还挺好。 我们还可以计算 2 个环境之间的 MAE 以及 Spearman Correlation 系数,我们可以在每个16宫格的小标题处看到这些信息。 需要说明的是 MAE以及 Correlation 系数是在 16 个子图中,以及每个 action 上做了平均。

手动绘制

REVIVE 中提供了手动绘制响应曲线的脚本。

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_obsaction 的响应曲线。 如下所示:

image

下面我们详细解释响应曲线是如何生成。假定我们的数据有以下形式定义:

obsContinuous(17,)Si=[s0i,s1i,...,s16i]
actionContinuous(6,)Ai=[a0i,a1i,...,a5i]
next_obsContinuous(17,)NSi=[ns0i,ns1i,...,ns16i]

首先,我们从数据集中采样 16 个数据点:(S0,A0,NS0),(S1,A1,NS1),...,(S15,A15,NS15)。例如,宫格图 (next_obs_dim: t , action_dim: k) 中有 16 个子图,它们代表:我们对 aki 取遍 action 第 k 维的数据范围,也即 [1,1] 中取遍每一个值,同时观察 nsti 的变化情况。也就是说,在给定 Si 的情况下,观察 nstiaki 的响应情况。这里 i[0,15], t[0,16], k[0,5]

绘制多步长响应曲线

另外在REVIVE1.0当中我们新增加了多步长响应曲线的绘制功能,在此功能下用户可以根据自己的定义对多步的响应曲线进行绘制。


python
import pickle
from revive.data.dataset import OfflineDataset
from revive.utils.common_utils import  rollout_response_curve

if __name__ == "__main__":
   node_name = 'cat_delta_obs_reward' #替换成需要进行画图的节点
   dataset_path = "data/halfcheetah-medium-v2.npz"  # 替换为对应数据集路径
   yaml_path = "data/halfcheetah-medium-v2.yaml"  # 替换为对应 yaml 文件路径
   venv = pickle.load(open("logs/revive/env.pkl", 'rb'), encoding='utf-8')

   expert_func_dict = {'action_0+10': {'node':'action', 'dim':0, 'func':'rollout_response_func.action_0_add_10'},
                       'action_0+20': {'node':'action', 'dim':0, 'func':'rollout_response_func.action_0_add_20'}}
   plot_path = './rollout_response'

   dataset = OfflineDataset(dataset_path, yaml_path, None)
   rollout_response_curve(dataset, venv, expert_func_dict, node_name, plot_path, 100)

其中, expert_func_dict 中用户可以根据自己的设定,对所需要修改的数据节点和维度进行修改, func 中包含了用户设定所必要的专家函数。 在示例中,我们需要对 action 节点的第0维进行加法运算,其中 action_0+10 是将第0维加10, action_0+20 是将第0维加20。 那么REVIVE则会先将随机算则的某一条轨迹 action 节点先进行用户专家函数所定义的操作,然后将结果带入到模型中进行单步推演, 得到轨迹中 node_name 所对应的结果,并绘制多步长响应曲线。

专家函数的格式如下所示:

python
import torch
import numpy as np

def action_0_add_10(data):
   action = data['action']
   action[..., 0 ] += 0.1
   return action


def action_0_add_20(data):
   action = data['action']
   action[..., 0 ] += 0.2
   return action

最后我们得到了根据用户设定绘制的多步长响应曲线图。

image