From f0b9f178daf4f3ebd21781b05bdc7f83fcbd6ce4 Mon Sep 17 00:00:00 2001 From: duxin Date: Thu, 30 Jul 2026 13:12:14 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=85=89=E8=B0=B1=E9=BB=84=E9=87=91?= =?UTF-8?q?=E5=8C=BA=E9=97=B4=E8=BF=87=E6=BB=A4=20=E2=80=94=20=E8=AE=AD?= =?UTF-8?q?=E7=BB=83=E6=B3=A2=E9=95=BF=E7=BB=9F=E4=B8=80=E6=94=B6=E7=BC=A9?= =?UTF-8?q?=E5=88=B0=20400-1000nm?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 WAVELENGTH_RANGE = (400.0, 1000.0) 类常量 - 新增 _is_wavelength_in_range() 范围感知波长列判断 - _extract_train_wavelengths() 自动过滤超出区间的波长 - _extract_feature_columns / train_single_model / pre-scan 三处调用点 统一切换为范围感知判断 - 效果: 308 波段 → 300 波段 (裁掉 <400nm 的 4 个 + >1000nm 的 4 个) - 推理端通过 metadata train_wavelengths 自动继承过滤后的网格 --- src/core/modeling/modeling_batch.py | 38 ++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/src/core/modeling/modeling_batch.py b/src/core/modeling/modeling_batch.py index fc1d917..10e4cc9 100644 --- a/src/core/modeling/modeling_batch.py +++ b/src/core/modeling/modeling_batch.py @@ -250,6 +250,9 @@ class WaterQualityModelingBatch: self.results = {} self.best_models = {} + # ★ 黄金光谱区间:统一收缩到 400-1000nm,消除边缘噪声和跨传感器不一致 + WAVELENGTH_RANGE = (400.0, 1000.0) + @staticmethod def _is_wavelength_column(col_name: str) -> bool: """判断列名是否为波长值(纯数字字符串,如 '374.285004')""" @@ -259,22 +262,35 @@ class WaterQualityModelingBatch: except (ValueError, TypeError): return False + @classmethod + def _is_wavelength_in_range(cls, col_name: str) -> bool: + """判断列名是否为波长值且在黄金区间 [400, 1000] nm 内。""" + try: + wl = float(str(col_name)) + lo, hi = cls.WAVELENGTH_RANGE + return lo <= wl <= hi + except (ValueError, TypeError): + return False + @staticmethod def _is_wqi_column(col_name: str) -> bool: """判断列名是否为 WQI 水质指数列('WQI_' 前缀)""" return str(col_name).startswith('WQI_') - @staticmethod - def _extract_train_wavelengths(columns) -> List[float]: - """从列名列表中提取波长值(float 列表) + @classmethod + def _extract_train_wavelengths(cls, columns) -> List[float]: + """从列名列表中提取波长值(float 列表),自动过滤到黄金区间。 - 遍历列名,将所有可转为 float 的列名提取为波长列表。 + 遍历列名,将所有可转为 float 且落在 [400, 1000] nm 的列名提取为波长列表。 用于写入模型 metadata['train_wavelengths'],供推理端光谱重采样。 """ + lo, hi = cls.WAVELENGTH_RANGE wl_list = [] for c in columns: try: - wl_list.append(float(str(c))) + wl = float(str(c)) + if lo <= wl <= hi: + wl_list.append(wl) except (ValueError, TypeError): pass return wl_list @@ -327,8 +343,8 @@ class WaterQualityModelingBatch: # 跳过元数据列 if col_lower in _meta_patterns: continue - # 保留波长列 - if self._is_wavelength_column(col): + # 保留波长列(仅黄金区间 400-1000nm) + if self._is_wavelength_in_range(col): feature_indices.append(i) # 保留 WQI 列 elif self._is_wqi_column(col): @@ -613,9 +629,9 @@ class WaterQualityModelingBatch: # ★ DualStream_MNF:只取纯光谱列,WQI 由 Pipeline 内 PhysicalExtractor 动态计算 # ═══════════════════════════════════════════════════════════ if preprocess_method in ("DualStream_MNF", "Physical_Only"): - _spec_cols = [c for c in X_raw.columns if self._is_wavelength_column(c)] + _spec_cols = [c for c in X_raw.columns if self._is_wavelength_in_range(c)] X_raw = X_raw[_spec_cols] - print(f"[{preprocess_method}] 精简为纯光谱: {X_raw.shape[1]} 列 " + print(f"[{preprocess_method}] 精简为纯光谱(400-1000nm): {X_raw.shape[1]} 列 " f"({X_raw.columns[0]} ~ {X_raw.columns[-1]} nm)") # 使用指定方法分割训练集和测试集 @@ -975,9 +991,9 @@ class WaterQualityModelingBatch: X_clean = X_raw[mask] - # 只保留纯光谱列(与 DualStream_MNF Pipeline 内的逻辑一致) + # 只保留纯光谱列(与 DualStream_MNF Pipeline 内的逻辑一致,400-1000nm) _spec_cols = [c for c in X_clean.columns - if self._is_wavelength_column(c)] + if self._is_wavelength_in_range(c)] X_spec = X_clean[_spec_cols].values.astype(np.float64) try: