nestedtune 0.0.0.9000
vignette("estimate"),vignette("tuners"),vignette("results")and the parallel article are shorter and follow the shape of the tidymodels.org articles.vignette("estimate")now says where a held-out test set fits and how to choose the number of folds.vignette("tuners")gives each search one short section.vignette("results")reads one run from the estimate to the plots, and the column tour, the failed-fold run and the dplyr rules left it.The help pages for reading a nested run are shorter and follow the shape of tune’s help pages. They cover the collect, compute and augment methods,
agreement(),autoplot(),selection_rule(), the extractors, and the print, summary and predict methods. The condition classes and the lists of errors left these pages.?collect_metrics.nested_resultsnow states the standard error in three sentences and points tovignette("estimate").Seven more help pages are shorter and follow the shape of tune’s help pages:
nested_tune_bayes(), the two racing functions,nested_tune_sim_anneal(),nested_fit_resamples(),nested_workflow_map(),nested_final_fit()andnested_resamples(). The four loop pages point to?nested_tune_gridfor what the loop functions share. The condition classes left the pages, and most lists of errors did too, because each error message says what went wrong.?nested_tune_grid, the nested cross-validation guide and the README opening are shorter and follow the shape of tune’s help pages and the tidymodels.org articles. The help page keeps what a user decides and what the result holds. The guide is one worked example. The shared sections on the other loop pages are shorter too.The tuning results change for a design whose outer split repeats a row in its
in_id. Each inner tuning call now gets its inner splits on the outer fold’s analysis set. It already did so for a design with no repeated row. Before, the inner splits stayed on the whole data. So tune finalized some parameter ranges on a frame that held the outer fold’s held-out rows. An example is amin_n()range finalized by row count. Each copy of a repeated row is its own row of the analysis set. Take an inner assessment set that the design leaves as the complement. It now holds every copy that the outer split holds of each row that the inner split does not train on. The next item, the fix for a leak of outer held-out rows, held each row once. That fix now covers a second case. There the outer split repeats no row. Itsin_idholds an index that is fractional, negative or past the data. The fold still fails, and its inner metrics come from assessment sets that hold only rows the outer split holds.Fixed a leak of outer held-out rows into inner tuning. Take an outer split whose
in_idrepeats a row, and an inner split on the outer split’s frame whoseout_idis the logicalNA. The inner assessment set was every row outside the innerin_id, so it held the outer fold’s held-out rows. Now it holds only rows that the outer split holds.The nested tuning functions and
nested_fit_resamples()now refuse a design whose outer or inner splits hold anNAin anin_idorout_id. The error has classnestedtune_bad_design, and it names each outer fold, inner split and slot that holds one.nested_resamples()refuses the same in a split ofoutside. Before, anNAin an outerin_idpassed the entry check, and the fold failed inside rsample. Anout_idthat is the logicalNAis still accepted, because rsample reads it as the complement.The same refusal now covers three more shapes of row index. It refuses an
in_idorout_idthat is not a numeric vector, such as row numbers stored as character. It refuses a slot that holds a value outside integer range. It also refuses anout_idthat isNULLor empty.nested_resamples()refuses the same in a split ofoutside. Before, a value such as3e9passed the entry check in most slots, and the fold failed inside rsample. The entry check refused it in an innerin_idof anested_resamples()design. It named it as a row the outer split does not hold, with a coercion warning. A character index failed the fold in vctrs. An empty innerout_idwas left out of tuning with no message. Theout_idthat is the logicalNAis still accepted. The error names each split and slot, and says how the slot breaks the rule.The README has a second table, which lists eight tuning functions from tune, finetune, workflowsets and tidyclust and the nestedtune function for each. Seven are supported, and
tidyclust::tune_cluster()is not. The prose under the resampling table is shorter. The reason for each refused design now sits in the “Differences from rsample” section of?nested_resamples. The error for an outer bootstrap no longer says thatrsample::nested_cv()only warns about it, because rsample builds agroup_bootstraps()call with no warning.-
Four refusals of malformed designs changed, each with class
nestedtune_bad_design.If an element of a
splitscolumn has thersplitclass but is not a list, it is now refused in either loop.check_nested()also refuses an element of theinner_resamplescolumn that has thersetclass but is not a list. Before, the check stopped with an R error such as “subscript out of bounds”.nested_resamples()refuses an element ofoutside, or of the rset thatinsidegives, that is not anrsplitat all. The refusal of an inner split that is a list but not anrsplitnow says that it is a list.Take an inner split on the outer split’s frame whose two sets share only rows that the outer split holds out. It now gets the error that says it indexes rows its outer fold does not hold, which names the leak. Before, it got the error about shared rows.
Take a split whose
out_idisNAand whose class has acomplement()method in the global environment. If every row that method returns is a row of the data, the rule on shared rows now reads those rows, as rsample does. Before, the rule read the rows of rsample’s own method.
The entry check runs faster on designs with many large inner splits.
A split whose assessment set holds a row of its analysis set is now refused in either loop, with class
nestedtune_bad_design. Such a split scores the model on rows it trained on. Before, a split rebuilt withrsample::make_splits()escaped the refusals that read a design’s class. Such an outer split ran, and its fold was scored on its training rows. In the inner loop, an index into an outer analysis set counts as the data row it copies. An outer split can repeat a row, as a rebuilt bootstrap does. The design is then refused if an inner split puts one copy of that row in each set. An inner apparent split rebuilt withmake_splits()under the id “Apparent” now gets this refusal. Before, the error told you to give it another id. The apparent split of an inner bootstrap design stays exempt under the id “Apparent”, because tune leaves it out of its estimates.nested_resamples(), the entry checks and the inner design thatnested_final_fit()rebuilds all apply the rule. The rule also refusesrsample::rolling_origin()withlagabove 0 in either loop, because each assessment set then holds the lastlaganalysis rows. Before, such a design ran. While the design keeps itslagsetting, the error suggestslag = 0, with the lagged predictors built before resampling. A design cut to fewer rows loses that setting, and is refused with no hint.An inner split whose
idis missing is now refused, and so is an inner design in which two splits carry the same values in every id column. tune leaves the first split out of its estimates, and it miscounts the resamples of the second design.nested_final_fit()now applies these rules to the inner design it rebuilds on all the data. It also refusesloo_cv(),apparent()andpermutations()designs there, where before it told anapparent()design to rename its split. Each refusal has classnestedtune_bad_design.An inner split with the id “Apparent” is now refused unless it is the apparent split of a bootstrap design. tune leaves every split with that id out of its estimates, so before, such a fold tuned on fewer resamples than its design held, with nothing said.
nested_tune_race_anova()andnested_tune_race_win_loss()also refuse the apparent split of a bootstrap, such as the onebootstraps(apparent = TRUE)adds. finetune eliminates race candidates on its score, which comes from the rows the model trained on. If a workflow in a set routes to a racer,nested_workflow_map()refuses such a design before any workflow runs.nested_final_fit()applies both rules to the inner design it rebuilds on all the data. Each refusal has classnestedtune_bad_design.An apparent split beside bootstrap or permutation splits now needs the id “Apparent” to count as part of that design. tune leaves a split with that id out of its estimates. Under any other id, tune scores the split on the rows it trained on. So an inner bootstrap design whose apparent split carries another id is refused as an
apparent()design. This holds whether the id was changed in place or the design was rebuilt withrsample::manual_rset().nested_resamples()also refuses aninsidethat returns such a design, and names the outer fold. The error says that a bootstrap keeps its apparent split only under the id “Apparent”. Before, such an inner design ran and tune averaged that split’s score into the estimate. An outer design rebuilt withrsample::manual_rset()was refused before and still is, but its error now names that split as anapparent()row, not a bootstrap or permutation row.A
loo_cv(),apparent()orpermutations()design, or an outer bootstrap, is now refused even when the design no longer carries that design’s class. nestedtune finds the design from the class that each split keeps. The seven functions that take a nested design refuse a row subset such asfolds[1:2, ], a design rebuilt from its splits withrsample::manual_rset(), and a design with one such split among valid ones, in either loop.nested_resamples()refuses such a rebuilt or mixedoutside, and refuses a row-subsetoutsideas before, because it is not an rset. It also refuses aninsidethat returns such splits, and names the outer fold. Before, such an outer design and a rebuilt or mixed inner design ran unrefused. A row subset of an inner design got an error that called the column malformed. The new error has classnestedtune_bad_designand names the rsample function, as the outer bootstrap refusals now also do.loo_cv(),apparent()andpermutations()are now refused in either loop, because none gives a valid nested estimate there.nested_resamples()refuses them when it builds the design. The seven functions that take a nested design refuse them in a design built another way, such as withrsample::nested_cv(), before any fold runs. Before, most of these designs failed every outer fold only after the whole loop ran. The error has classnestedtune_bad_designand names the rsample function. The outer bootstrap refusal innested_resamples()now has this class too. The README’s table marks the six designs as refused.The README has a table of 15 rsample resampling functions. It says whether each one works as the outer loop and as the inner loop, and why the ones that do not work are refused or give no valid estimate. A design marked as working is one the tests run through
nested_tune_grid().collect_predictions()on a nested result or a workflow-set result gainssummarize, which defaults toFALSE. Withsummarize = TRUEit returns one averaged prediction per data row, over every completed outer fold that held the row out. So on a repeated or Monte Carlo design, a row held out more than once gets one prediction there. The default per-fold table is unchanged. The average follows tune’s rules forsummarize = TRUE. Because each fold selected its own candidate, the average spans those candidates, and the fold labels and.configare dropped. Quantile predictions are refused. The average refuses saved predictions whose.rowcolumn no longer holds exactly the rows its fold held out, each once. It also refuses three edited shapes that its rules cannot read: two or more factor outcome columns, a.pred_classcolumn with no factor outcome, and a censored.predentry that is notNULLand has no.eval_time. ANULLcensored entry is left out of its row’s average. A metric computed on the averages describes several fitted models, not the tuning procedure, socollect_metrics()stays the nested estimate.The per-fold tables of
collect_metrics(summarize = FALSE)andcompute_metrics(summarize = FALSE)carry the design’s fold labels each in its own column, as tune’s tables do. On a repeated design they now carryidandid2. Before, they carried oneidthat pasted the two together, such as"Repeat1, Fold1", and that pastedidis gone. A join on a repeated design’s folds uses both columns. The wide shape ofcollect_metrics()and the tables of a workflow-set result follow. The performance plot still labels its folds"Repeat1, Fold1".summary()of a nested result, of a workflow-set result and of a final fit, and the final fit’s print, name the metric that chose the selected candidates. A line such asSelecting metric: rmseprints under the"best","one_std_err"and"pct_loss"rules, the default included. It is absent under the"desirability"rule. The record thatextract_procedure()returns holds the name asfirst_metric, and the summaries carry it as a component of the same name. The help fornested_workflow_map()says which metric of ametricspassed to it selects. The five tuning functions andnested_fit_resamples()now refuse a metric set that does not suit the model’s mode before any fold runs. An example is a classification metric on a regression model.nested_workflow_map()makes the same refusal for every workflow the map runs, before any workflow runs. Before, every fold ran and failed.The help for
metricsonnested_tune_grid()and its tuning siblings says which metric selects and which metrics the outer loop scores. The “Running the loop” section of the nested cross-validation guide says so too. Under the"best","one_std_err"and"pct_loss"rules, the first metric in the set chooses each fold’s candidate. Every metric in the set is scored, sometric_set(mae, rmse)chooses bymaeand also reportsrmse. The help formetricsonnested_fit_resamples()says that every metric in the set is scored.selection_rule()gains a fourth rule,"desirability", which selects withdesirability2::select_best_desirability()over goals such asmaximize(rsq)andminimize(num_comp). A goal can name a metric or a tuned parameter.nested_tune_grid(),nested_tune_bayes()andnested_final_fit()apply it.nested_tune_grid()andnested_tune_bayes()refuse at entry a goal that names neither a metric of the run nor a tuned parameter, with classnestedtune_selection_rule_unknown_term. The racing tuners andnested_tune_sim_anneal()refuse the rule with classnestedtune_selection_rule_unsupported.nested_tune_grid()andnested_tune_bayes()refuse it with the same class on a censored regression model.selection_rule()refuses a goal desirability2 refuses, with classnestedtune_selection_rule_terms. It refuses a goal that names a variable or a metric outside its first argument, with classnestedtune_selection_rule_term_arg. It refuses alimitunder the rule, with classnestedtune_selection_rule_limit. The rule needs desirability2 0.2.0 or later, now in Suggests. Where it is absent,selection_rule(),nested_tune_grid(),nested_tune_bayes()andnested_final_fit()refuse the rule with classnestedtune_pkg_not_installed.Every orchestrator and
nested_final_fit()support an outerrsample::rolling_origin(),rsample::sliding_window(),rsample::sliding_index()orrsample::sliding_period()design with an innerrsample::rolling_origin()design.nested_tune_grid()andnested_fit_resamples()are tested on all four, and so isnested_final_fit()for their results.nested_tune_bayes(),nested_tune_race_anova(),nested_tune_race_win_loss()andnested_tune_sim_anneal()are tested on the rolling-origin design, and so isnested_final_fit()for their results, plus the sliding-window design fornested_tune_bayes()results.nested_workflow_map()is tested on the rolling-origin design.nested_resamples()builds all four designs with the same splits asrsample::nested_cv().An outer
rsample::rolling_origin()design with an innerrsample::sliding_window(),rsample::sliding_index()orrsample::sliding_period()design is tested undernested_tune_grid(), and so isnested_final_fit()for its results.nested_resamples()builds these three designs with the same splits asrsample::nested_cv(). These designs are also tested undernested_tune_bayes(),nested_tune_race_anova(),nested_tune_race_win_loss()andnested_tune_sim_anneal(), and so isnested_final_fit()for the results of those four tuners.nested_workflow_map()is tested on these three designs with its defaultfn. Withfnset to each of those four tuners, it is tested on the sliding-period design alone.nested_fit_resamples()is tested to accept these designs. It checks the inner design but fits nothing on it. Any other inner design is not tested.An outer
rsample::sliding_window(),rsample::sliding_index()orrsample::sliding_period()design with an inner design of one of these three kinds gives nine pairs.nested_resamples()builds each pair with the same splits asrsample::nested_cv(), and each pair is tested undernested_tune_grid(). The pair of an outer and an innerrsample::sliding_window()is also tested undernested_tune_bayes(),nested_tune_race_anova(),nested_tune_race_win_loss(),nested_tune_sim_anneal()andnested_workflow_map()with its defaultfn. On that pair,nested_final_fit()is tested fornested_tune_grid()results, andnested_fit_resamples()is tested to accept the design. It checks the inner design but fits nothing on it. On the other eight pairs, no function butnested_resamples()andnested_tune_grid()is tested.When an outer design leaves rows out of every assessment set,
augment()now names the first five of those rows in its error, or all of them when there are five or fewer. The error names no design type. The condition class is stillnestedtune_augment_rows.nested_tune_grid(),nested_tune_bayes(),nested_tune_race_anova(),nested_tune_race_win_loss(),nested_tune_sim_anneal()andnested_fit_resamples()now take a parsnip model specification with a formula or a recipe, in tune’s order:nested_tune_grid(spec, preprocessor, resamples). The call gives the same result as the one onworkflows::workflow(preprocessor, spec)under the same seed. A specification with no preprocessor, or with one that is not a formula or a recipe, is refused with classnestedtune_bad_preprocessor. A preprocessor given beside a workflow is refused with classnestedtune_preprocessor_with_workflow.nested_final_fit()still takes a workflow, and its message for a bare specification namesworkflows::workflow(preprocessor, spec).A
nested_final_fitnow answersextract_fit_parsnip(),extract_fit_engine(),extract_recipe(),extract_mold(),extract_preprocessor(),extract_spec_parsnip()andoutcome_names()with what the same call gives on its trained workflow.extract_recipe()takesestimated. Apart fromextract_recipe(), the workflow methods drop an argument they do not know, so these refuse one instead.A
nested_final_fitnow answersextract_parameter_set_dials()with the parameter set tune stored on its tuning run. The trained workflow holds notune()placeholder, so the set is read from that run and not from the workflow. With a data-framegrid, the set can keep an unknown range such as that ofmtry. A fit fromnested_fit_resamples()is refused with classnestedtune_no_tuning_run.collect_metrics()on anested_resultsor anested_results_settakestype = "wide", which returns one column per metric, as tune’scollect_metrics()does. A summarized table holds each metric’s mean, and an unsummarized one holds each outer fold’s estimate. The fold labels,.eval_timeandwflow_idstay as key columns. An unknowntypeis refused with classnestedtune_bad_type. A metric scored with two estimators, or named like a key column, is refused with classnestedtune_wide_collision.autoplot()on anested_resultsor anested_results_settakesmetricandeval_time, which choose the panels oftype = "performance". A static metric’s panel is drawn whatevereval_timenames, as in tune. A metric or a time the run did not score, or either argument withtype = "parameters", is refused with classnestedtune_bad_plot_filter.predict()on anested_resultsor anested_results_setnow refuses with classnestedtune_predict_resultsand namesnested_final_fit(), which fits the model to predict with. Before, R gave its generic “no applicable method” error.Five messages no longer break across two lines partway through a sentence. They used a line continuation that
cli::format_inline()does not join, so the reader saw a newline and an indent. The refusalnested_final_fit()gives for reordered model arguments showed a stray backslash as well. The other four are three refusals of a malformed nested design and the completion line of a workflow set’s print.The workflow identity a result records no longer depends on the number formatting the session happens to use.
deparse()reads thescipenoption, so a workflow holding a value such as1e5recorded one identity in a session that set the option and another in a session that did not, andnested_final_fit()refused a workflow the user had built from the same code. The option is now fixed while the identity is written, so a record made on one machine matches the workflow rebuilt on another.The workflow identity every result records now holds a case-weights column, as written, and a tailor postprocessor, as its adjustments in order with each one’s type and arguments, when the workflow carries them.
nested_final_fit()refuses a workflow that differs in either, with classnestedtune_workflow_mismatch, and the message names the part: the column, the adjustment and its argument, or one side carrying the part and the other not. A workflow with neither keeps the identity it had, so a results object saved before this change is accepted under the workflow it ran under.tailorjoins Suggests for the tests.Weights set on the design with
tune::add_resample_weights()now reach the outer average.collect_metrics(),summary(),autoplot()andcompute_metrics()report the weighted mean and tune’s weighted standard error over the folds that scored. The per-fold table fromcollect_metrics(summarize = FALSE)carries each fold’s weight in a.weightcolumn. A fold that fails or scoresNAis left out and the remaining weights are scaled to sum to one. A design without weights reports the numbers it did before.compute_metrics()now refuses a completed fold whose saved predictions do not hold exactly the rows that fold held out, each once, before any fold is scored. The refusal has classnestedtune_compute_metrics_predictionsand names each fold that fails. Five shapes this refuses are a missing row, a repeated.row, anNA.row, a row the fold did not hold out, and no.rowcolumn. A.rowthat is not a whole number is refused too.augment()refuses the same shapes. On a workflow-set run the message names the workflow.The printed
summary()of a run, the final fit’s print and itssummary()now name a selection rule other than the default. The line readsSelected by:and then the rule’s name, orderings and limit, in the words the print ofselection_rule()uses after its class tag. A workflow set’s printed summary adds the line inside each tuned workflow’s section. Both summaries gain aselectcomponent holding the rule.The help for
nested_tune_grid(),nested_tune_bayes(),nested_tune_race_anova(),nested_tune_race_win_loss(),nested_tune_sim_anneal()andnested_fit_resamples()now takes the text forgrid,param_info,iterandmetricsfrom tune’s and finetune’s own pages. What this package adds for one of those arguments reads in the page’s Details.The note
summary()prints for a run or a workflow set and theautoplot(type = "performance")subtitles now name the nested estimate as the number to report for the modelnested_final_fit()builds. The help fornested_tune_bayes(), the racing tuners andnested_tune_sim_anneal()now says the same. The summary note limits this to a procedure chosen before seeing the estimate. For a fit built from a workflow set, the message a final fit prints names that workflow’s rows ofcollect_metrics()on the set as the number to report. This holds for a workflow chosen before seeing the set’s estimates.compute_metrics()andaugment()now answer on a run whose control setsave_pred = TRUE, and on a workflow-set run.compute_metrics()scores each outer fold’s saved predictions with a metric set you give it. It summarizes them ascollect_metrics()does, and it does not run the inner selection again. Itsevent_leveldefaults to the level the run recorded.augment()joins each data row’s out-of-fold prediction onto the data. On a design that holds each row out once, it joins the saved predictions as they are. A repeated v-fold or a Monte Carlo design can hold some row out more than once. There, every row joins the average thatcollect_predictions(summarize = TRUE)gives for it. On such a design it refuses saved quantile predictions, because that average does not cover them. It refuses there the three edited shapes that average refuses. It refuses an outer design that leaves some row out of every assessment set. It also refuses a fold whose saved predictions do not hold exactly the rows that fold held out, each once. A data column named like a prediction column is refused before any refusal of the average.The coverage job no longer fails after every test passed. Daemons started by the test suite write their coverage traces to a directory of their own, and the job merges those traces afterwards, skipping any file a daemon was killed in the middle of writing.
Every help page now passes the same plain-English sweep as the guides: no semicolon, no contraction, no
has beenorhave been, none of the words should, may, might, could and would, no word ending in -ing after a comma other than a few prepositions and pronouns, and none of the filler words and phrases, in any roxygen prose sentence.The four guides, the parallel article and the README are rewritten to pass a plain-English sweep: no semicolon, no contraction, no
has beenorhave been, none of the words should, may, might, could and would, no word ending in -ing after a comma other than a few prepositions and pronouns (including, during, nothing), and none of a list of filler words and phrases, in any prose sentence.Every result records the model specification and the preprocessor of the workflow it ran under, as the
workflowentry of the recordextract_procedure()returns. The entry holds the model’s type, engine, mode and arguments, and the preprocessor, in deparsed form, with recipe step ids and the data left out. Case weights and a postprocessor are not part of the entry.nested_final_fit()compares the workflow it is handed against that entry and refuses one whose model or preprocessor differs, with classnestedtune_workflow_mismatch, naming the part that differs. A workflow rebuilt from the same code is accepted. A results object saved before this entry existed is refused as one from an earlier version.Every help page is rewritten for someone who has run
tune_grid()and never nested: no roxygen sentence over 30 words, no sentence naming more than four code spans, each page opening on what the reader gets from it, and the words “procedure”, “orchestrator” and “candidate” set up once on?nested_tune_gridand either set up again or preceded by a link to that page wherever another page uses them.extract_scored_candidates(),agreement(),selection_rule()andextract_procedure()have new titles; nothing else about any page’s arguments or behaviour changed.The four guides, the parallel article and the README are rewritten for someone who has run
tune_grid()and never nested: no prose sentence over 30 words, the words “procedure” and “candidate” set up on each page before it relies on them, and the word “orchestrator” gone. Those pages, and this file, keep each explanation on one page with a link from the others. The site-only article “Why nest: a simulation” and its simulation script are removed; the estimate page’s cited measurements make the same point.Every help page is rewritten for a tidymodels user: argument entries of at most two sentences, detail under section headings, the arguments an orchestrator shares with the tune, finetune or workflowsets function it wraps inherited from that page, and examples written with
|>that run underR CMD check.?nested_resamplescarries the memory table the README used to.The documentation site no longer carries pages built from files internal to the repository, and its build fails if any tracked markdown file other than the README, this file, the licence, the code of conduct or the contributing guide gets a top-level page.
autoplot()on anested_results_setwithtype = "performance"adds a subtitle sentence counting the workflows whose average for a metric comes from fewer outer folds than the workflow completed, pointing atsummary()for which metric and how many folds.A
nested_results_setkeeps its class only while every row is one of the run’s own workflows, so dropping or reordering rows and adding columns keep it and a record column dropped or renamed, a repeatedwflow_idor a row not the run’s own give a plain tibble. A warning or error raised for one workflow is the original condition withWorkflow "<id>":in front of its message.summary(),autoplot()andagreement()answer on anested_results_set, each workflow’s view keyed by itswflow_id:summary()returns one summary per workflow and prints one section each, the performance plot puts the workflows along the x axis inside a panel per metric, the parameters plot draws a panel per workflow and tuned parameter, andagreement()stacks each workflow’s table underwflow_id.nested_workflow_map()runs every workflow of aworkflowsets::workflow_set()through one nested design in one call, withfnnaming the orchestrator, the orchestrator’s arguments in..., and the set’soptioncolumn overriding an argument for one workflow. It returns anested_results_set, onenested_resultsper row, whosecollect_*()readers stack each workflow’s table underwflow_id, andnested_final_fit(x, id = )fits one workflow by its own record;workflowsetsjoins Suggests.nested_fit_resamples()scores a workflow with nothing to tune on the outer folds of a nested design, the same outer loop with the inner stage removed, so a fixed workflow and a tuned one score on identical folds. Its result answers every reader, with.selectedempty on every fold andextract_procedure()naming the tuner"fit_resamples".The five tuning orchestrators refuse a workflow with no
tune()marker at entry, with classnestedtune_untuned_workflow, namingnested_fit_resamples(), which in turn refuses a workflow carrying a marker with classnestedtune_tuned_workflow.A
selectargument on the five tuning orchestrators names the rule each outer fold selects its candidate by, built by the newselection_rule():"best"by default, or"one_std_err"and"pct_loss"with the parameter orderings tune’s rules take. The rule is recorded asextract_procedure(res)$selectandnested_final_fit()selects by it.save_predandextracton a control passed ascontrolreach the outer fit, adding a.predictionsor.extractslist column to the result, andcollect_predictions()andcollect_extracts()stack them with the fold labels over the folds that completed. A run that did not ask for the column is refused with classnestedtune_column_not_saved.extract_procedure()returns the record of what ran, the tuner, its arguments and the control as it took effect, from a results object and from a final fit alike.The em dash is gone from every text the package publishes.
Three readers stack a per-fold list column into one table with the design’s fold labels beside it:
collect_notes()over every outer fold, andcollect_selections()andcollect_inner_metrics()over the folds that completed, warning once with classnestedtune_partial_summaryon a partial run.tidymodelsjoins Suggests. Every vignette attaches it beforenestedtune, behind a guard that ends the page with one notice when it or another of the page’s optional packages is absent.The parallel article and three further vignettes are added. The parallel article runs the guide’s loop on two mirai daemons and shows the result identical to the serial run;
vignette("results")reads the results object;vignette("tuners")runs the Bayesian, racing and annealing searches on the guide’s design; andvignette("estimate")says what the nested number estimates, leavingvignette("nested-cv")as the getting-started path.The tuning orchestrators refuse a malformed
resamplesdesign at the call, before any fold runs, with classnestedtune_bad_design, naming every offending fold, split, index or column: an inner element that is not anrsplitorrset, an inner split over a frame other than the outer split’s own or its analysis set, an inner split indexing a row its outer fold holds out, an empty inner design, anNAor repeated label, and a label column that is not character or factor or not namedidoridfollowed by a digit. Designs fromnested_resamples()andrsample::nested_cv()pass unchanged.Before any fold is dispatched to mirai daemons, the startup check asks every daemon for each package the workflow and the tuner need, and stops with class
nestedtune_daemons_missing_pkgsnaming how many daemons are affected and which packages. The host’s own entry check refuses a package the workflow needs that is not installed, a recipe step’s as well as the engine’s, undernestedtune_pkg_not_installedwith aninstall.packages()call to paste.extract_tune_results()andextract_scored_candidates()on an object they have no method for signalnestedtune_no_extract_methodnaming that object, whatever else was passed in....Printing the columnless type token
vctrs::vec_cbind_frame_ptype()hands back writes the banner and the rows alone. A column add that leaves two columns sharing a record column’s name returns a bare tibble, andnames<-keeps the object intact when each record column keeps its name and returns a bare tibble when one is renamed or shadowed.On a
nested_resamples()design, every inner tuning call sees only its outer fold’s analysis rows, so aparam_infoparameter whose range tune finalizes from the data is finalized without the rows that fold holds out, as it already was on anrsample::nested_cv()design. The candidates such a run searches, and so its selections and estimate, change from earlier development versions;nested_final_fit()still finalizes on the full data.nested_final_fit()refuses a results object in which no outer fold completed, with classnestedtune_no_completed_folds, the classcollect_metrics(),autoplot()andagreement()raise on the same object.nested_tune_sim_anneal()runs the outer loop with finetune’s simulated annealing inside: each fold scoresinitialcandidates on its inner resamples, then perturbs the current candidate foriteriterations, with afinetune::control_sim_anneal()passed ascontrol.iterbelow 1 andinitialbelow 1 or given as atune_resultsare refused at entry, andcontrol_sim_anneal(verbose_iter = FALSE)keeps a serial run quiet (#35).nested_tune_race_anova()andnested_tune_race_win_loss()run the outer loop with finetune’s two racing tuners inside, takingnested_tune_grid()’s arguments and afinetune::control_race()ascontrol; each fold’s.inner_metricsholds every candidate its race scored withnthe inner resamples each was scored on. A package the race needs that is not installed, a control of the wrong kind, and an inner design with no more resamples than the control’sburn_inare refused at entry; finetune, lme4 and BradleyTerry2 join Suggests (#35).Each outer fold of a
nested_resultscarries its inner tuning run’s metrics as.inner_metrics,tune::collect_metrics()of that fold’s run with one row per candidate and metric, plus.iterfrom the iterating searches. A fold that scored nothing carries a zero-row table, andextract_scored_candidates()no longer carries.eval_time(#57).nested_tune_grid()andnested_tune_bayes()take a control object passed ascontrol,tune::control_grid()ortune::control_bayes(), and pass it to the inner tuning call in every fold, withallow_parforced toFALSEand the Bayesianseedset to each fold’s tuning seed. A control of the wrong kind is refused with classnestedtune_bad_control, and any other name or an unnamed value in...withnestedtune_bad_dots(#33, #35).nested_final_fit()takes the workflow and thenested_resultsobject,nested_final_fit(object, results), and re-runs the procedure that result recorded: the design’s inner resampling specification, the tuner and its arguments, the metric set and the selection rule. A results object with no such record, one that is no longer anested_results, or one with no rows is refused before any fitting with classnestedtune_bad_results.predict()andaugment()work directly on anested_final_fit, returning what the same call onextract_workflow(final)returns;augmentis re-exported.augment()takesnew_dataandeval_timeonly and refuses anything else.print()andsummary()on anested_final_fitname the procedure that ran: the candidates scored for a grid search, and for an iterating search the initial candidates and iterations, each as what ran beside what was requested.nested_tune_bayes()runs the outer loop withtune::tune_bayes()as the inner tuner, scoringinitialspace-filling candidates on each fold’s inner resamples and letting a Gaussian process propose up toitermore underobjective. The Gaussian process is seeded from the fold’s tuning seed, so a fold reproduces from its.tuning_seedalone, andinitialis a count only, since one tuning run cannot serve every outer fold.Every
nested_resultscarries aprocedureattribute recording the tuner that ran, its own arguments, andparam_info,event_levelandeval_time, which travels with the class and is shed with it. The metric set travels beside it asattr(x, "metrics"), absent when none was passed.agreement()reports how often each candidate was selected across the outer folds: one row per distinct combination of selected values, withnandpropover the completed folds, most frequent first. The most frequent combination is not the final model’s parameters.print()on anested_resultsacceptsnandwidthand passes them to the rendering of the outer-fold rows, matched by full name only.nested_tune_grid()takes aneval_timeargument, passed to every tune call whose answer depends on it, so a censored regression workflow scored by a dynamic survival metric is measured at the times named. A metric measured at several times is summarized per time bycollect_metrics()andsummary()in an.eval_timecolumn and drawn one panel per time byautoplot(type = "performance").summary()on anested_final_fitreports the full-data tuning run’s resampling scheme, the candidates it scored and the values selection chose. Where a number would be, it names the nested estimate as the number to report for this model.Printing a
nested_resultsshows the object: its outer folds as the tibble rows they are, the resampling scheme, a count of the folds that did not complete, and a note when the folds did not all search the same grid. Printing never warns and never errors, a run in which no fold completed included.summary()on anested_resultsreturns an object holding the requested and completed fold counts, the failed folds with the stage each failed at, the values the completed folds selected, and the metric estimates over the folds that completed. A partial run warns and still returns the summary, and one where every fold failed does the same.A
nested_resultswhose record of its fold-label columns cannot label its rows names each fold by its row position.An operation that changes which outer folds a
nested_resultsholds returns a plain tibble:slice(),head(),x[1, ], afilter()that drops a fold,bind_rows(), and dropping any of the columns the run is recorded in. Reordering rows witharrange(), adding a column withmutate()orbind_cols(), reordering columns withrelocate(), and aleft_join()that matches one row apiece keep the class and the run’s record.The same rule covers the vctrs verbs and base
rbind():vctrs::vec_slice(x, 1),vctrs::vec_rbind(),vctrs::vec_c()andrbind()return a plain tibble, while reordering rows withvec_slice()and adding a column withvctrs::vec_cbind(x, extra)keep the class.vec_cbind()andbind_cols()build on the first argument’s type, so with the results object second they return a plain tibble.dplyr::rename()moving one of the columns the run is recorded in returns a plain tibble.dplyrandvctrsare hard dependencies; both were already installed alongside nestedtune throughtune.A results object records the columns its resampling design labelled the folds with, so a column you add is read as a fold label only when the design itself carries a column of that name. Before, the fold-label columns were worked out from the column names, so adding
id_extrareported the folds asFold1, x.Replacing a fold-label column with a value that cannot be ordered, as
dplyr::mutate(x, id = list(c(1, 2), 3, 4))does, returns a plain tibble rather than failing inside the class rule.The packages a workflow declares are attached inside each mirai daemon before any fold is dispatched, so a recipe with unqualified selectors such as
all_numeric_predictors()resolves on a worker as it does serially.nested_tune_grid(),nested_final_fit()andnested_resamples()take...immediately after their required arguments, sogrid,metricsandparam_infomust be named and a mistyped or unsupported argument is an error naming the function it was passed to. Every method the package registers whose...is documented as unused refuses an argument the same way.collect_metrics()on anested_resultstakessummarizeafter..., matching tune’s own method, so it must be named.nested_tune_grid()takesparam_info, passed unchanged totune::tune_grid()on every outer fold, and refuses one that is not adials::parameters()object before the first fold is fitted.nested_tune_grid()takesevent_level, naming which level of a two-class outcome factor counts as the event, and sends it to the inner tuning run and the outer scoring fit alike. A value that is not"first"or"second"is refused before the first fold is fitted.The documentation site builds with the tidymodels organization’s shared pkgdown theme, and the organization’s contributing guide and code of conduct build as pages of the site.
The package has moved to the tidymodels organization, at https://github.com/tidymodels/nestedtune with its documentation site at https://nestedtune.tidymodels.org/. The old repository address redirects; the old documentation address does not.
A parallel run refuses to start when a daemon is holding an older install of nestedtune, with class
nestedtune_daemons_incompatible, naming the functions its copy is missing and the fix: reinstall, then restart the pool. A running daemon keeps the version it has already loaded, so reinstalling underneath one changes nothing.A parallel run started on a pool that cannot be cancelled, one from
mirai::daemons(n, dispatcher = FALSE), warns once at the start of the run with classnestedtune_pool_not_cancellable. Its results are correct; what the pool lacks is the ability to stop on an interrupt.Running the outer folds in parallel sends each fold one copy of the data instead of one copy per inner resample, the splits being emptied before dispatch and refilled on the daemon. Results are unchanged, and the serial path is untouched.
The object
nested_final_fit()returns has two accessors for the tuning run behind it:extract_tune_results()returns that run, andextract_scored_candidates()the candidate settings it scored. Every metric inside that run was computed on the resamples that chose the candidate it describes, so it is not the model’s performance.nested_tune_grid()andnested_final_fit()refuse a workflow that has a model but no preprocessor, pointing atworkflows::add_formula(),add_recipe()andadd_variables(), and a workflow with no model, pointing atworkflows::add_model().When
nested_final_fit()cannot re-run a design’s stored inner specification, the error names the caller’s call rather than an internal function.nested_resamples()refuses aninsidespecification that does not produce anrset.When a resampling specification fails to evaluate, the error names the specification that was tried instead of deparsing the data into the message, and is wrapped in a nestedtune error carrying the original as its cause.
The reference pages and the vignettes are built into a documentation website, rebuilt whenever a change lands on the default branch that the package itself can see.
Interrupting a parallel run asks the folds already sent to the daemons to stop, so the pool goes idle rather than computing results nobody will read. Cancelling needs mirai’s dispatcher, which
mirai::daemons(n)starts by default, and a fold already inside a compiled fitting routine may not be interruptible.The check that runs before parallel dispatch asks every connected daemon whether it can load the package, and a daemon that does not answer is reported as a non-response, class
nestedtune_daemons_no_response, rather than as one that cannot load the package, classnestedtune_daemons_cannot_load. Both also carrynestedtune_daemons_unusable.The wait for that check is settable with
options(nestedtune.preflight_timeout = <milliseconds>), a single positive, finite number, 30 seconds by default. The first parallel call after starting a cold pool is the slow one, since it is what makes each daemon load the package.Cancelling a parallel run stops it, raising a
nestedtune_cancelledcondition that inherits fromnestedtune_interruptedand returning nothing, with the caller’s RNG state restored. Callingmirai::daemons(0)while folds are outstanding is recorded as fold failures instead, since it produces exactly what a daemon dying mid-fold produces.autoplot()draws a nested cross-validation result. The default view puts one point per outer fold at the value that fold’s inner tuning selected, one panel per tuned parameter, andtype = "performance"draws each outer fold’s score with a dashed line at the nested estimate, read from the same placecollect_metrics()reads it.Both views keep every outer fold that was attempted on the axis, a fold that failed leaving a visible gap. The subtitle says how much of the requested design ran, and each panel says when fewer folds contributed to it than completed, as
mtry (2 of 3 chose)orrmse (from 2 folds).ggplot2is a hard dependency. Plotting a run where no outer fold completed, or asking for the parameters view of a design with no tuned parameters, is refused with a message saying which it was.nested_tune_grid()runs its outer folds in parallel when mirai daemons are connected, with no argument to set, and inner tuning stays serial because nesting parallelism inside parallelism oversubscribes cores. Parallel results are identical to serial ones, because each fold’s seeds are drawn before the loop starts and assigned by position.nested_final_fit()builds the model to deploy by running the same tuning procedure the nested estimate describes with the whole dataset in hand, and returns it as a separate object. The nested estimate is the number to report for that model.collect_metrics(),show_best()andselect_best()refuse a final fit rather than returning something that reads as its score.Because the inner resampling specification is stored unevaluated and re-evaluated at final-fit time, it is written with literal arguments,
inside = vfold_cv(v = 5)rather thaninside = vfold_cv(v = k). A specification whose variables have gone out of scope fails with a message naming it.An outer fold that fails does not end the run: the remaining folds still run,
.completedmarks the failed one, and.notessays which stage failed and why, carrying tune’s own notes about the cause. A fold that completes on only part of its inner design keeps the notes explaining what was lost.nested_tune_grid()checks a data-framegridagainst the workflow before fitting anything, refusing by name a column that is not marked for tuning or a tuned parameter with no column.collect_metrics()summarizes only the outer folds that completed, warns naming the ones that did not, and errors rather than returningNAwhen none completed.nested_tune_grid()runs the nested cross-validation loop end to end: for each outer fold it tunes on that fold’s inner resamples withtune::tune_grid(), selects a candidate, finalizes the workflow, and fits and scores it on the outer split. The result keeps each fold’s chosen parameters alongside its metrics, so disagreement between folds is visible rather than averaged away, andcollect_metrics()returns the per-fold metrics or their summary across outer folds.nested_tune_grid()is reproducible from a singleset.seed()before the call: it derives one tuning seed and one outer-fit seed per fold up front, so a fold’s result depends on its position in the design rather than on the order folds run in, and it leaves the caller’s random-number state as it found it.nested_resamples()builds a nested resampling design without keeping a copy of the data for every outer fold, selecting the same rows asrsample::nested_cv()for the same seed and specifications. On a 20000-row dataset with a five-fold inner resampling, a 50-fold outer design holds 10× the source data rather than 57×.nested_resamples()refuses an outer bootstrap, since the same observation can otherwise land in both the inner analysis and the inner assessment set.
