4. 配方空间的设计变量选择

贝叶斯优化的第一步不是选代理模型,而是把“配方”翻译成优化器能读懂的向量。这一步做错,后面再精细的采集函数也救不回来。配方空间的设计变量编码,本质上要回答四个问题:哪些量是连续可调的、哪些量只能在候选集合里挑、哪些量是类别标签、以及这些量之间必须满足什么约束。本节围绕这四类变量,给出可落地的编码方式与归一化处理。

一、连续比例变量:先定基准,再决定用绝对量还是相对量

配方中最常见的是“份数”型连续变量,例如环氧树脂 100 份、固化剂 20~40 份、填料 0~60 份。这类变量有两种编码路线:绝对份数和相对比例。绝对份数直接以“每 100 份基体对应的添加份数”作为变量,物理意义直观,但各维量纲差异大,填料可能跨 0~60,而偶联剂只有 0.1~2,直接送进高斯过程会导致长度尺度被大量纲维度主导。

相对比例编码则把配方视为单纯形上的点:设各组分比例为 xi,满足 Σxi=1。此时可用“前 n−1 个比例 + 最后一个由 1 减出”的方式降维,避免共线。但纯比例会丢失“总添加量”这一自由度——同样比例下,总填料量不同,黏度和力学性能差异很大。因此更实用的做法是:把“总填充量”作为一个独立连续变量,把“各填料之间的分配比例”作为另一组变量,二者相乘还原实际份数。这样既保留了总量控制,又让比例维度落在同一量纲上。

二、离散原料与类别选择:候选集、序号与独热编码

离散原料指只能在有限牌号中选择的变量,例如“固化剂类型:A 牌、B 牌、C 牌”。这类变量不能当作连续量做插值,因为 A 牌和 B 牌之间没有“中间牌号”。最稳妥的编码是类别索引 + 候选表:在优化器内部用整数 0/1/2 表示,在评估函数中通过查表映射回真实牌号。整数编码的缺点是代理模型可能误认为 0 和 2 比 0 和 1 更“远”,因此当类别数较少(≤4)时,建议改用独热编码,把一维类别展开为多维 0/1 向量,让模型对各类别保持等距。

类别选择还包括“是否添加某助剂”这类二元开关。二元变量可直接用 0/1 表示,但要注意它与对应添加量变量存在耦合:开关为 0 时,添加量应被约束为 0,否则会出现“未添加却有份数”的无效配方。处理方式是在评估函数中做条件裁剪,而不是让优化器自由探索这个无效区域。

三、约束条件的编码:边界、线性约束与非线性约束

约束分三层。第一层是箱式边界,即每个变量的上下限,直接写在搜索空间定义里。第二层是线性约束,典型如“树脂 + 固化剂 + 填料 + 助剂 = 100 份”,或“填料 A + 填料 B ≤ 50 份”。这类约束可用等式消元或不等式投影处理:等式约束消去一个变量,不等式约束在采集候选点后做可行性过滤。第三层是非线性约束,例如“固化剂份数 / 环氧份数 落在 0.8~1.2 之间”,或“黏度预测值不超过 5000 mPa·s”。这类约束无法用简单投影处理,通常做法是在采集函数中引入可行性惩罚,或使用约束贝叶斯优化(如 EI 乘以可行概率)。

需要强调的是:约束不是越早裁剪越好。过早把搜索空间裁成不规则形状,会让初始化点难以均匀铺开。推荐流程是——先在大箱体内做拉丁超立方采样,再对样本做可行性过滤,保留可行点作为初始设计;后续迭代中,对每个候选点先判可行、再算采集值。

四、变量归一化:让每一维站在同一起跑线

归一化的目标不是“好看”,而是让核函数的长度尺度对各维公平。对连续变量,最常用的是 min-max 归一化到 [0,1]:x′=(x−xmin)/(xmax−xmin)。若某变量跨越多个数量级(如偶联剂 0.1~2 份),可先取对数再归一化。对类别变量,独热编码后本身就是 0/1,无需再归一化;若用整数索引,则不应做 min-max,否则会人为制造“中间类别”。对二元开关,保持 0/1 即可。

归一化参数必须固定:用初始设计阶段的边界确定 xmin、xmax,后续所有迭代都用同一组参数反归一化。若中途因约束收紧而改变边界,必须重新映射历史数据,否则代理模型会学到错误的距离关系。

