diff --git a/src/core/modeling/modeling_batch.py b/src/core/modeling/modeling_batch.py index 497a3e2..c0add04 100644 --- a/src/core/modeling/modeling_batch.py +++ b/src/core/modeling/modeling_batch.py @@ -606,7 +606,16 @@ class WaterQualityModelingBatch: print(f"开始训练模型: {model_name} (预处理: {preprocess_method})") - # 使用指定方法分割训练集和测试集(用原始 X_raw,Pipeline 内置 transform 处理) + # ═══════════════════════════════════════════════════════════ + # ★ DualStream_MNF:只取纯光谱列,WQI 由 Pipeline 内 PhysicalExtractor 动态计算 + # ═══════════════════════════════════════════════════════════ + if preprocess_method == "DualStream_MNF": + _spec_cols = [c for c in X_raw.columns if self._is_wavelength_column(c)] + X_raw = X_raw[_spec_cols] + print(f"[DualStream_MNF] 精简为纯光谱: {X_raw.shape[1]} 列 " + f"({X_raw.columns[0]} ~ {X_raw.columns[-1]} nm)") + + # 使用指定方法分割训练集和测试集 X_train, X_test, y_train, y_test = self.split_data( X_raw, y, method=split_method, test_size=test_size, random_state=random_state ) diff --git a/src/core/prediction/inference_batch.py b/src/core/prediction/inference_batch.py index aed83b1..31b5022 100644 --- a/src/core/prediction/inference_batch.py +++ b/src/core/prediction/inference_batch.py @@ -477,15 +477,14 @@ class WaterQualityInference: metadata = self.loaded_model_data.get('metadata', {}) # ═══════════════════════════════════════════════════════════ - # ★ DualStream_MNF:重建训练特征空间(308→113列), - # 让 Pipeline.predict() 完整走 imputer→preproc→cleaner→SVR + # ★ DualStream_MNF:纯光谱 → 重采样到训练波长 → pipeline.predict() + # Pipeline 内置的 FeatureUnion[PhysicalExtractor + MNF] + # 自动计算物理指数和降维,无需外部补 WQI # ═══════════════════════════════════════════════════════════ if actual_preprocess_method == "DualStream_MNF" and isinstance(model, Pipeline): - print("[DualStream_MNF] 推理:重建训练特征集,交给 Pipeline 完整处理") + print("[DualStream_MNF] 推理:纯光谱重采样 → Pipeline 全自动处理") train_wl = metadata.get('train_wavelengths', None) - train_cols = metadata.get('train_columns', None) - if train_wl is not None and len(train_wl) > 0 and train_cols is not None: - # 1) 重采样 308 → 训练波长 + if train_wl is not None and len(train_wl) > 0: spec_cols = [] for c in spectra.columns: try: @@ -500,26 +499,11 @@ class WaterQualityInference: resampled[i] = np.interp(dst_wl, src_wl, spec_data[i], left=np.nan, right=np.nan) resampled = np.nan_to_num(resampled, nan=0.0) - wl_col_names = [f'{wl:.6f}' for wl in train_wl] - spectra = pd.DataFrame(resampled, columns=wl_col_names) - # 2) 计算 WQI + 补零到训练列数 - n_need = len(train_cols) - if spectra.shape[1] < n_need: - print(f"[DualStream_MNF] 计算 WQI: {spectra.shape[1]} → {n_need}") - try: - from src.utils.water_index import WaterQualityIndexCalculator - wqi = WaterQualityIndexCalculator().calculate_many( - WaterQualityIndexCalculator().list_available(), - spectra, fast=True) - spectra = pd.concat([spectra, wqi], axis=1) - except Exception as e: - print(f"[DualStream_MNF] WQI 失败: {e}") - while spectra.shape[1] < n_need: - spectra[f'_pad_{spectra.shape[1]}'] = 0.0 - spectra = spectra.iloc[:, :n_need] - print(f"[DualStream_MNF] 特征重建完成: {spectra.shape}") + spectra = pd.DataFrame(resampled, + columns=[f'{wl:.6f}' for wl in train_wl]) + print(f"[DualStream_MNF] 纯光谱重采样完成: {spectra.shape[1]} 列 " + f"→ pipeline.predict() 将自动完成 Physical+MNF 变换") print(f"[特征对齐] 最终输入维度: {spectra.shape}") - # 返回 DataFrame,后续 model.predict() 走完整 Pipeline return spectra.values train_wavelengths = metadata.get('train_wavelengths', None)