feat: 推理端光谱覆盖率智能预警

- 新增 _check_spectral_coverage() 静态方法
- 比较预测波长 vs 训练波长的起止范围
- 左端缺口 >15nm → 黄色警告:蓝端/紫外特征丢失
- 右端缺口 >15nm → 黄色警告:近红外特征丢失
- 在 _preprocess_dual_stream 和 preprocess_spectra 两处调用
- 使用 ANSI \033[93m 黄色高亮,不中断程序运行
This commit is contained in:
duxin
2026-07-30 13:12:19 +08:00
parent f0b9f178da
commit e3a08e0ad0

View File

@ -443,6 +443,28 @@ class WaterQualityInference:
# DualStream_MNF 专用预处理:纯光谱重采样 → Pipeline 全自动
# ═══════════════════════════════════════════════════════════
@staticmethod
def _check_spectral_coverage(train_wl, infer_wl):
"""光谱覆盖率智能预警:检测预测数据波长范围是否充分覆盖训练波长。
若预测波长的起止端与训练波长差距超过 15nm说明边缘波段缺失
np.interp 会依赖 left/right 恒定外推补齐,可能导致特征丢失。
"""
train_min, train_max = np.min(train_wl), np.max(train_wl)
infer_min, infer_max = np.min(infer_wl), np.max(infer_wl)
gap_left = infer_min - train_min
gap_right = train_max - infer_max
if gap_left > 15:
print(f"\033[93m[WARN] 预测数据起始波长 ({infer_min:.1f}nm) 晚于"
f" 训练波长 ({train_min:.1f}nm) 达 {gap_left:.0f}nm"
f"系统将自动向左横推补齐,这可能会导致蓝端/紫外特征丢失。\033[0m")
if gap_right > 15:
print(f"\033[93m[WARN] 预测数据截止波长 ({infer_max:.1f}nm) 短于"
f" 训练波长 ({train_max:.1f}nm) 达 {gap_right:.0f}nm"
f"系统将自动向右横推补齐,这可能会导致近红外特征丢失,影响预测精度。\033[0m")
def _preprocess_dual_stream(self, spectra: pd.DataFrame,
metadata: dict) -> np.ndarray:
"""纯光谱重采样到训练波长网格,返回后由 pipeline.predict() 全自动处理。
@ -471,6 +493,9 @@ class WaterQualityInference:
spec_data = spectra[spec_cols].values.astype(np.float64)
src_wl = np.array([float(c) for c in spec_cols], dtype=np.float64)
dst_wl = np.array(train_wl, dtype=np.float64)
# ★ 光谱覆盖率预警
self._check_spectral_coverage(train_wl, src_wl)
resampled = np.zeros((spec_data.shape[0], len(dst_wl)), dtype=np.float64)
for i in range(spec_data.shape[0]):
y_vals = spec_data[i]
@ -574,6 +599,9 @@ class WaterQualityInference:
train_wl_arr = np.array(train_wavelengths, dtype=np.float64)
target_wl_arr = np.array(target_wavelengths, dtype=np.float64)
# ★ 光谱覆盖率预警
self._check_spectral_coverage(train_wavelengths, target_wavelengths)
print(f"[光谱重采样] 执行重采样: {len(target_wavelengths)}"
f"{len(train_wavelengths)} 个波长点 ...")
resampled = np.zeros((spectral_data.shape[0], len(train_wavelengths)),