From cfe45af75212e3c25d2bc305dc8164a95aca757b Mon Sep 17 00:00:00 2001 From: alexisdubs Date: Fri, 4 Sep 2026 14:54:19 -0400 Subject: [PATCH] Fix: numpy scalars break JSON export of results The sanitizer before json.dump converts np.ndarray values but not numpy scalar types, so any model storing an integer hyperparameter as np.int64 raised "TypeError: Object of type int64 is not JSON serializable". PLS and SPLS both store n_components this way. The model trains fine and the pickle is written first, so results are not lost, but the run ends in a traceback and no JSON is produced. This reproduces on any environment with NumPy 2.x. Passing default= to json.dump converts numpy scalars via .item(). It only affects objects the encoder would otherwise reject, so output for currently-working models is unchanged (verified: OLS and LCEN test R^2 identical before and after). Co-Authored-By: Claude Opus 5 --- Code-SPA/SPA.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Code-SPA/SPA.py b/Code-SPA/SPA.py index e64adee..e2aebcb 100644 --- a/Code-SPA/SPA.py +++ b/Code-SPA/SPA.py @@ -578,7 +578,9 @@ def main_SPA(main_data, main_data_y = None, test_data = None, test_data_y = None pickle.dump(fitting_result, f) # Saving as a json file with open(f'SPA_results_{time_now}.json', 'w') as f: - json.dump(fr2, f, indent = 4) + # Numpy scalars (e.g. PLS n_components as int64) are not caught by the ndarray + # conversion above and are not JSON-serializable; convert them on the fly. + json.dump(fr2, f, indent = 4, default = lambda o: o.item() if isinstance(o, np.generic) else str(o)) if verbosity_level: print(f'The best model is {selected_model}. View its results via fitting_result["{selected_model}"] or by opening the SPA_results json/pickle files.') if verbosity_level >= 2 and not classification: print(f'Train set: RMSE = {fitting_result[selected_model]["RMSE_train_nontrans"]:.4f} | Mean relative error = {fitting_result[selected_model]["Mean_relative_error_train"]:.4f}') if verbosity_level and not classification: print(f'Test set : RMSE = {fitting_result[selected_model]["RMSE_test_nontrans"]:.4f} | Mean relative error = {fitting_result[selected_model]["Mean_relative_error_test"]:.4f}')