From 6849ff6877bf6b8deb0d3024e25df24b7ba1f199 Mon Sep 17 00:00:00 2001 From: duxin Date: Wed, 29 Jul 2026 14:32:59 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=20Physical=5FOnly=20?= =?UTF-8?q?=E9=A2=84=E5=A4=84=E7=90=86=E5=88=86=E6=94=AF=20=E2=80=94=20?= =?UTF-8?q?=E7=BA=AF=E7=89=A9=E7=90=86=E7=89=B9=E5=BE=81+=E6=A0=87?= =?UTF-8?q?=E5=87=86=E5=8C=96=EF=BC=8C=E4=B8=8E=20MNF=20A/B=20=E5=AF=B9?= =?UTF-8?q?=E6=AF=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit spectral_Preprocessing.py: - 新增 Physical_Only 分支: Pipeline[PhysicalFeatureExtractor + StandardScaler] - 纯物理特征流: 20个指数 → StandardScaler → SVR - DualStream_MNF 逻辑完全不变 modeling_batch.py: - preprocessing_methods 新增 Physical_Only - 训练时 Physical_Only 也只取纯光谱50列 - 波长列表传递覆盖 Physical_Only GUI: - 两个面板同步新增「纯物理特征 (指数+标准化)」选项 --- src/core/modeling/modeling_batch.py | 10 +++++----- src/gui/panels/step8_ml_train_panel.py | 3 ++- src/new/views/step8_view.py | 3 ++- src/preprocessing/spectral_Preprocessing.py | 8 +++++++- 4 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/core/modeling/modeling_batch.py b/src/core/modeling/modeling_batch.py index c0add04..0b9b5d0 100644 --- a/src/core/modeling/modeling_batch.py +++ b/src/core/modeling/modeling_batch.py @@ -241,7 +241,7 @@ class WaterQualityModelingBatch: # 预处理方法列表 self.preprocessing_methods = [ "None", "MMS", "SS", "CT", "SNV", "MA", "SG", "MSC", "D1", "D2", "DT", "WVAE", - "DualStream_MNF" + "DualStream_MNF", "Physical_Only" ] # 样本划分方法列表 @@ -609,10 +609,10 @@ class WaterQualityModelingBatch: # ═══════════════════════════════════════════════════════════ # ★ DualStream_MNF:只取纯光谱列,WQI 由 Pipeline 内 PhysicalExtractor 动态计算 # ═══════════════════════════════════════════════════════════ - if preprocess_method == "DualStream_MNF": + if preprocess_method in ("DualStream_MNF", "Physical_Only"): _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]} 列 " + print(f"[{preprocess_method}] 精简为纯光谱: {X_raw.shape[1]} 列 " f"({X_raw.columns[0]} ~ {X_raw.columns[-1]} nm)") # 使用指定方法分割训练集和测试集 @@ -637,9 +637,9 @@ class WaterQualityModelingBatch: base_model.set_params(verbose=-1) # ============ 关键:把预处理器塞进 Pipeline ============ - # DualStream_MNF 需要传入波长列表,供 PhysicalFeatureExtractor 定位波段 + # DualStream_MNF / Physical_Only 需要波长列表,供 PhysicalFeatureExtractor 定位波段 _wl_list = None - if preprocess_method == "DualStream_MNF": + if preprocess_method in ("DualStream_MNF", "Physical_Only"): _wl_list = self._extract_train_wavelengths(X_raw.columns) preproc = get_preprocessing_transformer(preprocess_method, wavelengths=_wl_list) pipeline = Pipeline([ diff --git a/src/gui/panels/step8_ml_train_panel.py b/src/gui/panels/step8_ml_train_panel.py index eaf17cb..ff2d0a3 100644 --- a/src/gui/panels/step8_ml_train_panel.py +++ b/src/gui/panels/step8_ml_train_panel.py @@ -41,6 +41,7 @@ PREPROC_CHINESE = { 'CT': '中心化 (CT)', 'WVAE': '小波去噪 (WVAE)', 'DualStream_MNF': '双流MNF (物理指数+降维)', + 'Physical_Only': '纯物理特征 (指数+标准化)', } # 模型类型:内部键 -> 显示文本 @@ -177,7 +178,7 @@ class Step8MlTrainPanel(QWidget): preproc_grid = QGridLayout() self.preproc_checkboxes = {} - preproc_methods = ['None', 'MMS', 'SS', 'SNV', 'MA', 'SG', 'MSC', 'D1', 'D2', 'DT', 'CT', 'WVAE', 'DualStream_MNF'] + preproc_methods = ['None', 'MMS', 'SS', 'SNV', 'MA', 'SG', 'MSC', 'D1', 'D2', 'DT', 'CT', 'WVAE', 'DualStream_MNF', 'Physical_Only'] for i, method in enumerate(preproc_methods): checkbox = QCheckBox(PREPROC_CHINESE.get(method, method)) diff --git a/src/new/views/step8_view.py b/src/new/views/step8_view.py index cbab4d5..4eff2fd 100644 --- a/src/new/views/step8_view.py +++ b/src/new/views/step8_view.py @@ -43,6 +43,7 @@ PREPROC_CHINESE = { "CT": "中心化 (CT)", "WVAE": "小波去噪 (WVAE)", "DualStream_MNF": "双流MNF (物理指数+降维)", + "Physical_Only": "纯物理特征 (指数+标准化)", } MODEL_CHINESE = { @@ -70,7 +71,7 @@ SPLIT_CHINESE = { "random": "随机划分 (Random)", } -PREPROC_METHODS = ["None", "MMS", "SS", "SNV", "MA", "SG", "MSC", "D1", "D2", "DT", "CT", "WVAE", "DualStream_MNF"] +PREPROC_METHODS = ["None", "MMS", "SS", "SNV", "MA", "SG", "MSC", "D1", "D2", "DT", "CT", "WVAE", "DualStream_MNF", "Physical_Only"] MODEL_GROUPS = [ ("【线性模型】", ["LinearRegression", "Ridge", "Lasso", "ElasticNet", "PLS"]), ("【树模型】", ["DecisionTree", "RF", "ExtraTrees", "XGBoost", "LightGBM", "CatBoost"]), diff --git a/src/preprocessing/spectral_Preprocessing.py b/src/preprocessing/spectral_Preprocessing.py index 453876b..f309c3b 100644 --- a/src/preprocessing/spectral_Preprocessing.py +++ b/src/preprocessing/spectral_Preprocessing.py @@ -553,7 +553,13 @@ def get_preprocessing_transformer(method: str, wavelengths=None): from sklearn.pipeline import FeatureUnion return FeatureUnion([ ('physical', PhysicalFeatureExtractor(wavelengths=wavelengths)), - ('mnf', MNFTransformer()), # n_components=0.95 自动确定 + ('mnf', MNFTransformer()), + ]) + if method == "Physical_Only": + from sklearn.pipeline import Pipeline as _Pipeline + return _Pipeline([ + ("physical", PhysicalFeatureExtractor(wavelengths=wavelengths)), + ("scaler", StandardScaler()), ]) if method not in _PREPROCESSING_TRANSFORMERS: print(f"未知预处理方法 '{method}',回退为 IdentityTransformer")