fix(backbones): 修复 shufflenet 无法构建,并让换骨架不再踩配置合并的坑
- shufflenet_v2_x1_0 列在支持清单里却直接 AttributeError:ShuffleNetV2 既不是 扁平 children 也没有 .features,需要按 conv1/maxpool/stage2..4/conv5 自己拼。 该 bug 同时影响 SimCLR 与检测模型 - 新增参数化测试覆盖清单里的每个 arch:能前向、声明的 out_channels 与实际一致 - 配置支持 `_replace_: true`:子字典整块替换而不与 base 合并。换骨架时 tiny_conv 的 widths/depths 会残留并传给新骨架,此前无论用 --set 还是 _base_ 都绕不开,只能改原文件 - Registry.build 提前校验字段,报错直接指出是哪些字段不被接受、该怎么办, 取代裸 TypeError - README 补充可选骨架表与三种改法(含不该用 --set 改 name 的说明) Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
e4bd794025
commit
e581d9b3d7
+21
-3
@@ -10,6 +10,7 @@ from typing import Any
|
||||
import yaml
|
||||
|
||||
BASE_KEY = "_base_"
|
||||
REPLACE_KEY = "_replace_"
|
||||
|
||||
|
||||
class Config(dict):
|
||||
@@ -53,16 +54,33 @@ class Config(dict):
|
||||
|
||||
|
||||
def deep_merge(base: Mapping, override: Mapping) -> dict:
|
||||
"""递归合并;override 中的标量/列表直接覆盖 base。"""
|
||||
"""递归合并;override 中的标量/列表直接覆盖 base。
|
||||
|
||||
子字典默认是**合并**而不是替换,这在换组件时会出问题:把 backbone 从
|
||||
`tiny_conv` 换成 `torchvision`,base 里 tiny_conv 专有的 widths/depths
|
||||
会残留下来,传给新组件直接报错。这时在该字典里写 `_replace_: true`,
|
||||
表示整块替换掉 base 的同名字典。
|
||||
"""
|
||||
merged = dict(base)
|
||||
for key, value in override.items():
|
||||
if key in merged and isinstance(merged[key], Mapping) and isinstance(value, Mapping):
|
||||
if isinstance(value, Mapping) and value.get(REPLACE_KEY):
|
||||
merged[key] = _strip_replace_key(value)
|
||||
elif key in merged and isinstance(merged[key], Mapping) and isinstance(value, Mapping):
|
||||
merged[key] = deep_merge(merged[key], value)
|
||||
else:
|
||||
merged[key] = value
|
||||
merged[key] = _strip_replace_key(value) if isinstance(value, Mapping) else value
|
||||
return merged
|
||||
|
||||
|
||||
def _strip_replace_key(value: Mapping) -> dict:
|
||||
"""去掉 `_replace_` 标记本身,避免它漏进组件的构造参数。"""
|
||||
return {
|
||||
k: (_strip_replace_key(v) if isinstance(v, Mapping) else v)
|
||||
for k, v in value.items()
|
||||
if k != REPLACE_KEY
|
||||
}
|
||||
|
||||
|
||||
def _load_raw(path: Path, seen: set[Path]) -> dict:
|
||||
path = path.resolve()
|
||||
if path in seen:
|
||||
|
||||
Reference in New Issue
Block a user