feat(gui): 全流程面板合并 + 一键式运行 GUI 入口集成
This commit is contained in:
@ -8,7 +8,17 @@ Pipeline 调度核心:基于 Context 的内存级依赖注入。
|
||||
- 不绑定具体 Pipeline 实现(duck-typed),WorkerThread / Web API / 单测可共用
|
||||
"""
|
||||
|
||||
from .context import PipelineContext
|
||||
from .runner import StepSpec, PIPELINE_STEPS, PipelineRunner
|
||||
from .context import (
|
||||
PipelineContext,
|
||||
STEP_MAP_OLD_TO_NEW, STEP_MAP_NEW_TO_OLD,
|
||||
resolve_step_id, ALL_STEP_IDS,
|
||||
)
|
||||
from .runner import (
|
||||
StepSpec, PIPELINE_STEPS, PipelineRunner, PipelineHalt,
|
||||
)
|
||||
|
||||
__all__ = ["PipelineContext", "StepSpec", "PIPELINE_STEPS", "PipelineRunner"]
|
||||
__all__ = [
|
||||
"PipelineContext", "StepSpec", "PIPELINE_STEPS", "PipelineRunner", "PipelineHalt",
|
||||
"STEP_MAP_OLD_TO_NEW", "STEP_MAP_NEW_TO_OLD",
|
||||
"resolve_step_id", "ALL_STEP_IDS",
|
||||
]
|
||||
|
||||
@ -12,7 +12,34 @@ PipelineContext:内存级数据载体,跨 14 个 step 传递路径与元信
|
||||
|
||||
from __future__ import annotations
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Any, Dict, List, Optional
|
||||
from typing import Any, Dict, List, Optional, Set
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 步骤命名映射(定义在叶子节点,打破循环依赖)
|
||||
# ============================================================
|
||||
|
||||
STEP_MAP_OLD_TO_NEW: Dict[str, str] = {
|
||||
"step5_5": "step8",
|
||||
"step6_5": "step8_non_empirical_modeling",
|
||||
"step6_75": "step9",
|
||||
"step8_5": "step11",
|
||||
"step8_75": "step12",
|
||||
"step7": "step10",
|
||||
"step8": "step11_ml",
|
||||
"step9": "step14",
|
||||
}
|
||||
|
||||
STEP_MAP_NEW_TO_OLD: Dict[str, str] = {v: k for k, v in STEP_MAP_OLD_TO_NEW.items()}
|
||||
|
||||
ALL_STEP_IDS: Set[str] = set(STEP_MAP_OLD_TO_NEW.keys()) | set(STEP_MAP_OLD_TO_NEW.values())
|
||||
|
||||
|
||||
def resolve_step_id(step_id: str) -> str:
|
||||
"""将任意 step_id 转换为标准新格式。"""
|
||||
if step_id in STEP_MAP_OLD_TO_NEW:
|
||||
return STEP_MAP_OLD_TO_NEW[step_id]
|
||||
return step_id
|
||||
|
||||
|
||||
@dataclass
|
||||
@ -63,10 +90,29 @@ class PipelineContext:
|
||||
pipeline_end_time: Optional[float] = None
|
||||
last_error: Optional[str] = None
|
||||
|
||||
# ── 错误汇总(全流程结束后可用) ──
|
||||
error_summary: List[tuple[str, str]] = field(default_factory=list)
|
||||
# ── 出错时立即停止全流程(默认 False:继续后续步骤) ──
|
||||
breakpoint_on_error: bool = False
|
||||
# ── ★ 智能补全锁定步骤列表(由 _auto_fill_missing_steps 自动开启的步骤) ──
|
||||
# GUI 层读取此字段,在运行期间禁用对应面板的启用复选框
|
||||
locked_steps: List[str] = field(default_factory=list)
|
||||
|
||||
# ============================================================
|
||||
# 读写辅助
|
||||
# ============================================================
|
||||
|
||||
def step_id(self, step_id: str) -> str:
|
||||
"""将任意 step_id(可能是旧名)转换为标准新格式。
|
||||
|
||||
用法示例:
|
||||
ctx.status[ctx.step_id('step6_5')] # 'step8_non_empirical_modeling'
|
||||
ctx.user_config[ctx.step_id('step8_5')] # 'step11'
|
||||
"""
|
||||
if step_id in STEP_MAP_OLD_TO_NEW:
|
||||
return STEP_MAP_OLD_TO_NEW[step_id]
|
||||
return step_id
|
||||
|
||||
def set(self, key: str, value: Any) -> None:
|
||||
"""原地写入任意属性。
|
||||
|
||||
|
||||
@ -660,7 +660,7 @@ class WaterQualityInversionPipeline:
|
||||
self._notify("completed", f"训练光谱数据已保存: {result}")
|
||||
return result
|
||||
|
||||
def step5_5_calculate_water_quality_indices(self,
|
||||
def step8_water_quality_indices(self,
|
||||
training_csv_path: Optional[str] = None,
|
||||
formula_csv_file: Optional[str] = None,
|
||||
formula_names: Optional[List[str]] = None,
|
||||
@ -704,7 +704,7 @@ class WaterQualityInversionPipeline:
|
||||
self._notify("completed", f"水质指数已保存: {result}")
|
||||
return result
|
||||
|
||||
def step6_train_models(self, feature_start_column: str = "374.285004",
|
||||
def step7_ml_modeling(self, feature_start_column: str = "374.285004",
|
||||
preprocessing_methods: List[str] = None,
|
||||
model_names: List[str] = None,
|
||||
split_methods: List[str] = None,
|
||||
@ -747,7 +747,7 @@ class WaterQualityInversionPipeline:
|
||||
self._notify("completed", f"模型训练完成,结果保存在: {result}")
|
||||
return result
|
||||
|
||||
def step7_generate_sampling_points(self, deglint_img_path: Optional[str] = None,
|
||||
def step10_sampling(self, deglint_img_path: Optional[str] = None,
|
||||
interval: int = 50,
|
||||
sample_radius: int = 5,
|
||||
chunk_size: int = 1000,
|
||||
@ -756,7 +756,7 @@ class WaterQualityInversionPipeline:
|
||||
use_adaptive_sampling: bool = True,
|
||||
skip_dependency_check: bool = False, **kwargs) -> str:
|
||||
"""
|
||||
步骤7: 生成根据水域掩膜内且耀斑掩膜外的采样点,统计采样点的平均光谱
|
||||
步骤10: 生成根据水域掩膜内且耀斑掩膜外的采样点,统计采样点的平均光谱
|
||||
|
||||
Args:
|
||||
deglint_img_path: 去除耀斑后的影像文件路径(如果为None,使用步骤3的结果)
|
||||
@ -779,7 +779,7 @@ class WaterQualityInversionPipeline:
|
||||
if water_mask_path is None and self.water_mask_path is not None:
|
||||
water_mask_path = self.water_mask_path
|
||||
|
||||
self._notify("started", "步骤7: 生成预测采样点")
|
||||
self._notify("started", "步骤10: 生成预测采样点")
|
||||
result = PredictionStep.generate_sampling_points(
|
||||
deglint_img_path=img_path,
|
||||
interval=interval,
|
||||
@ -790,21 +790,21 @@ class WaterQualityInversionPipeline:
|
||||
output_dir=str(self.sampling_dir),
|
||||
use_adaptive_sampling=use_adaptive_sampling,
|
||||
)
|
||||
self._record_step_time("步骤7: 生成预测采样点", 0, 0)
|
||||
self._record_step_time("步骤10: 生成预测采样点", 0, 0)
|
||||
self._notify("completed", f"采样点光谱数据已保存: {result}")
|
||||
return result
|
||||
|
||||
def step8_predict_water_quality(self, sampling_csv_path: str,
|
||||
def step11_ml_prediction(self, sampling_csv_path: str,
|
||||
models_dir: Optional[str] = None,
|
||||
metric: str = 'test_r2',
|
||||
prediction_column: str = 'prediction',
|
||||
skip_dependency_check: bool = False, **kwargs) -> Dict[str, str]:
|
||||
"""
|
||||
步骤8: 将训练好的最佳机器学习模型应用到采样点的平均光谱上,预测水质参数
|
||||
|
||||
步骤11: 将训练好的最佳机器学习模型应用到采样点的平均光谱上,预测水质参数
|
||||
|
||||
Args:
|
||||
sampling_csv_path: 采样点光谱数据CSV路径
|
||||
models_dir: 模型保存目录(如果为None,使用步骤6的结果)
|
||||
models_dir: 模型保存目录(如果为None,使用步骤7的结果)
|
||||
metric: 选择最佳模型的指标
|
||||
prediction_column: 预测结果列名
|
||||
|
||||
@ -818,7 +818,7 @@ class WaterQualityInversionPipeline:
|
||||
print(f"[Pipeline] 收到字典: {'Yes' if _external_models_dict else 'No'}"
|
||||
f", 收到单模型: {'Yes' if _external_model else 'No'}")
|
||||
|
||||
self._notify("started", "步骤8: 预测水质参数")
|
||||
self._notify("started", "步骤11: 预测水质参数")
|
||||
result = PredictionStep.predict_water_quality(
|
||||
sampling_csv_path=sampling_csv_path,
|
||||
models_dir=models_dir if models_dir else str(self.models_dir),
|
||||
@ -831,11 +831,11 @@ class WaterQualityInversionPipeline:
|
||||
_external_models_dict=_external_models_dict,
|
||||
_external_model_dir=_external_model_dir,
|
||||
)
|
||||
self._record_step_time("步骤8: 预测水质参数", 0, 0)
|
||||
self._record_step_time("步骤11: 预测水质参数", 0, 0)
|
||||
self._notify("completed", f"预测完成,结果保存在: {self.prediction_dir}")
|
||||
return result
|
||||
|
||||
def step9_generate_distribution_map(self, prediction_csv_path: str,
|
||||
def step14_distribution_map(self, prediction_csv_path: str,
|
||||
boundary_shp_path: str,
|
||||
output_image_path: Optional[str] = None,
|
||||
resolution: float = 30,
|
||||
@ -1524,99 +1524,99 @@ class WaterQualityInversionPipeline:
|
||||
else:
|
||||
self._notify("步骤5: 光谱提取", "skipped", "未配置")
|
||||
|
||||
# 步骤5.5: 计算水质指数
|
||||
if 'step5_5' in config:
|
||||
self._notify("步骤5.5: 水质指数计算", "start")
|
||||
self.step5_5_calculate_water_quality_indices(**config['step5_5'])
|
||||
self._notify("步骤5.5: 水质指数计算", "completed", f"(输出: {self.indices_path})")
|
||||
# 步骤8: 计算水质指数
|
||||
if 'step8' in config:
|
||||
self._notify("步骤8: 水质指数计算", "start")
|
||||
self.step8_water_quality_indices(**config['step8'])
|
||||
self._notify("步骤8: 水质指数计算", "completed", f"(输出: {self.indices_path})")
|
||||
else:
|
||||
self._notify("步骤5.5: 水质指数计算", "skipped", "未配置")
|
||||
self._notify("步骤8: 水质指数计算", "skipped", "未配置")
|
||||
|
||||
# 步骤6: 训练模型
|
||||
if 'step6' in config:
|
||||
self._notify("步骤6: 模型训练", "start")
|
||||
self.step6_train_models(**config['step6'])
|
||||
self._notify("步骤6: 模型训练", "completed", f"(输出: {self.models_dir})")
|
||||
else:
|
||||
self._notify("步骤6: 模型训练", "skipped", "未配置")
|
||||
|
||||
# 步骤6.5: 非经验统计回归模型训练
|
||||
if 'step6_5' in config:
|
||||
self._notify("步骤6.5: 非经验模型训练", "start")
|
||||
self.step6_5_non_empirical_modeling(**config['step6_5'])
|
||||
self._notify("步骤6.5: 非经验模型训练", "completed", f"(输出: {self.models_dir})")
|
||||
else:
|
||||
self._notify("步骤6.5: 非经验模型训练", "skipped", "未配置")
|
||||
|
||||
# 步骤6.75: 自定义回归分析
|
||||
if 'step6_75' in config:
|
||||
self._notify("步骤6.75: 自定义回归", "start")
|
||||
self.step6_75_custom_regression(**config['step6_75'])
|
||||
self._notify("步骤6.75: 自定义回归", "completed", f"(输出: {self.custom_regression_path})")
|
||||
else:
|
||||
self._notify("步骤6.75: 自定义回归", "skipped", "未配置")
|
||||
|
||||
# 步骤7: 生成预测采样点
|
||||
# 步骤7: 训练模型
|
||||
if 'step7' in config:
|
||||
self._notify("步骤7: 采样点生成", "start")
|
||||
sampling_csv_path = self.step7_generate_sampling_points(**config['step7'])
|
||||
self._notify("步骤7: 采样点生成", "completed", f"(输出: {sampling_csv_path})")
|
||||
self._notify("步骤7: 模型训练", "start")
|
||||
self.step7_ml_modeling(**config['step7'])
|
||||
self._notify("步骤7: 模型训练", "completed", f"(输出: {self.models_dir})")
|
||||
else:
|
||||
self._notify("步骤7: 模型训练", "skipped", "未配置")
|
||||
|
||||
# 步骤8_non_empirical_modeling: 非经验统计回归模型训练
|
||||
if 'step8_non_empirical_modeling' in config:
|
||||
self._notify("步骤8: 非经验模型训练", "start")
|
||||
self.step8_non_empirical_modeling(**config['step8_non_empirical_modeling'])
|
||||
self._notify("步骤8: 非经验模型训练", "completed", f"(输出: {self.models_dir})")
|
||||
else:
|
||||
self._notify("步骤8: 非经验模型训练", "skipped", "未配置")
|
||||
|
||||
# 步骤9: 自定义回归分析
|
||||
if 'step9' in config:
|
||||
self._notify("步骤9: 自定义回归", "start")
|
||||
self.step9_custom_regression(**config['step9'])
|
||||
self._notify("步骤9: 自定义回归", "completed", f"(输出: {self.custom_regression_path})")
|
||||
else:
|
||||
self._notify("步骤9: 自定义回归", "skipped", "未配置")
|
||||
|
||||
# 步骤10: 生成预测采样点
|
||||
if 'step10' in config:
|
||||
self._notify("步骤10: 采样点生成", "start")
|
||||
sampling_csv_path = self.step10_sampling(**config['step10'])
|
||||
self._notify("步骤10: 采样点生成", "completed", f"(输出: {sampling_csv_path})")
|
||||
else:
|
||||
sampling_csv_path = None
|
||||
self._notify("步骤7: 采样点生成", "skipped", "未配置")
|
||||
self._notify("步骤10: 采样点生成", "skipped", "未配置")
|
||||
|
||||
# 步骤8: 预测水质参数
|
||||
if 'step8' in config and sampling_csv_path:
|
||||
self._notify("步骤8: 参数预测", "start")
|
||||
step8_config = config['step8'].copy()
|
||||
step8_config['sampling_csv_path'] = sampling_csv_path
|
||||
prediction_files = self.step8_predict_water_quality(**step8_config)
|
||||
self._notify("步骤8: 参数预测", "completed", f"(生成{len(prediction_files)}个预测文件)")
|
||||
# 步骤11_ml: 预测水质参数
|
||||
if 'step11_ml' in config and sampling_csv_path:
|
||||
self._notify("步骤11: 参数预测", "start")
|
||||
step11_ml_config = config['step11_ml'].copy()
|
||||
step11_ml_config['sampling_csv_path'] = sampling_csv_path
|
||||
prediction_files = self.step11_ml_prediction(**step11_ml_config)
|
||||
self._notify("步骤11: 参数预测", "completed", f"(生成{len(prediction_files)}个预测文件)")
|
||||
else:
|
||||
prediction_files = {}
|
||||
self._notify("步骤8: 参数预测", "skipped", "未配置或缺少采样点")
|
||||
self._notify("步骤11: 参数预测", "skipped", "未配置或缺少采样点")
|
||||
|
||||
# 步骤8.5: 使用非经验模型进行参数预测
|
||||
# 步骤11: 使用非经验模型进行参数预测
|
||||
non_empirical_prediction_files = {}
|
||||
if 'step8_5' in config and sampling_csv_path:
|
||||
self._notify("步骤8.5: 非经验模型预测", "start")
|
||||
step8_5_config = config['step8_5'].copy()
|
||||
step8_5_config['sampling_csv_path'] = sampling_csv_path
|
||||
non_empirical_prediction_files = self.step8_5_predict_with_non_empirical_models(**step8_5_config)
|
||||
self._notify("步骤8.5: 非经验模型预测", "completed", f"(生成{len(non_empirical_prediction_files)}个预测文件)")
|
||||
if 'step11' in config and sampling_csv_path:
|
||||
self._notify("步骤11: 非经验模型预测", "start")
|
||||
step11_config = config['step11'].copy()
|
||||
step11_config['sampling_csv_path'] = sampling_csv_path
|
||||
non_empirical_prediction_files = self.step11_non_empirical_prediction(**step11_config)
|
||||
self._notify("步骤11: 非经验模型预测", "completed", f"(生成{len(non_empirical_prediction_files)}个预测文件)")
|
||||
else:
|
||||
self._notify("步骤8.5: 非经验模型预测", "skipped", "未配置或缺少采样点")
|
||||
self._notify("步骤11: 非经验模型预测", "skipped", "未配置或缺少采样点")
|
||||
|
||||
# 步骤8.75: 使用自定义回归模型进行参数预测
|
||||
# 步骤12: 使用自定义回归模型进行参数预测
|
||||
custom_regression_prediction_files = {}
|
||||
if 'step8_75' in config and sampling_csv_path:
|
||||
self._notify("步骤8.75: 自定义回归预测", "start")
|
||||
step8_75_config = config['step8_75'].copy()
|
||||
step8_75_config['sampling_csv_path'] = sampling_csv_path
|
||||
custom_regression_prediction_files = self.step8_75_predict_with_custom_regression(**step8_75_config)
|
||||
self._notify("步骤8.75: 自定义回归预测", "completed", f"(生成{len(custom_regression_prediction_files)}个预测文件)")
|
||||
if 'step12' in config and sampling_csv_path:
|
||||
self._notify("步骤12: 自定义回归预测", "start")
|
||||
step12_config = config['step12'].copy()
|
||||
step12_config['sampling_csv_path'] = sampling_csv_path
|
||||
custom_regression_prediction_files = self.step12_custom_regression_prediction(**step12_config)
|
||||
self._notify("步骤12: 自定义回归预测", "completed", f"(生成{len(custom_regression_prediction_files)}个预测文件)")
|
||||
else:
|
||||
self._notify("步骤8.75: 自定义回归预测", "skipped", "未配置或缺少采样点")
|
||||
self._notify("步骤12: 自定义回归预测", "skipped", "未配置或缺少采样点")
|
||||
|
||||
# 合并机器学习预测、非经验模型预测和自定义回归预测结果
|
||||
all_prediction_files = {**prediction_files, **non_empirical_prediction_files, **custom_regression_prediction_files}
|
||||
|
||||
# 步骤9: 生成分布图
|
||||
# 步骤14: 生成分布图
|
||||
distribution_maps = {}
|
||||
if 'step9' in config and all_prediction_files:
|
||||
self._notify("步骤9: 分布图生成", "start")
|
||||
if 'step14' in config and all_prediction_files:
|
||||
self._notify("步骤14: 分布图生成", "start")
|
||||
for target_name, pred_file in all_prediction_files.items():
|
||||
step9_config = config['step9'].copy()
|
||||
step14_config = config['step14'].copy()
|
||||
for _k in ('step9_batch_mode', 'prediction_csv_dir', 'recursive_csv_scan'):
|
||||
step9_config.pop(_k, None)
|
||||
step9_config['prediction_csv_path'] = pred_file
|
||||
if 'output_image_path' not in step9_config:
|
||||
step9_config['output_image_path'] = None
|
||||
dist_map_path = self.step9_generate_distribution_map(**step9_config)
|
||||
step14_config.pop(_k, None)
|
||||
step14_config['prediction_csv_path'] = pred_file
|
||||
if 'output_image_path' not in step14_config:
|
||||
step14_config['output_image_path'] = None
|
||||
dist_map_path = self.step14_distribution_map(**step14_config)
|
||||
distribution_maps[target_name] = dist_map_path
|
||||
self._notify("步骤9: 分布图生成", "completed", f"(生成{len(distribution_maps)}个分布图)")
|
||||
self._notify("步骤14: 分布图生成", "completed", f"(生成{len(distribution_maps)}个分布图)")
|
||||
else:
|
||||
self._notify("步骤9: 分布图生成", "skipped", "未配置或缺少预测结果")
|
||||
self._notify("步骤14: 分布图生成", "skipped", "未配置或缺少预测结果")
|
||||
|
||||
# 生成可视化图表
|
||||
output_files = {}
|
||||
@ -1716,10 +1716,10 @@ class WaterQualityInversionPipeline:
|
||||
pipeline_info['step3'] = {'status': 'completed', 'output_file': str(self.deglint_img_path) if self.deglint_img_path else 'N/A'}
|
||||
pipeline_info['step4'] = {'status': 'completed', 'output_file': str(self.processed_csv_path) if self.processed_csv_path else 'N/A'}
|
||||
pipeline_info['step5'] = {'status': 'completed', 'output_file': str(self.training_csv_path) if self.training_csv_path else 'N/A'}
|
||||
pipeline_info['step5_5'] = {'status': 'completed', 'output_file': str(self.indices_path) if self.indices_path else 'N/A'}
|
||||
pipeline_info['step6'] = {'status': 'completed', 'output_file': str(self.models_dir)}
|
||||
pipeline_info['step6_75'] = {'status': 'completed', 'output_file': str(self.custom_regression_path) if self.custom_regression_path else 'N/A'}
|
||||
pipeline_info['training_params'] = config.get('step6', {})
|
||||
pipeline_info['step8'] = {'status': 'completed', 'output_file': str(self.indices_path) if self.indices_path else 'N/A'}
|
||||
pipeline_info['step7'] = {'status': 'completed', 'output_file': str(self.models_dir)}
|
||||
pipeline_info['step9'] = {'status': 'completed', 'output_file': str(self.custom_regression_path) if self.custom_regression_path else 'N/A'}
|
||||
pipeline_info['training_params'] = config.get('step7', {})
|
||||
|
||||
summary_path = self.report_generator.generate_batch_inference_summary(pipeline_info)
|
||||
print(f"批量处理摘要已生成: {summary_path}")
|
||||
@ -1769,7 +1769,7 @@ class WaterQualityInversionPipeline:
|
||||
traceback.print_exc()
|
||||
raise
|
||||
|
||||
def step6_5_non_empirical_modeling(self, csv_path: Optional[str] = None,
|
||||
def step8_non_empirical_modeling(self, csv_path: Optional[str] = None,
|
||||
preprocessing_methods: List[str] = None,
|
||||
algorithms: List[str] = None,
|
||||
value_cols: Union[int, Dict[str, int]] = 0,
|
||||
@ -1819,7 +1819,7 @@ class WaterQualityInversionPipeline:
|
||||
self._notify("completed", f"非经验模型训练完成")
|
||||
return result
|
||||
|
||||
def step6_75_custom_regression(self,
|
||||
def step9_custom_regression(self,
|
||||
csv_path: Optional[str] = None,
|
||||
x_columns: Optional[Union[str, List[str]]] = None,
|
||||
y_columns: Optional[Union[str, List[str]]] = None,
|
||||
@ -1999,7 +1999,7 @@ class WaterQualityInversionPipeline:
|
||||
|
||||
return summary_path
|
||||
|
||||
def step8_5_predict_with_non_empirical_models(self, sampling_csv_path: str,
|
||||
def step11_non_empirical_prediction(self, sampling_csv_path: str,
|
||||
non_empirical_models_dir: Optional[str] = None,
|
||||
output_path: Optional[str] = None,
|
||||
metric: str = 'Average Accuracy(%)',
|
||||
@ -2007,13 +2007,13 @@ class WaterQualityInversionPipeline:
|
||||
enabled: bool = True,
|
||||
skip_dependency_check: bool = False, **kwargs) -> Dict[str, str]:
|
||||
"""
|
||||
步骤8.5: 使用非经验统计回归模型进行参数预测
|
||||
步骤11: 使用非经验统计回归模型进行参数预测
|
||||
|
||||
根据非经验模型训练结果汇总CSV筛选给定方法的准确率最高的模型,使用该模型进行预测
|
||||
|
||||
Args:
|
||||
sampling_csv_path: 采样点光谱数据CSV路径
|
||||
non_empirical_models_dir: 非经验模型保存目录(如果为None,使用步骤6.5的结果)
|
||||
non_empirical_models_dir: 非经验模型保存目录(如果为None,使用步骤8的结果)
|
||||
output_path: 输出目录路径(如果为None,使用默认目录)
|
||||
metric: 选择最佳模型的指标(默认使用平均准确率)
|
||||
prediction_column: 预测结果列名
|
||||
@ -2021,7 +2021,7 @@ class WaterQualityInversionPipeline:
|
||||
Returns:
|
||||
预测结果文件路径字典(键为算法名)
|
||||
"""
|
||||
self._notify("started", "步骤8.5: 使用非经验模型进行参数预测")
|
||||
self._notify("started", "步骤11: 使用非经验模型进行参数预测")
|
||||
result = PredictionStep.predict_with_non_empirical_models(
|
||||
sampling_csv_path=sampling_csv_path,
|
||||
non_empirical_models_dir=non_empirical_models_dir,
|
||||
@ -2031,11 +2031,11 @@ class WaterQualityInversionPipeline:
|
||||
enabled=enabled,
|
||||
work_dir=str(self.work_dir),
|
||||
)
|
||||
self._record_step_time("步骤8.5: 非经验模型预测", 0, 0)
|
||||
self._record_step_time("步骤11: 非经验模型预测", 0, 0)
|
||||
self._notify("completed", f"非经验模型预测完成,结果保存在: {self.prediction_dir}")
|
||||
return result
|
||||
|
||||
def step8_75_predict_with_custom_regression(self, sampling_csv_path: str,
|
||||
def step12_custom_regression_prediction(self, sampling_csv_path: str,
|
||||
custom_regression_dir: Optional[str] = None,
|
||||
formula_csv_path: Optional[str] = None,
|
||||
coordinate_columns: Optional[List[str]] = None,
|
||||
@ -2044,13 +2044,13 @@ class WaterQualityInversionPipeline:
|
||||
enabled: bool = True,
|
||||
skip_dependency_check: bool = False, **kwargs) -> Dict[str, str]:
|
||||
"""
|
||||
步骤8.75: 使用自定义回归模型进行参数预测
|
||||
|
||||
步骤12: 使用自定义回归模型进行参数预测
|
||||
|
||||
使用新的CustomRegressionPredictor模块,基于9_Custom_Regression_Modeling文件夹中的CSV,
|
||||
根据r_squared选择最佳模型,批量预测水质参数
|
||||
|
||||
|
||||
Args:
|
||||
sampling_csv_path: 采样点光谱数据CSV路径(来自步骤7)
|
||||
sampling_csv_path: 采样点光谱数据CSV路径(来自步骤10)
|
||||
custom_regression_dir: 自定义回归模型目录(9_Custom_Regression_Modeling)
|
||||
formula_csv_path: 公式CSV文件路径,用于查找index_formula
|
||||
coordinate_columns: 坐标列名列表,默认为['longitude', 'latitude']或自动识别
|
||||
@ -2058,11 +2058,11 @@ class WaterQualityInversionPipeline:
|
||||
filename_prefix: 输出文件名前缀
|
||||
enabled: 是否启用
|
||||
skip_dependency_check: 是否跳过依赖检查
|
||||
|
||||
|
||||
Returns:
|
||||
预测结果文件路径字典(键为参数名)
|
||||
"""
|
||||
self._notify("started", "步骤8.75: 使用自定义回归模型进行参数预测")
|
||||
self._notify("started", "步骤12: 使用自定义回归模型进行参数预测")
|
||||
result = PredictionStep.predict_with_custom_regression(
|
||||
sampling_csv_path=sampling_csv_path,
|
||||
custom_regression_dir=custom_regression_dir,
|
||||
@ -2073,7 +2073,7 @@ class WaterQualityInversionPipeline:
|
||||
enabled=enabled,
|
||||
work_dir=str(self.work_dir),
|
||||
)
|
||||
self._record_step_time("步骤8.75: 自定义回归模型预测", 0, 0)
|
||||
self._record_step_time("步骤12: 自定义回归模型预测", 0, 0)
|
||||
self._notify("completed", f"自定义回归预测完成")
|
||||
return result
|
||||
|
||||
@ -2161,20 +2161,20 @@ def main():
|
||||
# 单步运行时建议显式指定;完整流程中可省略,将使用步骤2输出的耀斑掩膜
|
||||
# 'glint_mask_path': r"path/to/severe_glint_area.dat",
|
||||
},
|
||||
'step5_5': {
|
||||
'step8': {
|
||||
'formula_csv_file': 'path/to/water_quality_formulas.csv', # 公式CSV文件路径
|
||||
'formula_names': ['Al10SABI', 'TurbBe16RedOverViolet'], # 要计算的公式名称列表
|
||||
'output_filename': 'water_quality_indices.csv',
|
||||
'enabled': True # 是否启用水质指数计算
|
||||
},
|
||||
'step6': {
|
||||
'step7': {
|
||||
'feature_start_column': '374.285004',
|
||||
'preprocessing_methods': ['None', 'MMS', 'SS', 'SNV', 'MA', 'SG', 'MSC', 'D1', 'D2', 'DT', 'CT'],
|
||||
'model_names': ['SVR', 'RF', 'Ridge', 'Lasso'],
|
||||
'split_methods': ['spxy', 'ks', 'random'],
|
||||
'cv_folds': 3
|
||||
},
|
||||
'step6_5': {
|
||||
'step8_non_empirical_modeling': {
|
||||
'preprocessing_methods': ['None', 'MMS', 'SS', 'SNV', 'MA', 'SG', 'MSC', 'D1', 'D2', 'DT', 'CT'],
|
||||
'algorithms': ['chl_a', 'nh3', 'mno4', 'tn', 'tp', 'tss'],
|
||||
'value_cols': 0, # 可以是单个整数或字典,如 {'chl_a': 0, 'nh3': 1, 'mno4': 2, 'tn': 3, 'tp': 4, 'tss': 5}
|
||||
@ -2182,14 +2182,14 @@ def main():
|
||||
'window': 5,
|
||||
'enabled': True # 是否启用非经验模型训练
|
||||
},
|
||||
'step6_75': {
|
||||
'step9': {
|
||||
'x_columns': ['NDWI', 'NDVI'], # 自变量列名列表
|
||||
'y_columns': ['chl_a', 'tn', 'tp'], # 因变量列名列表
|
||||
'methods': 'all', # 回归方法
|
||||
'output_dir': 'custom_regression_results', # 输出目录
|
||||
'enabled': True # 是否启用自定义回归分析
|
||||
},
|
||||
'step7': {
|
||||
'step10': {
|
||||
'interval': 50,
|
||||
'sample_radius': 5,
|
||||
'chunk_size': 1000,
|
||||
@ -2197,16 +2197,16 @@ def main():
|
||||
# 可选:耀斑掩膜文件(dat),若不提供将使用步骤2结果;需要外部指定时取消注释
|
||||
# 'glint_mask_path': r"D:\path\to\severe_glint_area.dat",
|
||||
},
|
||||
'step8': {
|
||||
'step11_ml': {
|
||||
'metric': 'test_r2',
|
||||
'prediction_column': 'prediction'
|
||||
},
|
||||
'step8_5': {
|
||||
'step11': {
|
||||
'metric': 'Average Accuracy(%)', # 选择最佳模型的指标
|
||||
'prediction_column': 'prediction',
|
||||
'enabled': True # 是否启用非经验模型预测
|
||||
},
|
||||
'step8_75': {
|
||||
'step12': {
|
||||
'custom_regression_dir': None, # 自定义回归模型目录(None表示使用9_Custom_Regression_Modeling)
|
||||
'formula_csv_path': None, # 公式CSV文件路径,用于查找index_formula(如water_quality_formulas.csv)
|
||||
'coordinate_columns': None, # 坐标列名(None表示自动识别)
|
||||
@ -2214,7 +2214,7 @@ def main():
|
||||
'filename_prefix': 'custom_regression_prediction', # 输出文件名前缀
|
||||
'enabled': True # 是否启用自定义回归预测
|
||||
},
|
||||
'step9': {
|
||||
'step14': {
|
||||
'boundary_shp_path': r"D:\BaiduNetdiskDownload\yaobao\roi\roi.shp" ,
|
||||
'resolution': 30,
|
||||
'input_crs': 'EPSG:32651',
|
||||
@ -2345,41 +2345,41 @@ def example_independent_steps():
|
||||
except Exception as e:
|
||||
print(f"步骤6失败: {e}")
|
||||
|
||||
# 示例6: 独立运行步骤7 - 采样点生成
|
||||
print("\n示例6: 独立运行步骤7 - 采样点生成")
|
||||
# 示例6: 独立运行步骤10 - 采样点生成
|
||||
print("\n示例6: 独立运行步骤10 - 采样点生成")
|
||||
try:
|
||||
sampling_csv = pipeline.step7_generate_sampling_points(
|
||||
sampling_csv = pipeline.step10_sampling(
|
||||
deglint_img_path="path/to/deglint_image.bsq",
|
||||
water_mask_path="path/to/water_mask.dat",
|
||||
skip_dependency_check=True
|
||||
)
|
||||
print(f"采样点数据: {sampling_csv}")
|
||||
except Exception as e:
|
||||
print(f"步骤7失败: {e}")
|
||||
print(f"步骤10失败: {e}")
|
||||
|
||||
# 示例7: 独立运行步骤8 - 水质预测
|
||||
print("\n示例7: 独立运行步骤8 - 水质预测")
|
||||
# 示例7: 独立运行步骤11 - 水质预测
|
||||
print("\n示例7: 独立运行步骤11 - 水质预测")
|
||||
try:
|
||||
predictions = pipeline.step8_predict_water_quality(
|
||||
predictions = pipeline.step11_ml_prediction(
|
||||
sampling_csv_path="path/to/sampling_spectra.csv",
|
||||
models_dir="path/to/models_directory",
|
||||
skip_dependency_check=True
|
||||
)
|
||||
print(f"预测结果: {predictions}")
|
||||
except Exception as e:
|
||||
print(f"步骤8失败: {e}")
|
||||
print(f"步骤11失败: {e}")
|
||||
|
||||
# 示例8: 独立运行步骤9 - 分布图生成
|
||||
print("\n示例8: 独立运行步骤9 - 分布图生成")
|
||||
# 示例8: 独立运行步骤14 - 分布图生成
|
||||
print("\n示例8: 独立运行步骤14 - 分布图生成")
|
||||
try:
|
||||
distribution_map = pipeline.step9_generate_distribution_map(
|
||||
distribution_map = pipeline.step14_distribution_map(
|
||||
prediction_csv_path="path/to/prediction_results.csv",
|
||||
boundary_shp_path="path/to/boundary.shp",
|
||||
skip_dependency_check=True
|
||||
)
|
||||
print(f"分布图: {distribution_map}")
|
||||
except Exception as e:
|
||||
print(f"步骤9失败: {e}")
|
||||
print(f"步骤14失败: {e}")
|
||||
|
||||
print("\n" + "="*80)
|
||||
print("独立步骤运行示例完成")
|
||||
|
||||
Reference in New Issue
Block a user