跳转到内容

专家特征库 ​

REVIVE 提供可复用的专家特征,用于将领域公式和先验信息加入模型输入。本页列出内置特征、公式语法和自定义特征的注册方式。

概述 ​

在实际工业场景中,领域专家积累了大量经验公式与机理知识——例如污水处理的水力停留时间、供水系统的氯衰减规律、化工反应的 Monod 动力学。这些知识往往以「不成文」的形式存在,在建模时被忽略,或需要每次从头实现。

专家特征库提供了一套统一机制,将这类知识编码为可复用的计算模块,在数据驱动模型中作为额外输入特征使用。其核心价值在于:

  • 物理一致性:模型的中间表示包含有明确物理意义的量,不依赖数据量即可学到正确的归纳偏置
  • 可复用性:同一份知识只需实现一次,可在不同项目、不同节点间共享使用
  • 可学习参数:公式中的物理参数可以设为可学习,让模型从数据中反演真实物理系数
  • 零侵入集成:以独立特征节点接入计算图,不修改任何已有网络结构

快速上手 ​

在模型中使用内置特征 ​

YAML 配置中,在任意节点的 expert_features 字段引用特征名即可:

yaml
graph:
  columns:
    obs: [V, Q, S, DO, T]
    action: [Q_waste]
  nodes:
    delta_state:
      inputs: [obs, action]

      expert_features:
        - name: hrt            # 水力停留时间 HRT = V / Q
          inputs: [obs]

        - name: monod           # Monod 限制因子 S / (Ks + S)
          inputs: [obs]
          params:
            Ks: 20.0

        - name: temp_correction # 温度修正因子 θ^(T-Tref)
          inputs: [obs]
          params:
            theta: 1.047
            T_ref: 20.0

框架会自动将这些特征计算后拼接,作为额外输入送入下游神经网络。

在 YAML 中直接定义公式 ​

无需预先注册,任何公式都可以在配置文件中直接编写:

yaml
expert_features:
  - name: dose_concentration
    formula: "D_eff * C_drug / Q_in"
    inputs: [obs, action]
    params:
      C_drug: 80.0         # 药液浓度 g/L

  - name: angular_acc
    formula: "g_coef * sin_theta + u_coef * torque"
    inputs: [obs, action]
    params:
      g_coef: 15.0
      u_coef: 3.0
    learnable: true        # 参数可学习,由数据反演真实物理系数

公式语法支持四则运算、指数对数、三角函数,以及对输入向量按索引访问(如 obs[2])。

将多维输入映射为有名变量 ​

当公式中的变量名与输入向量的列名不对应时,使用 input_slices 建立映射:

yaml
graph:
  nodes:
    delta_state:
      inputs: [obs, action]

      input_slices:
        H:      "obs[0]"      # 液位
        C_in:   "obs[1]"      # 入口余氯
        Q_out:  "obs[2]"      # 出水流量
        D_eff:  "action[0]"   # 实际投加量

      expert_features:
        - name: hrt_clearwell
          formula: "H * 1200.0 / Q_out"   # 清水池 HRT,面积 1200 m²

        - name: chlorine_decay
          formula: "C_in * exp(-0.05 * H * 1200.0 / Q_out)"

如果顶层 columns 已定义列名,框架会自动将列名注册为语义变量,无需重复声明 input_slices。

内置特征目录 ​

框架内置了覆盖三大领域的 14 个特征模板,开箱即用:

污水/供水处理 ​

特征名物理含义公式所需变量
hrt水力停留时间V / QV(容积), Q(流量)
srt污泥停留时间V × MLSS / Q_wasteV, MLSS, Q_waste
fm_ratio食微比Q × S0 / (V × MLSS)Q, S0, V, MLSS
volumetric_load容积负荷Q × S0 / VQ, S0, V

反应动力学 ​

