You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
nmWTAI-Platform/ML/nmWTAI-ML/src/evaluation/autofit_objective.py

72 lines
2.8 KiB
Python

# -*- coding: utf-8 -*-
"""自动拟合候选曲线目标函数。
本模块提供轻量级的曲线误差计算用于比较目标曲线和代理模型预测曲线的匹配度
目标函数同时考虑相对误差和绝对误差并分别计算 log_pressure log_derivative
两条曲线的贡献适合在参数筛选PSO 候选排序和局部邻域验证中复用
"""
from __future__ import annotations
import numpy as np
def split_curve_by_layout(curve: np.ndarray, layout: dict) -> dict[str, np.ndarray]:
"""按照 curve_layout 拆分曲线。"""
parts: dict[str, np.ndarray] = {}
for part in layout["parts"]:
start = int(part["start"])
end = int(part["end"])
parts[str(part["name"])] = np.asarray(curve[start:end], dtype=np.float64)
return parts
def calculate_curve_objective_1d(target: np.ndarray, pred: np.ndarray) -> float:
"""计算单段曲线的自动拟合目标,兼顾相对误差和绝对误差。"""
target = np.asarray(target, dtype=np.float64).reshape(-1)
pred = np.asarray(pred, dtype=np.float64).reshape(-1)
if target.size == 0 or pred.size != target.size:
return float("inf")
if not (np.isfinite(target).all() and np.isfinite(pred).all()):
return float("inf")
# 对较大的 log 值适当降权,避免其完全主导排序结果。
weight_factor = np.minimum(100.0, np.abs(target) * 0.01)
weight = 1.0 / (1.0 + weight_factor)
scale = np.maximum(np.maximum(np.abs(target), np.abs(pred)), 1e-12)
relative_error = np.abs(target - pred) / scale
absolute_error = np.abs(target - pred)
# 相对误差用于跨尺度比较曲线形态,绝对误差用于保留整体幅值差异。
point_error = 0.7 * relative_error + 0.3 * absolute_error
weighted_mse = np.sum(weight * (point_error**2)) / max(np.sum(weight), 1e-12)
return float(np.sqrt(weighted_mse))
def dual_log_objective(
curve_target: np.ndarray,
curve_pred: np.ndarray,
curve_layout: dict,
w_pressure: float = 0.5,
w_derivative: float = 0.5,
) -> dict[str, float]:
"""分别计算压力和导数目标,并按权重合成双对数自动拟合目标。"""
parts_target = split_curve_by_layout(curve_target, curve_layout)
parts_pred = split_curve_by_layout(curve_pred, curve_layout)
p_obj = calculate_curve_objective_1d(parts_target["log_pressure"], parts_pred["log_pressure"])
d_obj = calculate_curve_objective_1d(parts_target["log_derivative"], parts_pred["log_derivative"])
total_w = max(float(w_pressure) + float(w_derivative), 1e-12)
combined = (float(w_pressure) * p_obj + float(w_derivative) * d_obj) / total_w
return {
"log_pressure_objective": float(p_obj),
"log_derivative_objective": float(d_obj),
"dual_log_objective": float(combined),
}