mirror of
https://github.com/unanmed/ginka-generator.git
synced 2026-08-15 02:22:28 +08:00
406 lines
17 KiB
Markdown
406 lines
17 KiB
Markdown
# 邻接损失与 Patch 损失设计文档
|
||
|
||
## 1. 问题分析
|
||
|
||
当前三阶段 MaskGIT 训练仅使用逐格 Cross Entropy(CE)损失,每个格子的损失完全独立计算。然而地图生成任务中不同格子之间存在强烈的空间相关性:
|
||
|
||
- **邻接关系**:两格是否同为可通行区域(地板)是地图连通性的基础,孤立的地板块意味着该区域无法到达
|
||
- **局部一致性**:一个格子的类别高度依赖其周围格子的布局,例如门必须出现在墙与地板的交界处、怪物通常成簇分布
|
||
|
||
CE 损失将每个格子的预测视为独立的多分类问题,无法显式建模这些空间依赖,导致生成的地图在连通性和局部结构上表现不佳。
|
||
|
||
本方案引入两种互补的空间损失函数:
|
||
|
||
| 损失类型 | 作用范围 | 核心机制 | 主要受益阶段 |
|
||
| -------- | -------- | -------- | ------------ |
|
||
| 邻接损失 | 紧邻四邻域 | BCE 约束相邻两格同时为空地的概率 | 阶段一(墙壁骨架) |
|
||
| Patch 损失 | K×K 邻域 | 高斯核加权 CE 平滑,使损失梯度在空间上扩散 | 全部三个阶段 |
|
||
|
||
## 2. 邻接损失
|
||
|
||
### 2.1 设计思路
|
||
|
||
对于地图中的每一条相邻边(共 312 条:13×12 水平 + 12×13 垂直),计算两端格子均为空地的联合概率,并与真实标注做 BCE(二元交叉熵)对比。
|
||
|
||
$$
|
||
P(\text{both floor})_{(u,v)} = P(\text{floor} \mid u) \cdot P(\text{floor} \mid v)
|
||
$$
|
||
|
||
其中 $P(\text{floor} \mid u) = \text{softmax}(\text{logits}_u)[\text{class}=0]$,即第 0 类(地板)的 softmax 概率。
|
||
|
||
真实标注为二元值:若目标地图中两格均为地板(ID=0),则为 1;否则为 0。
|
||
|
||
**直觉解释**:
|
||
- 若两格都是地板,BCE 推动二者的 floor 概率同时提高,强化连通区域的一致性
|
||
- 若一格是墙、一格是地板,BCE 推动墙格的 floor 概率降低,与 CE 损失形成梯度叠加
|
||
- 若两格都是墙,BCE 推动二者的 floor 概率同时降低,与 CE 一致
|
||
|
||
邻接损失的核心价值不在于引入新信息,而在于**改变损失曲面的几何形状**——通过将逐格独立损失改为逐边联合损失,使相邻格子的梯度互相耦合。当一个格子的预测出错时,其四个邻居的梯度也会受到影响,从而加速模型学习空间一致性。
|
||
|
||
### 2.2 数学定义
|
||
|
||
设地图尺寸为 $H \times W = 13 \times 13$,logits 形状为 $[B, S, C]$,目标形状为 $[B, S]$($S = 169$,$C = 8$)。
|
||
|
||
对水平边 $(i,j) \leftrightarrow (i,j+1)$(共 $H \times (W-1) = 156$ 条):
|
||
|
||
$$
|
||
\mathcal{L}_{\text{adj}}^h = \frac{1}{B \cdot H \cdot (W-1)} \sum_b \sum_{i=0}^{H-1} \sum_{j=0}^{W-2} \text{BCE}\left(
|
||
p_{b,i,j}^f \cdot p_{b,i,j+1}^f,\;
|
||
\mathbb{I}[t_{b,i,j} = 0 \land t_{b,i,j+1} = 0]
|
||
\right)
|
||
$$
|
||
|
||
对垂直边 $(i,j) \leftrightarrow (i+1,j)$(共 $(H-1) \times W = 156$ 条):
|
||
|
||
$$
|
||
\mathcal{L}_{\text{adj}}^v = \frac{1}{B \cdot (H-1) \cdot W} \sum_b \sum_{i=0}^{H-2} \sum_{j=0}^{W-1} \text{BCE}\left(
|
||
p_{b,i,j}^f \cdot p_{b,i+1,j}^f,\;
|
||
\mathbb{I}[t_{b,i,j} = 0 \land t_{b,i+1,j} = 0]
|
||
\right)
|
||
$$
|
||
|
||
总邻接损失为二者均值:
|
||
|
||
$$
|
||
\mathcal{L}_{\text{adj}} = \frac{1}{2} (\mathcal{L}_{\text{adj}}^h + \mathcal{L}_{\text{adj}}^v)
|
||
$$
|
||
|
||
### 2.3 实现
|
||
|
||
```python
|
||
import torch
|
||
import torch.nn.functional as F
|
||
|
||
def adjacency_loss(logits, target):
|
||
# logits: [B, S, C] — MaskGIT 解码器输出
|
||
# target: [B, S] — 目标类别 ID,不含 MASK 标记
|
||
B, S, C = logits.shape
|
||
H = W = 13
|
||
probs = F.softmax(logits, dim=-1) # [B, S, C]
|
||
p_floor = probs[:, :, 0].view(B, H, W) # [B, H, W] — 地板概率
|
||
t = target.view(B, H, W) # [B, H, W]
|
||
t_floor = (t == 0).float() # 地板标注为 1,其余为 0
|
||
|
||
# 水平边:左格 × 右格
|
||
joint_h = p_floor[:, :, :-1] * p_floor[:, :, 1:] # [B, H, W-1]
|
||
target_h = t_floor[:, :, :-1] * t_floor[:, :, 1:] # [B, H, W-1]
|
||
|
||
# 垂直边:上格 × 下格
|
||
joint_v = p_floor[:, :-1, :] * p_floor[:, 1:, :] # [B, H-1, W]
|
||
target_v = t_floor[:, :-1, :] * t_floor[:, 1:, :] # [B, H-1, W]
|
||
|
||
loss_h = F.binary_cross_entropy(joint_h, target_h, reduction='mean')
|
||
loss_v = F.binary_cross_entropy(joint_v, target_v, reduction='mean')
|
||
return (loss_h + loss_v) / 2.0
|
||
```
|
||
|
||
**边界处理**:只计算完整存在的边(水平 13×12=156 条,垂直 12×13=156 条),共计 312 条边。边界格子的某些方向没有邻居,自然不产生该方向的边。
|
||
|
||
**阶段适用性**:邻接损失直接对地板-地板连通性建模,在三个阶段中的适用程度不同:
|
||
|
||
| 阶段 | target 地板占比 | 邻接损失有效性 | 说明 |
|
||
| ---- | --------------- | -------------- | ---- |
|
||
| 一 | ~50% | 高 | 地板/墙壁二分类,地板连通性决定地图骨架质量 |
|
||
| 二 | ~70% | 中 | 墙壁已降级为地板,地板占比更高,但仍有门与怪物放置的地板连通约束 |
|
||
| 三 | ~90% | 低 | 仅保留地板与资源,大部分区域为地板,BCE 信号趋弱 |
|
||
|
||
**建议**:邻接损失默认仅作用于阶段一。若想对所有阶段生效,可为二、三阶段设置更小的权重 `LAMBDA_ADJ_STAGE2`、`LAMBDA_ADJ_STAGE3`。
|
||
|
||
### 2.4 超参数
|
||
|
||
| 参数 | 建议值 | 说明 |
|
||
| ---- | ------ | ---- |
|
||
| `LAMBDA_ADJ` | 0.1 | 邻接损失总权重,作用于阶段一 |
|
||
| `LAMBDA_ADJ_STAGE2` | 0.05 | 阶段二邻接损失权重(可选,默认与 LAMBDA_ADJ 相同) |
|
||
| `LAMBDA_ADJ_STAGE3` | 0.02 | 阶段三邻接损失权重(可选) |
|
||
|
||
### 2.5 扩展方向
|
||
|
||
当前方案仅建模地板-地板成对关系。可扩展为多类别邻接矩阵:
|
||
|
||
- 对 7 个有效类别两两组合得到 7×7 = 49 种邻接关系
|
||
- 计算联合概率 `P(class_a | u) * P(class_b | v)` 得到 49 维向量
|
||
- 与目标地图的 one-hot 邻接关系做 CE
|
||
|
||
多类邻接能显式建模"门必须出现在墙与地板交界""怪物应位于地板上"等约束,但计算量较大(49 × 312 = 15,288 对/样本),建议作为地板块邻接验证有效后的进阶方案。
|
||
|
||
## 3. Patch 损失
|
||
|
||
### 3.1 设计思路
|
||
|
||
逐格 CE 损失的梯度仅作用于单格。Patch 损失通过高斯核对每格的 CE 损失进行空间卷积,使一个格子的损失值等于其 K×K 邻域内所有格子 CE 的加权平均。这带来的效果是:
|
||
|
||
- 一个格子的预测错误会通过高斯核"扩散"到其邻居,邻居的梯度也会向纠错方向移动
|
||
- 等效于增强了局部区域的梯度信号,使模型更难忽视局部上下文
|
||
- 相比邻接损失关心特定类别关系(地板-地板),Patch 损失是**类别无关**的空间平滑,对所有 tile 类型均有效
|
||
|
||
**与邻接损失的区别**:
|
||
|
||
| 维度 | 邻接损失 | Patch 损失 |
|
||
| ---- | -------- | ---------- |
|
||
| 作用范围 | 仅紧邻四邻域(距离 1) | K×K 邻域(距离 2,可调) |
|
||
| 类别感知 | 是(地板-地板特定) | 否(CE 已包含类别) |
|
||
| 权重机制 | 等权(乘积) | 高斯衰减权重 |
|
||
| 梯度耦合 | 乘性(P_A × P_B) | 加性(加权 CE 求和) |
|
||
|
||
### 3.2 数学定义
|
||
|
||
设 CE 损失在每格的定义为(不做 reduction):
|
||
|
||
$$
|
||
\text{ce}_{b,i,j} = -\log \frac{\exp(\text{logits}_{b,i,j}[t_{b,i,j}])}{\sum_{c=0}^{C-1} \exp(\text{logits}_{b,i,j}[c])}
|
||
$$
|
||
|
||
高斯核 $G \in \mathbb{R}^{K \times K}$,中心 $(k_c, k_c) = (\lfloor K/2 \rfloor, \lfloor K/2 \rfloor)$:
|
||
|
||
$$
|
||
G_{u,v} = \frac{1}{Z} \exp\left(-\frac{(u - k_c)^2 + (v - k_c)^2}{2\sigma^2}\right), \quad Z = \sum_{u,v} G_{u,v}
|
||
$$
|
||
|
||
Patch 损失定义为逐格平滑后的 CE 的均值:
|
||
|
||
$$
|
||
\mathcal{L}_{\text{patch}} = \frac{1}{B \cdot H \cdot W} \sum_b \sum_{i=0}^{H-1} \sum_{j=0}^{W-1} \sum_{u=0}^{K-1} \sum_{v=0}^{K-1}
|
||
G_{u,v} \cdot \text{ce}_{b,\; i+u-k_c,\; j+v-k_c}
|
||
$$
|
||
|
||
其中越界的 $\text{ce}$ 用边缘复制(replicate padding)填充。
|
||
|
||
### 3.3 实现
|
||
|
||
```python
|
||
import torch
|
||
import torch.nn.functional as F
|
||
|
||
def gaussian_kernel(kernel_size, sigma, device):
|
||
# 生成归一化二维高斯卷积核 [1, 1, K, K]
|
||
k = kernel_size
|
||
center = (k - 1) / 2.0
|
||
xs = torch.arange(k, dtype=torch.float32, device=device) - center
|
||
gx = torch.exp(-xs ** 2 / (2.0 * sigma ** 2))
|
||
gy = torch.exp(-xs ** 2 / (2.0 * sigma ** 2))
|
||
g2d = gx[:, None] * gy[None, :] # [K, K]
|
||
g2d = g2d / g2d.sum() # 归一化
|
||
return g2d.view(1, 1, k, k)
|
||
|
||
def patch_loss(logits, target, kernel_size=5, sigma=1.2):
|
||
# logits: [B, S, C]
|
||
# target: [B, S]
|
||
B, S, C = logits.shape
|
||
H = W = 13
|
||
|
||
# 逐格 CE(不做 reduction)
|
||
ce = F.cross_entropy(
|
||
logits.reshape(-1, C), target.reshape(-1), reduction='none'
|
||
).view(B, H, W) # [B, H, W]
|
||
|
||
# 高斯核
|
||
kernel = gaussian_kernel(kernel_size, sigma, logits.device) # [1, 1, K, K]
|
||
|
||
# replicate 填充后用 unfold 提取邻域
|
||
pad = kernel_size // 2
|
||
ce_padded = F.pad(ce.view(B, 1, H, W), (pad, pad, pad, pad), mode='replicate')
|
||
# patches: [B, K*K, H*W]
|
||
patches = F.unfold(ce_padded, kernel_size=(kernel_size, kernel_size))
|
||
patches = patches.view(B, kernel_size * kernel_size, H, W) # [B, K*K, H, W]
|
||
|
||
# 加权求和
|
||
k_flat = kernel.view(1, kernel_size * kernel_size, 1, 1) # [1, K*K, 1, 1]
|
||
smoothed = (patches * k_flat).sum(dim=1) # [B, H, W]
|
||
|
||
return smoothed.mean()
|
||
```
|
||
|
||
**设计要点**:
|
||
|
||
- `replicate` 填充:边界格子的邻域超出地图范围时,用最近的边缘值填充,避免引入零值的虚假信号
|
||
- 核归一化:高斯核归一化到和为 1,确保 Patch 损失的数值量级与原始 CE 大致相当,便于权重调参
|
||
- `F.unfold` 实现:比手动循环或 `conv2d` 更高效,在 CUDA 上有针对性的算子优化
|
||
|
||
### 3.4 超参数
|
||
|
||
| 参数 | 建议值 | 说明 |
|
||
| ---- | ------ | ---- |
|
||
| `PATCH_KERNEL_SIZE` | 5 | 卷积核尺寸,5×5 覆盖约 15% 的地图面积 |
|
||
| `PATCH_SIGMA` | 1.2 | 高斯核标准差,控制权重衰减速度。σ 越大平滑越强 |
|
||
| `LAMBDA_PATCH` | 0.1 | Patch 损失总权重 |
|
||
| `LAMBDA_PATCH_STAGE1` | 0.1 | 阶段一 Patch 权重(可选,默认同 LAMBDA_PATCH) |
|
||
| `LAMBDA_PATCH_STAGE2` | 0.1 | 阶段二 Patch 权重 |
|
||
| `LAMBDA_PATCH_STAGE3` | 0.1 | 阶段三 Patch 权重 |
|
||
|
||
**Kernel Size 选择**:13×13 地图上,5×5 是合理的起点(覆盖每个方向 ±2 格)。若效果不明显可尝试 7×7,但需注意边界效应增强。
|
||
|
||
**Sigma 选择**:σ = 1.2 在 5×5 内权重分布为:
|
||
|
||
| 距离 | 0 | 1 | 2 |
|
||
| ---- | --- | --- | --- |
|
||
| 权重 | ~0.273 | ~0.164 | ~0.053 |
|
||
|
||
中心权重约为边缘的 5 倍,保证自身 CE 仍占主导,同时给予邻居适度的梯度贡献。
|
||
|
||
### 3.5 扩展方向
|
||
|
||
**可学习卷积核**:将固定高斯核替换为可训练参数 `nn.Parameter`,在训练过程中自适应学习最优的空间权重分布。实现简单,只需将 `gaussian_kernel` 改为可学习参数即可。
|
||
|
||
**多尺度 Patch**:同时使用 3×3、5×5、7×7 三种核,各自的平滑结果取加权和,使模型在不同空间尺度上均受到约束。
|
||
|
||
**类感知核**:不同类别使用不同的平滑权重。例如墙壁类不应与怪物类互相平滑,可以按类别加权。实现时需在 CE 中保留类别维度,对每类分别卷积。
|
||
|
||
## 4. 总损失组合
|
||
|
||
最终训练损失为原有各项与新两项的加权和:
|
||
|
||
$$
|
||
\begin{aligned}
|
||
\mathcal{L}_{\text{total}} = &
|
||
\sum_{s=1}^{3} w_{\text{ce}}^s \cdot \mathcal{L}_{\text{ce}}^s \\
|
||
+ & \sum_{s=1}^{3} \lambda_{\text{adj}}^s \cdot \mathcal{L}_{\text{adj}}^s \\
|
||
+ & \sum_{s=1}^{3} \lambda_{\text{patch}}^s \cdot \mathcal{L}_{\text{patch}}^s \\
|
||
+ & \beta \cdot \mathcal{L}_{\text{commit}} + \beta_{\text{dist}} \cdot \mathcal{L}_{\text{commit\_dist}}
|
||
\end{aligned}
|
||
$$
|
||
|
||
其中 $w_{\text{ce}}^s$ 即现有的 `STAGE1_CE_WEIGHT` / `STAGE2_CE_WEIGHT` / `STAGE3_CE_WEIGHT`(默认均为 1.0)。
|
||
|
||
**推荐权重配置**:
|
||
|
||
| 损失项 | 阶段一 | 阶段二 | 阶段三 |
|
||
| ------ | ------ | ------ | ------ |
|
||
| CE 损失 | 1.0 | 1.0 | 1.0 |
|
||
| 邻接损失 | 0.1 | 0.05 | 0.02 |
|
||
| Patch 损失 | 0.1 | 0.1 | 0.1 |
|
||
|
||
阶段一地板/墙壁二分类是连通性建模的核心,邻接损失权重最高。阶段二、三地板占比渐增,邻接损失的判别力减弱,权重递减。Patch 损失作为类别无关的平滑约束,三个阶段等权重即可。
|
||
|
||
### 与现有超参数的位置关系
|
||
|
||
新增超参数应追加在 `train_seperated.py` 现有超参数块(第 42-118 行)之后:
|
||
|
||
```python
|
||
# 邻接损失权重(三阶段)
|
||
LAMBDA_ADJ1 = 0.1
|
||
LAMBDA_ADJ2 = 0.05
|
||
LAMBDA_ADJ3 = 0.02
|
||
|
||
# Patch 损失权重(三阶段)及核参数
|
||
LAMBDA_PATCH1 = 0.1
|
||
LAMBDA_PATCH2 = 0.1
|
||
LAMBDA_PATCH3 = 0.1
|
||
PATCH_KERNEL_SIZE = 5
|
||
PATCH_SIGMA = 1.2
|
||
```
|
||
|
||
## 5. 训练集成
|
||
|
||
### 5.1 代码变更范围
|
||
|
||
| 文件 | 变更类型 | 说明 |
|
||
| ---- | -------- | ---- |
|
||
| `ginka/train_seperated.py` | 修改 | 新增两个损失函数定义、超参数、训练循环中的损失累加 |
|
||
|
||
损失函数直接定义在 `train_seperated.py` 中,与现有的 `cross_entropy_loss`(第 201 行)并列放置,保持代码组织的一致性。
|
||
|
||
### 5.2 训练循环修改
|
||
|
||
在现有损失计算(第 969-977 行)的基础上,追加邻接损失与 Patch 损失:
|
||
|
||
```python
|
||
# 三阶段 Cross Entropy(不变)
|
||
loss1 = cross_entropy_loss(logits1, target1)
|
||
loss2 = cross_entropy_loss(logits2, target2)
|
||
loss3 = cross_entropy_loss(logits3, target3)
|
||
|
||
# 新增:邻接损失
|
||
adj1 = adjacency_loss(logits1, target1) if LAMBDA_ADJ1 > 0 else 0.0
|
||
adj2 = adjacency_loss(logits2, target2) if LAMBDA_ADJ2 > 0 else 0.0
|
||
adj3 = adjacency_loss(logits3, target3) if LAMBDA_ADJ3 > 0 else 0.0
|
||
|
||
# 新增:Patch 损失
|
||
patch1 = patch_loss(
|
||
logits1, target1, PATCH_KERNEL_SIZE, PATCH_SIGMA
|
||
) if LAMBDA_PATCH1 > 0 else 0.0
|
||
patch2 = patch_loss(
|
||
logits2, target2, PATCH_KERNEL_SIZE, PATCH_SIGMA
|
||
) if LAMBDA_PATCH2 > 0 else 0.0
|
||
patch3 = patch_loss(
|
||
logits3, target3, PATCH_KERNEL_SIZE, PATCH_SIGMA
|
||
) if LAMBDA_PATCH3 > 0 else 0.0
|
||
|
||
# 加权汇总
|
||
loss1_weighted = STAGE1_CE_WEIGHT * loss1
|
||
loss2_weighted = STAGE2_CE_WEIGHT * loss2
|
||
loss3_weighted = STAGE3_CE_WEIGHT * loss3
|
||
adj_weighted = (
|
||
LAMBDA_ADJ1 * adj1 + LAMBDA_ADJ2 * adj2 + LAMBDA_ADJ3 * adj3
|
||
)
|
||
patch_weighted = (
|
||
LAMBDA_PATCH1 * patch1 + LAMBDA_PATCH2 * patch2 + LAMBDA_PATCH3 * patch3
|
||
)
|
||
commit_weighted = VQ_BETA * commit_loss + VQ_BETA_DIST * commit_loss_dist
|
||
|
||
loss = (
|
||
loss1_weighted + loss2_weighted + loss3_weighted
|
||
+ adj_weighted + patch_weighted + commit_weighted
|
||
)
|
||
```
|
||
|
||
对应地在日志输出区域追加邻接损失和 Patch 损失的值,便于监控。
|
||
|
||
### 5.3 验证循环同步修改
|
||
|
||
`validate` 函数(第 720-780 行附近)中同样需要追加邻接损失和 Patch 损失的计算,保持训练/验证损失口径一致。
|
||
|
||
### 5.4 性能影响
|
||
|
||
| 损失函数 | 额外计算量 | 额外显存 |
|
||
| -------- | ---------- | -------- |
|
||
| adjacency_loss | softmax + 4 次逐元素乘法 + 2 次 BCE | 极小(仅 B×H×W 级中间张量) |
|
||
| patch_loss | 逐格 CE + unfold + 加权求和 | 中等(unfold 产生 B×K²×H×W 中间张量) |
|
||
|
||
对于 B=64、K=5、H=W=13,unfold 中间张量大小为 64×25×169 ≈ 270k float,显存开销约 1MB,可以忽略。总额外计算时间预估在 5% 以内。
|
||
|
||
## 6. 验证方案
|
||
|
||
### 6.1 定量指标
|
||
|
||
在验证集上对比以下指标(基线 vs 加邻接损失 vs 加 Patch 损失 vs 两者叠加):
|
||
|
||
| 指标 | 含义 | 期望趋势 |
|
||
| ---- | ---- | -------- |
|
||
| 阶段一 CE 损失 | 墙壁骨架准确度 | 基本持平或微降 |
|
||
| 阶段二 CE 损失 | 门/怪物/入口准确度 | 持平或改善 |
|
||
| 阶段三 CE 损失 | 资源放置准确度 | 持平或改善 |
|
||
| 邻接损失值 | 地板连通性 | 显著下降 |
|
||
| 地板连通分量数 | 生成地图中可通行区域的连通分量个数(理想为 1) | 下降 |
|
||
| 孤立地板块比例 | 四邻域均为墙壁的地板格子占比 | 下降 |
|
||
| Codebook 使用率 | VQ 码本利用率 | 不变或微升 |
|
||
|
||
### 6.2 可视化验证
|
||
|
||
对相同随机种子、相同随机采码条件下生成的地图进行可视化对比,重点关注:
|
||
|
||
1. **墙壁骨架质量**(阶段一):墙壁是否形成合理的房间轮廓和通道,是否出现孤立墙壁碎片
|
||
2. **连通性**(全图):从入口出发能否到达所有可通行区域,是否存在被墙壁完全包围的孤岛
|
||
3. **局部一致性**:门是否出现在墙壁上并连接两个地板区域、怪物是否出现在地板上而非墙壁上
|
||
4. **资源分布**(阶段三):资源是否均匀分布在可通行区域内
|
||
|
||
验证时对不同 z 采样分别生成 4-8 张图,并排对比,使用 `shared/image.py` 的 `matrix_to_image_cv` 输出 PNG 文件。
|
||
|
||
### 6.3 消融实验
|
||
|
||
| 实验编号 | CE 损失 | 邻接损失 | Patch 损失 | 目的 |
|
||
| -------- | ------- | -------- | ---------- | ---- |
|
||
| E0 | ✓ | ✗ | ✗ | 基线(当前模型) |
|
||
| E1 | ✓ | ✓ | ✗ | 验证邻接损失单独效果 |
|
||
| E2 | ✓ | ✗ | ✓ | 验证 Patch 损失单独效果 |
|
||
| E3 | ✓ | ✓ | ✓ | 验证两者叠加效果 |
|
||
|
||
### 6.4 超参数搜索建议
|
||
|
||
若初值效果不理想,按以下优先级调参:
|
||
|
||
1. `LAMBDA_ADJ1`:[0.05, 0.1, 0.2, 0.5] — 邻接损失最关键,先找到合适的强度
|
||
2. `LAMBDA_PATCH1`:[0.05, 0.1, 0.2] — Patch 损失作为补充平滑
|
||
3. `PATCH_SIGMA`:[0.8, 1.2, 1.6] — 控制平滑范围,sigma 越大平滑越强
|
||
4. `PATCH_KERNEL_SIZE`:[3, 5, 7] — 控制邻域大小,注意 7×7 在地图上的覆盖接近 30%
|