smash.backward_run#
- smash.backward_run(model, diff_target='j', cotangent=None, mapping='uniform', optimizer=None, optimize_options=None, cost_options=None, common_options=None, return_options=None)[source]#
Run the backward Model.
Let us define the models \(y = A(x)\), \(z = B(y)\), and their composition \(C = B \circ A\).
The backward run of model \(A\) returns
\[\bar{x} = \left(\frac{\partial y}{\partial x}\right)^T \bar{y},\]where \(\bar{y}\) is the cotangent vector associated with the output \(y\) of model \(A\).
For model \(B\), the cotangent vector is propagated according to
\[\bar{y} = \left(\frac{\partial z}{\partial y}\right)^T \bar{z},\]where \(\bar{z}\) is the cotangent vector associated with the output \(z\) of model \(B\).
The cotangent vector represents the sensitivity of a model’s output with respect to a quantity of interest. For an output \(y\), the corresponding cotangent vector, denoted \(\bar{y}\), describes how a small variation of \(y\) affects the quantity being differentiated. \(\bar{y}\) is the information received by model \(A\) from the subsequent part of the computation, and \(\bar{x}\) is the corresponding sensitivity propagated back to its input \(x\).
In reverse mode, the backward runs are applied in the reverse order of the forward computation. Starting from the cotangent vector \(\bar{z}\) of the output of model \(B\), it is first propagated backward through \(B\), producing the cotangent \(\bar{y}\) associated with \(y\). This cotangent can then be passed to the backward run of \(A\). The cotangent vector therefore provides the mechanism for coupling models \(A\) and \(B\) and computing the gradient of the composed model \(C\). Combining the two steps gives
\[\bar{x} = \left(\frac{\partial y}{\partial x}\right)^T \left(\frac{\partial z}{\partial y}\right)^T \bar{z} = \left(\frac{\partial z}{\partial x}\right)^T \bar{z}.\]- Parameters:
- model
Model Primary data structure of the hydrological model
smash.- diff_targetstr, default ‘j’
Differentiation target. Should be one of
'j'(cost function)'q'(discharge)
- cotangentfloat,
numpy.ndarrayor None, default None Cotangent vector associated with the differentiation target.
Note
If not given, the cotangent is set to 1 for a scalar differentiation target (
'j') or to an array of ones with the same shape as the target for a non-scalar differentiation target ('q'). The expected shape for the differentiation target'q'is (mesh.nac,setup.ntime_step)- mappingstr, default ‘uniform’
Type of mapping. Should be one of
'uniform''distributed''multi-linear''multi-power''ann'
Hint
See the Mapping section.
- optimizerstr or None, default None
Name of optimizer. Should be one of
'sbs'(only for'uniform'mapping)'nelder-mead'(only for'uniform'mapping)'powell'(only for'uniform'mapping)'lbfgsb'(for all mappings except'ann')'adam'(for all mappings)'adagrad'(for all mappings)'rmsprop'(for all mappings)'sgd'(for all mappings)
Note
If not given, a default optimizer will be set as follows:
'sbs'for mapping ='uniform''lbfgsb'for mapping ='distributed','multi-linear','multi-power''adam'for mapping ='ann'
Hint
See the Optimization Algorithms section.
- optimize_optionsdict[str, Any] or None, default None
Dictionary containing optimization options for fine-tuning the optimization process. See
default_optimize_optionsto retrieve the default optimize options based on the mapping and optimizer.- parametersstr, list[str, …] or None, default None
Name of parameters to optimize. Should be one or a sequence of any key of:
Model.nn_parameters, if using a hybrid model structure (depending on hydrological_module)
>>> optimize_options = { "parameters": "cp", } >>> optimize_options = { "parameters": ["cp", "ct", "kexc", "llr"], }
Note
- If not given, all parameters in
Model.rr_parameters,Model.nn_parameters(if used) will be optimized.
- boundsdict[str, tuple[float, float]] or None, default None
Bounds on optimized parameters. A dictionary where the keys represent parameter names, and the values are pairs of
(min, max)values (i.e., a list or tuple) withminlower thanmax. The keys must be included in parameters.>>> optimize_options = { "bounds": { "cp": (1, 2000), "ct": (1, 1000), "kexc": (-10, 5) "llr": (1, 1000) }, }
Note
If not given, default bounds will be applied to each parameter. See
Model.get_rr_parameters_bounds,Model.get_rr_initial_states_bounds- control_tfmstr or None, default None
Transformation method applied to bounded parameters of the control vector. Should be one of
'keep''normalize''sbs'('sbs'optimizer only)
Note
If not given, the default control vector transformation is control_tfm =
'normalize'except for the'sbs'optimizer, where control_tfm ='sbs'. This options is not used when mapping is'ann'.- descriptordict[str, list[str, …]] or None, default None
Descriptors linked to optimized parameters. A dictionary where the keys represent parameter names, and the values are list of descriptor names. The keys must be included in parameters.
>>> optimize_options = { "descriptor": { "cp": ["slope", "dd"], "ct": ["slope"], "kexc": ["slope", "dd"], "llr": ["dd"], }, }
Note
If not given, all descriptors will be used for each parameter. This option is only be used when mapping is
'multi-linear'or'multi-power'. In case of'ann', all descriptors will be used.- net
Netor None, default None The regionalization neural network used to learn the descriptors-to-parameters mapping.
Note
If not given, a default neural network will be used. This option is only used when mapping is
'ann'. SeeNetto learn how to create a customized neural network for training.- learning_ratefloat or None, default None
The learning rate used for updating trainable parameters when using adaptive optimizers (i.e.,
'adam','adagrad','rmsprop','sgd').Note
If not given, a default learning rate for each optimizer will be used.
- random_stateint or None, default None
A random seed used to initialize neural network parameters.
Note
If not given, the neural network parameters will be initialized with a random seed. This options is only used when mapping is
'ann', and the weights and biases of net are not yet initialized.- termination_critdict[str, Any] or None, default None
Termination criteria. The elements are:
'maxiter': The maximum number of iterations.'xatol': Absolute error in solution parameters between iterations that is acceptable for convergence. Only used when optimizer is'nelder-mead'.'fatol': Absolute error in cost function value between iterations that is acceptable for convergence. Only used when optimizer is'nelder-mead'.'factr': An additional termination criterion based on cost values. Only used when optimizer is'lbfgsb'.'pgtol': An additional termination criterion based on the projected gradient of the cost function. Only used when optimizer is'lbfgsb'.'early_stopping': A positive number to stop training when the cost function does not decrease below the current optimal value for early_stopping consecutive iterations. When set to zero, early stopping is disabled, and the training continues for the full number of iterations. Only used for adaptive optimizers (i.e.,'adam','adagrad','rmsprop','sgd').
>>> optimize_options = { "termination_crit": { "maxiter": 10, "factr": 1e6, }, } >>> optimize_options = { "termination_crit": { "maxiter": 200, "early_stopping": 20, }, }
Note
If not given, default values are set to each elements.
- cost_optionsdict[str, Any] or None, default None
Dictionary containing computation cost options for simulated and observed responses. The elements are:
- jobs_cmptstr or list[str, …], default ‘nse’
Type of observation objective function(s) to be computed. Should be one or a sequence of any of
'nse','nnse','kge','mae','mape','mse','rmse','lgrm'(classical evaluation metrics)'Crc','Crchf','Crclf','Crch2r','Cfp2','Cfp10','Cfp50','Cfp90'(continuous signatures-based error metrics)'Eff','Ebf','Erc','Erchf','Erclf','Erch2r','Elt','Epf'(flood event signatures-based error metrics)
>>> cost_options = { "jobs_cmpt": "nse", } >>> cost_options = { "jobs_cmpt": ["nse", "Epf"], }
Hint
See the Efficiency & Error Metric and Hydrological Signature sections
- wjobs_cmptstr or list[float, …], default ‘mean’
The corresponding weighting of observation objective functions in case of multi-criteria (i.e., a sequence of objective functions to compute). There are two ways to specify it:
An alias among
'mean'A sequence of value whose size must be equal to the number of observation objective function(s) in jobs_cmpt
>>> cost_options = { "wjobs_cmpt": "mean", } >>> cost_options = { "wjobs_cmpt": [0.7, 0.3], }
- jobs_cmpt_tfmstr or list[str, …], default ‘keep’
Type of transformation applied to discharge in observation objective function(s). Should be one or a sequence of any of
'keep': No transformation \(f:x \rightarrow x\)'sqrt': Square root transformation \(f:x \rightarrow \sqrt{x}\)'inv': Multiplicative inverse transformation \(f:x \rightarrow \frac{1}{x}\)
>>> cost_options = { "jobs_cmpt_tfm": "inv", } >>> cost_options = { "jobs_cmpt_tfm": ["keep", "inv"], }
Note
If jobs_cmpt is a list of multi-objective functions, and only one transformation is chosen in jobs_cmpt_tfm, the transformation will be applied to each observation objective function.
- end_warmupstr,
pandas.Timestampor None, default None The end of the warm-up period, which must be between the start time and the end time defined in
Model.setup.>>> cost_options = { "end_warmup": "1997-12-21", } >>> cost_options = { "end_warmup": pd.Timestamp("19971221"), }
Note
If not given, it is set to be equal to the
Model.setupstart time.- gaugestr or list[str, …], default ‘dws’
Type of gauge to be computed. There are two ways to specify it:
An alias among
'all'(all gauge codes) or'dws'(most downstream gauge code(s))A gauge code or any sequence of gauge codes. The gauge code(s) given must belong to the gauge codes defined in the
Model.mesh
>>> cost_options = { "gauge": "dws", } >>> cost_options = { "gauge": "V3524010", } >>> cost_options = { "gauge": ["V3524010", "V3515010"], }
- wgaugestr or list[float, …] default ‘mean’
Type of gauge weights. There are two ways to specify it:
An alias among
'mean','lquartile'(1st quantile or lower quantile),'median', or'uquartile'(3rd quantile or upper quantile)A sequence of value whose size must be equal to the number of gauges optimized in gauge
>>> cost_options = { "wgauge": "mean", } >>> cost_options = { "wgauge": [0.6, 0.4]", }
- event_segdict[str, float], default {‘peak_quant’: 0.995, ‘peak_value’: 0, ‘max_duration’: 240}
A dictionary of event segmentation options when calculating flood event signatures for cost computation (i.e., jobs_cmpt includes flood events signatures).
>>> cost_options = { "event_seg": { "peak_quant": 0.998, "max_duration": 120, } }
Hint
See the
hydrograph_segmentationfunction and Hydrograph Segmentation section.
- common_optionsdict[str, Any] or None, default None
Dictionary containing common options with two elements:
- ncpuint, default 1
Number of CPU(s) to perform a parallel computation.
Warning
Parallel computation is not supported on
Windows.- verbosebool, default False
Whether to display information about the running method.
- return_optionsdict[str, Any] or None, default None
Dictionary containing return options to save additional simulation results. The elements are:
- time_stepstr,
pandas.Timestamp,pandas.DatetimeIndexor list[str, …], default ‘all’ Returned time steps. There are five ways to specify it:
An alias among
'all'(return all time steps).A date as string which respect
pandas.TimestampformatA sequence of dates as strings.
>>> return_options = { "time_step": "all", } >>> return_options = { "time_step": "1997-12-21", } >>> return_options = { "time_step": pd.Timestamp("19971221"), } >>> return_options = { "time_step": pd.date_range( start="1997-12-21", end="1998-12-21", freq="1D" ), } >>> return_options = { "time_step": ["1998-05-23", "1998-05-24", "1998-05-25"], }
Note
It only applies to the following variables:
'rr_states'and'q_domain'- rr_statesbool, default False
Whether to return rainfall-runoff states for specific time steps.
- q_domainbool, default False
Whether to return simulated discharge on the whole domain for specific time steps.
- internal_fluxesbool, default False
Whether to return internal fluxes depending on the model structure on the whole domain for specific time steps.
- costbool, default False
Whether to return cost value.
- jobsbool, default False
Whether to return jobs (observation component of cost) value.
- gradbool, default False
Whether to return gradient value.
- time_stepstr,
- model
- Returns:
- model
Model It returns an updated copy of the initial Model object.
- backward_run
BackwardRunor None, default None It returns an object containing additional simulation results with the keys defined in return_options. If no keys are defined, it returns None.
- model
See also
BackwardRunRepresents backward run optional results.
Examples
>>> from smash.factory import load_dataset >>> setup, mesh = load_dataset("cance") >>> model = smash.Model(setup, mesh)
Run the inverse Model
>>> model_bwd, ret_bwd = smash.backward_run(return_options={"grad": True}) </> Backward Run
Get the control info to retrieve the parameter names
>>> control_info = smash.optimize_control_info(model)
Get the gradient values
>>> {str(name): float(grad) for name, grad in zip(control_info["name"], ret_bwd.grad)} { 'cp-0': 0.5914902091026306, 'ct-0': 0.5672875046730042, 'kexc-0': -0.01872028410434723, 'llr-0': -4.1801460611168295e-05 }