.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "auto_interfaces/observer.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr_auto_interfaces_observer.py: Network Observer ================ The `rectipy.observer.Observer` can be used to record neuron state variables during numerical simulations or training/testing procedures performed with `rectipy.Network` instances. It is used by the methods `Network.run` and `Network.test`, for example, which return a `rectipy.observer.Observer` instance with state variable recordings. Using the Observer in custom scripts ------------------------------------ Here, we will demonstrate how an `Observer` instance can be used within a custom simulation of the dynamics of a network of :math:`N=5` randomly coupled QIF neurons. For a detailed introduction to the neuron model used in this example, see our documentation of the `QIF spiking neuron `_. Step 1: Network initialization ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ First, let's set up the network. .. GENERATED FROM PYTHON SOURCE LINES 22-37 .. code-block:: Python import pandas as pd import numpy as np from rectipy import Network # network parameters N = 5 J = np.random.rand(N, N) * 20.0 node = "neuron_model_templates.spiking_neurons.qif.qif" # network initialization net = Network(dt=1e-3) net.add_diffeq_node("qif", node, weights=J, source_var="s", target_var="s_in", input_var="I_ext", output_var="s", op="qif_op", spike_def="v", spike_var="spike") .. GENERATED FROM PYTHON SOURCE LINES 38-42 Step 2: Observer initialization ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Next, we need to initialize our observer. This can be done as follows: .. GENERATED FROM PYTHON SOURCE LINES 42-47 .. code-block:: Python from rectipy import Observer obs = Observer(net.dt, record_output=True, record_loss=False, record_vars=[("qif", "v", False)]) .. GENERATED FROM PYTHON SOURCE LINES 48-61 The first argument to `Observer` is the integration step-size that we will use to solve the differential equations of our network. In addition, we told the observer to record the output variable of the network via :code:`record_output=True`. In our example, this is the variable :code:`s` of the neurons in our RNN layer. However, if we were to add an output layer to the network (see `this `_ example for information on how to do that), the output of that output layer would be recorded instead. We will demonstrate this at a later stage. The :code:`record_loss` keyword argument can be toggled on, if you would like to record the loss during a training or testing procedure (see `this `_ example for details on model training). Finally, the keyword argument :code:`record_vars` serves to declare which additional state variables the observer should stage for recording. It is passed as a list, where each list entry is a separate variable to record. List entries should be passed as tuples, where the first tuple entry is the name of the network node, the second tuple entry is the name of the variable on that node, and the third entry indicates whether to record this variable for every neuron in the RNN layer, or whether to record the average of that variable across all neurons. Choosing the latter option leads to reduced memory consumption. .. GENERATED FROM PYTHON SOURCE LINES 63-68 Step 3: Perform recordings ^^^^^^^^^^^^^^^^^^^^^^^^^^ Now that we have the network and observer initialized, we can use both of them to simulate the network dynamics and record the evolution of its state variables. .. GENERATED FROM PYTHON SOURCE LINES 68-83 .. code-block:: Python import torch # define input steps = 10000 inp = torch.zeros((steps, N)) + 15.0 # compile the network net.compile() # perform numerical simulation for step in range(steps): out = net.forward(inp[step, :]) obs.record(step, output=out, loss=0.0, record_vars=[net.get_var("qif", "v")]) .. GENERATED FROM PYTHON SOURCE LINES 84-93 In that example, we recorded the network output variable :math:`s` as well as the QIF neuron state variable :math:`v` at each integration step. For the latter, we made use of the `RNNLayer.record` method which yields the current state of each of the variables passed in the list. Note that the names of the variables that have been declared as :code:`record_vars` during the initialization of the Observer are also available via the attribute :code:`obs.recorded_rnn_variables`. Thus, you could also provide the keyword argument :code:`record_vars=[net[v] for v in obs.recorded_rnn_variables]` to the :code:`Observer.record` method. After this procedure, we can visualize our recordings via the `Observer.plot` method, which allows you to either plot state variables against time or against each other. .. GENERATED FROM PYTHON SOURCE LINES 93-102 .. code-block:: Python import matplotlib.pyplot as plt obs.plot(("qif", "v")) plt.show() obs.plot(y=("qif", "v"), x="out") plt.show() .. GENERATED FROM PYTHON SOURCE LINES 103-107 Note that the network output is always available via "out", whereas additional recorded variables are available via a tuple of the name of the network node ("qif) and the name of the variable on that node ("v"). Alternatively, you can simply retrieve the recordings from the observer for subsequent analysis/plotting via your own custom scripts. To this end, you have several options: .. GENERATED FROM PYTHON SOURCE LINES 107-112 .. code-block:: Python v = obs.to_dataframe(("qif", "v")) # type: pd.DataFrame s_raw = obs["out"] # type: list s_numpy = obs.to_numpy("out") # type: np.ndarray .. GENERATED FROM PYTHON SOURCE LINES 113-126 The `Observer.to_dataframe` method returns a `pandas.DataFrame` with the recorded variable, the indexing method returns a list with the recorded `torch.Tensor` objects, and `Observer.to_numpy` returns a numpy array with the stacked results. Using the Observer in custom scripts ------------------------------------ Standard numerical simulations, model training, and model testing methods are provided by `rectipy.Network` via its methods `run`, `train`, and `test`. You will not have to bother with observer initialization and manual variable recordings if you are using these methods. Instead, you can control the behavior of the observer via keyword arguments to these methods. The keyword arguments are the same for each of these methods and we will demonstrate how to use them via the `Network.run` method. The code below performs the same simulation that we performed manually above. .. GENERATED FROM PYTHON SOURCE LINES 127-130 .. code-block:: Python obs = net.run(inputs=inp, record_vars=[("qif", "v", True)], verbose=False) .. GENERATED FROM PYTHON SOURCE LINES 131-132 As additional options, you can change the sampling step-size of your recordings: .. GENERATED FROM PYTHON SOURCE LINES 132-141 .. code-block:: Python obs2 = net.run(inputs=inp, record_vars=[("qif", "v", True)], sampling_steps=2, verbose=False) print(len(obs[("qif", "v")])) print(len(obs2[("qif", "v")])) ax = obs.plot(("qif", "v")) obs2.plot(("qif", "v"), ax=ax) plt.legend(["obs", "obs2"]) plt.show() .. GENERATED FROM PYTHON SOURCE LINES 142-146 As you can see, the second observer stored the state variable :math:`v` at only every second integration step, when :code:`sampling_steps=2` was given. You can also toggle storage of the output variable and loss on and off, using the same keyword arguments as for the observer initialization: .. GENERATED FROM PYTHON SOURCE LINES 146-148 .. code-block:: Python net.run(inputs=inp, record_output=True, record_loss=False, verbose=False) .. _sphx_glr_download_auto_interfaces_observer.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: observer.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: observer.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: observer.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_