
Fit an epsilon-SVR with MAPE loss
psvr_mape.RdFits the percentage-error epsilon-SVR of the paper: Model 1 when
sym_type = "none", and the symmetric-kernel Model 2 when sym_type is
"even" or "odd". The dual is a quadratic program with the
sample-dependent box \(|\beta_k| \le 100C/y_k\)
and \(\sum_k \beta_k = 0\), solved by the built-in SMO
loop or by osqp.
Usage
psvr_mape(
X,
y,
sym_type = c("none", "even", "odd"),
kernel,
C,
eps,
solver = c("smo", "osqp"),
tol = 0.001,
max_iter = 100000L,
alpha_init = NULL,
alpha_star_init = NULL,
warm_start_check = TRUE,
block_k4_enabled = TRUE,
engine = c("rcpp", "r"),
...,
alpha_couple = 0.5,
precomputed_Omega = NULL,
precomputed_Omega_s = NULL
)Arguments
- X
Numeric matrix of training inputs, one observation per row (\(N \times p\)).
- y
Numeric vector of training targets, length \(N\). Must satisfy \(y_k > 0\) for every \(k\); percentage-error loss is undefined otherwise, and this is checked rather than coerced.
- sym_type
Symmetry type, one of
"none"(default),"even"or"odd". Maps onto the symmetry parameter \(a\) of the paper:"none"fits Model 1 and imposes no symmetry constraint;"even"sets \(a = +1\), enforcing \(f(x) = f(-x)\);"odd"sets \(a = -1\), enforcing \(f(x) = -f(-x)\). This is the same vocabulary as thesym_typeargument of the parsnip specifications, so the two public surfaces agree. The symmetric variants require a kernel satisfying Assumption 3 of the paper – seemake_kernel().- kernel
A kernel function created by
make_kernel().- C
Regularization parameter, \(C > 0\). Required.
- eps
Insensitivity tube half-width in percentage units, \(\epsilon \ge 0\). Required.
- solver
Backend for the dual quadratic program,
"smo"(default) or"osqp". See the section above.- tol
Numerical tolerance, default
1e-3. Its meaning depends onsolver. Under"smo"it is the convergence tolerance of the SMO loop, and tighter values produce more iterations. Under"osqp"the solver runs at its own fixed tolerances andtolis used only afterwards, as the threshold below which a dual variable counts as zero when identifying free, saturated and support-vector sets.- max_iter
Maximum SMO iterations, default
100000L. The solver emits awarning()and returnsconverged = FALSEif it does not converge withinmax_iter. Ignored forsolver = "osqp".- alpha_init, alpha_star_init
Optional warm-start vectors for the SMO solver, each a finite numeric vector of length \(N\). Projected onto \(\sum_k (\alpha_k - \alpha^*_k) = 0\) intersected with the per-sample box \([0, 100C/y_k]\) before the solve.
NULL(default) cold-starts.psvr_cv()manages these automatically across folds.- warm_start_check
Logical; if
TRUE(default), validate post-projection feasibility andstop()on violation. A surviving equality residual is fatal rather than cosmetic: SMO conserves \(\sum_k (\alpha_k - \alpha^*_k)\), so an infeasible start is carried through to the returned solution.- block_k4_enabled
Logical; if
TRUE(default), enable the block-k=4 SMO inner loop. Each outer iteration may select a second working pair and apply a two-dimensional joint update when the descent-guaranteed decoupling criterion holds.FALSErestores the k=2 behaviour bit-identically.- engine
One of
"rcpp"(default) or"r". Selects the SMO backend: the C++ core, or the R reference implementation. Both produce bit-identical results on the development toolchain;"r"is retained as the reference and will be deprecated in 0.0.4.0 and removed in 0.1.0.- ...
Must be empty. Present only so that
alpha_couple,precomputed_Omegaandprecomputed_Omega_smust be matched by their exact names rather than by position or partial matching – without itprecomputed_Omegawould be a partial-match prefix ofprecomputed_Omega_s. Passing anything here is an error, which is how a mistyped argument name is caught.- alpha_couple
Numeric in \([0, 1]\), default
0.5. Coupling penalty in the second-pair selection score \(\mathrm{gain} \times (1 - \alpha_{\mathrm{couple}} \cdot \mathrm{coupling})\). Exposed for empirical tuning; rarely needs adjustment. Ignored whenblock_k4_enabled = FALSE.- precomputed_Omega, precomputed_Omega_s
INTERNAL – used by
psvr_cv()to share one full-dataset kernel matrix across folds. Users should not set these.precomputed_Omegaapplies whensym_type = "none",precomputed_Omega_sotherwise.
Value
For sym_type = "none", an object of class "psvr_mape": a list
with components beta (the pruned dual differences
\(\beta = \alpha - \alpha^*\) over the
support-vector indices, used by predict()), alpha and alpha_star
(the length-\(N\) pre-pruning duals, retained for warm starts), b,
X_sv, y_sv, y_train, fitted_values, kernel, C, eps,
n_train, p_train, iterations, converged and block_k4.
For sym_type = "even" or "odd", an object of class "psvr_mape_sym":
the same components plus a (the symmetry parameter) and spectral
(adaptive spectral-shift diagnostics).
Methods are available for predict(), print(), coef(), summary(),
fitted() and residuals().
Details
For the least-squares / RMSPE family (Models 3 and 4) see psvr_rmspe().
The two are deliberately separate functions: they share no solver, no dual
structure and no hyperparameter search space, so a single signature would
make most of its own arguments conditional. The name psvr() is reserved
for a future automatic-selection front end and is not a synonym for
either.
Choosing a solver
solver = "smo" (the default) uses the built-in sequential minimal
optimisation loop. On some problems it does not converge within
max_iter: it emits a warning(), converged is FALSE and iterations
reaches the cap. This was first observed with linear and polynomial
kernels, but it also occurs with the RBF kernel, so the kernel is not
what determines it, and what does has not been established. Check
converged on the returned fit, and refit with solver = "osqp" when it
is FALSE and accuracy matters.
See also
psvr_rmspe() for the LS-SVR / RMSPE family, psvr_cv() for
cross-validation with warm-start carryover, make_kernel() for kernels.
Examples
set.seed(1)
X <- matrix(rnorm(40), 20, 2)
y <- rlnorm(20)
K <- make_kernel("rbf", sigma = 1)
fit <- psvr_mape(X, y, kernel = K, C = 10, eps = 5)
predict(fit, X[1:3, , drop = FALSE])
#> [1] 0.8068941 0.7370469 0.8548128
# Even-symmetric variant (Model 2): f(x) = f(-x).
fit_sym <- psvr_mape(X, y, sym_type = "even", kernel = K, C = 10, eps = 5)
predict(fit_sym, X[1:3, , drop = FALSE])
#> [1] 0.8909758 0.7372706 0.5317936