Skip to content

Commit

Permalink
Fix PR from FC first review
Browse files Browse the repository at this point in the history
  • Loading branch information
nghi-truyen committed Jul 31, 2024
1 parent eec16b9 commit 14af763
Show file tree
Hide file tree
Showing 13 changed files with 1,144 additions and 1,974 deletions.
4 changes: 2 additions & 2 deletions smash/_constant.py
Original file line number Diff line number Diff line change
Expand Up @@ -589,7 +589,7 @@ def get_rr_internal_fluxes_from_structure(structure: str) -> list[str]:
### OPTIMIZABLE NN PARAMETERS ###
#################################

OPTIMIZABLE_NN_PARAMETERS = ["weight_1", "bias_1", "weight_2", "bias_2"]
NN_PARAMETERS_KEYS = ["weight_1", "bias_1", "weight_2", "bias_2"]

### SETUP ###
#############
Expand Down Expand Up @@ -995,7 +995,7 @@ def get_rr_internal_fluxes_from_structure(structure: str) -> list[str]:
"atmos_data": ["mean_prcp", "mean_pet", "mean_snow", "mean_temp"],
"rr_parameters": ["keys", "values"],
"rr_initial_states": ["keys", "values"],
"nn_parameters": OPTIMIZABLE_NN_PARAMETERS,
"nn_parameters": NN_PARAMETERS_KEYS,
"serr_mu_parameters": ["keys", "values"],
"serr_sigma_parameters": ["keys", "values"],
"response": ["q"],
Expand Down
4 changes: 2 additions & 2 deletions smash/core/model/_build_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
DEFAULT_RR_PARAMETERS,
DEFAULT_SERR_MU_PARAMETERS,
DEFAULT_SERR_SIGMA_PARAMETERS,
OPTIMIZABLE_NN_PARAMETERS,
NN_PARAMETERS_KEYS,
SERR_MU_MAPPING_PARAMETERS,
SERR_SIGMA_MAPPING_PARAMETERS,
STRUCTURE_ADJUST_CI,
Expand Down Expand Up @@ -181,7 +181,7 @@ def _build_parameters(

# % Initalize weights and biases of ANN if hybrid model structure is used
if sum(setup.neurons) > 0:
for key in OPTIMIZABLE_NN_PARAMETERS:
for key in NN_PARAMETERS_KEYS:
# zero init
setattr(parameters.nn_parameters, key, 0)

Expand Down
10 changes: 7 additions & 3 deletions smash/core/model/_standardize.py
Original file line number Diff line number Diff line change
Expand Up @@ -416,7 +416,7 @@ def _standardize_model_setup_descriptor_name(descriptor_name: ListLike | None, *


def _standardize_model_setup_hidden_neuron(hidden_neuron: Numeric, **kwargs) -> int:
if isinstance(hidden_neuron, (int, float, np.number)):
if isinstance(hidden_neuron, (int, float)):
hidden_neuron = int(hidden_neuron)
if hidden_neuron <= 0:
raise ValueError("hidden_neuron model setup must be a positive number")
Expand Down Expand Up @@ -763,7 +763,9 @@ def _standardize_set_nn_parameters_weight_value(
f"from shape {arr.shape} into shape {weights[i].shape}"
)
else:
raise TypeError("Each element of value argument must be float or a Numpy array")
raise TypeError(
"Each element of value argument must be of Numeric type (int, float) or np.ndarray"
)

else:
raise TypeError("value argument must be a list of a same size with layers")
Expand Down Expand Up @@ -797,7 +799,9 @@ def _standardize_set_nn_parameters_bias_value(
f"from shape {arr.shape} into shape {biases[i].shape}"
)
else:
raise TypeError("Each element of value argument must be float or a Numpy array")
raise TypeError(
"Each element of value argument must be of Numeric type (int, float) or np.ndarray"
)

else:
raise TypeError("value argument must be a list of a same size with layers")
Expand Down
18 changes: 9 additions & 9 deletions smash/core/model/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -1145,7 +1145,7 @@ def nn_parameters(self) -> NN_ParametersDT:
>>> setup["hydrological_module"] = "gr4_mlp_alg"
>>> model = smash.Model(setup, mesh)
By default, the weights and biases of the parameterization neural network is set to zero.
By default, the weight and bias of the parameterization neural network are set to zero.
Access to their values with the getter method
`get_nn_parameters_weight <Model.get_nn_parameters_weight>` or
`get_nn_parameters_bias <Model.get_nn_parameters_bias>`
Expand Down Expand Up @@ -2394,7 +2394,7 @@ def get_nn_parameters_weight(self) -> list[NDArray[np.float32]]:
Returns
-------
value : list[`numpy.ndarray`]
A list of arrays representing the weights for each layer of the parameterization neural network.
A list of arrays representing the weights of all layers.
See Also
--------
Expand All @@ -2416,7 +2416,7 @@ def get_nn_parameters_weight(self) -> list[NDArray[np.float32]]:
>>> setup["hidden_neuron"] = 3
>>> model = smash.Model(setup, mesh)
By default, the weights of the parameterization neural network is set to zero.
By default, the weights of all layers are set to zero.
Access to their values with the getter methods
`get_nn_parameters_weight <Model.get_nn_parameters_weight>`
Expand All @@ -2440,7 +2440,7 @@ def get_nn_parameters_bias(self) -> list[NDArray[np.float32]]:
Returns
-------
value : list[`numpy.ndarray`]
A list of arrays representing the biases for each layer of the parameterization neural network.
A list of arrays representing the biases of all layers.
See Also
--------
Expand All @@ -2462,7 +2462,7 @@ def get_nn_parameters_bias(self) -> list[NDArray[np.float32]]:
>>> setup["hidden_neuron"] = 6
>>> model = smash.Model(setup, mesh)
By default, the biases of the parameterization neural network is set to zero.
By default, the biases of all layers are set to zero.
Access to their values with the getter methods
`get_nn_parameters_bias <Model.get_nn_parameters_bias>`
Expand All @@ -2486,8 +2486,8 @@ def set_nn_parameters_weight(
Parameters
----------
value : list[`float` or `numpy.ndarray`] or None, default None
The list of value(s) to set to the weights of the neural network.
If the value is a `numpy.ndarray`, its shape must be broadcastable into the weight shape.
The list of values to set to the weights of all layers. If an element of the list is
a `numpy.ndarray`, its shape must be broadcastable into the weight shape of that layer.
If not used, a default or specified initialization method will be used.
initializer : str, default 'glorot_uniform'
Expand Down Expand Up @@ -2580,8 +2580,8 @@ def set_nn_parameters_bias(
Parameters
----------
value : list[`float` or `numpy.ndarray`] or None, default None
The list of value(s) to set to the biases of the neural network.
If the value is a `numpy.ndarray`, its shape must be broadcastable into the bias shape.
The list of values to set to the biases of all layers. If an element of the list is
a `numpy.ndarray`, its shape must be broadcastable into the bias shape of that layer.
If not used, a default or specified initialization method will be used.
initializer : str, default 'zeros'
Expand Down
27 changes: 17 additions & 10 deletions smash/core/simulation/_doc.py
Original file line number Diff line number Diff line change
Expand Up @@ -1434,7 +1434,11 @@ def _gen_docstring_from_base_doc(
``'llr-slope-b'``, ``'ht-dd-a'``).
- ``<key>-<code>``: Structural error parameter where ``<key>`` is the name of any structural error mu
or sigma parameters and ``<code>``, the corresponding gauge (``'sg0-V3524010'``, ``'sg1-V3524010'``,
etc)
etc).
- ``<key>-<row>-<col>``: Weights and biases of the parameterization neural network where ``<key>``
indicates the layer and type of parameter (e.g., ``'weight_1'`` for the first layer weights,
``'bias_2'`` for the second layer biases), and ``<row>``, ``<col>`` represent the corresponding
position in the matrix or vector (``'weight_2-23-21'``, ``'bias_1-16'``, etc).
- x_bkg : `numpy.ndarray`
An array of shape *(n,)* containing the background values of the control vector.
Expand Down Expand Up @@ -1605,11 +1609,12 @@ def _gen_docstring_from_base_doc(
_smash_bayesian_optimize_doc_substitution = DocSubstitution(
model_parameter="model : `Model`\n\tPrimary data structure of the hydrological model `smash`.",
default_optimize_options_func="default_bayesian_optimize_options",
parameters_nn_parameters="",
parameters_note_nn_parameters="",
parameters_nn_parameters="- `Model.nn_parameters`, if using a hybrid structure model "
"(depending on **hydrological_module**)",
parameters_note_nn_parameters=", `Model.nn_parameters` (if used)",
parameters_serr_mu_parameters="- `Model.serr_mu_parameters`",
parameters_serr_sigma_parameters="- `Model.serr_sigma_parameters`",
parameters_note_serr_parameters=", `Model.serr_mu_parameters` and `Model.serr_sigma_parameters`",
parameters_note_serr_parameters=", `Model.serr_mu_parameters`, `Model.serr_sigma_parameters`",
bounds_get_serr_parameters_bounds=", `Model.get_serr_mu_parameters_bounds` and "
"`Model.get_serr_sigma_parameters_bounds`",
model_return="model : `Model`\n\t It returns an updated copy of the initial Model object.",
Expand All @@ -1620,11 +1625,12 @@ def _gen_docstring_from_base_doc(
_model_bayesian_optimize_doc_substitution = DocSubstitution(
model_parameter="",
default_optimize_options_func="default_bayesian_optimize_options",
parameters_nn_parameters="",
parameters_note_nn_parameters="",
parameters_nn_parameters="- `Model.nn_parameters`, if using a hybrid structure model "
"(depending on **hydrological_module**)",
parameters_note_nn_parameters=", `Model.nn_parameters` (if used)",
parameters_serr_mu_parameters="- `Model.serr_mu_parameters`",
parameters_serr_sigma_parameters="- `Model.serr_sigma_parameters`",
parameters_note_serr_parameters=", `Model.serr_mu_parameters` and `Model.serr_sigma_parameters`",
parameters_note_serr_parameters=", `Model.serr_mu_parameters`, `Model.serr_sigma_parameters`",
bounds_get_serr_parameters_bounds=", `Model.get_serr_mu_parameters_bounds` and "
"`Model.get_serr_sigma_parameters_bounds`",
model_return="",
Expand All @@ -1650,11 +1656,12 @@ def _gen_docstring_from_base_doc(
_bayesian_optimize_control_info_doc_appender = DocAppender(_bayesian_optimize_control_info_doc, indents=0)
_smash_bayesian_optimize_control_info_doc_substitution = DocSubstitution(
default_optimize_options_func="default_bayesian_optimize_options",
parameters_nn_parameters="",
parameters_note_nn_parameters="",
parameters_nn_parameters="- `Model.nn_parameters`, if using a hybrid structure model "
"(depending on **hydrological_module**)",
parameters_note_nn_parameters=", `Model.nn_parameters` (if used)",
parameters_serr_mu_parameters="- `Model.serr_mu_parameters`",
parameters_serr_sigma_parameters="- `Model.serr_sigma_parameters`",
parameters_note_serr_parameters=", `Model.serr_mu_parameters` and `Model.serr_sigma_parameters`",
parameters_note_serr_parameters=", `Model.serr_mu_parameters`, `Model.serr_sigma_parameters`",
bounds_get_serr_parameters_bounds=", `Model.get_serr_mu_parameters_bounds` and "
"`Model.get_serr_sigma_parameters_bounds`",
)
27 changes: 12 additions & 15 deletions smash/core/simulation/_standardize.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
MAPPING,
MAPPING_OPTIMIZER,
METRICS,
OPTIMIZABLE_NN_PARAMETERS,
NN_PARAMETERS_KEYS,
OPTIMIZABLE_RR_INITIAL_STATES,
OPTIMIZABLE_RR_PARAMETERS,
OPTIMIZABLE_SERR_MU_PARAMETERS,
Expand Down Expand Up @@ -146,24 +146,21 @@ def _standardize_simulation_optimize_options_parameters(
available_parameters = available_rr_parameters + available_rr_initial_states

if is_hybrid_structure:
available_parameters.extend(OPTIMIZABLE_NN_PARAMETERS)
available_parameters.extend(NN_PARAMETERS_KEYS)

if is_bayesian:
available_parameters.extend(available_serr_mu_parameters + available_serr_sigma_parameters)

if parameters is None:
default_parameters = available_rr_parameters

if is_bayesian:
parameters = np.array(
available_rr_parameters + available_serr_mu_parameters + available_serr_sigma_parameters,
ndmin=1,
)
elif (
is_hybrid_structure
): # hybrid structure is currently not working with bayes optim. TODO for later versions
parameters = np.array(available_rr_parameters + OPTIMIZABLE_NN_PARAMETERS, ndmin=1)
default_parameters += available_serr_mu_parameters + available_serr_sigma_parameters

else:
parameters = np.array(available_rr_parameters, ndmin=1)
if is_hybrid_structure:
default_parameters += NN_PARAMETERS_KEYS

parameters = np.array(default_parameters, ndmin=1)

else:
if isinstance(parameters, (str, list, tuple, np.ndarray)):
Expand Down Expand Up @@ -192,7 +189,7 @@ def _standardize_simulation_optimize_options_parameters(
def _standardize_simulation_optimize_options_bounds(
model: Model, parameters: np.ndarray, bounds: dict | None, **kwargs
) -> dict:
bounded_parameters = [p for p in parameters if p not in OPTIMIZABLE_NN_PARAMETERS]
bounded_parameters = [p for p in parameters if p not in NN_PARAMETERS_KEYS]

if bounds is None:
bounds = {}
Expand Down Expand Up @@ -1207,9 +1204,9 @@ def _standardize_simulation_optimize_options_finalize(
optimize_options["rr_initial_states_descriptor"][j, i] = 1

# % nn parameters
optimize_options["nn_parameters"] = np.zeros(shape=len(OPTIMIZABLE_NN_PARAMETERS), dtype=np.int32)
optimize_options["nn_parameters"] = np.zeros(shape=len(NN_PARAMETERS_KEYS), dtype=np.int32)

for i, key in enumerate(OPTIMIZABLE_NN_PARAMETERS):
for i, key in enumerate(NN_PARAMETERS_KEYS):
if key in optimize_options["parameters"]:
optimize_options["nn_parameters"][i] = 1

Expand Down
6 changes: 0 additions & 6 deletions smash/core/simulation/optimize/_standardize.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,12 +101,6 @@ def _standardize_bayesian_optimize_args(
) -> AnyTuple:
func_name = "bayesian_optimize"

if "mlp" in model.setup.hydrological_module:
raise ValueError(
f"Bayesian optimization method is currently not working with the hybrid model structure "
f"'{model.setup.hydrological_module}'"
)

# % In case model.set_rr_parameters or model.set_rr_initial_states were not used
_standardize_simulation_parameters_feasibility(model)

Expand Down
4 changes: 2 additions & 2 deletions smash/factory/net/_loss.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import numpy as np

from smash._constant import OPTIMIZABLE_NN_PARAMETERS
from smash._constant import NN_PARAMETERS_KEYS
from smash.fcore._mw_forward import forward_run_b as wrap_forward_run_b
from smash.fcore._mwd_parameters_manipulation import (
control_to_parameters as wrap_control_to_parameters,
Expand Down Expand Up @@ -102,7 +102,7 @@ def _hcost_prime(
grad_reg = np.reshape(grad_reg, (len(grad_reg), -1)).T

# % Get the gradient of parameterization NN if used
grad_par = [getattr(parameters_b.nn_parameters, key).copy() for key in OPTIMIZABLE_NN_PARAMETERS]
grad_par = [getattr(parameters_b.nn_parameters, key).copy() for key in NN_PARAMETERS_KEYS]

return grad_reg, grad_par

Expand Down
4 changes: 2 additions & 2 deletions smash/factory/net/net.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from typing import TYPE_CHECKING

from smash._constant import OPTIMIZABLE_NN_PARAMETERS, PY_OPTIMIZER, PY_OPTIMIZER_CLASS
from smash._constant import NN_PARAMETERS_KEYS, PY_OPTIMIZER, PY_OPTIMIZER_CLASS
from smash.factory.net._layers import Activation, Conv2D, Dense, Dropout, Flatten, Scale
from smash.factory.net._loss import _hcost, _hcost_prime, _inf_norm

Expand Down Expand Up @@ -564,7 +564,7 @@ def _fit_d2p(

# backpropagation and weights update
if epo < epochs - 1:
for i, key in enumerate(OPTIMIZABLE_NN_PARAMETERS):
for i, key in enumerate(NN_PARAMETERS_KEYS):
if key in parameters: # update trainable parameters of the parameterization NN if used
setattr(
instance.nn_parameters,
Expand Down
3 changes: 1 addition & 2 deletions smash/fcore/derived_type/mwd_optimize_options.f90
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,7 @@ subroutine Optimize_OptionsDT_initialise(this, setup)
allocate (this%rr_parameters_descriptor(setup%nd, setup%nrrp))
this%rr_parameters_descriptor = -99

!% contain 4 matrices/vectors: weight_1, bias_1, weight_2, bias_2
allocate (this%nn_parameters(4))
allocate (this%nn_parameters((size(setup%neurons) - 1)*2))
this%nn_parameters = -99

allocate (this%rr_initial_states(setup%nrrs))
Expand Down
Loading

0 comments on commit 14af763

Please sign in to comment.