Skip to content

← optimization package

ParameterOptimization

Optimize hyper-parameters of a pipeline given a dataset.

The main use case of this node is with machine-learning pipelines that have free parameters (e.g., regularization parameters). The node can auto-tune these parameters given a dataset and optionally an evaluation function (which defaults to an inner cross-validation on the dataset). This works as follows: the user specifies for each free parameter of the pipeline a search range, which can be discrete or continuous (see parameter documentation for the supported formats). The node then samples multiple combinations of parameter settings, and for each such setting it configures the pipeline with the setting and passes the pipeline to the evaluator, which assess the performance of the configured pipeline on the given dataset. Once training is completed, one can retrieve either the optimal parameter setting (via the optimal_params output), or the fully trained method graph (with parameters bound to optimal values) via the optimized output. Furthermore, the Parameter Optimization node can also be used as a proxy for the method and generate training-set predictions (via the data output) on the initial invocation or test-set predictions on subsequent invocations (if initialize_once is set). One can also save and re-load the node's trained model via the model input/output. The pipeline is typically a subgraph with a placeholder node with slotname "data" that represents the input data, and any number of other placeholder nodes representing the tunable parameters (e.g., "lambda", etc.). Note that the node represents a training strategy, and not a validation strategy. To obtain cross-validation scores, you need to pass the entire parameter search procedure with all its inputs, except for the data replaced by a "data" placeholder, into the "method" input of an outer cross-validation node, which then receives the dataset to use for validation. A key parameter is the compute budget, which specifies how many parameter settings to try; the default is a low value sufficient only for a single parameter. The node supports a number of different search strategies, including randomized grid searches and other gradient-free optimization strategies. The node also supports optional parallel computation via the num_procs argument, which can be useful for long-running optimization tasks. Note that the default evaluator is a parallel 5x-cross-validation, so it will by default already use multiple processes, which are further multiplied by the num_procs argument. You can override the evaluator by providing a subgraph with a data and pype argument placeholder, which typically, wire into a cross-validation node. The node will by default log into your NeuroPype logs folder to allow recovery of partial results in case of crashes or long-running tasks. More Info... Version 2.0.1

Ports/Properties

data

Data to process.

  • verbose name: Data
  • default value: None
  • port type: DataPort
  • value type: object (can be None)
  • data direction: INOUT

method

Pipeline to optimize.

  • verbose name: Method
  • default value: None
  • port type: GraphPort
  • value type: Graph

method__signature

Arguments for the pipeline. Note that you do not need to list the placeholders corresponding to the hyper-parameters here, since these are best thought of as optional parameters that should have defaults. The method may have a second argument named is_training, which, if present, receives a True value when training and otherwise False.

  • verbose name: Method [Signature]
  • default value: (data)
  • port type: Port
  • value type: object (can be None)

evaluator

Optional evaluation function.

  • verbose name: Evaluator
  • default value: None
  • port type: GraphPort
  • value type: Graph

evaluator__signature

Arguments for the optional evaluation function. The job of this function is to take a dataset, a pipeline representing the method to evaluate, and to return a loss measure that shall be minimized. The default graph is simply a Placeholder named data and a GraphPlaceholder named method, which are wired into the data and method inputs of a Crossvalidation node. The default configuration of that crossvalidation is configured to run in serial using the configured settings below, and if the wired-in method graph has a Segmentation node, then it will have its trial_size parameter set to equal the time bounds of that segmentation. This function may be provided in order to have more complete control over how the nested cross-validation is performed (e.g., parallelism, repeats etc), or to replace the cross-validation process by a different evaluation strategy altogether.

  • verbose name: Evaluator [Signature]
  • default value: (data,method)
  • port type: Port
  • value type: object (can be None)

optimized

Optimally parameterized pipeline or trained model.

  • verbose name: Optimized
  • default value: None
  • port type: GraphPort
  • value type: Graph

optimal_params

Set of optimal parameters.

  • verbose name: Optimal Params
  • default value: None
  • port type: DataPort
  • value type: dict (can be None)
  • data direction: OUT

searcher

