返回专辑
·Johan·4 分钟阅读

离散动作掩码:非法 move 别采样

棋类、调度里大量非法 action;logits mask 后再 softmax,否则浪费探索且梯度学错。

离散动作掩码:非法 move 别采样

1. 四千维 softmax,只有三十五个合法

国际象棋合法着法平均约三十五个,动作空间四千六百七十二。无掩码时概率质量分散在非法动作,采样浪费,梯度学错方向。棋类、调度、资源分配里大量非法 move;合法动作集合是动作空间的子集,策略 logits 对非法 index 设负无穷,再 softmax:

python
logits = logits.masked_fill(~legal_mask, float("-inf"))
probs = F.softmax(logits, dim=-1)

采样和对数概率都在 masked 分布上。非法动作概率应为零。训练时环境自动拒绝非法动作并给惩罚,不如掩码——后者梯度干净。

2. Mask 是契约,不是 penalty

Reject 式让 policy 学「试错 penalty」而非「不选非法」。Mask 逻辑写成纯函数,单测覆盖 corner case。Policy 网络只负责在合法集合上分布;环境不应靠「选了非法 action 给负一千 reward」来教合法性——那会让 value 曲面在非法区 arbitrary。Q-learning 若不对 illegal action mask max,会选非法 action——要在 Q 上对 illegal 设负无穷再 argmax。AlphaZero 系在 MCTS 里也 mask priors。

3. Train 与 eval 一致性

Train 和 eval 同一套 legal mask。Env 应提供 action_masks 或 info 里合法集。Mask 定义随 state 变,不能写死。库不内置 mask,要在 predict 前改 logits 或自定义 policy。Mask API 变更要 bump 版本号;下游换 mask 规则必须 retrain 或 fine-tune,无 silent compatibility。MCTS 与 policy 管线里 mask 必须同步:prior 在非法 action 上应为零。

4. 单测 corner case 与案例

全合法:softmax 正常。全非法:应 fallback 或 error,不应 NaN。唯一合法 action:prob 应为 1。Mask 漏了导致 NaN(全负无穷 softmax)。BC 数据含非法 action 未过滤,训练会污染。某调度 env 用 reject illegal 加 penalty 训练,policy 学会「试错 penalty」而非「不选非法」;换 mask 后同样步数 success rate 更高。

5. 象棋调度与 MCTS

国际象棋合法着法平均约三十五个,空间四千六百七十二;mask 后 softmax 只在三十五维上。无 mask 时概率质量分散在非法 action,采样浪费。AlphaZero 系在 MCTS 里也 mask priors。Training 时 reject illegal + penalty 不如 mask——后者梯度干净。Mask 变更版本号写入 config,旧 policy 权重不保证兼容新 mask 规则。

6. Replay 与稀疏度

Replay 存 transition 时 action index 与当时 mask 一致;PER 反复采样旧 transition 时若 mask 规则已变,会出现脏梯度。Notebook 里记录 legal mask 平均稀疏度(合法动作占比);稀疏度低于百分之五时 policy 几乎 deterministic,探索要靠 entropy 补。Release note 写明 train/eval 是否共用同一 legal_mask 实现。

掩码 API 变更要 bump 版本号;下游换 mask 规则必须 retrain 或 fine-tune,无 silent compatibility。MCTS 与 policy 管线里 mask 必须同步:prior 在非法 action 上应为零,否则 search 浪费在 invalid 分支。Replay 存 transition 时 action index 与当时 mask 一致;PER 反复采样旧 transition 时若 mask 规则已变,会出现脏梯度。Notebook 里记录 legal mask 平均稀疏度(合法动作占比);稀疏度低于百分之五时 policy 几乎 deterministic,探索要靠 entropy 补。Release note 写明 train/eval 是否共用同一 legal_mask 实现。

7. 调度与棋类里的工程实践

调度系统里合法动作随资源状态每步变化,掩码必须是状态的纯函数,不能写死在网络结构里。国际象棋类环境里平均只有三十五个合法着法,动作空间却高达四千多维;掩码后 softmax 只在合法子集上分配概率,采样效率数量级提升。训练时用拒绝非法动作加惩罚的方式,梯度会指向「 Avoid penalty」而非「只选合法」——后者才是我们想要的策略形状。发布时掩码规则版本号与策略权重绑定,下游换规则必须重训。

8. 验收

  • 每步 assert probs[~legal].sum() < 1e-6。
  • Random masked policy 只选合法 action。
  • 对比无 mask 训练是否 waste 在 invalid 上。
  • Train/eval 共用同一 legal_mask 实现。
  • Mask 变更版本号写入 config,旧 policy 权重不保证兼容新 mask 规则。

Mask 把「合法性」从 reward penalty 变成分布约束。棋类、调度里不做 mask,等于在指数级动作空间里盲搜。

相关

也可以看看

← 全部文章

johan's blog