Skip to content

Commit

Permalink
Add: noise_kwargs parameters to reservoirs to parameterize noise (#98)
Browse files Browse the repository at this point in the history
  • Loading branch information
nTrouvain committed Mar 20, 2023
1 parent 449fa06 commit 9a364b6
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 11 deletions.
13 changes: 10 additions & 3 deletions reservoirpy/nodes/reservoirs/intrinsic_plasticity.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from typing import Literal

from functools import partial
from typing import Callable, Optional, Sequence, Union
from typing import Callable, Optional, Sequence, Union, Dict

import numpy as np

Expand All @@ -18,7 +18,7 @@
from ...mat_gen import bernoulli, uniform
from ...node import Unsupervised, _init_with_sequences
from ...type import Weights
from ...utils.random import noise
from ...utils.random import noise, rand_generator
from ...utils.validation import is_array
from .base import forward_external
from .base import initialize as initialize_base
Expand Down Expand Up @@ -211,6 +211,9 @@ class IPReservoir(Unsupervised):
noise_type : str, default to "normal"
Distribution of noise. Must be a Numpy random variable generator
distribution (see :py:class:`numpy.random.Generator`).
noise_kwargs : dict, optional
Keyword arguments to pass to the noise generator, such as `low` and `high`
values of uniform distribution.
input_scaling : float or array-like of shape (features,), default to 1.0.
Input gain. An array of the same dimension as the inputs can be used to
set up different input scaling for each feature.
Expand Down Expand Up @@ -318,6 +321,7 @@ def __init__(
noise_in: float = 0.0,
noise_fb: float = 0.0,
noise_type: str = "normal",
noise_kwargs: Dict = None,
input_scaling: Union[float, Sequence] = 1.0,
bias_scaling: float = 1.0,
fb_scaling: Union[float, Sequence] = 1.0,
Expand Down Expand Up @@ -347,6 +351,9 @@ def __init__(
"appliying intrinsic plasticity."
)

rng = rand_generator(seed=seed)
noise_kwargs = dict() if noise_kwargs is None else noise_kwargs

super(IPReservoir, self).__init__(
fb_initializer=partial(
initialize_feedback,
Expand Down Expand Up @@ -387,7 +394,7 @@ def __init__(
),
"fb_activation": fb_activation,
"units": units,
"noise_generator": partial(noise, seed=seed),
"noise_generator": partial(noise, rng=rng, **noise_kwargs),
},
forward=forward_external,
initializer=partial(
Expand Down
14 changes: 11 additions & 3 deletions reservoirpy/nodes/reservoirs/reservoir.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@
from typing import Literal

from functools import partial
from typing import Callable, Optional, Sequence, Union
from typing import Callable, Optional, Sequence, Union, Dict

from ...activationsfunc import get_function, identity, tanh
from ...mat_gen import bernoulli, normal
from ...node import Node
from ...type import Weights
from ...utils.random import noise
from ...utils.random import noise, rand_generator
from ...utils.validation import is_array
from .base import forward_external, forward_internal, initialize, initialize_feedback

Expand Down Expand Up @@ -110,6 +110,9 @@ class Reservoir(Node):
noise_type : str, default to "normal"
Distribution of noise. Must be a Numpy random variable generator
distribution (see :py:class:`numpy.random.Generator`).
noise_kwargs : dict, optional
Keyword arguments to pass to the noise generator, such as `low` and `high`
values of uniform distribution.
input_scaling : float or array-like of shape (features,), default to 1.0.
Input gain. An array of the same dimension as the inputs can be used to
set up different input scaling for each feature.
Expand Down Expand Up @@ -221,6 +224,7 @@ def __init__(
noise_in: float = 0.0,
noise_fb: float = 0.0,
noise_type: str = "normal",
noise_kwargs: Dict = None,
input_scaling: Union[float, Sequence] = 1.0,
bias_scaling: float = 1.0,
fb_scaling: Union[float, Sequence] = 1.0,
Expand Down Expand Up @@ -259,6 +263,10 @@ def __init__(
if type(fb_activation) is str:
fb_activation = get_function(fb_activation)

rng = rand_generator(seed)

noise_kwargs = dict() if noise_kwargs is None else noise_kwargs

super(Reservoir, self).__init__(
fb_initializer=partial(
initialize_feedback,
Expand Down Expand Up @@ -290,7 +298,7 @@ def __init__(
"activation": activation,
"fb_activation": fb_activation,
"units": units,
"noise_generator": partial(noise, seed=seed),
"noise_generator": partial(noise, rng=rng, **noise_kwargs),
},
forward=forward,
initializer=partial(
Expand Down
35 changes: 30 additions & 5 deletions reservoirpy/nodes/tests/test_reservoir.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@


def test_reservoir_init():

node = Reservoir(100, lr=0.8, input_bias=False)

data = np.ones((1, 10))
Expand Down Expand Up @@ -38,7 +37,6 @@ def test_reservoir_init():


def test_reservoir_init_from_matrices():

Win = np.ones((100, 10))

node = Reservoir(100, lr=0.8, Win=Win, input_bias=False)
Expand Down Expand Up @@ -108,7 +106,6 @@ def test_reservoir_init_from_matrices():


def test_reservoir_bias():

node = Reservoir(100, lr=0.8, input_bias=False)

data = np.ones((1, 10))
Expand Down Expand Up @@ -169,7 +166,6 @@ def test_reservoir_run():


def test_reservoir_chain():

node1 = Reservoir(100, lr=0.8, input_bias=False)
node2 = Reservoir(50, lr=1.0, input_bias=False)

Expand All @@ -185,7 +181,6 @@ def test_reservoir_chain():


def test_reservoir_feedback():

node1 = Reservoir(100, lr=0.8, input_bias=False)
node2 = Reservoir(50, lr=1.0, input_bias=False)

Expand Down Expand Up @@ -226,3 +221,33 @@ def test_reservoir_feedback():
node1 <<= node2
data = np.ones((1, 10))
res = (node1 >> node2)(data)


def test_reservoir_noise():
node1 = Reservoir(100, seed=123, noise_rc=0.1, noise_in=0.5)
node2 = Reservoir(100, seed=123, noise_rc=0.1, noise_in=0.5)

data = np.ones((10, 10))

assert_array_equal(node1.run(data), node2.run(data))

node1 = Reservoir(
100,
seed=123,
noise_rc=0.1,
noise_in=0.5,
noise_type="uniform",
noise_kwargs={"low": -1, "high": 0.5},
)
node2 = Reservoir(
100,
seed=123,
noise_rc=0.1,
noise_in=0.5,
noise_type="uniform",
noise_kwargs={"low": -1, "high": 0.5},
)

data = np.ones((10, 10))

assert_array_equal(node1.run(data), node2.run(data))

0 comments on commit 9a364b6

Please sign in to comment.