Search method. The following choices are available. For few (under 3) and relatively well-behaved regularization parameters, sampling strategies like Scrambled Hammersley go a long way, and most ML practitioners look no further. For higher- dimensional search spaces, it is typically not possible to exhaustively explore the space, and in such cases the ideal optimizer performs local search in reasonable directions with the abilty to escape local minima; the advanced optimizers are different ways of doing this given different assumptions about the objective function. Despite their sophistication, many of these optimizers require a hefty compute budget well beyond the default setting. Typically, practitioners will try a few different optimizers early on and pick the one that works best. It is not advisable to aggressively tune the choice or parameters of the optimizers in an attempt to boost the generalization error for a paper, since this will yield unreliable (artificially good) results. Choices are:

  • Hammersley Sampling: sample the search space in a regular grid; note that the grid is typically not aligned with the parameter axes, but it ensures regular spacing of sample points.
  • Scrambled Hammersley Sampling: this is essentially Hammersley with additional randomization of the grid points, which has a better chance of exploring values for individual parameters, since it will not repetitively sample the same values along a given axis.
  • Two-Points Crossover Differential Evolution: this is a variant of differential evolution that uses two points to generate a new candidate solution. It is recommended for continuous search spaces.
  • Test-Based Population Size Adaptation: performs well in noisy situations.
  • Particle-Swarm Optimization: a fairly robust optimization strategy.
  • OnePlusOne (generic): a simple and robust optimization strategy for continuous parameters. Has numerous options.
  • Covariance Matrix Adaptation (generic): a capable optimization strategy for low-noise siutations, which requires a high compute budget. Has a number of options.
  • Bayesian Optimization (generic): a classic Bayesian method, note the presence of options.
  • Differential Evolution (generic): a powerful evolutionary strategy; also features additional settings.
  • Estimation of Multivariate Normal Algorithm (generic): a fairly efficient optimizer in parallel settings (i.e., high num_procs).
  • Latin Hypercube Sampling: This is another pseudo-random sampling pattern with fairly good coverage, but which it is considerably less regular than Hammersley sampling.

  • verbose name: Search Strategy
  • default value: Hammersley Sampling
  • port type: EnumPort
  • value type: str (can be None)

budget

Number of parameter settings to evaluate. This is the main parameter that determines how long the optimization will take, and it governs how many parameter combinations will be passed to the given evaluator for evaluation. Note that the budget required to maintain a given sampling density increases exponentially with the number of parameters to optimize.

  • verbose name: Compute Budget
  • default value: 10
  • port type: IntPort
  • value type: int (can be None)

param1

Search range for parameter 1. The following formats are supported: name=[1,2,3] (list of values), name=(1...3) (continuous range), name=2**(1...3) (log-spaced continuous range).

  • verbose name: Parameter 1
  • default value: alpha=[1,2,3]
  • port type: StringPort
  • value type: str (can be None)

param2

Search range for parameter 2. See param1 for supported formats.

  • verbose name: Parameter 2
  • default value:
  • port type: StringPort
  • value type: str (can be None)

param3

Search range for parameter 3. See param1 for supported formats.

  • verbose name: Parameter 3
  • default value:
  • port type: StringPort
  • value type: str (can be None)

param4

Search range for parameter 4. See param1 for supported formats.

  • verbose name: Parameter 4
  • default value:
  • port type: StringPort
  • value type: str (can be None)

param5

Search range for parameter 5. See param1 for supported formats.

  • verbose name: Parameter 5
  • default value:
  • port type: StringPort
  • value type: str (can be None)

searcher_config

Additional configuration for the searcher. This can be used to pass additional parameters to the chosen searcher, but is rarely necessary. The searchers are part of the nevergrad package, and the documentation for the searchers can be found at https://facebookresearch.github.io/nevergrad/optimizers_ref.html.

  • verbose name: Searcher Configuration
  • default value: None
  • port type: DictPort
  • value type: dict (can be None)

enabled

Whether to enable parameter search. If disabled, the node will use the midpoint of the respective search ranges as the parameter value.

  • verbose name: Enable Search
  • default value: True
  • port type: BoolPort
  • value type: bool (can be None)

