引入专家约束

引入专家约束可以为模型的训练和推断提供专业领域知识支持,避免从数据中学习到的环境模型违背约束的知识,减少任务难度,并提高环境模型预测精度。

在冰箱温度控制任务中,存在一个专家先验,即冰箱功率增大会导致冰箱温度下降的负相关关系。将这个负相关关系作为一个专家约束,对模型的训练和推断可以提供专业领域知识的支持, 有效地避免了从数据中学习到的环境模型与约束知识违背的情况。在模型中引入这个约束可以降低任务难度并提高预测精度,在实践中具有很高的应用价值。

REVIVE SDK支持以函数的形式引入专家约束。构建的方式类似于 奖励函数,约束函数根据环境转移是否违背约束来给予一个奖励。

下面是一个为冰箱示例引入专家约束的示例,首先我们定义一个类似奖励函数的专家约束:

import torch
from copy import deepcopy
from typing import Dict

# 是否对计算出奖励值进行归一化处理,默认False
normalize = False
# 计算出的奖励值的权重,可以修改进行调节,也可以直接在下面的函数中进行调节
weight = 1.0

# 配置matching_nodes可以帮助将规则放入指定的匹配器,也可以不配置
matching_nodes = ["temperature", "action", "next_temperature"]

# 函数名应该定义为get_reward
def get_reward(data : Dict[str, torch.Tensor], graph) -> torch.Tensor:
    # 拷贝一份原始数据
    noise_data = deepcopy(data)
    # 对原始数据的action节点加一个随机噪音
    noise_data["action"] += torch.randn_like(noise_data["action"]) * 0.1

    # 使用加噪之后的数据计算next_temperature节点的输出
    node_name = "next_temperature"
    if graph.get_node(node_name).node_type == 'network':
        # 调用graph计算网络节点输出
        node_output = graph.compute_node(node_name, noise_data).mode
    else:
        # 调用graph计算函数节点输出
        node_output = graph.compute_node(node_name, current_batch)

    # 计算action节点的变化和next_temperature节点变化的相关性
    correlation = ((noise_data["action"] - data["action"]) * (node_output-data[node_name]))

    # 如果存在正相关,则给出-0.2的奖励值,否则输出0的奖励值
    reward = torch.where(correlation> 0, -0.2 * torch.ones_like(correlation[...,:1]), torch.zeros_like(correlation[...,:1]))

    return reward

需要注意,在使用专家约束函数对数据进行处理时,通常会将多个数据按批量(batch)组织起来进行一次性运算处理。这种方式可以提高代码的运行效率。 因此,在编写奖励函数时,需要注意保证函数能够处理与输入张量形状相对应的多维数据。此外,在计算专家约束函数输出时,我们通常会关注最后一维的特征维度。 为方便处理,专家函数的计算维度通常都设在了最后一维。因此,在使用数据时需要使用切片([..., n:m ])的方式获取数据的最后一维的特征, 并对特征进行计算。而对应返回的reward应该是一个对应的Pytorch Tensor,batch维度保持和输入数据一致, 最后一维特征的维度应该是1。

通过-mrf参数引入专家约束函数进行环境训练的命令

python train.py -df test_data.npz -cf test.yaml -mrf data/test_rule.py -rf test_reward.py -vm once -pm once --run_id once

可以运行的示例请参考冰箱案例中的README文件。