fix: GUI 模型加载改为按 metric 遍历所有 .joblib 选最优
旧行为: _scan_external_model_dir 盲目取 joblib_files[0]
→ 字母序选到 LinearRegression 而非 SVR
→ 所有目标永远是 D1,因为字母序 D1 < SNV
新行为:
- 读取 GUI 中用户选择的 metric (R²/RMSE/MAE)
- 遍历每个子目录下全部 .joblib 文件
- 按指标自动选择最优模型:
R² → 取最大值
RMSE → 取最小值
MAE → 取最小值
- 控制台打印: [模型加载] 目标 BGA 根据 R² 自动选择最佳模型: BGA_spxy_SNV_SVR.joblib, 分数: 0.899001
This commit is contained in:
@ -233,6 +233,14 @@ class Step9MlPredictPanel(QWidget):
|
||||
return
|
||||
|
||||
self.external_model_dir = dir_path
|
||||
|
||||
# ★ 读取用户选择的模型评估指标
|
||||
_metric_key = self.metric.currentData() # "test_r2" / "test_rmse" / "test_mae"
|
||||
_metric_display = self.metric.currentText() # "R² (决定系数)" / ...
|
||||
_is_r2 = 'r2' in _metric_key.lower()
|
||||
_is_rmse = 'rmse' in _metric_key.lower()
|
||||
_is_mae = 'mae' in _metric_key.lower()
|
||||
|
||||
models_found = {}
|
||||
errors = []
|
||||
|
||||
@ -243,26 +251,53 @@ class Step9MlPredictPanel(QWidget):
|
||||
if not subentry.is_dir():
|
||||
continue
|
||||
subdir_name = subentry.name
|
||||
joblib_files = [
|
||||
joblib_files = sorted([
|
||||
f for f in os.scandir(subentry.path)
|
||||
if f.is_file() and f.name.lower().endswith(".joblib")
|
||||
]
|
||||
], key=lambda x: x.name)
|
||||
if not joblib_files:
|
||||
continue
|
||||
joblib_path = joblib_files[0].path
|
||||
try:
|
||||
loaded = joblib.load(joblib_path)
|
||||
if isinstance(loaded, dict) and "model" in loaded:
|
||||
# ★ 保留完整 dict(含 metadata / train_wavelengths),
|
||||
# 推理端需要 train_wavelengths 做光谱重采样
|
||||
models_found[subdir_name] = loaded
|
||||
elif hasattr(loaded, "predict"):
|
||||
models_found[subdir_name] = loaded
|
||||
else:
|
||||
errors.append(f"{subdir_name}: 无法识别的格式 {type(loaded).__name__}")
|
||||
|
||||
# ★ 遍历该子目录下全部 .joblib 文件,按 metric 选出最佳模型
|
||||
best_score = -float('inf') if _is_r2 else float('inf')
|
||||
best_entry = None
|
||||
best_fname = None
|
||||
|
||||
for f_entry in joblib_files:
|
||||
try:
|
||||
data = joblib.load(f_entry.path)
|
||||
if not isinstance(data, dict) or "model" not in data:
|
||||
continue
|
||||
meta = data.get('metadata', {})
|
||||
# 按指标优先级:test_xxx → train_xxx
|
||||
score = None
|
||||
if _is_r2:
|
||||
score = meta.get('test_r2', meta.get('train_r2', None))
|
||||
elif _is_rmse:
|
||||
score = meta.get('test_rmse', meta.get('train_rmse', None))
|
||||
elif _is_mae:
|
||||
score = meta.get('test_mae', meta.get('train_mae', None))
|
||||
|
||||
if score is None:
|
||||
continue
|
||||
|
||||
if _is_r2 and score > best_score:
|
||||
best_score = score
|
||||
best_entry = data
|
||||
best_fname = f_entry.name
|
||||
elif not _is_r2 and score < best_score:
|
||||
best_score = score
|
||||
best_entry = data
|
||||
best_fname = f_entry.name
|
||||
except Exception:
|
||||
continue
|
||||
except Exception as e:
|
||||
errors.append(f"{subdir_name}: {type(e).__name__}: {e}")
|
||||
|
||||
if best_entry is not None:
|
||||
models_found[subdir_name] = best_entry
|
||||
print(f"[模型加载] 目标 {subdir_name} 根据 {_metric_display} "
|
||||
f"自动选择最佳模型: {best_fname}, 分数: {best_score:.6f}")
|
||||
else:
|
||||
errors.append(f"{subdir_name}: 无可评估的 .joblib 文件")
|
||||
|
||||
except Exception as e:
|
||||
QMessageBox.warning(
|
||||
|
||||
Reference in New Issue
Block a user