default_settings

Default settings when search is NOT enabled. Formatted like a Python dictionary, i.e., {'alpha': 10, 'beta': 0.1}. This is useful when rapidly prototyping parts of a method that requires sensible parameter values without incurring the time cost of a parameter search. Note however that this field should not be used to dial in the final parameter values and then report the resulting performance scores as if they represented the generalization error of the method, since this would be cherry-picking and falls under scientific malpractice -- unless the final parameters were determined on an entirely different dataset that one evaluates performance on, or were educated a priori guesses made well before any data was seen. Instead, when final scores (e.g., for a paper or study) are to be reported, one should leave the parameter search enabled and measure performance in this fashion.

  • verbose name: Default Settings
  • default value: {}
  • port type: DictPort
  • value type: dict (can be None)

search_metric

Scoring metric with regards to which to optimize hyper-parameters. Note that which metric is being optimized matters, and the resulting model is likely to perform better with regards to that metric than others, although typically other metrics will also generally improve as a side effect of optimizing one metric; good candidates are BAcc (balanced accuracy) or AUC (area under ROC curve) for classification methods, MSE (mean squared error) or the more robust MAE (mean absolute error) for regression pipelines. It is also possible to optimize for metrics like sensitivity or specificity in limited circumstances. See also the cross-validation node for more details.

  • verbose name: Metric To Optimize
  • default value: BAcc
  • port type: EnumPort
  • value type: str (can be None)

num_folds

Number of nested cross-validation folds for parameter search. Note that it is also possible to wire in a subgraph into the evaluator input that gives full control over the nested cross-validation setup. If so, it is recommended to set this parameter to 0 to avoid confusion over which setting is in effect. Cross-validation proceeds by splitting up the data into this many blocks of trials, and then tests the method on each block. This happens on the respective training set (e.g., of an outer cross-validation). For each fold, the method is re-trained on all the other blocks, excluding the test block. This is not a randomized cross-validation, but a blockwise cross-validation, which is usually the correct choice if the data stem from a time series. If there are few trials in the data, one can use a higher number here (e.g., 10) to ensure that more data is available for training. It is also possible to set this to 1, which means leave-one-out CV; typically this is excessive, except in conjunction with the grouping field, which causes one group (of trials that have the same group id) to be held out at a time. If a number between 0 and 1 is used, this is p-holdout cross-validation, where the respective fixed fraction of trials is held out. See also the cross-validation node for additional details and options.

  • verbose name: Number Of Cross-Validation Folds
  • default value: 5
  • port type: FloatPort
  • value type: float (can be None)

cv_cond_field

The name of the instance data field that contains the values that the method should be optimized to predict. This parameter will be ignored if the input data packet has previously been processed by a BakeDesignMatrix node.

  • verbose name: Condition Field (Cross-Validaiton)
  • default value: TargetValue
  • port type: StringPort
  • value type: str (can be None)

cv_group_field

Optionally a field indicating the group from which each trial is sourced. If given, then data will be split such that test sets contain unseen groups. Examples groups are Subject_id, Session_id, etc.

  • verbose name: Grouping Field (Cross-Validation)
  • default value:
  • port type: StringPort
  • value type: str (can be None)

cv_stratified

Optionally perform stratified cross-validation. This means that all the folds have the same relative percentage of trials with each label. Note that this requires labels to be quantized or binned to be meaningful.

  • verbose name: Stratified Cross-Validation
  • default value: False
  • port type: BoolPort
  • value type: bool (can be None)

num_procs

Number of processes to use for parallel computation. If None, the global setting NUM_PROC, which defaults to the number of CPUs on the system, will be used.

  • verbose name: Max Parallel Processes
  • default value: 1
  • port type: IntPort
  • value type: int (can be None)

num_threads_per_proc

Number of threads to use for each process. This can be used to limit the number of threads by each process to mitigate potential churn. This can be further overridden by the used evaluator.

  • verbose name: Threads Per Process
  • default value: 4
  • port type: IntPort
  • value type: int (can be None)

multiprocess_backend