配方空间设计变量编码与归一化流程 真实配方对象 环氧树脂 100 份 连续 · 基准固定 固化剂 20~40 份 连续 · 比例变量 填料 A/B/C 牌号 离散 · 类别选择 偶联剂 0.1~2 份 连续 · 跨数量级 是否加阻燃剂 二元 · 开关变量 约束:总量=100 份 固化剂/环氧 ∈ [0.8,1.2] 编码 优化器输入向量 x₁ 固化剂比例 min-max → [0,1] x₂ 总填充量 min-max → [0,1] x₃ 填料A占比 比例归一化 x₄ 填料B占比 比例归一化 x₅ 偶联剂 log → min-max x₆ x₇ x₈ 牌号独热 0/1 等距编码 x₉ 阻燃剂开关 0/1 约束投影 可行域判定与评估 ① 箱式边界检查 各维是否落在 [x_min, x_max] 越界 → 直接丢弃 ② 线性约束检查 Σ份数 = 100;填料A+B ≤ 50 不满足 → 投影或丢弃 ③ 非线性约束检查 固化剂/环氧 ∈ [0.8,1.2] 黏度预测 ≤ 5000 mPa·s ④ 反归一化 → 真实配方 查表还原牌号,计算实际份数 ⑤ 实验/仿真评估 返回目标值,更新代理模型 归一化参数在初始设计阶段固定,后续迭代统一复用,避免历史数据距离关系漂移

五、一个可复用的编码配置示例

下面给出一个配方优化任务的变量定义片段,展示如何把上述四类变量写进配置。示例参数为教学假设,实际使用时按真实边界替换。

variables:
  - name: curing_ratio        # 固化剂/环氧 比例
    type: continuous
    bounds: [0.8, 1.2]
    normalize: minmax
  - name: total_filler        # 总填充量(份)
    type: continuous
    bounds: [0, 60]
    normalize: minmax
  - name: filler_A_frac       # 填料A在总填充中的占比
    type: continuous
    bounds: [0, 1]
    normalize: none           # 比例本身已在 [0,1]
  - name: filler_B_frac
    type: continuous
    bounds: [0, 1]
    normalize: none
  - name: coupling_agent      # 偶联剂份数
    type: continuous
    bounds: [0.1, 2.0]
    normalize: log_minmax
  - name: hardener_grade      # 固化剂牌号
    type: categorical
    categories: [A, B, C]
    encode: onehot
  - name: flame_retardant     # 是否加阻燃剂
    type: binary
    bounds: [0, 1]

constraints:
  - type: equality
    expr: "resin + hardener + total_filler + coupling_agent == 100"
  - type: inequality
    expr: "filler_A_frac + filler_B_frac <= 1.0"
  - type: nonlinear
    expr: "viscosity_pred <= 5000"

这份配置的关键点有三处:其一,filler_A_frac 与 filler_B_frac 不做 min-max,因为它们本身就是比例,再归一化会破坏“和为 1”的语义;其二,coupling_agent 用对数归一化,避免 0.1~2 的跨度被压缩到几乎不可分辨;其三,等式约束在评估函数中通过“树脂份数 = 100 − 其余之和”自动满足,而不是让优化器在四维空间里盲目搜索一个三维流形。

判断编码是否合理的一个快速检验:随机生成 1000 个候选点,统计可行点比例。若可行率低于 5%,说明约束过紧或编码维度冗余,应先放宽边界或消去等式约束中的冗余变量,再启动贝叶斯优化。

六、常见错误与规避

  • 把类别当连续:用 0/1/2 表示牌号却做 min-max,会让模型认为 A 与 C 的距离是 A 与 B 的两倍。类别数少时改独热,类别数多时改用类别核或分组建模。
  • 归一化参数漂移:迭代中因约束收紧而修改边界,却未同步重映射历史数据,导致代理模型在旧尺度上训练、新尺度上预测。
  • 忽略开关与份数的耦合:阻燃剂开关为 0 时,其份数变量仍被采样,产生大量无效配方,浪费评估预算。
  • 等式约束未消元:把“总量=100”直接作为惩罚项,会让可行域变成一条窄带,初始化点几乎全部不可行。

把变量编码与归一化做扎实,配方空间就从“一堆原料名称”变成了“一个边界清晰、约束明确、各维可比的向量空间”。后续的代理模型、采集函数和实验设计,都建立在这个空间之上。