feat(utils): 配置继承、注册表、日志与 Nvidia GPU 守卫

- config: yaml `_base_` 继承 + 深度合并 + 命令行 `--set a.b.c=value` 覆盖,检测循环引用
- registry: 组件按名注册与构建,模型/数据集共用
- device: require_cuda() 守卫,按 CLAUDE.md 约定禁止在无 Nvidia GPU 的设备上训练;
  评估与导出走 resolve_device() 允许 CPU
- labels: multilabel / multiclass 两种图像级标签形式的共用定义
- logging / seed: 控制台+文件日志、随机种子与 cudnn 确定性

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Shaun Zhou
2026-09-02 17:54:55 +08:00
co-authored by Claude Opus 5
parent 0645fc19f7
commit f4eff8beee
7 changed files with 327 additions and 0 deletions
+54
View File
@@ -0,0 +1,54 @@
"""设备检查。
项目硬性约定(见 CLAUDE.MD):禁止在没有 Nvidia GPU 的设备上训练。
所有训练入口必须先调用 `require_cuda()`,检查不通过直接抛错退出。
"""
from __future__ import annotations
class NoNvidiaGpuError(RuntimeError):
"""当前设备不具备可用的 Nvidia GPU。"""
def cuda_devices() -> list[str]:
"""返回可用的 Nvidia GPU 名称列表;没有 torch 或没有 GPU 时返回空列表。"""
try:
import torch
except ImportError:
return []
if not torch.cuda.is_available() or torch.version.cuda is None:
return []
return [torch.cuda.get_device_name(i) for i in range(torch.cuda.device_count())]
def require_cuda() -> list[str]:
"""训练前的守卫;无 Nvidia GPU 时抛出 `NoNvidiaGpuError`。"""
try:
import torch
except ImportError as exc:
raise NoNvidiaGpuError("未安装 PyTorch,无法确认 Nvidia GPU,训练已中止。") from exc
if torch.version.cuda is None:
raise NoNvidiaGpuError(
f"当前 PyTorch ({torch.__version__}) 不是 CUDA 构建(可能是 CPU/ROCm/MPS 版本),"
"本项目禁止在非 Nvidia GPU 设备上训练。"
)
if not torch.cuda.is_available() or torch.cuda.device_count() == 0:
raise NoNvidiaGpuError(
"未检测到可用的 Nvidia GPU,本项目禁止在无 GPU 的设备上训练。"
"评估/推理请使用 eval.py 并显式指定 device=cpu。"
)
return cuda_devices()
def resolve_device(device: str = "cuda"):
"""把配置中的 device 字符串解析为 `torch.device`。
仅用于评估/推理等允许 CPU 的场景;训练路径请先走 `require_cuda()`。
"""
import torch
if device.startswith("cuda") and not torch.cuda.is_available():
raise NoNvidiaGpuError(f"请求了 {device},但当前设备没有可用的 Nvidia GPU。")
return torch.device(device)