专家特征库
REVIVE 提供可复用的专家特征,用于将领域公式和先验信息加入模型输入。本页列出内置特征、公式语法和自定义特征的注册方式。
概述
在实际工业场景中,领域专家积累了大量经验公式与机理知识——例如污水处理的水力停留时间、供水系统的氯衰减规律、化工反应的 Monod 动力学。这些知识往往以「不成文」的形式存在,在建模时被忽略,或需要每次从头实现。
专家特征库提供了一套统一机制,将这类知识编码为可复用的计算模块,在数据驱动模型中作为额外输入特征使用。其核心价值在于:
- 物理一致性:模型的中间表示包含有明确物理意义的量,不依赖数据量即可学到正确的归纳偏置
- 可复用性:同一份知识只需实现一次,可在不同项目、不同节点间共享使用
- 可学习参数:公式中的物理参数可以设为可学习,让模型从数据中反演真实物理系数
- 零侵入集成:以独立特征节点接入计算图,不修改任何已有网络结构
快速上手
在模型中使用内置特征
YAML 配置中,在任意节点的 expert_features 字段引用特征名即可:
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 中直接定义公式
无需预先注册,任何公式都可以在配置文件中直接编写:
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 建立映射:
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 / Q | V(容积), Q(流量) |
srt | 污泥停留时间 | V × MLSS / Q_waste | V, MLSS, Q_waste |
fm_ratio | 食微比 | Q × S0 / (V × MLSS) | Q, S0, V, MLSS |
volumetric_load | 容积负荷 | Q × S0 / V | Q, S0, V |
反应动力学
| 特征名 | 物理含义 | 公式 | 参数 |
|---|---|---|---|
monod | Monod 底物限制因子 | 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 |
arrhenius | Arrhenius 速率因子 | exp(−Ea / RT) | Ea, R |
化工过程
| 特征名 | 物理含义 | 公式 | 所需变量 |
|---|---|---|---|
residence_time | 停留时间 τ | V / Q | V, Q |
space_velocity | 空速 SV | Q / V | Q, V |
damkohler | Damköhler 数 Da | k × τ | k, tau |
conversion | 转化率 X | (C_in − C_out) / C_in | C_in, C_out |
编写自定义特征
当内置模板不满足需求,或需要将复杂的多步计算封装为可复用模块时,可以用 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,自动处理分母接近零的情况。
更多示例
多参数可学习特征(适合物理系数反演):
@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)多维输出特征(同时输出多个相关量):
@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) 定位,没有单独的 命令行参数),因此只需按如下结构组织目录:
my_project/
├── config.yaml
└── custom_networks/
└── water_features.py # 其中是 @register_expert_feature 标注的类revive train --config my_project/config.yaml --train-data data/train.npz单独导出时不经过配置解析,需显式指定注册位置:revive export --artifact ... --project my_project。
使用 Python API 时,在调用 revive.run(...) 之前 import 一次即可:
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 树完整验证,不合法的公式在配置加载时即报错,不会运行到训练阶段
完整示例:次氯酸钠投加控制
以清水池余氯控制场景为例,展示专家特征的完整应用:
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),计算基于历史的特征(如滑动平均水力负荷) |
| 多节点共享 | 同一个特征类在多个图节点中可独立实例化,参数互不干扰 |