Weight sharing for ReSuMe learning algorithm

Description of problem

I encountered a problem when using ReSuMe. I need to construct synapses from the liquid layer to the output layer and synapses from the liquid layer to the teachers layer. However, both synapses need to share the same synaptic weights. My current idea is to use the shared variable in Brian2, but the code will report an error.

Minimal code to reproduce problem

S_liquid_to_output = Synapses(neurons_liquid, neurons_output,
                              '''w_final : 1 (shared)
                                    dAl/dt = -Al / taul : 1 (event-driven)''',
                              on_pre='''ge += w_final
                                     Al -= dAl''',
                              on_post='''
                                      w_final = clip(w_final - Al, 0, gmax)''')
S_liquid_to_output.connect()  
S_liquid_to_output.w_final = 'rand() * gmax'  

S_liquid_to_teachers = Synapses(neurons_liquid, neurons_teachers,
                                '''w_final : 1 (shared)
                                      dAd/dt = -Ad / taud : 1 (event-driven)''',
                                on_pre='''
                                       Ad += dAd''',
                                on_post='''
                                        w_final = clip(w_final + Ad, 0, gmax)''')
S_liquid_to_teachers.connect()  

Full traceback of error (if relevant)

ERROR      Brian 2 encountered an unexpected error. If you think this is a bug in Brian 2, please report this issue either to the discourse forum at <http://brian.discourse.group/>, or to the issue tracker at <https://github.com/brian-team/brian2/issues>. Please include this file with debug information in your report: C:\Users\52493\AppData\Local\Temp\brian_debug_s2xh9fd8.log  Additionally, you can also include a copy of the script that was run, available at: C:\Users\52493\AppData\Local\Temp\brian_script_rctgtqud.py Thanks! [brian2]
Traceback (most recent call last):
  File "D:\Code\LSM\Brian\LSM_brain2\.venv\Lib\site-packages\brian2\core\network.py", line 1002, in before_run
    obj.before_run(run_namespace)
  File "D:\Code\LSM\Brian\LSM_brain2\.venv\Lib\site-packages\brian2\core\base.py", line 335, in device_override_decorated_function
    return func(*args, **kwds)
           ^^^^^^^^^^^^^^^^^^^
  File "D:\Code\LSM\Brian\LSM_brain2\.venv\Lib\site-packages\brian2\synapses\synapses.py", line 366, in before_run
    super().before_run(run_namespace)
  File "D:\Code\LSM\Brian\LSM_brain2\.venv\Lib\site-packages\brian2\groups\group.py", line 1266, in before_run
    self.create_code_objects(run_namespace)
  File "D:\Code\LSM\Brian\LSM_brain2\.venv\Lib\site-packages\brian2\synapses\synapses.py", line 394, in create_code_objects
    weakref.proxy(self.create_default_code_object(run_namespace)),
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\Code\LSM\Brian\LSM_brain2\.venv\Lib\site-packages\brian2\groups\group.py", line 1240, in create_default_code_object
    self.codeobj = create_runner_codeobj(
                   ^^^^^^^^^^^^^^^^^^^^^^
  File "D:\Code\LSM\Brian\LSM_brain2\.venv\Lib\site-packages\brian2\codegen\codeobject.py", line 378, in create_runner_codeobj
    _, uk, u = analyse_identifiers(v, all_variables, recursive=True)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\Code\LSM\Brian\LSM_brain2\.venv\Lib\site-packages\brian2\codegen\translation.py", line 97, in analyse_identifiers
    scalar_stmts, vector_stmts = make_statements(
                                 ^^^^^^^^^^^^^^^^
  File "D:\Code\LSM\Brian\LSM_brain2\.venv\Lib\site-packages\brian2\utils\caching.py", line 107, in cached_func
    func._cache[cache_key] = func(*args, **kwds)
                             ^^^^^^^^^^^^^^^^^^^
  File "D:\Code\LSM\Brian\LSM_brain2\.venv\Lib\site-packages\brian2\codegen\translation.py", line 319, in make_statements
    raise SyntaxError(
SyntaxError: All writes to scalar variables in a code block have to be made before writes to vector variables. Illegal write to 'w_final'.

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "D:\Code\LSM\Brian\LSM_brain2\ReSuMe.py", line 130, in <module>
    run(run_time)  # èź­ç»ƒçœ‘ç»œ
    ^^^^^^^^^^^^^
  File "D:\Code\LSM\Brian\LSM_brain2\.venv\Lib\site-packages\brian2\units\fundamentalunits.py", line 2652, in new_f
    result = f(*args, **kwds)
             ^^^^^^^^^^^^^^^^
  File "D:\Code\LSM\Brian\LSM_brain2\.venv\Lib\site-packages\brian2\core\magic.py", line 407, in run
    return magic_network.run(
           ^^^^^^^^^^^^^^^^^^
  File "D:\Code\LSM\Brian\LSM_brain2\.venv\Lib\site-packages\brian2\core\magic.py", line 248, in run
    Network.run(
  File "D:\Code\LSM\Brian\LSM_brain2\.venv\Lib\site-packages\brian2\core\base.py", line 335, in device_override_decorated_function
    return func(*args, **kwds)
           ^^^^^^^^^^^^^^^^^^^
  File "D:\Code\LSM\Brian\LSM_brain2\.venv\Lib\site-packages\brian2\units\fundamentalunits.py", line 2652, in new_f
    result = f(*args, **kwds)
             ^^^^^^^^^^^^^^^^
  File "D:\Code\LSM\Brian\LSM_brain2\.venv\Lib\site-packages\brian2\core\network.py", line 1138, in run
    self.before_run(namespace)
  File "D:\Code\LSM\Brian\LSM_brain2\.venv\Lib\site-packages\brian2\core\base.py", line 335, in device_override_decorated_function
    return func(*args, **kwds)
           ^^^^^^^^^^^^^^^^^^^
  File "D:\Code\LSM\Brian\LSM_brain2\.venv\Lib\site-packages\brian2\core\network.py", line 1004, in before_run
    raise BrianObjectException(
brian2.core.base.BrianObjectException: Error encountered with object named 'synapses_2_post'.
Object was created here (most recent call only, full details in debug log):
  File 'D:\Code\LSM\Brian\LSM_brain2\ReSuMe.py', line 87, in <module>
    S_liquid_to_output = Synapses(neurons_liquid, neurons_output,

An error occurred when preparing an object. (See above for original error message and traceback.)

Hi @jrsydtm. Brian’s syntax and features were originally developed for biological neural networks, where the concept of sharing weights does not really apply. It therefore doesn’t support this as a built-in feature. The shared flag that you used in your code means that a value is shared between all synapses of a single Synapses object. You cannot update them in statements that only apply to single synapses (such as on_post), you therefore get an error. But as I explained above, even if this worked it wouldn’t do what you want it to do.

The good news is that – assuming that both Synapses have the same number of synapses – you can use a low-level mechanism in Brian to make one of the two w_final variables a “pointer” to the other variable. In your code, this would look like this:

S_liquid_to_output = Synapses(neurons_liquid, neurons_output,
                              '''w_final : 1
                                    dAl/dt = -Al / taul : 1 (event-driven)''',
                              on_pre='''ge += w_final
                                     Al -= dAl''',
                              on_post='''
                                      w_final = clip(w_final - Al, 0, gmax)''')
S_liquid_to_output.connect()  
S_liquid_to_output.w_final = 'rand() * gmax'  

S_liquid_to_teachers = Synapses(neurons_liquid, neurons_teachers,
                                '''# no w_final in the equations
                                      dAd/dt = -Ad / taud : 1 (event-driven)''',
                                on_pre='''
                                       Ad += dAd''',
                                on_post='''
                                        w_final = clip(w_final + Ad, 0, gmax)''')
S_liquid_to_teachers.connect()  
# Add w_final to S_liquid_to_teachers, by pointing it to the variable of S_liquid_to_output
 S_liquid_to_teachers.variables.add_reference("w_final", S_liquid_to_output, "w_final")

Hope that works for you!

PS: Note that code becomes more readable if you include it in triple backticks like this:

```
# a comment
print("This is Python code")
```

I edited your post in that way.

1 Like