Fit SSRHE-Style Hessian-Energy Regression
Source:R/ssrhe_hessian_energy.R
fit.ssrhe.hessian.regression.RdFits the \(\ell_2\) Hessian-energy regularized estimator associated with
ssrhe.hessian.operator. This is a direct SSRHE-style
comparator for Hessian smoothing on point clouds; it is not a replacement
for graph trend-filtering regression and is distinct from
\(\ell_1\)-adaptive graph trend filtering.
Usage
fit.ssrhe.hessian.regression(
X,
y,
k = NULL,
tangent.dim,
lambda1,
lambda2 = 0,
weights = NULL,
nn.index = NULL,
neighborhood.type = c("knn", "adaptive.radius", "supplied"),
support.index = NULL,
adaptive.k.scale = NULL,
radius.rule = c("geomean", "max", "min"),
radius.factor = 1.25,
min.support = NULL,
max.support = NULL,
support.buffer = 2L,
support.topup = c("nearest", "none"),
tangent.dim.rule = c("fixed", "eigen.cumulative"),
eigen.tolerance = 0.95,
derivative.order = 2L,
stabilizer = lambda2 > 0,
pinv.tol = sqrt(.Machine$double.eps),
local.solver = c("auto", "normal.equations", "svd", "qr"),
normal.equations.max.condition = 10000,
ridge = 0,
return.A = TRUE,
return.local.diagnostics = FALSE,
return.timing = FALSE,
verbose = FALSE,
lambda.selection = c("fixed", "cv", "gcv"),
lambda1.grid = NULL,
lambda2.grid = NULL,
cv.control = list(),
gcv.control = list()
)Arguments
- X
Numeric matrix with one observation per row. Distances for the default neighborhood search are Euclidean distances in these coordinates.
- y
Numeric response vector of length
nrow(X)or numeric matrix withnrow(X)rows. Matrix columns are fit as separate responses.NAvalues are allowed and are treated as unobserved by setting the corresponding observation weight to zero.- k
Integer number of nearest neighbors per point, including the point itself, used when
neighborhood.type = "knn". This follows the SSRHE Matlab convention. For adaptive-radius neighborhoods,kmay be omitted whenadaptive.k.scaleis supplied.- tangent.dim
Integer tangent dimension used for the local PCA chart. Required when
tangent.dim.rule = "fixed". IfNULLandtangent.dim.rule = "eigen.cumulative", the dimension is selected locally from the PCA variance ratio.- lambda1
Nonnegative Hessian-energy penalty multiplier for \(f^\top B f = \|Af\|_2^2\).
- lambda2
Nonnegative supplemental-stabilizer multiplier for \(f^\top B_S f\). If positive,
stabilizermust beTRUE. Currently supported only forderivative.order = 2L.- weights
Optional nonnegative observation weights. May be
NULL, a vector of lengthnrow(X), or a matrix with the same dimensions asy.- nn.index
Optional integer matrix of neighbor indices, with
nrow(X)rows andkcolumns. Each row must contain its center vertex. IfNULL, Euclidean k-NN including self is computed in C++.- neighborhood.type
Local support rule.
"knn"uses the original rectangular self-including kNN neighborhoods."adaptive.radius"builds variable-size supports fromdgraphs::create.rknn.graph()."supplied"usessupport.indexdirectly.- support.index
Optional list of integer vectors, one per row of
X. Each element gives a variable-size local support and must contain its center vertex.- adaptive.k.scale
Integer local-scale k used by
dgraphs::create.rknn.graph()whenneighborhood.type = "adaptive.radius".- radius.rule, radius.factor
Adaptive-radius graph parameters passed to
dgraphs::create.rknn.graph().- min.support
Optional minimum local support size for adaptive-radius supports. Defaults to the local quadratic design size plus
support.buffer, clamped tonrow(X).- max.support
Optional maximum local support size. Oversized adaptive supports are trimmed to the closest
max.supportvertices while keeping the center vertex.- support.buffer
Nonnegative integer added to the local quadratic design size when choosing the default
min.support.- support.topup
How undersized adaptive-radius supports are enlarged.
"nearest"appends ambient nearest neighbors."none"leaves supports unchanged and lets the C++ operator reject undersized supports.- tangent.dim.rule
Either
"fixed"or"eigen.cumulative".- eigen.tolerance
Cumulative local PCA variance threshold used when
tangent.dim.rule = "eigen.cumulative"andtangent.dim = NULL.- derivative.order
Integer derivative order of the local SSRHE-style operator.
2Lis the original local Hessian energy.3Lis an experimental third-derivative energy whose rows estimate unique symmetric third-derivative tensor components with factorial and tensor-multiplicity scaling.- stabilizer
Logical. If
TRUE, also construct the supplemental stabilizer matrix described in the SSRHE supplement. Currently supported only forderivative.order = 2L.- pinv.tol
Nonnegative tolerance multiplier for local pseudoinverses.
- local.solver
Local least-squares backend used to map local function values to derivative coefficients.
"auto"is the default: it uses normal equations when the local design is full rank and has condition number no larger thannormal.equations.max.condition, and otherwise falls back to SVD."normal.equations"requests the normal-equation solve for full-rank local designs and falls back only on hard numerical failures."svd"is the most stable reference path."qr"uses pivoted QR and falls back to SVD for rank-deficient local designs.- normal.equations.max.condition
Positive condition-number guard used by
local.solver = "auto"before accepting the normal-equation backend. The default is deliberately conservative because normal-equation solves square the effective condition number and order-3 near-minimum local supports can be numerically fragile.- ridge
Nonnegative diagonal ridge added to the linear system for numerical stabilization.
- return.A
Logical. If
TRUE, return \(A\) as a sparse matrix.- return.local.diagnostics
Logical. If
TRUE, compute additional R-side local chart diagnostics such as chart distortion and boundary asymmetry. These diagnostics are useful for operator audits, but can be skipped in fitting and cross-validation paths for speed.- return.timing
Logical. If
TRUE, attach a phase-level elapsed time table to the returned operator. The timings separate R-side validation, neighborhood/support construction, native local operator construction, optional local diagnostics, sparse matrix assembly, and output finalization. For adaptive-radius neighborhoods, subphase timings are also attached inneighborhoods$timing.- verbose
Logical. If
TRUE, print a short native construction message.- lambda.selection
Penalty selection:
"fixed"(the default) useslambda1andlambda2;"cv"holds out observed labels;"gcv"uses generalized cross-validation. Grid inputs require an explicit"cv"or"gcv"selection mode.- lambda1.grid, lambda2.grid
Nonnegative penalty candidates for CV or GCV.
lambda1.gridis required in either selection mode;lambda2.grid = NULLmeans0. Do not also supply scalarlambda1orlambda2. Unless explicitly set,stabilizeris enabled when any supplemental penalty candidate is positive.- cv.control
Named list used only with
lambda.selection = "cv". Entries:foldid = NULL(one fold label per row ofX; nonpositive or missing labels are ignored),cv.folds = 5L,loss = "mse"(or"mae"), andselection = "min"(or"one.se", choosing the largest total penalty within one standard error of the minimum). Support-search entries aresupport.selection = "rule"(or"cv"),support.grid = NULL, andsupport.max.candidates = 8L. Fold count is ignored whenfoldidis supplied.- gcv.control
Named list used only with
lambda.selection = "gcv". Entries:trace.method = "exact"(or"hutchinson"),trace.n.probes = 50L,trace.seed = NULL,support.selection = "rule"(or"gcv"),support.grid = NULL, andsupport.max.candidates = 8L. Unknown, unnamed, or duplicated control entries are errors. Controls for a different selection mode are rejected rather than ignored.
Value
A list of class "ssrhe.hessian.fit" containing fitted values,
residuals, input response, weights, lambda parameters, objective/energy
diagnostics, the reused operator, solver metadata, the call, and
lambda.selection. CV adds class "ssrhe.hessian.cv.fit",
cv.table, fold.id, and selection; GCV adds class
"ssrhe.hessian.gcv.fit", gcv.table, gcv.trace, and
selection. Support searches retain selected.support and
the corresponding support.cv.table or support.gcv.table.
Details
For each response column, this function solves
$$
(W + \lambda_1 B + \lambda_2 B_S + \epsilon I)\hat f = Wy,
$$
where \(W\) is the diagonal matrix of observation weights and
\(\epsilon\) is ridge. Fully observed data with
lambda1 = lambda2 = ridge = 0 therefore reproduce the observed
response exactly. Missing responses are excluded from the data-fit term by
setting their weights to zero. The Matlab SSRHE semi-supervised convention is
represented by a 0/1 labeled-indicator weights vector, or
equivalently by setting unlabeled responses to NA: labeled vertices
contribute unit diagonal data-fit terms and unlabeled vertices contribute no
data-fit term.
The lower-level operator is matched to the Kim–Steinke–Hein SSRHE Matlab construction: self-including kNN neighborhoods, local PCA charts, a fixed-intercept local quadratic fit, doubled diagonal Hessian components, and optional supplemental stabilizer. The package exposes both \(A\) and \(B=A^\top A\); the fitted \(\ell_2\) estimator uses \(B\).
Penalty selection
Fixed fitting supports response vectors or matrices. CV and GCV currently
select penalties for one response vector at a time. Label CV removes each
validation fold from the data-fit term and scores its held-out observed
positive-weight labels. It supports missing responses. GCV requires a fully
observed response and strictly positive observation weights, and minimizes
$$\frac{n^{-1}\sum_i w_i(y_i-\hat f_i)^2}
{(1-\mathrm{tr}(S_\lambda)/n)^2},$$
where \(S_\lambda=(W+\lambda_1 B+\lambda_2 B_S+\epsilon I)^{-1}W\).
The exact trace is deterministic. The Hutchinson option uses Rademacher
probes, reports trace standard errors, and is reproducible with
gcv.control = list(trace.method = "hutchinson", trace.seed = ...).
Both selection modes can also search adaptive-radius support profiles:
set support.selection to the same mode in its control list. Each row
of support.grid contains adaptive.k.scale, min.support,
and optionally max.support. A NULL grid is constructed by
ssrhe.support.grid. Each profile requires a new operator and
a full penalty search, so this can substantially increase runtime.
Migration
The former fit.ssrhe.hessian.regression.cv() and
fit.ssrhe.hessian.regression.gcv() entry points have been retired.
Use this function with lambda.selection = "cv" or "gcv".
Move fold.id to cv.control$foldid, nfolds to
cv.control$cv.folds, and loss/selection to
cv.control. Move gcv.trace.method, gcv.trace.n.probes,
and gcv.trace.seed to trace.method, trace.n.probes,
and trace.seed in gcv.control. Support search settings also
belong in the active control list; both former support candidate limits
are now named support.max.candidates.
Choosing controls
First fit: supply X, y, neighborhood size k, tangent.dim, and
lambda1; use lambda.selection = "fixed" for a specified penalty.
Selection: lambda.selection, lambda1.grid, and lambda2.grid select
penalties. Fold settings belong in cv.control; trace settings belong in
gcv.control. Label CV and GCV are different criteria. Support selection
rebuilds the operator for each candidate and multiplies this work.
Geometry: neighborhood, adaptive-radius, tangent and derivative controls determine the operator. Reuse it when fitting multiple responses.
Numerics: ridge and local conditioning controls stabilize solves. Exact GCV traces require more solves than stochastic trace estimates; the latter report sampling uncertainty and need a reproducible probe seed.
Diagnostics: inspect the selection table, energies, observed-label mask,
and solver metadata. fitted() and residuals() preserve response matrices.
References
Kim, K. I., Steinke, F., and Hein, M. (2009). Semi-supervised regression using Hessian energy with an application to semi-supervised dimensionality reduction. Advances in Neural Information Processing Systems 22. https://papers.nips.cc/paper_files/paper/2009/hash/f4552671f8909587cf485ea990207f3b-Abstract.html
Examples
X <- matrix(seq(0, 1, length.out = 12), ncol = 1)
fit.ssrhe.hessian.regression(
X, sin(2 * pi * X[, 1]), k = 6L, tangent.dim = 1L, lambda1 = 0.1
)
#> SSRHE Hessian regression fit
#> responses: 1
#> lambda1: 0.1
#> lambda2: 0
#> objective: 1.509
fit.ssrhe.hessian.regression(
X, sin(2 * pi * X[, 1]), k = 6L, tangent.dim = 1L,
lambda.selection = "cv", lambda1.grid = c(0.01, 0.1),
cv.control = list(cv.folds = 2L)
)
#> SSRHE Hessian regression CV fit
#> responses: 1
#> selected lambda1: 0.1
#> selected lambda2: 0
#> CV mse : 0.2803
fit.ssrhe.hessian.regression(
X, sin(2 * pi * X[, 1]), k = 6L, tangent.dim = 1L,
lambda.selection = "gcv", lambda1.grid = c(0.01, 0.1)
)
#> SSRHE Hessian regression GCV fit
#> responses: 1
#> selected lambda1: 0.1
#> selected lambda2: 0
#> GCV: 0.3712
#> trace(S): 2.167