特征名物理含义公式参数
monodMonod 底物限制因子S / (Ks + S)Ks(半饱和常数)
double_monod双 Monod 因子S/(Ks+S) × DO/(Ko+DO)Ks, Ko
do_saturation溶解氧饱和因子DO / (Ko + DO)Ko
inhibition底物抑制因子Ki / (Ki + S)Ki
temp_correction温度修正(van't Hoff)θ^(T−Tref)theta, T_ref
arrheniusArrhenius 速率因子exp(−Ea / RT)Ea, R

化工过程 ​

特征名物理含义公式所需变量
residence_time停留时间 τV / QV, Q
space_velocity空速 SVQ / VQ, V
damkohlerDamköhler 数 Dak × τk, tau
conversion转化率 X(C_in − C_out) / C_inC_in, C_out

编写自定义特征 ​

当内置模板不满足需求,或需要将复杂的多步计算封装为可复用模块时,可以用 Python 定义特征类。

特征类结构 ​

python
from revive.core.features import ExpertFeature, register_expert_feature
import torch

@register_expert_feature('chlorine_decay')
class ChlorineDecay(ExpertFeature):
    """一阶氯衰减模型: C(t) = C0 × exp(−k × HRT)

    适用于清水池/配水管网出口余氯预测。
    """
    # 声明所需输入变量名
    required_inputs = ['C0', 'HRT']
    # 输出维度(通常为 1)
    output_dim = 1
    # 可配置参数及其默认值
    params = {'k': 0.05}
    # 是否允许参数在训练中被优化
    learnable = False

    # 描述(`ExpertFeature` 声明的字段,会进 `to_dict()`)
    description = "一阶氯衰减预测"

    def compute(self, inputs):
        C0 = inputs['C0']
        HRT = inputs['HRT']
        return C0 * torch.exp(-self.k * HRT)

关键规则 ​

输入变量:required_inputs 中列出的每个变量名,框架会自动从 input_slices 或 columns 定义中解析并提取,输入 compute() 时为 Tensor 格式(形状 [B] 或 [B, D])。

输出形状:compute() 的返回值需为 [B, output_dim],框架会自动处理维度补齐。

参数访问:params 中声明的参数,通过 self.参数名 访问,在实例化时可覆盖默认值。若 learnable=True,参数会被注册为 nn.Parameter,参与梯度优化。

安全除法:直接使用 self.safe_div(a, b) 代替 a / b,自动处理分母接近零的情况。

更多示例 ​

多参数可学习特征(适合物理系数反演):

python
@register_expert_feature('cstr_decay')
class CSTRDecay(ExpertFeature):
    """CSTR 串联中的氯衰减: C_out = C_in / (1 + k × τ)"""
    required_inputs = ['C_in', 'tau']
    output_dim = 1
    params = {'k': 0.03}
    learnable = True   # 让模型从数据中学习真实的 k 值
    description = "CSTR 串联氯衰减(可学习速率常数)"

    def compute(self, inputs):
        C_in, tau = inputs['C_in'], inputs['tau']
        return self.safe_div(C_in, 1.0 + self.k * tau)

多维输出特征(同时输出多个相关量):

python
@register_expert_feature('cl2_mass_balance')
class Cl2MassBalance(ExpertFeature):
    """氯质量平衡: 同时输出投加量增量和衰减量"""
    required_inputs = ['D_eff', 'C_drug', 'Q_in', 'C_pool', 'HRT']
    output_dim = 2   # [投加浓度增量, 衰减量]
    params = {'k': 0.05}

    def compute(self, inputs):
        D_eff = inputs['D_eff']
        C_drug = inputs['C_drug']
        Q_in = inputs['Q_in']
        C_pool = inputs['C_pool']
        HRT = inputs['HRT']

        dose_delta = self.safe_div(D_eff * C_drug * 1000.0, Q_in)
        decay = C_pool * (1 - torch.exp(-self.k * HRT))
        return torch.stack([dose_delta, decay], dim=-1)

自定义特征的注册机制 ​

注册依赖 import 时执行的装饰器:@register_expert_feature('chlorine_decay') 在模块被导入 的那一刻将类写入注册表。因此问题只有一个——由谁来 import 该文件。

框架的项目目录发现机制(discover_custom_networks / discover_custom_functions)会导入 custom_networks/ 与 custom_functions/ 下的每个 .py。将特征定义放入其中任一目录,导入 随之发生,特征即完成注册;这两个发现机制只校验落入网络注册表的类,纯特征文件不受影响。

项目目录即配置文件所在的目录(Recipe 用 dirname(config) 定位,没有单独的 命令行参数),因此只需按如下结构组织目录:

text
my_project/
├── config.yaml
└── custom_networks/
    └── water_features.py      # 其中是 @register_expert_feature 标注的类
bash
revive train --config my_project/config.yaml --train-data data/train.npz

单独导出时不经过配置解析,需显式指定注册位置:revive export --artifact ... --project my_project。

使用 Python API 时,在调用 revive.run(...) 之前 import 一次即可:

python
import my_features          # 装饰器在这一行执行
import revive

revive.run(config="config.yaml", train_data="data/train.npz")

当前自定义特征通过显式导入完成注册。尚未提供专门的特征发现目录、安装后自动启用机制、 目录扫描环境变量或特征浏览 CLI。

安全性 ​

公式引擎在执行用户定义的公式字符串时采用严格的沙箱机制:

  • 白名单语法:仅允许数学运算符和预定义的安全函数(exp、log、sqrt、sin、cos 等)
  • 禁止代码注入:import、exec、eval、属性访问等一律拒绝
  • 数值稳定:除法自动添加保护项防止除零,exp 和 log 自动边界保护
  • AST 验证:公式在编译阶段经过 AST 树完整验证,不合法的公式在配置加载时即报错,不会运行到训练阶段

完整示例:次氯酸钠投加控制 ​

以清水池余氯控制场景为例,展示专家特征的完整应用:

yaml
graph:
  columns:
    obs:    [H, C_tank, C_out, Q_in, Q_out, D_actual, C_drug]
    action: [D_cmd_norm]
  nodes:
    delta_state:
      inputs: [obs, action]

      input_slices:
        H:        "obs[0]"      # 清水池液位 [m]
        C_tank:   "obs[1]"      # 池内监测点余氯 [mg/L]
        C_out:    "obs[2]"      # 出口余氯 [mg/L]
        Q_in:     "obs[3]"      # 进水流量 [m3/h]
        Q_out:    "obs[4]"      # 出水流量 [m3/h]
        D_actual: "obs[5]"      # 实际投加速率 [L/h]
        C_drug:   "obs[6]"      # 药液浓度 [g/L]

      expert_features:
        # 1. 当前清水池水力停留时间
        - name: hrt_clearwell
          formula: "H * 1200.0 / Q_out"

        # 2. 当前批次投加氯浓度(换算为 mg/L)
        - name: dose_concentration
          formula: "D_actual * C_drug * 1000.0 / Q_in"

        # 3. 出口余氯一阶衰减预测(可学习速率)
        - name: cl2_decay_pred
          formula: "C_tank * exp(-k_decay * H * 1200.0 / Q_out)"
          params:
            k_decay: 0.05
          learnable: true   # 从数据中反演真实衰减速率

        # 4. 余氯安全裕度(目标范围 0.8~1.0 mg/L 的居中程度)
        - name: cl2_margin
          formula: "C_out - 0.9"   # 相对目标中心的偏差

这 4 个特征向量与神经网络的其余输入拼接,使网络在学习状态转移规律时,天然具备对氯化学机理的感知能力。

与 REVIVE 其他功能的配合 ​

功能配合方式
混合建模网络专家特征适合作为混合网络的机理项输入,提供解析先验;其内部修正结构不改变 Graph 的 delta-only transition 约定
可学习参数反演learnable: true 配合 venv 训练阶段,可从轨迹数据中辨识物理参数(如衰减速率、动力学常数)
历史窗口专家特征节点可接收历史变量(var@-1),计算基于历史的特征(如滑动平均水力负荷)
多节点共享同一个特征类在多个图节点中可独立实例化,参数互不干扰