feat: log regression metrics as parameters in Training class
- Added a method to persist computed regression metrics (MSE, MAE, R²) as MLflow parameters during model training, enhancing model evaluation and tracking. - Updated the Training class to log the equation path if available, improving artifact management.
This commit is contained in:
@@ -5,7 +5,10 @@ from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
|
||||
from model_manager.utils.models.train_model_params import TrainModelParams
|
||||
from model_manager.utils.models.train_model_params import (
|
||||
TrainModelParams,
|
||||
validate_frontend_date_format,
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@@ -262,3 +265,11 @@ def test_validate_model_param_all_schema_branches(valid_train_params_dict):
|
||||
p.model_kwargs = {}
|
||||
p.opt_params = {}
|
||||
p.validate_business_rules()
|
||||
|
||||
|
||||
def test_validate_frontend_date_format_whitespace_returns():
|
||||
validate_frontend_date_format(' ')
|
||||
|
||||
|
||||
def test_validate_frontend_date_format_valid_returns():
|
||||
validate_frontend_date_format('dd/MM/yyyy HH:mm:ss')
|
||||
|
||||
@@ -100,10 +100,23 @@ def test_prepare_training_data_empty_after_load():
|
||||
p = TrainModelParams.from_dict(_minimal_dict_for_prepare())
|
||||
# empty csv with headers only
|
||||
csv_bytes = b'v1,t\n'
|
||||
with pytest.raises(ValueError, match='Training data view is empty'):
|
||||
with pytest.raises(ValueError, match='Index is not a DatetimeIndex'):
|
||||
repo.prepare_training_data(csv_bytes, None, p, {})
|
||||
|
||||
|
||||
def test_prepare_training_data_empty_after_transformation(monkeypatch):
|
||||
repo = dmr.DataManagerRepository(MagicMock())
|
||||
p = TrainModelParams.from_dict(_minimal_dict_for_prepare())
|
||||
monkeypatch.setattr(
|
||||
repo,
|
||||
'_configure_datetime_index',
|
||||
lambda *_args, **_kwargs: pd.DataFrame(columns=['v1', 't']),
|
||||
)
|
||||
monkeypatch.setattr(repo, '_set_timezone_on_index', lambda data, *_args, **_kwargs: data)
|
||||
with pytest.raises(ValueError, match='Training data view is empty after transformation'):
|
||||
repo.prepare_training_data(b'v1,t\n', None, p, {})
|
||||
|
||||
|
||||
def _minimal_dict_for_prepare():
|
||||
return {
|
||||
'variable_columns': ['v1'],
|
||||
@@ -364,6 +377,8 @@ def test_generate_report_success(tmp_path):
|
||||
params=p,
|
||||
train_data=pd.DataFrame({'v1': [1.0, 2.0], 't': [1.0, 2.0]}),
|
||||
val_data=pd.DataFrame({'v1': [1.0, 2.0], 't': [1.0, 2.0]}),
|
||||
y_train_pred=pd.DataFrame({'t': [1.0, 2.0]}),
|
||||
y_pred=pd.DataFrame({'t': [1.0, 2.0]}),
|
||||
run_name='testrun',
|
||||
)
|
||||
tmr.equation = {'target_variable': 't'}
|
||||
@@ -388,6 +403,8 @@ def test_generate_report_skips_equation_file_when_not_linear(tmp_path):
|
||||
params=p,
|
||||
train_data=pd.DataFrame({'v1': [1.0, 2.0], 't': [1.0, 2.0]}),
|
||||
val_data=pd.DataFrame({'v1': [1.0, 2.0], 't': [1.0, 2.0]}),
|
||||
y_train_pred=pd.DataFrame({'t': [1.0, 2.0]}),
|
||||
y_pred=pd.DataFrame({'t': [1.0, 2.0]}),
|
||||
run_name='testrun',
|
||||
equation={'k': 'v'},
|
||||
)
|
||||
@@ -412,6 +429,21 @@ def test_generate_report_run_name_missing():
|
||||
repo.generate_report(tmr, {})
|
||||
|
||||
|
||||
def test_generate_report_requires_predictions():
|
||||
repo = dmr.DataManagerRepository(MagicMock())
|
||||
p = TrainModelParams.from_dict(_minimal_dict_for_prepare())
|
||||
tmr = TrainModelResult(
|
||||
params=p,
|
||||
train_data=pd.DataFrame({'t': [1.0]}),
|
||||
val_data=pd.DataFrame({'t': [1.0]}),
|
||||
run_name='testrun',
|
||||
y_train_pred=None,
|
||||
y_pred=None,
|
||||
)
|
||||
with pytest.raises(ValueError, match='y_train_pred or y_pred is not set'):
|
||||
repo.generate_report(tmr, {})
|
||||
|
||||
|
||||
def test_cleanup_run_directory_empty():
|
||||
repo = dmr.DataManagerRepository(MagicMock())
|
||||
repo.cleanup_run_directory('', {})
|
||||
|
||||
Reference in New Issue
Block a user