--- title: "Iterative multi-response input expansion" output: rmarkdown::html_vignette bibliography: ../inst/REFERENCES.bib vignette: > %\VignetteIndexEntry{Iterative multi-response input expansion} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r setup, include = FALSE} knitr::opts_chunk$set(collapse = TRUE, comment = "#>") library(ssel) ``` `chainPipeline()` repeatedly refits the supervised helper family while allowing delivery values for other responses to become predictors. The idea is related to multi-target input-space expansion [@spyromitros2016chains], but the recurrences, gates, stopping rules, and stitch described here are ssel package policies. The function is neither a standard regressor-chain estimator nor a general equation solver. ## Responses, row classes, and companion values Let $R$ be the declared response set and $t=0,1,\ldots$ the iteration. Training and prediction rows have different companion sequences: - $Y_k^{(t)}(i)$ is response $k$'s `p = 0.50` signed-residual-offset delivery for training row $i$; - $Z_k^{(t)}(u)$ is the corresponding delivery for prediction row $u$. Both are in response $k$'s units and have already passed through the documented response bounds. They are not raw point predictions or raw OOF predictions. Iteration zero uses no companion columns. At a key present in both row classes, the training value takes precedence; the target response's own companion is always excluded from its predictor set. `aggregateResponses()` constructs these delivery values. `chainPipeline()` suffixes and joins them to assembled predictors before asking the supervised helpers to refit each target. ## Jacobi recurrence Let $A^{(t-1)}\subseteq R$ be the active companion set entering iteration $t$, and let $j$ be the target response. A Jacobi sweep builds one frozen augmented snapshot. Its training and prediction companion sets are $$ C_{j,t}^{J,tr}(i)= \{Y_k^{(t-1)}(i):k\in A^{(t-1)}\setminus\{j\}\}, $$ $$ C_{j,t}^{J,pred}(u)= \{Z_k^{(t-1)}(u):k\in A^{(t-1)}\setminus\{j\}\}. $$ Every target therefore sees only values from the preceding completed iteration. “Jacobi” names this package update order; it does not imply parallel execution or a convergence theorem. ## Asymmetric Gauss--Seidel recurrence Gauss--Seidel targets are processed in sorted response-name order. Write $k\prec j$ when $k$ precedes $j$. Earlier targets can supply new training-row values to later targets in the same sweep: $$ \begin{aligned} C_{j,t}^{GS,tr}(i) &=\{Y_k^{(t)}(i):k\in A^{(t-1)},k\prec j\}\\ &\quad\cup \{Y_k^{(t-1)}(i):k\in A^{(t-1)},j\prec k\}. \end{aligned} $$ Prediction companions do **not** refresh within the sweep: $$ C_{j,t}^{GS,pred}(u)= \{Z_k^{(t-1)}(u):k\in A^{(t-1)}\setminus\{j\}\}. $$ This asymmetry is essential. Describing both row classes with one Gauss--Seidel recurrence would misstate the implemented method. ## Companion-importance normalization `extractChainImportance()` reads individual fitted model files. For model cell $c$, let $I_{fc}$ be caret's `Overall` importance for feature $f$, and let $T_c=\sum_f I_{fc}$, omitting missing scores. ssel defines $$ J_{fc}= \begin{cases} 100I_{fc}/T_c, & T_c>0,\\ 0, & T_c\le0. \end{cases} $$ The sum is computed before companion features are filtered, and normalized values are rounded to four decimals. This mechanical normalization does not establish comparability across learner families. ## Fixed and shadow gates The fixed gate retains companion response $k$ when its non-missing mean normalized importance reaches the supplied percentage threshold $\tau$: $$ \overline J_k\ge\tau. $$ The comparison is inclusive. The table helper demonstrates the exact rule: ```{r fixed-gate} importance <- data.table::data.table( feature = c("beta.o", "alpha.o", "beta.o", "alpha.o", "gamma.o"), normImportance = c(1, 2, 3, NA, NA) ) activeByImportance(importance, suffix = ".o", thresh = 2) ``` The shadow gate compares each companion row with the same row's single shadow score. A response passes only when strict successes are more than half of all its rows. Equality fails, and a missing shadow remains in the denominator as a failure. ```{r shadow-gate} importance <- data.table::data.table( feature = c("alpha.o", "alpha.o", "alpha.o", "beta.o", "beta.o", "gamma.o", "gamma.o"), normImportance = c(2, 3, 0, 2, 0, 2, 2), shadowImportance = c(1, 1, 1, 1, 1, 1, NA) ) activeByShadow(importance, suffix = ".o") ``` This is ssel's strict-majority, single-shadow policy. It does not implement Boruta's iterative random probes or statistical tests [@kursa2010boruta]. ## Active-set history Let $G_t$ be the raw gate result. The pipeline first applies the fallback $$ \widetilde G_t= \begin{cases} R, & G_t=\varnothing,\\ G_t, & \text{otherwise}. \end{cases} $$ With history width $K=\texttt{chainStable}$, once enough preceding returned sets exist it defines $$ A_t=\widetilde G_t\cap A_{t-1}\cap\cdots\cap A_{t-K+1}. $$ Those preceding sets may already contain older intersections. An empty intersection is not replaced by $R$ a second time. The standalone `computeActiveByImportance()` helper performs only its documented fixed-gate intersection; it does not implement the pipeline's empty-result fallback. ## Change score and stopping policy Consecutive training delivery tables are compared by current row and response column position, not by a key join. Compatible ordering is therefore a precondition. ssel defines $$ \delta_t=\max_{i,r} \frac{|Y_r^{(t)}(i)-Y_r^{(t-1)}(i)|} {\max\{1,|Y_r^{(t-1)}(i)|\}}, $$ removing missing cells only in the final maximum. Although dimensionless, $\delta_t$ is not invariant to response-unit rescaling or translation because of the fixed floor 1. It is a stopping heuristic, not evidence that a fixed point has been reached. For metric history, ssel retains the first minimum-RMSE `ensemble.RMSE` dataset row for each response and uses that row's squared sample correlation $R^2_{r,t}$. The iteration mean is $$ \overline{R^2}_t=|R|^{-1}\sum_rR^2_{r,t}. $$ Only a strict increase over the accepted historical mean resets the non-improvement strike. A separate divergence strike increments only when $\delta_t>\delta_{t-1}$. After current products are written, stop checks run in this order: $\delta_t<\texttt{tol}$, divergence strikes reaching `patience`, then non-improvement strikes reaching `patience`. Resume restores selected file state but resets both strike counters and active history. Its first resumed active set is `NULL`, so all available companions enter that first resumed augmentation. `maxIter` is additional work, not an absolute lifetime cap. The full file prerequisites and partial-write behavior are documented on `?chainPipeline`. ## Per-response iteration stitch At completion, response $r$ selects $$ t_r^\star=\operatorname*{first\,argmax}_{t\in\{0,\ldots,T\}}R^2_{r,t}. $$ Iteration zero is eligible. Baseline scores are unrounded; later candidates use stored four-decimal scores, so rounding can affect the choice. The final `Yo.csv` and the five current summary products are replaced response by response from selected snapshots. Models, split files, cell files, `Y.csv`, `X.csv`, and `Xo.csv` remain from the last fitted iteration. The resulting installation can therefore contain stitched delivery summaries alongside a different last-fitted model state; this is an explicit product boundary, not a recommendation to regenerate models. ## Interpretation and limits The recurrences describe exactly which companion values may enter a fit. The gates are deterministic package policies over supplied importance tables, and the stopping criteria are operational heuristics. None establishes an optimal response order, a calibrated importance threshold, convergence of an equation solver, or superiority of one sweep. For a complete, temporary-directory function example and all side effects, see `?chainPipeline`. ## References