feat: 光谱黄金区间过滤 — 训练波长统一收缩到 400-1000nm
- 新增 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 自动继承过滤后的网格
This commit is contained in:
@ -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:
|
||||
|
||||
Reference in New Issue
Block a user