ginka-generator/docs/cond-simplify-design.md
2026-05-18 13:55:00 +08:00

5.1 KiB
Raw Blame History

条件简化与剩余密度条件设计文档

背景问题

当前三阶段级联生成模型的条件系统主要有五个问题:

  1. 结构条件中的房间数和分支数指导意义有限。这两个标签依赖离散分档,噪声大,和最终生成质量的关系不稳定。

  2. 直接给模型输入整张图的最终密度仍然过于间接。模型拿到的是终态目标,但生成过程是逐步展开的,模型需要自己从当前地图里数出已经放了多少,再反推出还差多少,这对 Transformer 并不友好。

  3. 第一阶段缺少足够的全局统计条件。实验上第二、三阶段可以较好过拟合,但第一阶段明显更难,说明骨架生成还缺少能够直接约束复杂度的全局量。墙壁密度正好可以承担这个角色。

  4. 第二阶段除了门和怪物,入口也存在生成失控的问题。既然入口本来就属于第二阶段负责的功能性实体,那么它也应该进入同一套密度条件,而不是继续裸奔。

  5. 不适合直接把真实计数作为条件,也不适合用相对目标量做归一化。前者会把条件值拉得过大,后者又会让非零目标在初始时刻统一退化成 1容易诱发整图铺满某类图块的极端行为。

因此,条件系统应统一改成“真实剩余密度”方案,并覆盖三个阶段需要的全部关键对象。

核心方案

保留简化后的结构条件,只使用对称性和外围墙信息;删除房间数、分支数这类噪声较大的离散标签。

密度条件不再表示“最终应该有多少”,而是表示“当前还剩多少没放完”。所有密度都统一按固定地图面积计算:


d^{\text{remain}} = d^{\text{target}} - d^{\text{visible}}

其中:

  • d^{\text{target}} 表示目标地图中的真实密度
  • d^{\text{visible}} 表示当前输入地图中已经可见的真实密度
  • 分母固定为地图总面积 13 \times 13 = 169

这样做有两个直接好处:

  • 条件值始终处于小范围浮点数区间,不会因为资源、墙壁或其他图块数量较大而把激活值拉爆。
  • 初始条件不再因为“目标非零”而统一退化成 1模型能真正区分稀疏目标和稠密目标。

条件内容

结构条件继续采用两维:对称性和外围墙。

密度条件扩展为五维,顺序为:墙壁、门、怪物、入口、资源。

这样设计的原因是:

  • 墙壁密度直接约束第一阶段骨架复杂度。
  • 门、怪物、入口都属于第二阶段的功能性实体,应该共享同一套“还剩多少要放”的控制思路。
  • 资源属于第三阶段,继续保留独立控制。

不单独加入 floor 密度因为在地图总面积固定时floor 和 wall 基本互补,额外增加一维收益有限。

分阶段使用方式

第一阶段只使用墙壁剩余密度,用来约束骨架稠密程度。

第二阶段使用门、怪物、入口的剩余密度,用来约束功能性实体的总量,避免某一类实体明显过多。

第三阶段只使用资源剩余密度,用来约束资源分布总量。

虽然模型内部可以继续使用统一的条件接口,但语义上每个阶段只关注自己负责的那几维,其他维度在该阶段不提供有效信号。

训练与采样原则

密度条件不能在样本读取时一次性写死,而必须根据当前输入地图动态计算。也就是说,同一张目标地图在不同阶段、不同采样步、不同当前状态下,对应的剩余密度都可能不同。

这件事在训练和推理里都一样重要:

  • 训练时,模型应看到“当前已经放了多少”之后对应的剩余密度。
  • 推理时,每一步去掩码之后都要重新计算剩余密度,否则模型不知道自己刚刚已经新增了多少墙壁、门、怪物、入口或资源。

自由生成时,如果需要随机条件,建议从训练集真实分布中采样密度组合,而不是各维完全独立均匀采样。特别是墙壁密度和第二、三阶段实体密度往往存在耦合关系,独立采样容易产生不自然组合。

验证重点

这套方案的目标不是单纯让损失更低,而是让条件真正可控。验证时应重点看四类现象:

  1. 第一阶段墙壁密度误差是否明显下降墙壁目标密度从低到高时stage1 输出的墙壁数量是否随之单调上升。

  2. 第二阶段门、怪物、入口的过量生成是否下降,尤其要观察入口是否还会出现明显离谱的数量。

  3. 第三阶段资源的过量生成是否下降。

  4. 固定结构和潜变量时,只改变某一维目标密度,最终对应图块数量是否发生方向一致的变化。

验证指标建议以真实密度误差为主,计数误差可以作为辅助观察项。

兼容性结论

这次改动不仅改变条件语义,也会改变密度条件的维度,因此旧 checkpoint 不再兼容。

旧模型学习的是整图最终密度,或相对目标量的剩余比例;新模型学习的是按总面积计的动态剩余密度,并且新增了第一阶段墙壁条件和第二阶段入口条件。两者不是同一套任务定义,需要从头训练。