refactor: DualStream 纯光谱输入 — 消除 WQI 冗余双向断层
训练端: - DualStream_MNF 时只取纯光谱列(50列)传给 Pipeline - PhysicalFeatureExtractor + MNFTransformer 都只收纯光谱 - 不再从 CSV 预读 WQI 列混入输入 推理端: - 只做 308→50 光谱重采样,不补 WQI - pipeline.predict() 自动完成 Physical 指数计算 + MNF 降维 - 删除 30+ 行 WQI 补齐代码 训练/推理完全对称: 纯光谱入 → FeatureUnion → SVR 出
This commit is contained in:
@ -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
|
||||
)
|
||||
|
||||
@ -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)
|
||||
|
||||
Reference in New Issue
Block a user