fix: DualStream_MNF 推理先重采样308→训练网格再进Pipeline
- 推理数据 308 波段 vs 训练时 113 列(50光谱+63WQI)维度不同 - SimpleImputer fit在113列上不接受308列输入 - 修复: 先 np.interp 重采样到训练波长网格, 再 WQI 补齐, 然后喂入 Pipeline 的 imputer+preproc+cleaner 最终进 SVR
This commit is contained in:
@ -478,13 +478,54 @@ class WaterQualityInference:
|
||||
|
||||
# ═══════════════════════════════════════════════════════════
|
||||
# ★ DualStream_MNF 快速通道:Pipeline 已内置 MNF + 物理指数
|
||||
# 无需手动重采样或 WQI 补齐,直接走 Pipeline 的 preproc 步骤
|
||||
# 但需先将推理光谱重采样到训练特征空间(308→113列),
|
||||
# 再走 Pipeline 的 imputer+preproc 步骤
|
||||
# ═══════════════════════════════════════════════════════════
|
||||
if actual_preprocess_method == "DualStream_MNF" and isinstance(model, Pipeline):
|
||||
print("[DualStream_MNF] 推理直通 Pipeline(MNF+物理指数已内置)")
|
||||
# Pipeline 的 imputer + preproc 步骤会处理一切
|
||||
spectra_processed = model.named_steps['imputer'].transform(spectra.values)
|
||||
spectra_processed = model.named_steps['preproc'].transform(spectra_processed)
|
||||
print("[DualStream_MNF] 推理:先重建训练特征集再直通 Pipeline")
|
||||
# 1) 重采样 308 波段 → 训练波长网格
|
||||
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:
|
||||
# 从 spectra 中提取光谱列(列名可转 float 的即为波长列)
|
||||
spec_cols = []
|
||||
for c in spectra.columns:
|
||||
try:
|
||||
float(str(c)); spec_cols.append(c)
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
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)
|
||||
resampled = np.zeros((spec_data.shape[0], len(dst_wl)), dtype=np.float64)
|
||||
for i in range(spec_data.shape[0]):
|
||||
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)
|
||||
# 2) 计算 WQI 补齐到训练列数
|
||||
wl_col_names = [f'{wl:.6f}' for wl in train_wl]
|
||||
spectra_df = pd.DataFrame(resampled, columns=wl_col_names)
|
||||
n_need = len(train_cols)
|
||||
if spectra_df.shape[1] < n_need:
|
||||
print(f"[DualStream_MNF] 计算 WQI 补齐: {spectra_df.shape[1]} → {n_need}")
|
||||
try:
|
||||
from src.utils.water_index import WaterQualityIndexCalculator
|
||||
calc = WaterQualityIndexCalculator()
|
||||
formulas = calc.list_available()
|
||||
wqi = calc.calculate_many(formulas, spectra_df, fast=True)
|
||||
spectra_df = pd.concat([spectra_df, wqi], axis=1)
|
||||
except Exception as e:
|
||||
print(f"[DualStream_MNF] WQI 失败: {e}")
|
||||
# 如果还不够,补零
|
||||
while spectra_df.shape[1] < n_need:
|
||||
spectra_df[f'_pad_{spectra_df.shape[1]}'] = 0.0
|
||||
spectra_df = spectra_df.iloc[:, :n_need]
|
||||
# 3) 喂入 Pipeline
|
||||
spectra_processed = model.named_steps['imputer'].transform(spectra_df.values)
|
||||
spectra_processed = model.named_steps['preproc'].transform(spectra_processed)
|
||||
else:
|
||||
spectra_processed = model.named_steps['imputer'].transform(spectra.values)
|
||||
spectra_processed = model.named_steps['preproc'].transform(spectra_processed)
|
||||
spectra_processed = np.nan_to_num(spectra_processed, nan=0.0, posinf=0.0, neginf=0.0)
|
||||
print(f"[DualStream_MNF] 预处理完成: {spectra_processed.shape}")
|
||||
print(f"[特征对齐] 最终输入维度: {spectra_processed.shape}")
|
||||
|
||||
Reference in New Issue
Block a user