Refactor code for improved readability and consistency

- Reorganized import statements in `ml_surrogate_train.py`, `rbf_model.py`, `rbf_optimization_de.py`, `rbf_surrogate_train.py` for clarity. - Simplified dictionary and list comprehensions for better readability. - Updated print statements for consistent formatting. - Enhanced function definitions with clearer parameter formatting. - Added a new `pyproject.toml` file for Ruff configuration to enforce code style. - Removed unnecessary comments and improved inline documentation.
parent 66a1c42f
output,best_model,cv_rmse,std_rmse,cv_rmse_dispersion,cv_mae,cv_r2,BEST_PARAMS,model_path,train_time_sec,gpr_kernel,selected_by
exymax_tw1,SVR,0.006585985009931142,0.0064982791163432545,0.9866829497097801,0.006585985009931142,,"{""svr__C"": 1245.9545122809943, ""svr__epsilon"": 0.0012027645559314329, ""svr__gamma"": 0.005025785483194675}",../../models/width_optimization/3W/ml_models/per_output_models_B29_H45/it0/best_model_exymax_tw1.joblib,395.13,,lowest_cv_rmse_dispersion_within_5pct_rmse_band
exymax_tw3,SVR,0.006837992343800181,0.004553580884860971,0.6659236594480216,0.006837992343800181,,"{""svr__C"": 448.7880306471758, ""svr__epsilon"": 0.00013403355081127117, ""svr__gamma"": 0.005847007418075073}",../../models/width_optimization/3W/ml_models/per_output_models_B29_H45/it0/best_model_exymax_tw3.joblib,271.87,,lowest_cv_rmse_dispersion_within_5pct_rmse_band
exymax_tw2,SVR,0.0074343683500841745,0.004806222418653051,0.6464869901958292,0.0074343683500841745,,"{""svr__C"": 1578.3879853890564, ""svr__epsilon"": 0.002061045404501547, ""svr__gamma"": 0.003800674800490907}",../../models/width_optimization/3W/ml_models/per_output_models_B29_H45/it0/best_model_exymax_tw2.joblib,357.86,,lowest_cv_rmse_dispersion_within_5pct_rmse_band
tfmmax_frame,SVR,2.619870006205032,2.179555686783801,0.8319327606414179,2.619870006205032,,"{""svr__C"": 5387.889822738673, ""svr__epsilon"": 0.00023269836732785153, ""svr__gamma"": 0.07097468738318204}",../../models/width_optimization/3W/ml_models/per_output_models_B29_H45/it0/best_model_tfmmax_frame.joblib,379.78,,lowest_cv_rmse_dispersion_within_5pct_rmse_band
tfmmax_tw3,SVR,5.238414599827629,6.046768431344908,1.1543126868086917,5.238414599827629,,"{""svr__C"": 5330.328717919815, ""svr__epsilon"": 0.05582902448723831, ""svr__gamma"": 0.04143240634749279}",../../models/width_optimization/3W/ml_models/per_output_models_B29_H45/it0/best_model_tfmmax_tw3.joblib,503.18,,lowest_cv_rmse_dispersion_within_5pct_rmse_band
tfmmax_tw2,GaussianProcess,7.603551373657773,7.080381390450335,0.9311939963975333,7.603551373657773,,"{""gpr__amplitude"": 17.76576664980768, ""gpr__kernel_type"": ""RBF"", ""gpr__length_scale"": 2.467108843522573, ""gpr__n_restarts_optimizer"": 4, ""gpr__noise"": 2.3000512910597964e-12, ""gpr__rq_alpha"": 0.024337729656929853}",../../models/width_optimization/3W/ml_models/per_output_models_B29_H45/it0/best_model_tfmmax_tw2.joblib,593.72,1.91**2 * RBF(length_scale=2.5) + WhiteKernel(noise_level=2.3e-12),lowest_cv_rmse_dispersion_within_5pct_rmse_band
tfmmax_tw1,FlexibleMLP,9.347145297566009,11.923942423962007,1.275677444221071,9.347145297566009,,"{""mlp__activation"": ""relu"", ""mlp__alpha"": 1.9379088771032204e-05, ""mlp__learning_rate_init"": 0.0004224115725246676, ""mlp__n_layers"": 4, ""mlp__n_neurons"": 489}",../../models/width_optimization/3W/ml_models/per_output_models_B29_H45/it0/best_model_tfmmax_tw1.joblib,1210.15,,lowest_cv_rmse_dispersion_within_5pct_rmse_band
output,best_model,cv_rmse,std_rmse,cv_rmse_dispersion,cv_mae,cv_r2,BEST_PARAMS,model_path,train_time_sec,gpr_kernel,selected_by
exymax_tw3,SVR,0.007202212127447048,0.004481301562810276,0.6222118265209654,0.007202212127447048,,"{""svr__C"": 1117.125712746634, ""svr__epsilon"": 0.0006465958496706061, ""svr__gamma"": 0.004670356278081838}",../../models/width_optimization/3W/ml_models/per_output_models_B34_H45/it0/best_model_exymax_tw3.joblib,889.41,,lowest_cv_rmse_dispersion_within_5pct_rmse_band
exymax_tw1,GradientBoosting,0.007300943573175188,0.007955575607590385,1.089664031484974,0.007300943573175188,,"{""learning_rate"": 0.016754195403105226, ""max_depth"": 3, ""max_features"": 0.6676595772974903, ""n_estimators"": 1169, ""subsample"": 0.7322018725625201}",../../models/width_optimization/3W/ml_models/per_output_models_B34_H45/it0/best_model_exymax_tw1.joblib,425.58,,lowest_cv_rmse_dispersion_within_5pct_rmse_band
exymax_tw2,SVR,0.008460412231077893,0.011444731445050746,1.3527392203196034,0.008460412231077893,,"{""svr__C"": 9808.35589449746, ""svr__epsilon"": 0.00016322664292135178, ""svr__gamma"": 0.00038258041488189597}",../../models/width_optimization/3W/ml_models/per_output_models_B34_H45/it0/best_model_exymax_tw2.joblib,382.41,,lowest_cv_rmse_dispersion_within_5pct_rmse_band
tfmmax_frame,SVR,1.7183858166563564,1.8940457119290446,1.1022237809285973,1.7183858166563564,,"{""svr__C"": 2338.7077018101695, ""svr__epsilon"": 0.0015121721150378067, ""svr__gamma"": 0.08059242367780602}",../../models/width_optimization/3W/ml_models/per_output_models_B34_H45/it0/best_model_tfmmax_frame.joblib,334.62,,lowest_cv_rmse_dispersion_within_5pct_rmse_band
tfmmax_tw2,SVR,6.570230475951083,8.231729016702195,1.252882839777489,6.570230475951083,,"{""svr__C"": 9598.629415551462, ""svr__epsilon"": 0.008177764525277858, ""svr__gamma"": 0.06450806413377351}",../../models/width_optimization/3W/ml_models/per_output_models_B34_H45/it0/best_model_tfmmax_tw2.joblib,497.18,,lowest_cv_rmse_dispersion_within_5pct_rmse_band
tfmmax_tw3,SVR,6.867884256625402,7.773194090294852,1.131817864110931,6.867884256625402,,"{""svr__C"": 4770.813296275575, ""svr__epsilon"": 0.0156951512570451, ""svr__gamma"": 0.04171961411779374}",../../models/width_optimization/3W/ml_models/per_output_models_B34_H45/it0/best_model_tfmmax_tw3.joblib,505.18,,lowest_cv_rmse_dispersion_within_5pct_rmse_band
tfmmax_tw1,GaussianProcess,12.729753975937573,16.8283131798545,1.3219668826015203,12.729753975937573,,"{""gpr__amplitude"": 42.64486576023699, ""gpr__kernel_type"": ""Matern32"", ""gpr__length_scale"": 1.5803508571081364, ""gpr__n_restarts_optimizer"": 10, ""gpr__noise"": 2.537051332183834e-05, ""gpr__rq_alpha"": 0.01469218297101831}",../../models/width_optimization/3W/ml_models/per_output_models_B34_H45/it0/best_model_tfmmax_tw1.joblib,872.27,"1.98**2 * Matern(length_scale=4.65, nu=1.5) + WhiteKernel(noise_level=2.91e-12)",lowest_cv_rmse_dispersion_within_5pct_rmse_band
output,best_model,cv_rmse,std_rmse,cv_rmse_dispersion,cv_mae,cv_r2,BEST_PARAMS,model_path,train_time_sec,gpr_kernel,selected_by
exymax_tw5,GaussianProcess,0.0037397014620559475,0.0018524494485466028,0.4953468792474669,0.002564404130278725,0.9436289596508454,"{""gpr__amplitude"": 66.2941072502412, ""gpr__kernel_type"": ""Matern52"", ""gpr__length_scale"": 9.110383232654469, ""gpr__n_restarts_optimizer"": 2, ""gpr__noise"": 1.1864143515274533e-09, ""gpr__rq_alpha"": 0.09863897962847874}",../../models/width_optimization/5W/ml_models/per_output_models_B34_H60/it0/best_model_exymax_tw5.joblib,1245.86,"2.7**2 * Matern(length_scale=5.93, nu=2.5) + WhiteKernel(noise_level=1.19e-09)",lowest_cv_rmse_dispersion_within_5pct_rmse_band
exymax_tw2,GaussianProcess,0.005176366137444404,0.0013486668112550314,0.2605431639580415,0.003913884402047848,0.9629242548153287,"{""gpr__amplitude"": 0.4369339947510315, ""gpr__kernel_type"": ""Matern52"", ""gpr__length_scale"": 53.88550972627239, ""gpr__n_restarts_optimizer"": 10, ""gpr__noise"": 3.3825346762279944e-05, ""gpr__rq_alpha"": 0.014523514317963207}",../../models/width_optimization/5W/ml_models/per_output_models_B34_H60/it0/best_model_exymax_tw2.joblib,1452.49,"3.2**2 * Matern(length_scale=6.89, nu=2.5) + WhiteKernel(noise_level=2.91e-12)",lowest_cv_rmse_dispersion_within_5pct_rmse_band
exymax_tw1,SVR,0.0065461931973238765,0.0016275998090011273,0.2486330237956466,0.004822458246245301,0.941070262320398,"{""svr__C"": 1535.8841058246376, ""svr__epsilon"": 0.00014352665858615663, ""svr__gamma"": 0.0018620005892167522}",../../models/width_optimization/5W/ml_models/per_output_models_B34_H60/it0/best_model_exymax_tw1.joblib,1235.52,,lowest_cv_rmse_dispersion_within_5pct_rmse_band
exymax_tw4,GaussianProcess,0.006603966975088371,0.001775601440057033,0.2688689157221706,0.004692998066122281,0.9507369331408887,"{""gpr__amplitude"": 50.805556206537666, ""gpr__kernel_type"": ""Matern32"", ""gpr__length_scale"": 21.652164558122173, ""gpr__n_restarts_optimizer"": 1, ""gpr__noise"": 2.9548225428033293e-06, ""gpr__rq_alpha"": 2.558711165466693}",../../models/width_optimization/5W/ml_models/per_output_models_B34_H60/it0/best_model_exymax_tw4.joblib,2001.22,"4.2**2 * Matern(length_scale=13.2, nu=1.5) + WhiteKernel(noise_level=2.95e-06)",lowest_cv_rmse_dispersion_within_5pct_rmse_band
exymax_tw3,XGBoost,0.011296370910068609,0.0028544467636858533,0.25268706086320575,0.008438430960753036,0.8887122017660922,"{""colsample_bytree"": 0.922975236986968, ""learning_rate"": 0.09616759998521371, ""max_depth"": 3, ""min_child_weight"": 2, ""n_estimators"": 645, ""subsample"": 0.8928281167713635}",../../models/width_optimization/5W/ml_models/per_output_models_B34_H60/it0/best_model_exymax_tw3.joblib,1263.38,,lowest_cv_rmse_dispersion_within_5pct_rmse_band
tfmmax_tw5,GaussianProcess,3.7384297568091562,1.3274899260227968,0.3550929166463309,2.7368501751524046,0.9723615024471302,"{""gpr__amplitude"": 0.4369339947510315, ""gpr__kernel_type"": ""Matern52"", ""gpr__length_scale"": 53.88550972627239, ""gpr__n_restarts_optimizer"": 10, ""gpr__noise"": 3.3825346762279944e-05, ""gpr__rq_alpha"": 0.014523514317963207}",../../models/width_optimization/5W/ml_models/per_output_models_B34_H60/it0/best_model_tfmmax_tw5.joblib,1810.68,"3.38**2 * Matern(length_scale=7.88, nu=2.5) + WhiteKernel(noise_level=2.91e-12)",lowest_cv_rmse_dispersion_within_5pct_rmse_band
tfmmax_tw4,GaussianProcess,5.133123529769486,1.3469976699248127,0.26241286852204443,3.8771940588901117,0.978992912143702,"{""gpr__amplitude"": 0.4369339947510315, ""gpr__kernel_type"": ""Matern52"", ""gpr__length_scale"": 53.88550972627239, ""gpr__n_restarts_optimizer"": 10, ""gpr__noise"": 3.3825346762279944e-05, ""gpr__rq_alpha"": 0.014523514317963207}",../../models/width_optimization/5W/ml_models/per_output_models_B34_H60/it0/best_model_tfmmax_tw4.joblib,1117.45,"3.2**2 * Matern(length_scale=7.86, nu=2.5) + WhiteKernel(noise_level=2.91e-12)",lowest_cv_rmse_dispersion_within_5pct_rmse_band
tfmmax_tw2,GaussianProcess,6.576362420451899,1.5033765740006209,0.22860306015453988,5.3484335100709925,0.9804048469267181,"{""gpr__amplitude"": 0.4369339947510315, ""gpr__kernel_type"": ""Matern52"", ""gpr__length_scale"": 53.88550972627239, ""gpr__n_restarts_optimizer"": 10, ""gpr__noise"": 3.3825346762279944e-05, ""gpr__rq_alpha"": 0.014523514317963207}",../../models/width_optimization/5W/ml_models/per_output_models_B34_H60/it0/best_model_tfmmax_tw2.joblib,2133.81,"4.15**2 * Matern(length_scale=8.2, nu=2.5) + WhiteKernel(noise_level=2.91e-12)",lowest_cv_rmse_dispersion_within_5pct_rmse_band
tfmmax_frame,SVR,7.362379567538453,2.0424917941910397,0.2774227782545486,5.5591589929609775,0.6082838664236161,"{""svr__C"": 193.7932286428093, ""svr__epsilon"": 0.00012005001235516034, ""svr__gamma"": 0.04170927843815279}",../../models/width_optimization/5W/ml_models/per_output_models_B34_H60/it0/best_model_tfmmax_frame.joblib,2858.91,,lowest_cv_rmse_dispersion_within_5pct_rmse_band
tfmmax_tw3,GaussianProcess,8.477766506568951,2.0065315944971487,0.23668162987768046,6.501673146641316,0.9810053418137713,"{""gpr__amplitude"": 1.102823280779196, ""gpr__kernel_type"": ""RBF"", ""gpr__length_scale"": 0.4345689693488521, ""gpr__n_restarts_optimizer"": 6, ""gpr__noise"": 7.227269699156097e-05, ""gpr__rq_alpha"": 0.05336277986968177}",../../models/width_optimization/5W/ml_models/per_output_models_B34_H60/it0/best_model_tfmmax_tw3.joblib,2040.23,4.53**2 * RBF(length_scale=4.85) + WhiteKernel(noise_level=0.000709),lowest_cv_rmse_dispersion_within_5pct_rmse_band
tfmmax_tw1,SVR,9.729020339610338,3.3410734652444916,0.3434131442445218,6.791137893865481,0.9561686375984351,"{""svr__C"": 3513.591055460674, ""svr__epsilon"": 0.08923278628428069, ""svr__gamma"": 0.013747294826820433}",../../models/width_optimization/5W/ml_models/per_output_models_B34_H60/it0/best_model_tfmmax_tw1.joblib,785.03,,lowest_cv_rmse_dispersion_within_5pct_rmse_band
Parameter,Value
Configuration_W,3.0
Configuration_B,29.0
Configuration_H,45.0
Configuration_TFD_W,90.0
Iteration,0.0
tw1_optimal,5.525014015514342
tw2_optimal,8.471896290298302
tw3_optimal,9.333863643334162
Objective_score,-1.1926307429844958e-06
Exy_tw1,0.062156306095972946
Exy_tw2,0.04245576123008932
Exy_tw3,0.04710451673468341
TFM_tw1,90.00000000228151
TFM_tw2,90.00000000327702
TFM_tw3,90.00000000384767
TFM_frame,70.8310257119319
Parameter,Value
Configuration_W,3.0
Configuration_B,34.0
Configuration_H,45.0
Configuration_TFD_W,90.0
Iteration,0.0
tw1_optimal,7.333816578195384
tw2_optimal,9.279818580001832
tw3_optimal,10.121143978945401
Objective_score,-1.0932680460256248e-06
Exy_tw1,0.030541286356165126
Exy_tw2,0.038966386800767694
Exy_tw3,0.04736176051237062
TFM_tw1,90.00000000888014
TFM_tw2,90.0000000363739
TFM_tw3,90.00000004969976
TFM_frame,71.65152648580627
Parameter,Value
Configuration_W,5.0
Configuration_B,34.0
Configuration_H,60.0
Configuration_TFD_W,90.0
Iteration,0.0
tw1_optimal,5.694179976812822
tw2_optimal,7.254866605325219
tw3_optimal,8.140135383492023
tw4_optimal,6.653343430447909
tw5_optimal,5.0
Objective_score,17.106344387688598
Exy_tw1,0.06127584151539267
Exy_tw2,0.05514946520902724
Exy_tw3,0.06789993494749069
Exy_tw4,0.06857663218038944
Exy_tw5,0.053409088461247346
TFM_tw1,90.00000005473717
TFM_tw2,90.00000072572061
TFM_tw3,90.0000006322008
TFM_tw4,90.00031542767577
TFM_tw5,72.89365290337983
TFM_frame,73.03210418991345
......@@ -29,7 +29,7 @@ THICKNESS_FILE = os.path.join(BASE_DIR, f"widthsH{H}_B{B}.txt")
# === Read window thickness data ===
thickness_data = []
with open(THICKNESS_FILE, "r", encoding="utf-8") as f:
with open(THICKNESS_FILE, encoding="utf-8") as f:
for line in f:
parts = line.strip().split()
if parts:
......@@ -130,7 +130,7 @@ for folder_name in case_folders_sorted:
df_curve["Case"] = i
# thickness correcto por case
trow = thickness_by_case.get(i, None)
trow = thickness_by_case.get(i)
if trow is None:
print(f"⚠️ No thickness data for case {i}, skipping.")
continue
......@@ -290,10 +290,7 @@ for (case, cycle), g in df.groupby(["Case", "CycleNum"]):
peak_displ = df.loc[idx_peak, "Displ"]
peak_force = df.loc[idx_peak, "Force"]
if peak_displ != 0:
K_sec = peak_force / peak_displ
else:
K_sec = np.nan
K_sec = peak_force / peak_displ if peak_displ != 0 else np.nan
row["SecantStiffness"] = K_sec
cycle_rows.append(row)
......
import os
import pandas as pd
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns
sns.set_theme(style="whitegrid", context="talk")
......@@ -29,6 +30,7 @@ os.makedirs(PLOT_DIR, exist_ok=True)
output_file_cycles = os.path.join(BASE_DIR, "merged_dataset_cycles.csv")
df_cycles = pd.read_csv(output_file_cycles)
def plot_envelope_per_case(df_cycles, case_number, outdir=PLOT_DIR):
g = df_cycles[df_cycles["Case"] == case_number]
......@@ -51,6 +53,7 @@ def plot_envelope_per_case(df_cycles, case_number, outdir=PLOT_DIR):
print(f"Saved: {fname}")
def plot_energy_degradation(df_cycles, case_number, outdir=PLOT_DIR):
g = df_cycles[df_cycles["Case"] == case_number]
......@@ -78,6 +81,7 @@ def plot_energy_degradation(df_cycles, case_number, outdir=PLOT_DIR):
print(f"Saved: {fname}")
def plot_stiffness_degradation(df_cycles, case_number, outdir=PLOT_DIR):
g = df_cycles[df_cycles["Case"] == case_number]
......@@ -118,7 +122,7 @@ def plot_all_envelopes(df_cycles, outdir=PLOT_DIR):
g["PosEnvForce"],
marker="o",
linestyle="-",
label=f"Case {case} (pos)"
label=f"Case {case} (pos)",
)
# Plot negative envelope
......@@ -127,7 +131,7 @@ def plot_all_envelopes(df_cycles, outdir=PLOT_DIR):
g["NegEnvForce"],
marker="o",
linestyle="--",
label=f"Case {case} (neg)"
label=f"Case {case} (neg)",
)
plt.axhline(0, color="black", linewidth=0.8)
......@@ -139,7 +143,7 @@ def plot_all_envelopes(df_cycles, outdir=PLOT_DIR):
plt.legend(bbox_to_anchor=(1.04, 1), loc="upper left")
plt.tight_layout()
fname = os.path.join(outdir, f"envelopes_all_cases.png")
fname = os.path.join(outdir, "envelopes_all_cases.png")
plt.savefig(fname)
plt.close()
......
......@@ -27,9 +27,10 @@ Stability fix:
from __future__ import annotations
import argparse
import contextlib
import gc
import os
from typing import Dict, List, Optional, Tuple, cast
from typing import cast
import joblib
import numpy as np
......@@ -86,8 +87,8 @@ def _make_grad_scaler(use_amp: bool):
def make_windows_for_case_fast(
df_case: pd.DataFrame, feature_cols: List[str], target_col: str, window_size: int
) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:
df_case: pd.DataFrame, feature_cols: list[str], target_col: str, window_size: int
) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
"""
Vectorized sliding windows.
xw: (n_windows, window_size, n_features) float32
......@@ -124,18 +125,18 @@ def make_windows_for_case_fast(
# -------------------------
# Window cache per window_size
# -------------------------
CaseWindows = Dict[
int, Tuple[np.ndarray, np.ndarray, np.ndarray]
CaseWindows = dict[
int, tuple[np.ndarray, np.ndarray, np.ndarray]
] # case -> (x, y, idx)
WINDOW_CACHE: Dict[
Tuple[str, int], CaseWindows
WINDOW_CACHE: dict[
tuple[str, int], CaseWindows
] = {} # (target_col, window_size) -> cache
def precompute_windows_for_cases(
df: pd.DataFrame,
cases: List[int],
feature_cols: List[str],
cases: list[int],
feature_cols: list[str],
target_col: str,
window_size: int,
) -> CaseWindows:
......@@ -151,8 +152,8 @@ def precompute_windows_for_cases(
def get_cache_for_window_size(
df: pd.DataFrame,
cases_to_cache: List[int],
feature_cols: List[str],
cases_to_cache: list[int],
feature_cols: list[str],
target_col: str,
window_size: int,
) -> CaseWindows:
......@@ -169,8 +170,8 @@ def get_cache_for_window_size(
def build_from_cache(
cache_ws: CaseWindows, cases: List[int]
) -> Tuple[Optional[np.ndarray], Optional[np.ndarray]]:
cache_ws: CaseWindows, cases: list[int]
) -> tuple[np.ndarray | None, np.ndarray | None]:
xs, ys = [], []
for c in cases:
x, y, _ = cache_ws[int(c)]
......@@ -229,17 +230,15 @@ class LSTMRegressor(nn.Module):
def maybe_compile(model: nn.Module, device: str, enable: bool) -> nn.Module:
if not enable or device != "cuda":
return model
try:
with contextlib.suppress(Exception):
model = torch.compile(model) # type: ignore
except Exception:
pass
return model
# -------------------------
# CV folds by CASE
# -------------------------
def make_case_folds(train_pool: List[int], seed=123, n_splits=5):
def make_case_folds(train_pool: list[int], seed=123, n_splits=5):
tp = np.array(sorted(train_pool), dtype=int)
if len(tp) < 2:
......@@ -291,8 +290,8 @@ def make_loader(
def train_one_fold_cached( # type: ignore
cache_ws: CaseWindows,
feature_dim: int,
train_cases: List[int],
val_cases: List[int],
train_cases: list[int],
val_cases: list[int],
hidden_dim,
dense_dim,
num_layers,
......@@ -449,7 +448,7 @@ def cv_score_for_params_cached(
grad_clip,
device,
compile_model: bool,
trial: Optional[object] = None,
trial: object | None = None,
):
fold_rmses = []
......@@ -491,12 +490,12 @@ def cv_score_for_params_cached(
def strip_compile_prefix(state_dict: dict) -> dict:
# torch.compile suele guardar keys como "_orig_mod.xxx"
if not any(k.startswith("_orig_mod.") for k in state_dict.keys()):
if not any(k.startswith("_orig_mod.") for k in state_dict):
return state_dict
return {k.replace("_orig_mod.", "", 1): v for k, v in state_dict.items()}
def target_sort_key(col_name: str) -> Tuple[int, int]:
def target_sort_key(col_name: str) -> tuple[int, int]:
if col_name == "Force":
return (0, 0)
if col_name.startswith("TFDMapW"):
......@@ -520,7 +519,7 @@ def target_prediction_col(target_col: str) -> str:
def train_final_full_trainpool_cached( # type: ignore
cache_ws: CaseWindows,
feature_dim: int,
train_cases: List[int],
train_cases: list[int],
hidden_dim,
dense_dim,
num_layers,
......@@ -713,9 +712,7 @@ def main():
predict_case = 0
if w_val == 2:
n_train_case = 8
if b_val == 29:
predict_case = 12
elif b_val == 34:
if b_val == 29 or b_val == 34:
predict_case = 12
else:
print(f"Warning: No predict_case set for W={w_val}, B={b_val}")
......@@ -818,7 +815,7 @@ def main():
direction="minimize", sampler=sampler, pruner=pruner
)
def objective(trial) -> float:
def objective(trial, target_col=target_col) -> float:
params = suggest_params(trial, device=device)
ws = int(params["window_size"])
......@@ -1041,7 +1038,7 @@ def main():
pred_col = target_prediction_col(target_col)
df_test_pred[pred_col] = np.nan
for idx, pred in zip(test_indices, y_pred):
for idx, pred in zip(test_indices, y_pred, strict=False):
df_test_pred.loc[idx, pred_col] = pred
del final_model, test_loader, test_ds
......
......@@ -418,7 +418,7 @@ print(f"Test RMSE on Case {PREDICT_CASE}: {test_rmse:.4f}")
df_test_pred = df_test.copy()
df_test_pred["Force_TCN"] = np.nan
for idx, pred in zip(test_indices, y_pred):
for idx, pred in zip(test_indices, y_pred, strict=False):
df_test_pred.loc[idx, "Force_TCN"] = pred
OUT_FILE = f"../../data/hysteretic_curves/{W}W/H{H}_B{B}/case_{PREDICT_CASE}_with_tcn_preds.csv"
......
# -*- coding: utf-8 -*-
"""
Created on Tue Jan 10 08:23:00 2023.
@author: jig
"""
from pyDOE import lhs
import pandas as pd
from pyDOE import lhs
class GenerateLHSCases(object):
class GenerateLHSCases:
"""
Class for generating a number of cases by varying a set of geometric features.
......@@ -22,14 +22,20 @@ class GenerateLHSCases(object):
"""Define the desired parameters for this case."""
# Info available in: https://github.com/tisimst/pyDOE/blob/master/pyDOE/doe_lhs.py
self.n_calculations = 64 # Number of desired calculations
self.criterion = 'maximin' # 'center', 'maximin', 'centermaximin', 'correlation'
self.iterations = 5 # Number of iterations for maximin and correlation (Default: 5)
self.ranges = [[4.0, 14.0],
self.criterion = (
"maximin" # 'center', 'maximin', 'centermaximin', 'correlation'
)
self.iterations = (
5 # Number of iterations for maximin and correlation (Default: 5)
)
self.ranges = [
[4.0, 14.0],
[4.0, 14.0],
[4.0, 14.0],
[4.0, 14.0],
# [4.0, 14.0],
[4.0, 14.0]]
[4.0, 14.0],
]
self.lhs_parameters = None
def run(self):
......@@ -39,14 +45,15 @@ class GenerateLHSCases(object):
def create_lhs_design(self):
"""Create the Latin Hypercube Sampling design."""
self.lhs_parameters = lhs(len(self.ranges),
samples=self.n_calculations,
criterion=self.criterion)
self.lhs_parameters = lhs(
len(self.ranges), samples=self.n_calculations, criterion=self.criterion
)
def generate_features_dataframe(self):
"""Generate the DataFrame from the Latin Hypercube Sampling design."""
features = [
[f'ml{ii + 1}'] + [
[f"ml{ii + 1}"]
+ [
round(r[0] + (r[1] - r[0]) * self.lhs_parameters[ii][i], 2)
for i, r in enumerate(self.ranges)
]
......@@ -54,14 +61,21 @@ class GenerateLHSCases(object):
]
# Define the column names for the DataFrame
column_names = ['Model', 'tw1', 'tw2', 'tw3', 'tw4', 'tw5',] # 'tf']
column_names = [
"Model",
"tw1",
"tw2",
"tw3",
"tw4",
"tw5",
] # 'tf']
# Create the DataFrame
features_df = pd.DataFrame(features, columns=column_names)
# Save as CSV and Excel
features_df.to_csv('ml_features.csv', index=False)
features_df.to_excel('ml_features.xlsx', index=False)
features_df.to_csv("ml_features.csv", index=False)
features_df.to_excel("ml_features.xlsx", index=False)
print("DataFrame saved as 'ml_features.csv' and 'ml_features.xlsx'.")
......
......@@ -10,7 +10,11 @@ of kernels during Bayesian optimization.
from sklearn.base import BaseEstimator, RegressorMixin
from sklearn.gaussian_process import GaussianProcessRegressor
from sklearn.gaussian_process.kernels import (
RBF, Matern, RationalQuadratic, WhiteKernel, ConstantKernel
RBF,
ConstantKernel,
Matern,
RationalQuadratic,
WhiteKernel,
)
......@@ -69,30 +73,27 @@ class FlexibleGPR(BaseEstimator, RegressorMixin):
if self.kernel_type == "RBF":
base = RBF(length_scale=ls, length_scale_bounds=(1e-6, 1e3))
elif self.kernel_type == "Matern32":
base = Matern(
length_scale=ls, nu=1.5, length_scale_bounds=(1e-6, 1e3)
)
base = Matern(length_scale=ls, nu=1.5, length_scale_bounds=(1e-6, 1e3))
elif self.kernel_type == "Matern52":
base = Matern(
length_scale=ls, nu=2.5, length_scale_bounds=(1e-6, 1e3)
)
base = Matern(length_scale=ls, nu=2.5, length_scale_bounds=(1e-6, 1e3))
elif self.kernel_type == "RQ":
base = RationalQuadratic(
length_scale=ls,
alpha=float(self.rq_alpha),
length_scale_bounds=(1e-6, 1e3),
alpha_bounds=(1e-6, 1e3)
alpha_bounds=(1e-6, 1e3),
)
else:
raise ValueError(f"Unknown kernel_type: {self.kernel_type}")
k = ConstantKernel(
constant_value=float(self.amplitude),
constant_value_bounds=(1e-6, 1e3)
) * base
k = (
ConstantKernel(
constant_value=float(self.amplitude), constant_value_bounds=(1e-6, 1e3)
)
* base
)
k += WhiteKernel(
noise_level=float(self.noise),
noise_level_bounds=(1e-12, 1e-2)
noise_level=float(self.noise), noise_level_bounds=(1e-12, 1e-2)
)
return k
......
......@@ -6,8 +6,8 @@ This module provides a scikit-learn compatible wrapper for MLPRegressor
that allows dynamic configuration of hidden layer architecture.
"""
from sklearn.neural_network import MLPRegressor
from sklearn.base import BaseEstimator, RegressorMixin
from sklearn.neural_network import MLPRegressor
class FlexibleMLP(BaseEstimator, RegressorMixin):
......@@ -17,9 +17,16 @@ class FlexibleMLP(BaseEstimator, RegressorMixin):
optimization.
"""
def __init__(self, n_layers=2, n_neurons=128, activation='relu',
alpha=1e-4, learning_rate_init=1e-3,
random_state=42, max_iter=5000):
def __init__(
self,
n_layers=2,
n_neurons=128,
activation="relu",
alpha=1e-4,
learning_rate_init=1e-3,
random_state=42,
max_iter=5000,
):
"""
Parameters
----------
......@@ -76,7 +83,7 @@ class FlexibleMLP(BaseEstimator, RegressorMixin):
n_iter_no_change=100,
validation_fraction=0.2,
max_iter=self.max_iter,
random_state=self.random_state
random_state=self.random_state,
)
self.model_.fit(x_data, y)
......
......@@ -19,7 +19,7 @@ class RBFModel:
"""
def __init__(
self, x_data, y_data, function='multiquadric', smooth=0.0, epsilon=None
self, x_data, y_data, function="multiquadric", smooth=0.0, epsilon=None
):
"""
Initialize and fit the RBF model.
......@@ -49,10 +49,11 @@ class RBFModel:
def fit(self):
"""Fit the RBF model using the stored data."""
self.model = Rbf(
*self.x_data.T, self.y_data,
*self.x_data.T,
self.y_data,
function=self.function,
smooth=self.smooth,
epsilon=self.epsilon
epsilon=self.epsilon,
)
def predict(self, x_new):
......
......@@ -6,17 +6,25 @@ This module handles the training of RBF surrogate models and performs
Leave-One-Out (LOO) validation to assess their predictive performance.
It automates the process for multiple output variables.
"""
import os
import argparse
import os
import joblib
import numpy as np
import pandas as pd
from rbf_model import RBFModel
from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score
from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score
def loo_validation_rbf(df_val, input_features, target_features,
function="multiquadric", smooth=0.0, epsilon=None):
def loo_validation_rbf(
df_val,
input_features,
target_features,
function="multiquadric",
smooth=0.0,
epsilon=None,
):
"""
Leave-One-Out (LOO) validation for RBF models.
......@@ -68,11 +76,7 @@ def loo_validation_rbf(df_val, input_features, target_features,
# Train RBF with N-1 samples
model = RBFModel(
x_train,
y_train,
function=function,
smooth=smooth,
epsilon=epsilon
x_train, y_train, function=function, smooth=smooth, epsilon=epsilon
)
pred_i = model.predict(x_test)[0]
......@@ -86,11 +90,10 @@ def loo_validation_rbf(df_val, input_features, target_features,
rmse = np.sqrt(mean_squared_error(y_true, y_pred))
mae = mean_absolute_error(y_true, y_pred)
r2 = r2_score(y_true, y_pred)
rmse_std, rmse_cv, mae_std, mse_std = compute_error_dispersion(
y_true, y_pred
)
rmse_std, rmse_cv, mae_std, mse_std = compute_error_dispersion(y_true, y_pred)
results.append({
results.append(
{
"output": tgt,
"LOO_RMSE": rmse,
"LOO_MAE": mae,
......@@ -98,8 +101,9 @@ def loo_validation_rbf(df_val, input_features, target_features,
"LOO_RMSE_STD": rmse_std,
"LOO_RMSE_CV": rmse_cv,
"LOO_MAE_STD": mae_std,
"LOO_SQERR_STD": mse_std
})
"LOO_SQERR_STD": mse_std,
}
)
print(
f" LOO_RMSE = {rmse:.5f} | LOO_MAE = {mae:.5f} | "
......@@ -164,7 +168,9 @@ def main():
print("Warning: H not set for W != 2, 3, or 5")
# Path configuration
data_path = f"../../data/width_optimization/{w_val}W/rbf_FEMdata_B{b_val}_H{h_val}.csv"
data_path = (
f"../../data/width_optimization/{w_val}W/rbf_FEMdata_B{b_val}_H{h_val}.csv"
)
output_models_dir = (
f"../../models/width_optimization/{w_val}W/rbf_models/"
f"per_output_models_B{b_val}_H{h_val}"
......@@ -187,9 +193,9 @@ def main():
)
return
print(f"\n\n{'='*60}")
print(f"\n\n{'=' * 60}")
print(f"ITERATION {i_iter}: Training RBF with {n_curr} rows")
print(f"{'='*60}")
print(f"{'=' * 60}")
# Create iteration specific directory
it_dir = os.path.join(output_models_dir, f"it{i_iter}")
......@@ -197,7 +203,7 @@ def main():
df = df_tot.iloc[:n_curr].copy()
input_features = [f"tw{i+1}" for i in range(w_val)]
input_features = [f"tw{i + 1}" for i in range(w_val)]
target_features = [
c for c in df.columns if c not in input_features and c != "eyymax_tf"
]
......@@ -210,12 +216,7 @@ def main():
print(f"→ Training RBF for {tgt} ...")
y = df[tgt].values
rbf = RBFModel(
x_values, y,
function="multiquadric",
smooth=0.0,
epsilon=None
)
rbf = RBFModel(x_values, y, function="multiquadric", smooth=0.0, epsilon=None)
joblib.dump(rbf, os.path.join(it_dir, f"rbf_{tgt}.joblib"))
print(f" saved to it{i_iter}/rbf_{tgt}.joblib")
......@@ -224,8 +225,12 @@ def main():
# Execute LOO validation
# =============================================================
loo_results = loo_validation_rbf(
df, input_features, target_features,
function="multiquadric", smooth=0.0, epsilon=None
df,
input_features,
target_features,
function="multiquadric",
smooth=0.0,
epsilon=None,
)
loo_csv = os.path.join(it_dir, "rbf_LOO_results.csv")
......
[tool.ruff]
target-version = "py310"
line-length = 88
src = ["Code/src"]
[tool.ruff.lint]
select = [
"E",
"F",
"I",
"UP",
"B",
"SIM",
]
ignore = [
"E501",
]
[tool.ruff.lint.per-file-ignores]
"Code/src/hysteretic_curves/predict_hysteretic_curves.py" = ["F821"]
"Code/src/hysteretic_curves/predict_hysteretic_curves_1d_cnn.py" = ["F821"]
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment