
Changelog
psvr 0.0.2.9003 (development)
Internal changes
-
.smo_solve()(R/smo_solve.R) now implements Theorems 3 and 8 of arXiv:2605.01446 v3:-
Theorem 3 (asymmetric freeze): the uniform freeze-counter threshold
n_freeze = 5Lis replaced by per-sample, per-variable-type thresholds:n_freeze_astar_per[k] = max(1L, floor(n_freeze * y[k] / mean(y))) n_freeze_alpha_per[k] = max(5L, ceil( n_freeze * mean(y) / y[k]))α*-variables tied to high-
y_ksamples freeze faster; α-variables tied to high-y_ksamples freeze slower. Reduces to the scalar default whenyis homogeneous. Theorem 8 (per-pair tolerance): the uniform convergence threshold
tol * mean(y)is replaced at the convergence test by a per-pair thresholdtol * max(y[p], y[k_j_w1]), where(p, k_j_w1)is the WSS1 pair. The WSS3 candidate filter at the working-set selection step retains the globaltol * mean(y)for noise-floor purposes.
-
Behavior change
- SMO iteration count decreases by ~10–30% on heterogeneous-target datasets (
rho_y = max(y) / min(y) >= 50). The wall-clock speedup is smaller (depends onN: kernel-matrix construction overhead dominates at moderateN). Empirical benchmark atN = 200,rho_y = 1273: 24.7% iter reduction, 5.6% wall-clock speedup. Homogeneous datasets (rho_y ~ 1) are unaffected — the new thresholds collapse to the F3 defaults.
Numerical drift
- Predictions on heterogeneous-target datasets differ from v0.0.2.9002 by
O(tol * max(y)). Empirical magnitude on the snapshot fixture (rho_y = 6.7,max(y) = 2.6,tol = 1e-3): max drift8.5e-4per prediction (well below the per-pair tolerance floor of2.6e-3). - The 28 golden snapshot tests have been re-recorded with F4 numerics as the new regression baseline at tolerance
1e-10within F4. Bit-identicalidad with v0.0.2.9002 is intentionally NOT preserved on SMO-backed paths; LS-SVR paths (Models 3, 4 via linear system) remain bit-identical.
Paper deviation
- The convergence test uses the WSS1 pair
(i_w1, j_w1)rather than the paper’s literal text (“j* = WSS3 pick”). Rationale documented inline inR/smo_solve.R:Delta_w3 <= Delta_w1by construction, so testingDelta_w3against the tolerance would stop prematurely before the true KKT optimality gap is below tolerance. Flagged for paper-side notation fix in F8 (paper TODO #4).
psvr 0.0.2.9002 (development)
Internal changes
-
.fit_mape_sym()(Model 2) now invokes Algorithm 2 (Theorem 2 of arXiv:2605.01446 v3) via the new.adaptive_spectral_shift()inR/kernel-spectral.R. Two-pass shifted power iteration estimatesλ_min(Ωs); if numerically negative, an adaptiveμ·Ishift is applied so the SMO Hessian is provably PSD. Diagnostics (mu,lambda_min_hat,lambda_max_hat,branch_taken,n_power_iterations) surface underpsvr_fit$solver_meta$spectralfor symmetric MAPE fits;NULLfor Models 1, 3, 4. The implementation deviates from the paper’s Algorithm 2 line 6 by using the spectral radius|Pass 1 Rayleigh|rather than the signed Rayleigh as the Pass 2 shift; rationale is documented inline inR/kernel-spectral.Rand to be flagged as a paper-side erratum in F8. With the three Mercer kernels supported bymake_kernel()(RBF / linear / polynomial),Ωsis always PSD by Aronszajn closure / Schur product theorem, so the shifted branch is unreachable in production fits and predictions are bit-identical to v0.0.2.9001 at tolerance1e-10on the 16 + 12 golden snapshots.
psvr 0.0.2.9001 (development)
Internal changes
- The SMO solver now reads kernel values via a
.make_kernel_accessor()wrapper (R/kernel-accessor.R), decoupling the inner loop from the matrix representation. The F2 implementation is a thin closure over the materialisedΩ/Ωs; future phases (F3 spectral shift, F6 LRU cache, F7 block working set) will swap in alternative implementations without touching the SMO loop or the fitters. No user-visible change; predictions are bit-identical to v0.0.2.9000 at tolerance1e-10on the 16 + 12 golden snapshots.
psvr 0.0.2.9000
New features
- New unified entry point
psvr(X, y, loss, sym, kernel, ...). Selects among the four model families vialoss = "mape" | "rmspe"andsym = NULL | +1L | -1L. Returns a singlepsvr_fitS3 object with a unified field schema (alpha,b,support_data,support_targets,n_train,n_sv,p_train,hyperparameters,solver_meta, plusloss,sym,kernel). - New methods on the
psvr_fitclass:predict(),print(),coef(), andsummary(). The summary method is new — there was no analogue on the four legacy classes.
Deprecations
-
mape_svr(),mape_sym_svr(),rmspe_lssvr(),rmspe_sym_lssvr()are soft-deprecated. They continue to work and return the same legacy shape (psvr_mape,psvr_mape_sym,psvr_rmspe,psvr_rmspe_sym) with the same predict/print/coef methods, but each emits.Deprecated("psvr"). Migrate by replacing, for example,mape_svr(X, y, kernel = K, C = 10, eps = 5)withpsvr(X, y, loss = "mape", kernel = K, C = 10, eps = 5). Scheduled removal: v0.2.0 or later.
Internal changes
- The 12 parsnip fit wrappers (
psvr_mape_rbf_fit()etc.) are now tagged@keywords internaland hidden from the pkgdown reference index. They remain exported (parsnip’s resolver requires it) but are no longer advertised as user API; call [psvr()] for direct fitting. The 12 spec constructors (psvr_mape_rbf()etc.) remain public API and are unchanged. - The four model fitter bodies have been renamed to internal helpers (
.fit_mape(),.fit_mape_sym(),.fit_rmspe(),.fit_rmspe_sym()). The deprecation wrappers delegate to these directly. - DRY consolidation: shared validation, large-N warnings, predict dispatch, preconditioner resolution, and kernel description live in new internal-only files under
R/utils-*.R. - Model 2 (symmetric MAPE epsilon-SVR) now uses
sym_kernel_matrix()to buildΩs = ½(Ω + a·Ω*)(matching Model 4’s existing convention), with diagonal jitter0.5e-6to preserve bit-identicality with the pre-F1 path.
psvr 0.0.2 (2026-04-30)
New features
- The
preconditionargument fromrmspe_lssvr()andrmspe_sym_lssvr()is now configurable via parsnip’sset_engine()for all six RMSPE spec functions (rbf/poly/linear, both symmetric and non-symmetric). Default is"auto"; pass viaset_engine("psvr", precondition = "always"),"never", or a numeric threshold. Not registered as a tunable parameter — it is a configuration flag, not a hyperparameter.
psvr 0.0.1
New features
- Added optional preconditioner for LS-SVR variants (
rmspe_lssvr(),rmspe_sym_lssvr()) via thepreconditionargument. Accepted values: “always”, “never”, “auto” (default; activates when max(y)/min(y) > 10), or a numeric threshold. The preconditioner is a mathematically exact change of variable that improves numerical conditioning at large target dynamic ranges without changing predictions in exact arithmetic. - Returned model objects now include
precondition_applied(logical) for diagnostic transparency. Theprintmethod displays this field when TRUE.
psvr 0.0.0.9005
New features
-
cost_psvr_ls_data(y, n, width_log2)— a data-driven cost range for LS-SVR psvr models (m3,m4). Default upper bound scales aslog2(var(y) * N) + width_log2(defaultwidth_log2 = 4), the standard heuristic for the LS-SVR regularisation parameterΓ(Suykens et al. 2002, Least Squares Support Vector Machines, §3.1.3). Use this instead ofcost_psvr()form3/m4workflows; the static[-2, 10]log2 range underestimatesΓon benchmark datasets (Boston Housing optimumΓ ≈ 1.7 × 10⁴, vs.cost_psvr()upper bound2^10 = 1024). -
psvr_option_add_cost_ls(wf_set, y, ...)— a convenience wrapper that appliescost_psvr_ls_data()to every LS-SVR psvr workflow in a workflow set (those whosewflow_idmatchesm3|m4), analogous topsvr_option_add()forrbf_sigma.
psvr 0.0.0.9004
New features
-
sym_typeis now a tunable parsnip argument inpsvr_mape_sym_rbf()andpsvr_rmspe_sym_rbf(). Passsym_type = tune()to let CV select between even (a = 1) and odd (a = -1) symmetry automatically. - Engine default
a = 1Lremoved from symmetric RBF specs; symmetry type is now controlled exclusively through thesym_typemodel argument.
psvr 0.0.0.9003
UX improvements
New function
rbf_sigma_psvr_data(): combinessigma_heuristic()andrbf_sigma_psvr()in a single call, returning a dials parameter with a data-driven search range centred on the median pairwise distance.New function
psvr_option_add(): appliesoption_add()to every psvr workflow (those whosewflow_idmatchesm1|m2|m3|m4) in a workflow set simultaneously, replacing therbf_sigmaparameter with a data-driven one. Replaces four individualoption_add()calls in typical workflows.Symmetric model specs (
psvr_mape_sym_*,psvr_rmspe_sym_*): even symmetry (a = 1L) is now the default engine argument. Callingset_engine("psvr")withouta = 1Lnow produces the same result as before — no action required for existing code that already passeda = 1L.All four core fitting functions now emit a warning when
N > 2000to remind users that the O(n²) kernel matrix may be expensive.The
y > 0input check in all four core fitting functions now reports the number of offending values and their minimum, making it easier to diagnose data issues.
psvr 0.0.0.9002
User-friendly hyperparameter defaults
New function
margin_percentage(): a dials parameter for the epsilon tube half-width in MAPE models, expressed in percentage units with default range[1, 20]. Replaces the absolute-unitdials::svm_margin()for all 6 MAPE specs.New function
sigma_heuristic(): returns the median pairwise Euclidean distance of a predictor matrix — a standard data-driven starting point for the RBF kernel bandwidth (Schölkopf & Smola, 2002).New function
rbf_sigma_psvr(): a dials parameter for the RBF kernel bandwidth with afinalizehook that auto-sets the search range usingsigma_heuristic()when training data are available. Replacesdials::rbf_sigma()for all RBF specs.New function
cost_psvr(): a dials parameter for the regularisation parameter with range[-2, 10]on the log2 scale (approx. 0.25 to 1024), wider thandials::cost()to accommodate the larger values typically needed by LS-SVR models. Replacesdials::cost()for all 12 specs.rbf_sigma_psvr(): removed non-functionalfinalizehook. The search range must be set manually usingsigma_heuristic()andoption_add(). See?rbf_sigma_psvrfor the recommended workflow.
psvr 0.0.0.9001
tidymodels / parsnip integration — breaking change
Expanded parsnip integration from 4 to 12 model specs following the tidymodels pattern used by svm_rbf(), svm_poly(), and svm_linear():
-
psvr_mape_rbf(),psvr_mape_poly(),psvr_mape_linear()— Model 1 specs. -
psvr_mape_sym_rbf(),psvr_mape_sym_poly(),psvr_mape_sym_linear()— Model 2 specs. -
psvr_rmspe_rbf(),psvr_rmspe_poly(),psvr_rmspe_linear()— Model 3 specs. -
psvr_rmspe_sym_rbf(),psvr_rmspe_sym_poly(),psvr_rmspe_sym_linear()— Model 4 specs.
Kernel parameters are now tunable parsnip args mapped to existing dials params: rbf_sigma → dials::rbf_sigma(), degree → dials::degree(), scale_factor → dials::scale_factor(). The kernel closure is built inside each fit wrapper and no longer appears in the parsnip layer.
The old single-spec API (psvr_mape(), psvr_mape_sym(), psvr_rmspe(), psvr_rmspe_sym()) has been removed. Migrate by replacing, for example, psvr_rmspe(cost = tune()) |> set_engine("psvr", kernel = K) with psvr_rmspe_rbf(cost = tune(), rbf_sigma = 1) |> set_engine("psvr").
psvr 0.0.0.9000
Initial development release.
New models
mape_svr()— epsilon-SVR with MAPE loss (Model 1). Solves the dual QP viaosqpwith per-sample box constraints|βk| ≤ 100C/yₖ.mape_sym_svr()— symmetric epsilon-SVR with MAPE loss (Model 2). Enforcesf(x) = a·f(-x)by replacing the kernel with the symmetric kernelKs(xi, xj) = K(xi, xj) + a·K(xi, -xj).rmspe_lssvr()— LS-SVR with RMSPE loss (Model 3). Solves the (N+1)×(N+1) linear system directly viabase::solve().rmspe_sym_lssvr()— symmetric LS-SVR with RMSPE loss (Model 4). Same linear system as Model 3 with the symmetrized kernel matrixΩs = ½(Ω + a·Ω*).
All four models are derived from a unified percentage-error loss framework; see Benavides-Herrera et al. (2026) for the mathematical proofs.
Kernel interface
-
make_kernel()— factory returning a kernel closure fromtype∈{"rbf", "linear", "polynomial"}. RBF and even-degree polynomial kernels satisfy the symmetry assumption (Assumption 3) required by Models 2 and 4.
tidymodels / parsnip integration
Four parsnip model specifications for use within tidymodels workflows:
-
psvr_mape()— spec for Model 1; hyperparameterscostandsvm_margin. -
psvr_mape_sym()— spec for Model 2; hyperparameterscostandsvm_margin. -
psvr_rmspe()— spec for Model 3; hyperparametercost(maps toΓ). -
psvr_rmspe_sym()— spec for Model 4; hyperparametercost(maps toΓ).
The kernel and (for symmetric models) symmetry parameter a are engine arguments supplied via set_engine("psvr", kernel = ..., a = ...). Hyperparameters map to dials::cost() and dials::svm_margin() for compatibility with tune_grid().