Backend to use for farming out computation across multiple (CPU) processes. Multiprocessing is the simple Python default, which is not a bad start. Pebble can be more robust than multi-pprocessing and can be a useful alternative to multiprocessing if you are running out of memory after a while or if tasks otherwise appear to hang or crash unexpectedly. Serial means to not run things in parallel but instead in series (even if num_procs is >1), which can help with debugging. Threading uses Python threads in the same process, but this is not recommended for most use cases due to what is known as GIL contention.

  • verbose name: Multiprocess Backend
  • default value: multiprocessing
  • port type: EnumPort
  • value type: str (can be None)

assign_gpus

Assign GPUs for the parameter search. If enabled, the parameter search will make sure that each process gets a different GPU (potentially giving the same GPU to more than one process if there are more processes than GPUs on the system).

  • verbose name: Assign Gpus
  • default value: False
  • port type: BoolPort
  • value type: bool (can be None)

serial_if_debugger

If True, then if the Python debugger is detected, the node will run in serial mode, even if multiprocess_backend is set to something else. This is useful for debugging, since the debugger does not work well with parallel processes. This can be disabled if certain steps should nevertheless run in parallel (e.g., to reach a breakpoint more quickly).

  • verbose name: Serial If Debugger
  • default value: True
  • port type: BoolPort
  • value type: bool (can be None)

loss_if_error

Loss value to return if an error occurs during evaluation. If None, the error will be raised. This can be useful to prevent the optimization from crashing if a parameter setting causes an error, but it can also mask errors that would otherwise be caught. This value may be set to the worst-case loss according to the measure used by the evaluator (e.g., 1.0 for accuracy); potentially larger values can also be used, but note that their effect on the search process depends on the selected search method (some may be more likely to steer cleer of error-causing parameters while others might become unstable).

  • verbose name: Loss Value If Error
  • default value: None
  • port type: FloatPort
  • value type: float (can be None)

straggler_cutoff

Cutoff time for stragglers in standard deviations. If a parameter setting takes more than this many standard deviations longer than the average time, it will be discarded. This helps mitigate hangs due to bad parameter settings hat take excessively long or hangs with individual runs. In rare cases this will trim off runs that would have been useful, in which case you may increase this parameter.

  • verbose name: Long-Running Task Cutoff
  • default value: 5
  • port type: FloatPort
  • value type: float (can be None)

random_seed

Random seed (int or None). Different values will give somewhat different outcomes.

  • verbose name: Random Seed
  • default value: 12345
  • port type: IntPort
  • value type: int (can be None)

log_folder

Folder to store optimization logs. This defaults to NeuroPype's log folder. This can be useful to recover partial results if your parameter search takes very long and has to be terminated (or crashes mid-way). If you set it to empty, no logs will be stored.

  • verbose name: Log Folder
  • default value: None
  • port type: StringPort
  • value type: str (can be None)

initialize_once

Calibrate the model only once. If set to False, then this node will recalibrate itself whenever a non-streaming data chunk is received that has both training labels and associated training instances.

  • verbose name: Calibrate Only Once
  • default value: True
  • port type: BoolPort
  • value type: bool (can be None)

dont_reset_model

Do not reset the model when the preceding graph is changed. Normally, when certain parameters of preceding nodes are being changed, the model will be reset. If this is enabled, the model will persist, but there is a chance that the model is incompatible when input data format to this node has changed.

  • verbose name: Do Not Reset Model
  • default value: False
  • port type: BoolPort
  • value type: bool (can be None)

verbose

Print verbose output.

  • verbose name: Verbose
  • default value: True
  • port type: BoolPort
  • value type: bool (can be None)

set_breakpoint

Set a breakpoint on this node. If this is enabled, your debugger (if one is attached) will trigger a breakpoint.

  • verbose name: Set Breakpoint (Debug Only)
  • default value: False
  • port type: BoolPort
  • value type: bool (can be None)

metadata

User-definable meta-data associated with the node. Usually reserved for technical purposes.

  • verbose name: Metadata
  • default value: {}
  • port type: DictPort
  • value type: dict (can be None)