Native PLS phase controls

Select the closed Methods RolePipeline profile explicitly to execute PLS parameters during cross-validation, native HPO and the final refit. Methods performs the numerical work; DAG-ML schedules the phases and owns signed execution evidence. Matching DAG-ML and Core native packages are required.

import nirs4all
from sklearn.cross_decomposition import PLSRegression
from sklearn.model_selection import KFold

result = nirs4all.run(
    [
        KFold(n_splits=3, shuffle=True, random_state=17),
        {
            "model": PLSRegression(n_components=1, scale=True),
            "train_params": {"n_components": 2},
            "finetune_params": {
                "engine": "n4m",
                "approach": "grouped",
                "sampler": "random",
                "pruner": "none",
                "n_trials": 4,
                "seed": 6,
                "metric": "rmse",
                "direction": "minimize",
                "model_params": {"scale": [False, True]},
            },
            "refit_params": {"n_components": 3, "scale": False},
        },
    ],
    {"X": X, "y": y, "sample_ids": sample_ids},
    engine="native",
    native_profile="n4m.pls_role_pipeline.v1",
    save_charts=False,
    methods_library_path=library_path,
)
archive = result.export("pls-winner.n4a")
result.close()

inspection = nirs4all.inspect_portable_predictor_archive_v2(
    archive, methods_library_path=library_path,
)
assert inspection["models"][0]["model_params"] == {
    "n_components": 3, "scale": False,
}
prediction = nirs4all.predict(
    archive,
    {"X": heldout_X, "sample_ids": heldout_ids},
    engine="native",
    methods_library_path=library_path,
)

Constructor values provide the base. train_params overrides that base for CV; each trial overrides only its searched keys. A train key and a search axis cannot own the same parameter. refit_params overrides the selected trial for the final model. Consequently, the CV score measures the trial’s CV recipe, while archive inspection reports the effective final refit recipe.

The executable model keys are n_components (a positive integer up to 2,147,483,647) and scale (a Python boolean). scale controls native scale_x and scale_y together. Search accepts n_components: ["int", 1, 3], scale: [False, True], or both. Boolean choices are normalized to this order without changing the caller’s declaration. HPO returns booleans for model.scale. Equal best CV scores use DAG-ML’s deterministic selection; result.tuning_best_params describes that selected trial. The native optimizer’s original incumbent remains in the checkpoint, with the same best score. The profile keeps centering enabled and the native NIPALS solver. Keep copy=True, max_iter=500 and tol=1e-6 on the declaration; other values, epochs, warm_start, and native flag aliases are refused.

Supported recipes are PLS alone or StandardNormalVariate() followed by SavitzkyGolay(window_length=5, polyorder=2) and PLS. Savitzky–Golay smoothing requires an odd window from 3 to 501, degree below the window, deriv=0, delta=1.0, and copy=True. The recipe order remains fixed. This profile accepts one model and explicit array data; local and nested native HPO are outside this profile.

result.tuning_resume_package retains the complete native checkpoint. Reuse it as finetune_params["resume_package"] with an increased trial budget. Changing data, folds, recipe, train/refit controls, or profile invalidates the checkpoint. Saved .n4a files retain the closed recipe and opaque native states; inspection imports and validates them without training. Prediction hydrates the saved final model and performs no fit or optimizer operation. Calls without native_profile retain the historical N4MM profile.

The opt-in qualification gate is NIRS4ALL_REQUIRE_NATIVE_PLS_PHASE_CONTROLS=1. Select the actual Methods library with NIRS4ALL_CORE_LIVE_METHODS_LIBRARY. Detached replay requires an installed SDK with the same production bytes; use NIRS4ALL_NATIVE_PLS_INSTALLED_PYTHON to select its Python executable when the parent test process uses a separate environment.