From a33ca0dc26d0a4b1182c5e51d33ef6f816a8c7be Mon Sep 17 00:00:00 2001 From: Willian-Girao Date: Fri, 31 May 2024 16:51:00 +0200 Subject: [PATCH] removed folder with algo. exploration simulations --- .../DynapcnnNetwork-example_1.ipynb | 597 --- .../DynapcnnNetwork-example_2.ipynb | 396 -- .../DynapcnnNetwork-example_3.ipynb | 402 -- .../DynapcnnNetwork-example_4.ipynb | 380 -- .../DynapcnnNetwork-example_5.ipynb | 400 -- .../DynapcnnNetwork-example_5a.ipynb | 390 -- .../DynapcnnNetwork-example_6.ipynb | 422 -- .../complex_network_structure.ipynb | 337 -- .../split_and_merge.ipynb | 359 -- .../two_networks_merging_outputs.ipynb | 378 -- .../DynapcnnNetwork-example_1.ipynb | 679 --- tests/test_nonsequential/NNI-test/main.ipynb | 136 - tests/test_nonsequential/NNI-test/model.py | 175 - .../baseline-SCNN-example_1-NNI.ipynb | 613 --- .../baseline-SCNN-example_2.ipynb | 630 --- .../baseline-SCNN-example_3.ipynb | 1500 ------ .../exp_set_A/baseline-SCNN-example_3.ipynb | 1500 ------ .../non-sequential-SCNN-example_3.ipynb | 1509 ------ .../exp_set_B/baseline-SCNN-example_3.ipynb | 1512 ------ .../baseline_exp_set_B_training_metrics.npy | Bin 172944 -> 0 bytes .../non-sequential-SCNN-example_3.ipynb | 1521 ------ .../exp_set_B1/baseline-SCNN-example_3.ipynb | 1071 ---- .../non-sequential-SCNN-example_3.ipynb | 1509 ------ .../exp_set_TA1/main_loop.py | 5 - .../exp_set_TA1/nonseq_conv1_weights.pth | Bin 1693 -> 0 bytes .../exp_set_TA1/nonseq_conv2_weights.pth | Bin 2973 -> 0 bytes .../exp_set_TA1/nonseq_conv3_weights.pth | Bin 4957 -> 0 bytes .../exp_set_TA1/nonseq_fc2_weights.pth | Bin 41299 -> 0 bytes .../exp_set_TA1/nonseq_fc3_weights.pth | Bin 41299 -> 0 bytes .../exp_set_TA1/nonseq_model.py | 117 - .../exp_set_TA1/train_script.py | 152 - .../non-sequential-SCNN-example_1.ipynb | 649 --- .../non-sequential-SCNN-example_2.ipynb | 639 --- .../non-sequential-SCNN-example_3.ipynb | 1509 ------ .../transfer-learning/baseline-SCNN-3.ipynb | 525 -- .../transfer-learning/seq_model.py | 86 - .../baseline-SCNN-example_3-SumPool.ipynb | 1539 ------ .../exp_set_A/baseline-SCNN-example_3.ipynb | 1500 ------ .../ARCHITECTURES_SEARCH/Res-SCNN3.ipynb | 1380 ----- .../architectures_results.ipynb | 306 -- .../ARCHITECTURES_SEARCH/main.py | 136 - .../ARCHITECTURES_SEARCH/model_training.py | 92 - .../single_training.ipynb | 4716 ----------------- .../ARCHITECTURES_SEARCH/train_all.py | 4 - .../HPO_GAUSSIAN_SEARCH/GS_utils.py | 54 - .../gaussian_search_history.csv | 57 - .../HPO_GAUSSIAN_SEARCH/main.py | 202 - .../HPO_GAUSSIAN_SEARCH/network.py | 83 - .../using_SumPool2d/Res-SCNN3.ipynb | 1509 ------ .../TOP_2_ARCHITECTURES/single_training.ipynb | 3837 -------------- .../using_SumPool2d/models/ResSCNN_1.py | 152 - .../using_SumPool2d/models/ResSCNN_10.py | 121 - .../using_SumPool2d/models/ResSCNN_11.py | 112 - .../using_SumPool2d/models/ResSCNN_12.py | 91 - .../using_SumPool2d/models/ResSCNN_13.py | 96 - .../using_SumPool2d/models/ResSCNN_2.py | 148 - .../using_SumPool2d/models/ResSCNN_3.py | 151 - .../using_SumPool2d/models/ResSCNN_4.py | 154 - .../using_SumPool2d/models/ResSCNN_5.py | 143 - .../using_SumPool2d/models/ResSCNN_6.py | 146 - .../using_SumPool2d/models/ResSCNN_7.py | 146 - .../using_SumPool2d/models/ResSCNN_8.py | 151 - .../using_SumPool2d/models/ResSCNN_9.py | 124 - .../using_SumPool2d/models/SCNN.py | 130 - .../test_nonsequential/utils/train_test_fn.py | 274 - .../utils/weight_initialization.py | 49 - 66 files changed, 37701 deletions(-) delete mode 100644 tests/test_nonsequential/DYNAPCNNNETWORK_EXAMPLES/DynapcnnNetwork-example_1.ipynb delete mode 100644 tests/test_nonsequential/DYNAPCNNNETWORK_EXAMPLES/DynapcnnNetwork-example_2.ipynb delete mode 100644 tests/test_nonsequential/DYNAPCNNNETWORK_EXAMPLES/DynapcnnNetwork-example_3.ipynb delete mode 100644 tests/test_nonsequential/DYNAPCNNNETWORK_EXAMPLES/DynapcnnNetwork-example_4.ipynb delete mode 100644 tests/test_nonsequential/DYNAPCNNNETWORK_EXAMPLES/DynapcnnNetwork-example_5.ipynb delete mode 100644 tests/test_nonsequential/DYNAPCNNNETWORK_EXAMPLES/DynapcnnNetwork-example_5a.ipynb delete mode 100644 tests/test_nonsequential/DYNAPCNNNETWORK_EXAMPLES/DynapcnnNetwork-example_6.ipynb delete mode 100644 tests/test_nonsequential/DYNAPCNNNETWORK_EXAMPLES/complex_network_structure.ipynb delete mode 100644 tests/test_nonsequential/DYNAPCNNNETWORK_EXAMPLES/split_and_merge.ipynb delete mode 100644 tests/test_nonsequential/DYNAPCNNNETWORK_EXAMPLES/two_networks_merging_outputs.ipynb delete mode 100644 tests/test_nonsequential/DynapcnnNetwork-example_1.ipynb delete mode 100644 tests/test_nonsequential/NNI-test/main.ipynb delete mode 100644 tests/test_nonsequential/NNI-test/model.py delete mode 100644 tests/test_nonsequential/baseline-SCNN-example_1-NNI.ipynb delete mode 100644 tests/test_nonsequential/baseline-SCNN-example_2.ipynb delete mode 100644 tests/test_nonsequential/baseline-SCNN-example_3.ipynb delete mode 100644 tests/test_nonsequential/exp_set_A/baseline-SCNN-example_3.ipynb delete mode 100644 tests/test_nonsequential/exp_set_A/non-sequential-SCNN-example_3.ipynb delete mode 100644 tests/test_nonsequential/exp_set_B/baseline-SCNN-example_3.ipynb delete mode 100644 tests/test_nonsequential/exp_set_B/baseline_exp_set_B_training_metrics.npy delete mode 100644 tests/test_nonsequential/exp_set_B/non-sequential-SCNN-example_3.ipynb delete mode 100644 tests/test_nonsequential/exp_set_B1/baseline-SCNN-example_3.ipynb delete mode 100644 tests/test_nonsequential/exp_set_B1/non-sequential-SCNN-example_3.ipynb delete mode 100644 tests/test_nonsequential/exp_set_TA1/main_loop.py delete mode 100644 tests/test_nonsequential/exp_set_TA1/nonseq_conv1_weights.pth delete mode 100644 tests/test_nonsequential/exp_set_TA1/nonseq_conv2_weights.pth delete mode 100644 tests/test_nonsequential/exp_set_TA1/nonseq_conv3_weights.pth delete mode 100644 tests/test_nonsequential/exp_set_TA1/nonseq_fc2_weights.pth delete mode 100644 tests/test_nonsequential/exp_set_TA1/nonseq_fc3_weights.pth delete mode 100644 tests/test_nonsequential/exp_set_TA1/nonseq_model.py delete mode 100644 tests/test_nonsequential/exp_set_TA1/train_script.py delete mode 100644 tests/test_nonsequential/non-sequential-SCNN-example_1.ipynb delete mode 100644 tests/test_nonsequential/non-sequential-SCNN-example_2.ipynb delete mode 100644 tests/test_nonsequential/non-sequential-SCNN-example_3.ipynb delete mode 100644 tests/test_nonsequential/transfer-learning/baseline-SCNN-3.ipynb delete mode 100644 tests/test_nonsequential/transfer-learning/seq_model.py delete mode 100644 tests/test_nonsequential/using_AvgPool2d/exp_set_A/baseline-SCNN-example_3-SumPool.ipynb delete mode 100644 tests/test_nonsequential/using_AvgPool2d/exp_set_A/baseline-SCNN-example_3.ipynb delete mode 100644 tests/test_nonsequential/using_SumPool2d/ARCHITECTURES_SEARCH/Res-SCNN3.ipynb delete mode 100644 tests/test_nonsequential/using_SumPool2d/ARCHITECTURES_SEARCH/architectures_results.ipynb delete mode 100644 tests/test_nonsequential/using_SumPool2d/ARCHITECTURES_SEARCH/main.py delete mode 100644 tests/test_nonsequential/using_SumPool2d/ARCHITECTURES_SEARCH/model_training.py delete mode 100644 tests/test_nonsequential/using_SumPool2d/ARCHITECTURES_SEARCH/single_training.ipynb delete mode 100644 tests/test_nonsequential/using_SumPool2d/ARCHITECTURES_SEARCH/train_all.py delete mode 100644 tests/test_nonsequential/using_SumPool2d/HPO_GAUSSIAN_SEARCH/GS_utils.py delete mode 100644 tests/test_nonsequential/using_SumPool2d/HPO_GAUSSIAN_SEARCH/gaussian_search_history.csv delete mode 100644 tests/test_nonsequential/using_SumPool2d/HPO_GAUSSIAN_SEARCH/main.py delete mode 100644 tests/test_nonsequential/using_SumPool2d/HPO_GAUSSIAN_SEARCH/network.py delete mode 100644 tests/test_nonsequential/using_SumPool2d/Res-SCNN3.ipynb delete mode 100644 tests/test_nonsequential/using_SumPool2d/TOP_2_ARCHITECTURES/single_training.ipynb delete mode 100644 tests/test_nonsequential/using_SumPool2d/models/ResSCNN_1.py delete mode 100644 tests/test_nonsequential/using_SumPool2d/models/ResSCNN_10.py delete mode 100644 tests/test_nonsequential/using_SumPool2d/models/ResSCNN_11.py delete mode 100644 tests/test_nonsequential/using_SumPool2d/models/ResSCNN_12.py delete mode 100644 tests/test_nonsequential/using_SumPool2d/models/ResSCNN_13.py delete mode 100644 tests/test_nonsequential/using_SumPool2d/models/ResSCNN_2.py delete mode 100644 tests/test_nonsequential/using_SumPool2d/models/ResSCNN_3.py delete mode 100644 tests/test_nonsequential/using_SumPool2d/models/ResSCNN_4.py delete mode 100644 tests/test_nonsequential/using_SumPool2d/models/ResSCNN_5.py delete mode 100644 tests/test_nonsequential/using_SumPool2d/models/ResSCNN_6.py delete mode 100644 tests/test_nonsequential/using_SumPool2d/models/ResSCNN_7.py delete mode 100644 tests/test_nonsequential/using_SumPool2d/models/ResSCNN_8.py delete mode 100644 tests/test_nonsequential/using_SumPool2d/models/ResSCNN_9.py delete mode 100644 tests/test_nonsequential/using_SumPool2d/models/SCNN.py delete mode 100644 tests/test_nonsequential/utils/train_test_fn.py delete mode 100644 tests/test_nonsequential/utils/weight_initialization.py diff --git a/tests/test_nonsequential/DYNAPCNNNETWORK_EXAMPLES/DynapcnnNetwork-example_1.ipynb b/tests/test_nonsequential/DYNAPCNNNETWORK_EXAMPLES/DynapcnnNetwork-example_1.ipynb deleted file mode 100644 index c4a3c8b7..00000000 --- a/tests/test_nonsequential/DYNAPCNNNETWORK_EXAMPLES/DynapcnnNetwork-example_1.ipynb +++ /dev/null @@ -1,597 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": { - "metadata": {} - }, - "outputs": [], - "source": [ - "import torch\n", - "import torch.nn as nn\n", - "from sinabs.backend.dynapcnn import DynapcnnNetwork\n", - "from sinabs.layers import Merge, IAFSqueeze, SumPool2d\n", - "from sinabs.activation.surrogate_gradient_fn import PeriodicExponential" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": { - "metadata": {} - }, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "torch.manual_seed(0)" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": { - "metadata": {} - }, - "outputs": [], - "source": [ - "channels = 2\n", - "height = 34\n", - "width = 34\n", - "batch_size = 8\n", - "\n", - "input_shape = (channels, height, width)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Network Module\n", - "\n", - "We need to define a `nn.Module` implementing the network we want the chip to reproduce." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": { - "metadata": {} - }, - "outputs": [], - "source": [ - "class SNN(nn.Module):\n", - " def __init__(self) -> None:\n", - " super().__init__()\n", - "\n", - " self.conv1 = nn.Conv2d(2, 10, 2, 1, bias=False) # node 0\n", - " self.iaf1 = IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, spike_threshold=1.0, surrogate_grad_fn=PeriodicExponential()) # node 1\n", - " self.pool1 = nn.AvgPool2d(3,3) # node 2\n", - " self.pool1a = nn.AvgPool2d(4,4) # node 3\n", - "\n", - " self.conv2 = nn.Conv2d(10, 10, 4, 1, bias=False)# node 4\n", - " self.iaf2 = IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, spike_threshold=1.0, surrogate_grad_fn=PeriodicExponential()) # node 6\n", - "\n", - " self.conv3 = nn.Conv2d(10, 1, 2, 1, bias=False) # node 8\n", - " self.iaf3 = IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, spike_threshold=1.0, surrogate_grad_fn=PeriodicExponential()) # node 9\n", - "\n", - " self.flat = nn.Flatten()\n", - "\n", - " self.fc1 = nn.Linear(49, 500, bias=False) # node 10\n", - " self.iaf4 = IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, spike_threshold=1.0, surrogate_grad_fn=PeriodicExponential()) # node 11\n", - " \n", - " self.fc2 = nn.Linear(500, 10, bias=False) # node 12\n", - " self.iaf5 = IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, spike_threshold=1.0, surrogate_grad_fn=PeriodicExponential()) # node 13\n", - "\n", - " self.adder = Merge()\n", - "\n", - " def forward(self, x):\n", - " \n", - " con1_out = self.conv1(x)\n", - " iaf1_out = self.iaf1(con1_out)\n", - " pool1_out = self.pool1(iaf1_out)\n", - " pool1a_out = self.pool1a(iaf1_out)\n", - "\n", - " conv2_out = self.conv2(pool1_out)\n", - " iaf2_out = self.iaf2(conv2_out)\n", - "\n", - " conv3_out = self.conv3(self.adder(pool1a_out, iaf2_out))\n", - " iaf3_out = self.iaf3(conv3_out)\n", - "\n", - " flat_out = self.flat(iaf3_out)\n", - " \n", - " fc1_out = self.fc1(flat_out)\n", - " iaf4_out = self.iaf4(fc1_out)\n", - " fc2_out = self.fc2(iaf4_out)\n", - " iaf5_out = self.iaf5(fc2_out)\n", - "\n", - " return iaf5_out" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": { - "metadata": {} - }, - "outputs": [], - "source": [ - "snn = SNN()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## DynapcnnNetwork Class\n", - "\n", - "In the constructor of `DynapcnnNetworkGraph` the SNN passed as argument (defined as a `nn.Module`) will be parsed such that each layer is represented in a computational graph (using `nirtorch.extract_torch_graph`). \n", - "\n", - "The layers are the `nodes` of the graph, while their connectivity (how the outputs from a layer are sent to other layers) is represented as `edges`, represented in a `list` of `tuples`.\n", - "\n", - "Once the constructor finishes its initialization, the `hw_model.dynapcnn_layers` property is a dictionary where each entry represents the ID of a `DynapcnnLayer` instance (an `int` from `0` to `L`), with this entry containing a `DynapcnnLayer` instance where a subset of the layers in the original SNN has been incorporated into, the core such instance has been assigned to, and the list of `DynapcnnLayer` instances (their IDs) the layer targets." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": { - "metadata": {} - }, - "outputs": [], - "source": [ - "hw_model = DynapcnnNetwork(\n", - " snn=snn,\n", - " input_shape=input_shape,\n", - " batch_size=batch_size,\n", - " discretize=False\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Notice in the model bellow how the property DynapcnnLayer in the model has yet to be assigned to a core. This is only done once\n", - "DynapcnnNetworkGraph.to() is called." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "----------------------- [ DynapcnnLayer 0 ] -----------------------\n", - "\n", - "COMPUTATIONAL NODES:\n", - "\n", - "(node 0): Conv2d(2, 10, kernel_size=(2, 2), stride=(1, 1), bias=False)\n", - "(node 1): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1.), min_v_mem=Parameter containing:\n", - "tensor(-1.), batch_size=8, num_timesteps=-1)\n", - "(node 2): SumPool2d(norm_type=1, kernel_size=(3, 3), stride=None, ceil_mode=False)\n", - "(node 3): SumPool2d(norm_type=1, kernel_size=(4, 4), stride=None, ceil_mode=False)\n", - "\n", - "METADATA:\n", - "\n", - "> network's entry point: True\n", - "> convolution's weight re-scaling factor: None\n", - "> assigned core index: None\n", - "> destination DynapcnnLayers: [1, 2]\n", - "> node 2 feeds input to nodes [4]\n", - "> node 3 feeds input to nodes [7]\n", - "\n", - "----------------------- [ DynapcnnLayer 1 ] -----------------------\n", - "\n", - "COMPUTATIONAL NODES:\n", - "\n", - "(node 4): Conv2d(10, 10, kernel_size=(4, 4), stride=(1, 1), bias=False)\n", - "(node 6): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1.), min_v_mem=Parameter containing:\n", - "tensor(-1.), batch_size=8, num_timesteps=-1)\n", - "\n", - "METADATA:\n", - "\n", - "> network's entry point: False\n", - "> convolution's weight re-scaling factor: 4.5\n", - "> assigned core index: None\n", - "> destination DynapcnnLayers: [2]\n", - "> node 6 feeds input to nodes [7]\n", - "\n", - "----------------------- [ DynapcnnLayer 2 ] -----------------------\n", - "\n", - "COMPUTATIONAL NODES:\n", - "\n", - "(node 7): Conv2d(10, 1, kernel_size=(2, 2), stride=(1, 1), bias=False)\n", - "(node 8): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1.), min_v_mem=Parameter containing:\n", - "tensor(-1.), batch_size=8, num_timesteps=-1)\n", - "\n", - "METADATA:\n", - "\n", - "> network's entry point: False\n", - "> convolution's weight re-scaling factor: 8.0\n", - "> assigned core index: None\n", - "> destination DynapcnnLayers: [3]\n", - "> node 8 feeds input to nodes [9]\n", - "\n", - "----------------------- [ DynapcnnLayer 3 ] -----------------------\n", - "\n", - "COMPUTATIONAL NODES:\n", - "\n", - "(node 9): Conv2d(1, 500, kernel_size=(7, 7), stride=(1, 1), bias=False)\n", - "(node 10): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1.), min_v_mem=Parameter containing:\n", - "tensor(-1.), batch_size=8, num_timesteps=-1)\n", - "\n", - "METADATA:\n", - "\n", - "> network's entry point: False\n", - "> convolution's weight re-scaling factor: None\n", - "> assigned core index: None\n", - "> destination DynapcnnLayers: [4]\n", - "> node 10 feeds input to nodes [11]\n", - "\n", - "----------------------- [ DynapcnnLayer 4 ] -----------------------\n", - "\n", - "COMPUTATIONAL NODES:\n", - "\n", - "(node 11): Conv2d(500, 10, kernel_size=(1, 1), stride=(1, 1), bias=False)\n", - "(node 12): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1.), min_v_mem=Parameter containing:\n", - "tensor(-1.), batch_size=8, num_timesteps=-1)\n", - "\n", - "METADATA:\n", - "\n", - "> network's entry point: False\n", - "> convolution's weight re-scaling factor: None\n", - "> assigned core index: None\n", - "> destination DynapcnnLayers: []\n", - "\n", - "\n" - ] - } - ], - "source": [ - "print(hw_model)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The `hw_model.to()` call will figure out into which core each `DynapcnnLayer` instance will be assigned to. Once this assingment is made the instance itself is used to configure the `CNNLayerConfig` instance representing the core's configuration assigned to it.\n", - "\n", - "If the call is sucessfull, the layers comprising the network and their associated metadata will be printed." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": { - "metadata": {} - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Network is valid: \n", - "\n", - "----------------------- [ DynapcnnLayer 0 ] -----------------------\n", - "\n", - "COMPUTATIONAL NODES:\n", - "\n", - "(node 0): Conv2d(2, 10, kernel_size=(2, 2), stride=(1, 1), bias=False)\n", - "(node 1): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1.), min_v_mem=Parameter containing:\n", - "tensor(-1.), batch_size=8, num_timesteps=-1)\n", - "(node 2): SumPool2d(norm_type=1, kernel_size=(3, 3), stride=None, ceil_mode=False)\n", - "(node 3): SumPool2d(norm_type=1, kernel_size=(4, 4), stride=None, ceil_mode=False)\n", - "\n", - "METADATA:\n", - "\n", - "> network's entry point: True\n", - "> convolution's weight re-scaling factor: None\n", - "> assigned core index: 0\n", - "> destination DynapcnnLayers: [1, 2]\n", - "> node 2 feeds input to nodes [4]\n", - "> node 3 feeds input to nodes [7]\n", - "\n", - "----------------------- [ DynapcnnLayer 1 ] -----------------------\n", - "\n", - "COMPUTATIONAL NODES:\n", - "\n", - "(node 4): Conv2d(10, 10, kernel_size=(4, 4), stride=(1, 1), bias=False)\n", - "(node 6): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1.), min_v_mem=Parameter containing:\n", - "tensor(-1.), batch_size=8, num_timesteps=-1)\n", - "\n", - "METADATA:\n", - "\n", - "> network's entry point: False\n", - "> convolution's weight re-scaling factor: 4.5\n", - "> assigned core index: 1\n", - "> destination DynapcnnLayers: [2]\n", - "> node 6 feeds input to nodes [7]\n", - "\n", - "----------------------- [ DynapcnnLayer 2 ] -----------------------\n", - "\n", - "COMPUTATIONAL NODES:\n", - "\n", - "(node 7): Conv2d(10, 1, kernel_size=(2, 2), stride=(1, 1), bias=False)\n", - "(node 8): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1.), min_v_mem=Parameter containing:\n", - "tensor(-1.), batch_size=8, num_timesteps=-1)\n", - "\n", - "METADATA:\n", - "\n", - "> network's entry point: False\n", - "> convolution's weight re-scaling factor: 8.0\n", - "> assigned core index: 2\n", - "> destination DynapcnnLayers: [3]\n", - "> node 8 feeds input to nodes [9]\n", - "\n", - "----------------------- [ DynapcnnLayer 3 ] -----------------------\n", - "\n", - "COMPUTATIONAL NODES:\n", - "\n", - "(node 9): Conv2d(1, 500, kernel_size=(7, 7), stride=(1, 1), bias=False)\n", - "(node 10): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1.), min_v_mem=Parameter containing:\n", - "tensor(-1.), batch_size=8, num_timesteps=-1)\n", - "\n", - "METADATA:\n", - "\n", - "> network's entry point: False\n", - "> convolution's weight re-scaling factor: None\n", - "> assigned core index: 3\n", - "> destination DynapcnnLayers: [4]\n", - "> node 10 feeds input to nodes [11]\n", - "\n", - "----------------------- [ DynapcnnLayer 4 ] -----------------------\n", - "\n", - "COMPUTATIONAL NODES:\n", - "\n", - "(node 11): Conv2d(500, 10, kernel_size=(1, 1), stride=(1, 1), bias=False)\n", - "(node 12): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1.), min_v_mem=Parameter containing:\n", - "tensor(-1.), batch_size=8, num_timesteps=-1)\n", - "\n", - "METADATA:\n", - "\n", - "> network's entry point: False\n", - "> convolution's weight re-scaling factor: None\n", - "> assigned core index: 4\n", - "> destination DynapcnnLayers: []\n", - "\n", - "\n" - ] - } - ], - "source": [ - "hw_model.to(device=\"speck2fmodule:0\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Notice above now how the layers of the model have been assigned to a chip core." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Training the HW model" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [], - "source": [ - "hw_model.init_weights()" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "device: NVIDIA GeForce RTX 3070 Ti\n" - ] - } - ], - "source": [ - "if torch.cuda.is_available():\n", - " device = torch.device('cuda:0')\n", - " print('device: ', torch.cuda.get_device_name(0))\n", - "else:\n", - " device = torch.device('cpu')" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [], - "source": [ - "hw_model.to(device)" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [], - "source": [ - "import sys\n", - "\n", - "sys.path.append('../utils')\n", - "\n", - "from train_test_fn import training_loop, load_dataset, split_train_validation, load_architecture" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [], - "source": [ - "batch_size = 8\n", - "num_workers = 4\n", - "epochs = 5\n", - "lr = 5e-4\n", - "\n", - "n_time_steps = 50" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [], - "source": [ - "from torch.utils.data import DataLoader\n", - "from torch.nn import CrossEntropyLoss\n", - "from torch.optim import Adam" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "(34, 34, 2)\n" - ] - } - ], - "source": [ - "snn_train_dataset, snn_test_dataset, sensor_size, nb_classes = load_dataset('NMNIST', n_time_steps, \"../NMNIST\")\n", - "\n", - "print(sensor_size)\n", - "\n", - "snn_train_dataloader = DataLoader(snn_train_dataset, batch_size=batch_size, num_workers=num_workers, drop_last=True, shuffle=True)\n", - "snn_test_dataloader = DataLoader(snn_test_dataset, batch_size=batch_size, num_workers=num_workers, drop_last=True, shuffle=False)" - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [], - "source": [ - "optimizer = Adam(hw_model.parameters(), lr=lr, betas=(0.9, 0.999), eps=1e-8)\n", - "loss_fn = CrossEntropyLoss()" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "70c30996c7164a019d9a9b26397a4a6c", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - " 0%| | 0/7500 [00:00 1\u001b[0m epochs_x, epochs_y, epochs_acc \u001b[38;5;241m=\u001b[39m training_loop(\n\u001b[1;32m 2\u001b[0m device, \n\u001b[1;32m 3\u001b[0m n_time_steps,\n\u001b[1;32m 4\u001b[0m batch_size,\n\u001b[1;32m 5\u001b[0m sensor_size,\n\u001b[1;32m 6\u001b[0m snn_train_dataloader, \n\u001b[1;32m 7\u001b[0m hw_model, \n\u001b[1;32m 8\u001b[0m loss_fn, \n\u001b[1;32m 9\u001b[0m optimizer, \n\u001b[1;32m 10\u001b[0m epochs, \n\u001b[1;32m 11\u001b[0m snn_test_dataloader)\n", - "File \u001b[0;32m~/Documents/github/sinabs/tests/test_nonsequential/DYNAPCNNNETWORK_EXAMPLES/../utils/train_test_fn.py:132\u001b[0m, in \u001b[0;36mtraining_loop\u001b[0;34m(device, nb_time_steps, batch_size, feature_map_size, dataloader_train, model, loss_fn, optimizer, epochs, dataloader_test)\u001b[0m\n\u001b[1;32m 130\u001b[0m \u001b[38;5;66;03m# gradient update\u001b[39;00m\n\u001b[1;32m 131\u001b[0m optimizer\u001b[38;5;241m.\u001b[39mzero_grad()\n\u001b[0;32m--> 132\u001b[0m loss\u001b[38;5;241m.\u001b[39mbackward()\n\u001b[1;32m 133\u001b[0m optimizer\u001b[38;5;241m.\u001b[39mstep()\n\u001b[1;32m 135\u001b[0m \u001b[38;5;66;03m# detach the neuron states and activations from current computation graph(necessary)\u001b[39;00m\n", - "File \u001b[0;32m~/.local/lib/python3.11/site-packages/torch/_tensor.py:522\u001b[0m, in \u001b[0;36mTensor.backward\u001b[0;34m(self, gradient, retain_graph, create_graph, inputs)\u001b[0m\n\u001b[1;32m 512\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m has_torch_function_unary(\u001b[38;5;28mself\u001b[39m):\n\u001b[1;32m 513\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m handle_torch_function(\n\u001b[1;32m 514\u001b[0m Tensor\u001b[38;5;241m.\u001b[39mbackward,\n\u001b[1;32m 515\u001b[0m (\u001b[38;5;28mself\u001b[39m,),\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 520\u001b[0m inputs\u001b[38;5;241m=\u001b[39minputs,\n\u001b[1;32m 521\u001b[0m )\n\u001b[0;32m--> 522\u001b[0m torch\u001b[38;5;241m.\u001b[39mautograd\u001b[38;5;241m.\u001b[39mbackward(\n\u001b[1;32m 523\u001b[0m \u001b[38;5;28mself\u001b[39m, gradient, retain_graph, create_graph, inputs\u001b[38;5;241m=\u001b[39minputs\n\u001b[1;32m 524\u001b[0m )\n", - "File \u001b[0;32m~/.local/lib/python3.11/site-packages/torch/autograd/__init__.py:266\u001b[0m, in \u001b[0;36mbackward\u001b[0;34m(tensors, grad_tensors, retain_graph, create_graph, grad_variables, inputs)\u001b[0m\n\u001b[1;32m 261\u001b[0m retain_graph \u001b[38;5;241m=\u001b[39m create_graph\n\u001b[1;32m 263\u001b[0m \u001b[38;5;66;03m# The reason we repeat the same comment below is that\u001b[39;00m\n\u001b[1;32m 264\u001b[0m \u001b[38;5;66;03m# some Python versions print out the first line of a multi-line function\u001b[39;00m\n\u001b[1;32m 265\u001b[0m \u001b[38;5;66;03m# calls in the traceback and some print out the last line\u001b[39;00m\n\u001b[0;32m--> 266\u001b[0m Variable\u001b[38;5;241m.\u001b[39m_execution_engine\u001b[38;5;241m.\u001b[39mrun_backward( \u001b[38;5;66;03m# Calls into the C++ engine to run the backward pass\u001b[39;00m\n\u001b[1;32m 267\u001b[0m tensors,\n\u001b[1;32m 268\u001b[0m grad_tensors_,\n\u001b[1;32m 269\u001b[0m retain_graph,\n\u001b[1;32m 270\u001b[0m create_graph,\n\u001b[1;32m 271\u001b[0m inputs,\n\u001b[1;32m 272\u001b[0m allow_unreachable\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mTrue\u001b[39;00m,\n\u001b[1;32m 273\u001b[0m accumulate_grad\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mTrue\u001b[39;00m,\n\u001b[1;32m 274\u001b[0m )\n", - "\u001b[0;31mKeyboardInterrupt\u001b[0m: " - ] - } - ], - "source": [ - "epochs_x, epochs_y, epochs_acc = training_loop(\n", - " device, \n", - " n_time_steps,\n", - " batch_size,\n", - " sensor_size,\n", - " snn_train_dataloader, \n", - " hw_model, \n", - " loss_fn, \n", - " optimizer, \n", - " epochs, \n", - " snn_test_dataloader)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "speck-rescnn", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.3" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/tests/test_nonsequential/DYNAPCNNNETWORK_EXAMPLES/DynapcnnNetwork-example_2.ipynb b/tests/test_nonsequential/DYNAPCNNNETWORK_EXAMPLES/DynapcnnNetwork-example_2.ipynb deleted file mode 100644 index abdda89e..00000000 --- a/tests/test_nonsequential/DYNAPCNNNETWORK_EXAMPLES/DynapcnnNetwork-example_2.ipynb +++ /dev/null @@ -1,396 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": { - "metadata": {} - }, - "outputs": [], - "source": [ - "import torch\n", - "import torch.nn as nn\n", - "from sinabs.backend.dynapcnn import DynapcnnNetworkGraph\n", - "from sinabs.layers import Merge, IAFSqueeze" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": { - "metadata": {} - }, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "torch.manual_seed(0)" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": { - "metadata": {} - }, - "outputs": [], - "source": [ - "channels = 2\n", - "height = 34\n", - "width = 34\n", - "\n", - "input_shape = (channels, height, width)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Network Module\n", - "\n", - "We need to define a `nn.Module` implementing the network we want the chip to reproduce." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": { - "metadata": {} - }, - "outputs": [], - "source": [ - "class SNN(nn.Module):\n", - " def __init__(self) -> None:\n", - " super().__init__()\n", - "\n", - " self.conv1 = nn.Conv2d(2, 10, 2, 1, bias=False)\n", - " self.conv1_iaf = IAFSqueeze(batch_size=1)\n", - " self.pool1 = nn.AvgPool2d(3,3)\n", - " self.pool1a = nn.AvgPool2d(4,4)\n", - "\n", - " self.conv2 = nn.Conv2d(10, 10, 4, 1, bias=False)\n", - " self.conv2_iaf = IAFSqueeze(batch_size=1)\n", - "\n", - " self.conv3 = nn.Conv2d(10, 1, 2, 1, bias=False)\n", - " self.conv3_iaf = IAFSqueeze(batch_size=1)\n", - "\n", - " self.flat = nn.Flatten()\n", - "\n", - " self.fc1 = nn.Linear(49, 100, bias=False)\n", - " self.fc1_iaf = IAFSqueeze(batch_size=1)\n", - " \n", - " self.fc2 = nn.Linear(100, 100, bias=False)\n", - " self.fc2_iaf = IAFSqueeze(batch_size=1)\n", - "\n", - " self.fc3 = nn.Linear(100, 10, bias=False)\n", - " self.fc3_iaf = IAFSqueeze(batch_size=1)\n", - "\n", - " self.merge1 = Merge()\n", - "\n", - " def forward(self, x):\n", - " # -- conv. block 1 --\n", - " con1_out = self.conv1(x)\n", - " conv1_iaf_out = self.conv1_iaf(con1_out)\n", - " pool1_out = self.pool1(conv1_iaf_out)\n", - " pool1a_out = self.pool1a(conv1_iaf_out)\n", - " # -- conv. block 2 --\n", - " conv2_out = self.conv2(pool1_out)\n", - " conv2_iaf_out = self.conv2_iaf(conv2_out)\n", - " # -- conv. block 3 --\n", - " merge1_out = self.merge1(pool1a_out, conv2_iaf_out)\n", - " conv3_out = self.conv3(merge1_out)\n", - " conv3_iaf_out = self.conv3_iaf(conv3_out)\n", - " flat_out = self.flat(conv3_iaf_out)\n", - " # -- fc clock 1 --\n", - " fc1_out = self.fc1(flat_out)\n", - " fc1_iaf_out = self.fc1_iaf(fc1_out)\n", - " # -- fc clock 2 --\n", - " fc2_out = self.fc2(fc1_iaf_out)\n", - " fc2_iaf_out = self.fc2_iaf(fc2_out)\n", - " # -- fc clock 3 --\n", - " fc3_out = self.fc3(fc2_iaf_out)\n", - " fc3_iaf_out = self.fc3_iaf(fc3_out)\n", - "\n", - " return fc3_iaf_out" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": { - "metadata": {} - }, - "outputs": [], - "source": [ - "snn = SNN()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The following exemplifies how each of the layers in the SNN should be grouped together to form a `DynapcnnLayer` instance. Let's check the shapes of the tensors each of the (original) layers in the model inputs and outputs by feeding a fake input through the model:" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": { - "metadata": {} - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "torch.Size([1, 10, 33, 33])\n", - "torch.Size([1, 10, 33, 33])\n", - "torch.Size([1, 10, 11, 11])\n", - "torch.Size([1, 10, 8, 8])\n", - "torch.Size([1, 10, 8, 8])\n", - "torch.Size([1, 10, 8, 8])\n", - "torch.Size([1, 10, 8, 8])\n", - "torch.Size([1, 1, 7, 7])\n", - "torch.Size([1, 1, 7, 7])\n", - "torch.Size([1, 49])\n", - "torch.Size([1, 100])\n", - "torch.Size([1, 100])\n", - "torch.Size([1, 100])\n", - "torch.Size([1, 100])\n", - "torch.Size([1, 10])\n", - "torch.Size([1, 10])\n" - ] - } - ], - "source": [ - "x = torch.randn((1, *input_shape))\n", - "\n", - "# -- conv. block 1 --\n", - "con1_out = snn.conv1(x)\n", - "print(con1_out.shape)\n", - "conv1_iaf_out = snn.conv1_iaf(con1_out)\n", - "print(conv1_iaf_out.shape)\n", - "pool1_out = snn.pool1(conv1_iaf_out)\n", - "print(pool1_out.shape)\n", - "pool1a_out = snn.pool1a(conv1_iaf_out)\n", - "print(pool1a_out.shape)\n", - "# -- conv. block 2 --\n", - "conv2_out = snn.conv2(pool1_out)\n", - "print(conv2_out.shape)\n", - "conv2_iaf_out = snn.conv2_iaf(conv2_out)\n", - "print(conv2_iaf_out.shape)\n", - "# -- conv. block 3 --\n", - "merge1_out = snn.merge1(pool1a_out, conv2_iaf_out)\n", - "print(merge1_out.shape)\n", - "conv3_out = snn.conv3(merge1_out)\n", - "print(conv3_out.shape)\n", - "conv3_iaf_out = snn.conv3_iaf(conv3_out)\n", - "print(conv3_iaf_out.shape)\n", - "flat_out = snn.flat(conv3_iaf_out)\n", - "print(flat_out.shape)\n", - "# -- fc clock 1 --\n", - "fc1_out = snn.fc1(flat_out)\n", - "print(fc1_out.shape)\n", - "fc1_iaf_out = snn.fc1_iaf(fc1_out)\n", - "print(fc1_iaf_out.shape)\n", - "# -- fc clock 2 --\n", - "fc2_out = snn.fc2(fc1_iaf_out)\n", - "print(fc2_out.shape)\n", - "fc2_iaf_out = snn.fc2_iaf(fc2_out)\n", - "print(fc2_iaf_out.shape)\n", - "# -- fc clock 3 --\n", - "fc3_out = snn.fc3(fc2_iaf_out)\n", - "print(fc3_out.shape)\n", - "fc3_iaf_out = snn.fc3_iaf(fc3_out)\n", - "print(fc3_iaf_out.shape)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## DynapcnnNetwork Class\n", - "\n", - "In the constructor of `DynapcnnNetworkGraph` the SNN passed as argument (defined as a `nn.Module`) will be parsed such that each layer is represented in a computational graph (using `nirtorch.extract_torch_graph`). \n", - "\n", - "The layers are the `nodes` of the graph, while their connectivity (how the outputs from a layer are sent to other layers) is represented as `edges`, represented in a `list` of `tuples`.\n", - "\n", - "Once the constructor finishes its initialization, the `hw_model.dynapcnn_layers` property is a dictionary where each entry represents the ID of a `DynapcnnLayer` instance (an `int` from `0` to `L`), with this entry containing a `DynapcnnLayer` instance where a subset of the layers in the original SNN has been incorporated into, the core such instance has been assigned to, and the list of `DynapcnnLayer` instances (their IDs) the layer targets." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": { - "metadata": {} - }, - "outputs": [], - "source": [ - "hw_model = DynapcnnNetworkGraph(\n", - " snn,\n", - " discretize=True,\n", - " input_shape=input_shape\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The `hw_model.to()` call will figure out into which core eac `DynapcnnLayer` instance will be assigned to. Once this assingment is made the instance itself is used to configure the `CNNLayerConfig` instance representing the core's configuration.\n", - "\n", - "If the cores' configuration is valid, each `DynapcnnLayer` instance and their respective destinations will be used to create a computational graph that encodes how the `forward` method of `hw_model.network` (a `nn.Module` using the `DynapcnnLayer` instances) propagates that through the network." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": { - "metadata": {} - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Network is valid\n", - "(0, 1)\n", - "(0, 2)\n", - "(1, 2)\n", - "(2, 3)\n", - "(3, 4)\n", - "(4, 5)\n" - ] - }, - { - "ename": "RuntimeError", - "evalue": "Device is already opened!", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mRuntimeError\u001b[0m Traceback (most recent call last)", - "Cell \u001b[0;32mIn[8], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m hw_model\u001b[38;5;241m.\u001b[39mto(device\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mspeck2fmodule:0\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n", - "File \u001b[0;32m~/Documents/github/sinabs/sinabs/backend/dynapcnn/dynapcnn_network_graph.py:172\u001b[0m, in \u001b[0;36mDynapcnnNetworkGraph.to\u001b[0;34m(self, device, chip_layers_ordering, monitor_layers, config_modifier, slow_clk_frequency)\u001b[0m\n\u001b[1;32m 163\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m device_name \u001b[38;5;129;01min\u001b[39;00m ChipFactory\u001b[38;5;241m.\u001b[39msupported_devices: \u001b[38;5;66;03m# pragma: no cover\u001b[39;00m\n\u001b[1;32m 165\u001b[0m config \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mmake_config( \u001b[38;5;66;03m# generate config.\u001b[39;00m\n\u001b[1;32m 166\u001b[0m chip_layers_ordering\u001b[38;5;241m=\u001b[39mchip_layers_ordering,\n\u001b[1;32m 167\u001b[0m device\u001b[38;5;241m=\u001b[39mdevice,\n\u001b[1;32m 168\u001b[0m monitor_layers\u001b[38;5;241m=\u001b[39mmonitor_layers,\n\u001b[1;32m 169\u001b[0m config_modifier\u001b[38;5;241m=\u001b[39mconfig_modifier,\n\u001b[1;32m 170\u001b[0m )\n\u001b[0;32m--> 172\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39msamna_device \u001b[38;5;241m=\u001b[39m open_device(device) \u001b[38;5;66;03m# apply configuration to device.\u001b[39;00m\n\u001b[1;32m 173\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39msamna_device\u001b[38;5;241m.\u001b[39mget_model()\u001b[38;5;241m.\u001b[39mapply_configuration(config)\n\u001b[1;32m 174\u001b[0m time\u001b[38;5;241m.\u001b[39msleep(\u001b[38;5;241m1\u001b[39m)\n", - "File \u001b[0;32m~/Documents/github/sinabs/sinabs/backend/dynapcnn/io.py:256\u001b[0m, in \u001b[0;36mopen_device\u001b[0;34m(device_id)\u001b[0m\n\u001b[1;32m 254\u001b[0m device_map \u001b[38;5;241m=\u001b[39m get_device_map()\n\u001b[1;32m 255\u001b[0m device_info \u001b[38;5;241m=\u001b[39m device_map[device_id]\n\u001b[0;32m--> 256\u001b[0m device_handle \u001b[38;5;241m=\u001b[39m samna\u001b[38;5;241m.\u001b[39mdevice\u001b[38;5;241m.\u001b[39mopen_device(device_info)\n\u001b[1;32m 258\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m device_handle \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m 259\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m device_handle\n", - "\u001b[0;31mRuntimeError\u001b[0m: Device is already opened!" - ] - } - ], - "source": [ - "hw_model.to(device=\"speck2fmodule:0\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The layers comprising our `hw_model` and their respective metadata can be inspected by calling `print` on a `DynapcnnNetworkGraph` instance." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "metadata": {} - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "---- DynapcnnLayer 0 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 0): Conv2d(2, 10, kernel_size=(2, 2), stride=(1, 1), bias=False)\n", - "(node 1): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1.), min_v_mem=Parameter containing:\n", - "tensor(-32768.), batch_size=1, num_timesteps=-1)\n", - "(node 2): SumPool2d(norm_type=1, kernel_size=(3, 3), stride=None, ceil_mode=False)\n", - "(node 3): SumPool2d(norm_type=1, kernel_size=(4, 4), stride=None, ceil_mode=False)\n", - "> layer destinations: [1, 2]\n", - "> assigned core: 0\n", - "\n", - "---- DynapcnnLayer 1 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 4): Conv2d(10, 10, kernel_size=(4, 4), stride=(1, 1), bias=False)\n", - "(node 6): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1.), min_v_mem=Parameter containing:\n", - "tensor(-32768.), batch_size=1, num_timesteps=-1)\n", - "> layer destinations: [2]\n", - "> assigned core: 1\n", - "\n", - "---- DynapcnnLayer 2 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 7): Conv2d(10, 1, kernel_size=(2, 2), stride=(1, 1), bias=False)\n", - "(node 8): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1.), min_v_mem=Parameter containing:\n", - "tensor(-32768.), batch_size=1, num_timesteps=-1)\n", - "> layer destinations: [3]\n", - "> assigned core: 2\n", - "\n", - "---- DynapcnnLayer 3 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 9): Conv2d(1, 100, kernel_size=(7, 7), stride=(1, 1), bias=False)\n", - "(node 10): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1.), min_v_mem=Parameter containing:\n", - "tensor(-32768.), batch_size=1, num_timesteps=-1)\n", - "> layer destinations: [4]\n", - "> assigned core: 3\n", - "\n", - "---- DynapcnnLayer 4 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 11): Conv2d(100, 100, kernel_size=(1, 1), stride=(1, 1), bias=False)\n", - "(node 12): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1.), min_v_mem=Parameter containing:\n", - "tensor(-32768.), batch_size=1, num_timesteps=-1)\n", - "> layer destinations: [5]\n", - "> assigned core: 4\n", - "\n", - "---- DynapcnnLayer 5 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 13): Conv2d(100, 10, kernel_size=(1, 1), stride=(1, 1), bias=False)\n", - "(node 14): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1.), min_v_mem=Parameter containing:\n", - "tensor(-32768.), batch_size=1, num_timesteps=-1)\n", - "> layer destinations: []\n", - "> assigned core: 5\n", - "\n", - "\n" - ] - } - ], - "source": [ - "print(hw_model)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "speck-rescnn", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.3" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/tests/test_nonsequential/DYNAPCNNNETWORK_EXAMPLES/DynapcnnNetwork-example_3.ipynb b/tests/test_nonsequential/DYNAPCNNNETWORK_EXAMPLES/DynapcnnNetwork-example_3.ipynb deleted file mode 100644 index 5b8e7216..00000000 --- a/tests/test_nonsequential/DYNAPCNNNETWORK_EXAMPLES/DynapcnnNetwork-example_3.ipynb +++ /dev/null @@ -1,402 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": { - "metadata": {} - }, - "outputs": [], - "source": [ - "import torch\n", - "import torch.nn as nn\n", - "from sinabs.backend.dynapcnn import DynapcnnNetworkGraph\n", - "from sinabs.layers import Merge, IAFSqueeze" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": { - "metadata": {} - }, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "torch.manual_seed(0)" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": { - "metadata": {} - }, - "outputs": [], - "source": [ - "channels = 2\n", - "height = 34\n", - "width = 34\n", - "\n", - "input_shape = (channels, height, width)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Network Module\n", - "\n", - "We need to define a `nn.Module` implementing the network we want the chip to reproduce." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": { - "metadata": {} - }, - "outputs": [], - "source": [ - "class SNN(nn.Module):\n", - " def __init__(self) -> None:\n", - " super().__init__()\n", - "\n", - " self.conv1 = nn.Conv2d(2, 10, 2, 1, bias=False)\n", - " self.conv1_iaf = IAFSqueeze(batch_size=1)\n", - " self.pool1 = nn.AvgPool2d(3,3)\n", - " self.pool1a = nn.AvgPool2d(4,4)\n", - "\n", - " self.conv2 = nn.Conv2d(10, 10, 4, 1, bias=False)\n", - " self.conv2_iaf = IAFSqueeze(batch_size=1)\n", - "\n", - " self.conv3 = nn.Conv2d(10, 1, 2, 1, bias=False)\n", - " self.conv3_iaf = IAFSqueeze(batch_size=1)\n", - "\n", - " self.flat = nn.Flatten()\n", - "\n", - " self.fc1 = nn.Linear(49, 100, bias=False)\n", - " self.fc1_iaf = IAFSqueeze(batch_size=1)\n", - " \n", - " self.fc2 = nn.Linear(100, 100, bias=False)\n", - " self.fc2_iaf = IAFSqueeze(batch_size=1)\n", - "\n", - " self.fc3 = nn.Linear(100, 10, bias=False)\n", - " self.fc3_iaf = IAFSqueeze(batch_size=1)\n", - "\n", - " self.merge1 = Merge()\n", - " self.merge2 = Merge()\n", - "\n", - " def forward(self, x):\n", - " # -- conv. block 0 --\n", - " con1_out = self.conv1(x)\n", - " conv1_iaf_out = self.conv1_iaf(con1_out)\n", - " pool1_out = self.pool1(conv1_iaf_out)\n", - " pool1a_out = self.pool1a(conv1_iaf_out)\n", - " # -- conv. block 1 --\n", - " conv2_out = self.conv2(pool1_out)\n", - " conv2_iaf_out = self.conv2_iaf(conv2_out)\n", - " # -- conv. block 2 --\n", - " merge1_out = self.merge1(pool1a_out, conv2_iaf_out)\n", - " conv3_out = self.conv3(merge1_out)\n", - " conv3_iaf_out = self.conv3_iaf(conv3_out)\n", - " flat_out = self.flat(conv3_iaf_out)\n", - " # -- fc clock 3 --\n", - " fc1_out = self.fc1(flat_out)\n", - " fc1_iaf_out = self.fc1_iaf(fc1_out)\n", - " # -- fc clock 4 --\n", - " fc2_out = self.fc2(fc1_iaf_out)\n", - " fc2_iaf_out = self.fc2_iaf(fc2_out)\n", - " # -- fc clock 5 --\n", - " merge2_out = self.merge2(fc1_iaf_out, fc2_iaf_out)\n", - " fc3_out = self.fc3(merge2_out)\n", - " fc3_iaf_out = self.fc3_iaf(fc3_out)\n", - "\n", - " return fc3_iaf_out" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": { - "metadata": {} - }, - "outputs": [], - "source": [ - "snn = SNN()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The following exemplifies how each of the layers in the SNN should be grouped together to form a `DynapcnnLayer` instance. Let's check the shapes of the tensors each of the (original) layers in the model inputs and outputs by feeding a fake input through the model:" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": { - "metadata": {} - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "torch.Size([1, 10, 33, 33])\n", - "torch.Size([1, 10, 33, 33])\n", - "torch.Size([1, 10, 11, 11])\n", - "torch.Size([1, 10, 8, 8])\n", - "torch.Size([1, 10, 8, 8])\n", - "torch.Size([1, 10, 8, 8])\n", - "merge1: torch.Size([1, 10, 8, 8])\n", - "torch.Size([1, 1, 7, 7])\n", - "torch.Size([1, 1, 7, 7])\n", - "torch.Size([1, 49])\n", - "torch.Size([1, 100])\n", - "torch.Size([1, 100])\n", - "torch.Size([1, 100])\n", - "torch.Size([1, 100])\n", - "merge2: torch.Size([1, 100])\n", - "torch.Size([1, 10])\n", - "torch.Size([1, 10])\n" - ] - } - ], - "source": [ - "x = torch.randn((1, *input_shape))\n", - "\n", - "# -- conv. block 0 --\n", - "con1_out = snn.conv1(x)\n", - "print(con1_out.shape)\n", - "conv1_iaf_out = snn.conv1_iaf(con1_out)\n", - "print(conv1_iaf_out.shape)\n", - "pool1_out = snn.pool1(conv1_iaf_out)\n", - "print(pool1_out.shape)\n", - "pool1a_out = snn.pool1a(conv1_iaf_out)\n", - "print(pool1a_out.shape)\n", - "# -- conv. block 1 --\n", - "conv2_out = snn.conv2(pool1_out)\n", - "print(conv2_out.shape)\n", - "conv2_iaf_out = snn.conv2_iaf(conv2_out)\n", - "print(conv2_iaf_out.shape)\n", - "# -- conv. block 2 --\n", - "merge1_out = snn.merge1(pool1a_out, conv2_iaf_out)\n", - "print(f'merge1: {merge1_out.shape}')\n", - "conv3_out = snn.conv3(merge1_out)\n", - "print(conv3_out.shape)\n", - "conv3_iaf_out = snn.conv3_iaf(conv3_out)\n", - "print(conv3_iaf_out.shape)\n", - "flat_out = snn.flat(conv3_iaf_out)\n", - "print(flat_out.shape)\n", - "# -- fc clock 3 --\n", - "fc1_out = snn.fc1(flat_out)\n", - "print(fc1_out.shape)\n", - "fc1_iaf_out = snn.fc1_iaf(fc1_out)\n", - "print(fc1_iaf_out.shape)\n", - "# -- fc clock 4 --\n", - "fc2_out = snn.fc2(fc1_iaf_out)\n", - "print(fc2_out.shape)\n", - "fc2_iaf_out = snn.fc2_iaf(fc2_out)\n", - "print(fc2_iaf_out.shape)\n", - "# -- fc clock 5 --\n", - "merge2_out = snn.merge2(fc1_iaf_out, fc2_iaf_out)\n", - "print(f'merge2: {merge2_out.shape}')\n", - "fc3_out = snn.fc3(merge2_out)\n", - "print(fc3_out.shape)\n", - "fc3_iaf_out = snn.fc3_iaf(fc3_out)\n", - "print(fc3_iaf_out.shape)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## DynapcnnNetwork Class\n", - "\n", - "In the constructor of `DynapcnnNetworkGraph` the SNN passed as argument (defined as a `nn.Module`) will be parsed such that each layer is represented in a computational graph (using `nirtorch.extract_torch_graph`). \n", - "\n", - "The layers are the `nodes` of the graph, while their connectivity (how the outputs from a layer are sent to other layers) is represented as `edges`, represented in a `list` of `tuples`.\n", - "\n", - "Once the constructor finishes its initialization, the `hw_model.dynapcnn_layers` property is a dictionary where each entry represents the ID of a `DynapcnnLayer` instance (an `int` from `0` to `L`), with this entry containing a `DynapcnnLayer` instance where a subset of the layers in the original SNN has been incorporated into, the core such instance has been assigned to, and the list of `DynapcnnLayer` instances (their IDs) the layer targets." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": { - "metadata": {} - }, - "outputs": [], - "source": [ - "hw_model = DynapcnnNetworkGraph(\n", - " snn,\n", - " discretize=True,\n", - " input_shape=input_shape\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The `hw_model.to()` call will figure out into which core eac `DynapcnnLayer` instance will be assigned to. Once this assingment is made the instance itself is used to configure the `CNNLayerConfig` instance representing the core's configuration.\n", - "\n", - "If the cores' configuration is valid, each `DynapcnnLayer` instance and their respective destinations will be used to create a computational graph that encodes how the `forward` method of `hw_model.network` (a `nn.Module` using the `DynapcnnLayer` instances) propagates that through the network." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": { - "metadata": {} - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Network is valid\n", - "(0, 1)\n", - "(0, 2)\n", - "(1, 2)\n", - "(2, 3)\n", - "(3, 4)\n", - "(3, 5)\n", - "(4, 5)\n" - ] - }, - { - "ename": "RuntimeError", - "evalue": "Device is already opened!", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mRuntimeError\u001b[0m Traceback (most recent call last)", - "Cell \u001b[0;32mIn[8], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m hw_model\u001b[38;5;241m.\u001b[39mto(device\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mspeck2fmodule:0\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n", - "File \u001b[0;32m~/Documents/github/sinabs/sinabs/backend/dynapcnn/dynapcnn_network_graph.py:172\u001b[0m, in \u001b[0;36mDynapcnnNetworkGraph.to\u001b[0;34m(self, device, chip_layers_ordering, monitor_layers, config_modifier, slow_clk_frequency)\u001b[0m\n\u001b[1;32m 163\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m device_name \u001b[38;5;129;01min\u001b[39;00m ChipFactory\u001b[38;5;241m.\u001b[39msupported_devices: \u001b[38;5;66;03m# pragma: no cover\u001b[39;00m\n\u001b[1;32m 165\u001b[0m config \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mmake_config( \u001b[38;5;66;03m# generate config.\u001b[39;00m\n\u001b[1;32m 166\u001b[0m chip_layers_ordering\u001b[38;5;241m=\u001b[39mchip_layers_ordering,\n\u001b[1;32m 167\u001b[0m device\u001b[38;5;241m=\u001b[39mdevice,\n\u001b[1;32m 168\u001b[0m monitor_layers\u001b[38;5;241m=\u001b[39mmonitor_layers,\n\u001b[1;32m 169\u001b[0m config_modifier\u001b[38;5;241m=\u001b[39mconfig_modifier,\n\u001b[1;32m 170\u001b[0m )\n\u001b[0;32m--> 172\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39msamna_device \u001b[38;5;241m=\u001b[39m open_device(device) \u001b[38;5;66;03m# apply configuration to device.\u001b[39;00m\n\u001b[1;32m 173\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39msamna_device\u001b[38;5;241m.\u001b[39mget_model()\u001b[38;5;241m.\u001b[39mapply_configuration(config)\n\u001b[1;32m 174\u001b[0m time\u001b[38;5;241m.\u001b[39msleep(\u001b[38;5;241m1\u001b[39m)\n", - "File \u001b[0;32m~/Documents/github/sinabs/sinabs/backend/dynapcnn/io.py:256\u001b[0m, in \u001b[0;36mopen_device\u001b[0;34m(device_id)\u001b[0m\n\u001b[1;32m 254\u001b[0m device_map \u001b[38;5;241m=\u001b[39m get_device_map()\n\u001b[1;32m 255\u001b[0m device_info \u001b[38;5;241m=\u001b[39m device_map[device_id]\n\u001b[0;32m--> 256\u001b[0m device_handle \u001b[38;5;241m=\u001b[39m samna\u001b[38;5;241m.\u001b[39mdevice\u001b[38;5;241m.\u001b[39mopen_device(device_info)\n\u001b[1;32m 258\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m device_handle \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m 259\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m device_handle\n", - "\u001b[0;31mRuntimeError\u001b[0m: Device is already opened!" - ] - } - ], - "source": [ - "hw_model.to(device=\"speck2fmodule:0\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The layers comprising our `hw_model` and their respective metadata can be inspected by calling `print` on a `DynapcnnNetworkGraph` instance." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "metadata": {} - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "---- DynapcnnLayer 0 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 0): Conv2d(2, 10, kernel_size=(2, 2), stride=(1, 1), bias=False)\n", - "(node 1): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1.), min_v_mem=Parameter containing:\n", - "tensor(-32768.), batch_size=1, num_timesteps=-1)\n", - "(node 2): SumPool2d(norm_type=1, kernel_size=(3, 3), stride=None, ceil_mode=False)\n", - "(node 3): SumPool2d(norm_type=1, kernel_size=(4, 4), stride=None, ceil_mode=False)\n", - "> layer destinations: [1, 2]\n", - "> assigned core: 0\n", - "\n", - "---- DynapcnnLayer 1 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 4): Conv2d(10, 10, kernel_size=(4, 4), stride=(1, 1), bias=False)\n", - "(node 6): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1.), min_v_mem=Parameter containing:\n", - "tensor(-32768.), batch_size=1, num_timesteps=-1)\n", - "> layer destinations: [2]\n", - "> assigned core: 1\n", - "\n", - "---- DynapcnnLayer 2 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 7): Conv2d(10, 1, kernel_size=(2, 2), stride=(1, 1), bias=False)\n", - "(node 8): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1.), min_v_mem=Parameter containing:\n", - "tensor(-32768.), batch_size=1, num_timesteps=-1)\n", - "> layer destinations: [3]\n", - "> assigned core: 2\n", - "\n", - "---- DynapcnnLayer 3 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 9): Conv2d(1, 100, kernel_size=(7, 7), stride=(1, 1), bias=False)\n", - "(node 10): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1.), min_v_mem=Parameter containing:\n", - "tensor(-32768.), batch_size=1, num_timesteps=-1)\n", - "> layer destinations: [4, 5]\n", - "> assigned core: 3\n", - "\n", - "---- DynapcnnLayer 4 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 11): Conv2d(100, 100, kernel_size=(1, 1), stride=(1, 1), bias=False)\n", - "(node 13): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1.), min_v_mem=Parameter containing:\n", - "tensor(-32768.), batch_size=1, num_timesteps=-1)\n", - "> layer destinations: [5]\n", - "> assigned core: 4\n", - "\n", - "---- DynapcnnLayer 5 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 14): Conv2d(100, 10, kernel_size=(1, 1), stride=(1, 1), bias=False)\n", - "(node 15): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1.), min_v_mem=Parameter containing:\n", - "tensor(-32768.), batch_size=1, num_timesteps=-1)\n", - "> layer destinations: []\n", - "> assigned core: 5\n", - "\n", - "\n" - ] - } - ], - "source": [ - "print(hw_model)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "speck-rescnn", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.3" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/tests/test_nonsequential/DYNAPCNNNETWORK_EXAMPLES/DynapcnnNetwork-example_4.ipynb b/tests/test_nonsequential/DYNAPCNNNETWORK_EXAMPLES/DynapcnnNetwork-example_4.ipynb deleted file mode 100644 index 1f190961..00000000 --- a/tests/test_nonsequential/DYNAPCNNNETWORK_EXAMPLES/DynapcnnNetwork-example_4.ipynb +++ /dev/null @@ -1,380 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": { - "metadata": {} - }, - "outputs": [], - "source": [ - "import torch\n", - "import torch.nn as nn\n", - "from sinabs.backend.dynapcnn import DynapcnnNetworkGraph\n", - "from sinabs.layers import Merge, IAFSqueeze" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": { - "metadata": {} - }, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "torch.manual_seed(0)" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": { - "metadata": {} - }, - "outputs": [], - "source": [ - "channels = 2\n", - "height = 34\n", - "width = 34\n", - "\n", - "input_shape = (channels, height, width)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Network Module\n", - "\n", - "We need to define a `nn.Module` implementing the network we want the chip to reproduce." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": { - "metadata": {} - }, - "outputs": [], - "source": [ - "class SNN(nn.Module):\n", - " def __init__(self) -> None:\n", - " super().__init__()\n", - "\n", - " self.conv1 = nn.Conv2d(2, 10, 2, 1, bias=False)\n", - " self.conv1_iaf = IAFSqueeze(batch_size=1)\n", - " self.pool1 = nn.AvgPool2d(3,3)\n", - " self.pool1a = nn.AvgPool2d(4,4)\n", - "\n", - " self.conv2 = nn.Conv2d(10, 10, 4, 1, bias=False)\n", - " self.conv2_iaf = IAFSqueeze(batch_size=1)\n", - "\n", - " self.conv3 = nn.Conv2d(10, 10, 2, 1, bias=False)\n", - " self.conv3_iaf = IAFSqueeze(batch_size=1)\n", - "\n", - " self.conv4 = nn.Conv2d(10, 1, 2, 1, bias=False)\n", - " self.conv4_iaf = IAFSqueeze(batch_size=1)\n", - "\n", - " self.flat = nn.Flatten()\n", - "\n", - " self.fc1 = nn.Linear(36, 100, bias=False)\n", - " self.fc1_iaf = IAFSqueeze(batch_size=1)\n", - " \n", - " self.fc2 = nn.Linear(100, 100, bias=False)\n", - " self.fc2_iaf = IAFSqueeze(batch_size=1)\n", - "\n", - " self.fc3 = nn.Linear(100, 10, bias=False)\n", - " self.fc3_iaf = IAFSqueeze(batch_size=1)\n", - "\n", - " self.merge1 = Merge()\n", - " self.merge2 = Merge()\n", - "\n", - " def forward(self, x):\n", - " # -- conv. block 0 --\n", - " con1_out = self.conv1(x)\n", - " conv1_iaf_out = self.conv1_iaf(con1_out)\n", - " pool1_out = self.pool1(conv1_iaf_out)\n", - " pool1a_out = self.pool1a(conv1_iaf_out)\n", - " # -- conv. block 1 --\n", - " conv2_out = self.conv2(pool1_out)\n", - " conv2_iaf_out = self.conv2_iaf(conv2_out)\n", - " # -- conv. block 2 --\n", - " merge1_out = self.merge1(pool1a_out, conv2_iaf_out)\n", - " conv3_out = self.conv3(merge1_out)\n", - " conv3_iaf_out = self.conv3_iaf(conv3_out)\n", - " # -- conv. block 3 --\n", - " conv4_out = self.conv4(conv3_iaf_out)\n", - " conv4_iaf_out = self.conv4_iaf(conv4_out)\n", - " flat_out = self.flat(conv4_iaf_out)\n", - " # -- fc clock 4 --\n", - " fc1_out = self.fc1(flat_out)\n", - " fc1_iaf_out = self.fc1_iaf(fc1_out)\n", - " # -- fc clock 5 --\n", - " fc2_out = self.fc2(fc1_iaf_out)\n", - " fc2_iaf_out = self.fc2_iaf(fc2_out)\n", - " # -- fc clock 6 --\n", - " merge2_out = self.merge2(fc1_iaf_out, fc2_iaf_out)\n", - " fc3_out = self.fc3(merge2_out)\n", - " fc3_iaf_out = self.fc3_iaf(fc3_out)\n", - "\n", - " return fc3_iaf_out" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": { - "metadata": {} - }, - "outputs": [], - "source": [ - "snn = SNN()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The following exemplifies how each of the layers in the SNN should be grouped together to form a `DynapcnnLayer` instance. Let's check the shapes of the tensors each of the (original) layers in the model inputs and outputs by feeding a fake input through the model:" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": { - "metadata": {} - }, - "outputs": [], - "source": [ - "x = torch.randn((1, *input_shape))\n", - "\n", - "# -- conv. block 0 --\n", - "con1_out = snn.conv1(x)\n", - "conv1_iaf_out = snn.conv1_iaf(con1_out)\n", - "pool1_out = snn.pool1(conv1_iaf_out)\n", - "pool1a_out = snn.pool1a(conv1_iaf_out)\n", - "# -- conv. block 1 --\n", - "conv2_out = snn.conv2(pool1_out)\n", - "conv2_iaf_out = snn.conv2_iaf(conv2_out)\n", - "# -- conv. block 2 --\n", - "merge1_out = snn.merge1(pool1a_out, conv2_iaf_out)\n", - "conv3_out = snn.conv3(merge1_out)\n", - "conv3_iaf_out = snn.conv3_iaf(conv3_out)\n", - "# -- conv. block 3 --\n", - "conv4_out = snn.conv4(conv3_iaf_out)\n", - "conv4_iaf_out = snn.conv4_iaf(conv4_out)\n", - "flat_out = snn.flat(conv4_iaf_out)\n", - "# -- fc clock 4 --\n", - "fc1_out = snn.fc1(flat_out)\n", - "fc1_iaf_out = snn.fc1_iaf(fc1_out)\n", - "# -- fc clock 5 --\n", - "fc2_out = snn.fc2(fc1_iaf_out)\n", - "fc2_iaf_out = snn.fc2_iaf(fc2_out)\n", - "# -- fc clock 6 --\n", - "merge2_out = snn.merge2(fc1_iaf_out, fc2_iaf_out)\n", - "fc3_out = snn.fc3(merge2_out)\n", - "fc3_iaf_out = snn.fc3_iaf(fc3_out)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## DynapcnnNetwork Class\n", - "\n", - "In the constructor of `DynapcnnNetworkGraph` the SNN passed as argument (defined as a `nn.Module`) will be parsed such that each layer is represented in a computational graph (using `nirtorch.extract_torch_graph`). \n", - "\n", - "The layers are the `nodes` of the graph, while their connectivity (how the outputs from a layer are sent to other layers) is represented as `edges`, represented in a `list` of `tuples`.\n", - "\n", - "Once the constructor finishes its initialization, the `hw_model.dynapcnn_layers` property is a dictionary where each entry represents the ID of a `DynapcnnLayer` instance (an `int` from `0` to `L`), with this entry containing a `DynapcnnLayer` instance where a subset of the layers in the original SNN has been incorporated into, the core such instance has been assigned to, and the list of `DynapcnnLayer` instances (their IDs) the layer targets." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": { - "metadata": {} - }, - "outputs": [], - "source": [ - "hw_model = DynapcnnNetworkGraph(\n", - " snn,\n", - " discretize=True,\n", - " input_shape=input_shape\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The `hw_model.to()` call will figure out into which core eac `DynapcnnLayer` instance will be assigned to. Once this assingment is made the instance itself is used to configure the `CNNLayerConfig` instance representing the core's configuration.\n", - "\n", - "If the cores' configuration is valid, each `DynapcnnLayer` instance and their respective destinations will be used to create a computational graph that encodes how the `forward` method of `hw_model.network` (a `nn.Module` using the `DynapcnnLayer` instances) propagates that through the network." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": { - "metadata": {} - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Network is valid\n", - "(0, 1)\n", - "(0, 2)\n", - "(1, 2)\n", - "(2, 3)\n", - "(3, 4)\n", - "(4, 5)\n", - "(4, 6)\n", - "(5, 6)\n" - ] - }, - { - "ename": "RuntimeError", - "evalue": "Device is already opened!", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mRuntimeError\u001b[0m Traceback (most recent call last)", - "Cell \u001b[0;32mIn[8], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m hw_model\u001b[38;5;241m.\u001b[39mto(device\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mspeck2fmodule:0\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n", - "File \u001b[0;32m~/Documents/github/sinabs/sinabs/backend/dynapcnn/dynapcnn_network_graph.py:172\u001b[0m, in \u001b[0;36mDynapcnnNetworkGraph.to\u001b[0;34m(self, device, chip_layers_ordering, monitor_layers, config_modifier, slow_clk_frequency)\u001b[0m\n\u001b[1;32m 163\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m device_name \u001b[38;5;129;01min\u001b[39;00m ChipFactory\u001b[38;5;241m.\u001b[39msupported_devices: \u001b[38;5;66;03m# pragma: no cover\u001b[39;00m\n\u001b[1;32m 165\u001b[0m config \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mmake_config( \u001b[38;5;66;03m# generate config.\u001b[39;00m\n\u001b[1;32m 166\u001b[0m chip_layers_ordering\u001b[38;5;241m=\u001b[39mchip_layers_ordering,\n\u001b[1;32m 167\u001b[0m device\u001b[38;5;241m=\u001b[39mdevice,\n\u001b[1;32m 168\u001b[0m monitor_layers\u001b[38;5;241m=\u001b[39mmonitor_layers,\n\u001b[1;32m 169\u001b[0m config_modifier\u001b[38;5;241m=\u001b[39mconfig_modifier,\n\u001b[1;32m 170\u001b[0m )\n\u001b[0;32m--> 172\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39msamna_device \u001b[38;5;241m=\u001b[39m open_device(device) \u001b[38;5;66;03m# apply configuration to device.\u001b[39;00m\n\u001b[1;32m 173\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39msamna_device\u001b[38;5;241m.\u001b[39mget_model()\u001b[38;5;241m.\u001b[39mapply_configuration(config)\n\u001b[1;32m 174\u001b[0m time\u001b[38;5;241m.\u001b[39msleep(\u001b[38;5;241m1\u001b[39m)\n", - "File \u001b[0;32m~/Documents/github/sinabs/sinabs/backend/dynapcnn/io.py:256\u001b[0m, in \u001b[0;36mopen_device\u001b[0;34m(device_id)\u001b[0m\n\u001b[1;32m 254\u001b[0m device_map \u001b[38;5;241m=\u001b[39m get_device_map()\n\u001b[1;32m 255\u001b[0m device_info \u001b[38;5;241m=\u001b[39m device_map[device_id]\n\u001b[0;32m--> 256\u001b[0m device_handle \u001b[38;5;241m=\u001b[39m samna\u001b[38;5;241m.\u001b[39mdevice\u001b[38;5;241m.\u001b[39mopen_device(device_info)\n\u001b[1;32m 258\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m device_handle \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m 259\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m device_handle\n", - "\u001b[0;31mRuntimeError\u001b[0m: Device is already opened!" - ] - } - ], - "source": [ - "hw_model.to(device=\"speck2fmodule:0\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The layers comprising our `hw_model` and their respective metadata can be inspected by calling `print` on a `DynapcnnNetworkGraph` instance." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "metadata": {} - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "---- DynapcnnLayer 0 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 0): Conv2d(2, 10, kernel_size=(2, 2), stride=(1, 1), bias=False)\n", - "(node 1): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1.), min_v_mem=Parameter containing:\n", - "tensor(-32768.), batch_size=1, num_timesteps=-1)\n", - "(node 2): SumPool2d(norm_type=1, kernel_size=(3, 3), stride=None, ceil_mode=False)\n", - "(node 3): SumPool2d(norm_type=1, kernel_size=(4, 4), stride=None, ceil_mode=False)\n", - "> layer destinations: [1, 2]\n", - "> assigned core: 0\n", - "\n", - "---- DynapcnnLayer 1 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 4): Conv2d(10, 10, kernel_size=(4, 4), stride=(1, 1), bias=False)\n", - "(node 6): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1.), min_v_mem=Parameter containing:\n", - "tensor(-32768.), batch_size=1, num_timesteps=-1)\n", - "> layer destinations: [2]\n", - "> assigned core: 1\n", - "\n", - "---- DynapcnnLayer 2 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 7): Conv2d(10, 10, kernel_size=(2, 2), stride=(1, 1), bias=False)\n", - "(node 8): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1.), min_v_mem=Parameter containing:\n", - "tensor(-32768.), batch_size=1, num_timesteps=-1)\n", - "> layer destinations: [3]\n", - "> assigned core: 2\n", - "\n", - "---- DynapcnnLayer 3 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 9): Conv2d(10, 1, kernel_size=(2, 2), stride=(1, 1), bias=False)\n", - "(node 10): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1.), min_v_mem=Parameter containing:\n", - "tensor(-32768.), batch_size=1, num_timesteps=-1)\n", - "> layer destinations: [4]\n", - "> assigned core: 3\n", - "\n", - "---- DynapcnnLayer 4 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 11): Conv2d(1, 100, kernel_size=(6, 6), stride=(1, 1), bias=False)\n", - "(node 12): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1.), min_v_mem=Parameter containing:\n", - "tensor(-32768.), batch_size=1, num_timesteps=-1)\n", - "> layer destinations: [5, 6]\n", - "> assigned core: 4\n", - "\n", - "---- DynapcnnLayer 5 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 13): Conv2d(100, 100, kernel_size=(1, 1), stride=(1, 1), bias=False)\n", - "(node 15): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1.), min_v_mem=Parameter containing:\n", - "tensor(-32768.), batch_size=1, num_timesteps=-1)\n", - "> layer destinations: [6]\n", - "> assigned core: 5\n", - "\n", - "---- DynapcnnLayer 6 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 16): Conv2d(100, 10, kernel_size=(1, 1), stride=(1, 1), bias=False)\n", - "(node 17): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1.), min_v_mem=Parameter containing:\n", - "tensor(-32768.), batch_size=1, num_timesteps=-1)\n", - "> layer destinations: []\n", - "> assigned core: 6\n", - "\n", - "\n" - ] - } - ], - "source": [ - "print(hw_model)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "speck-rescnn", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.3" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/tests/test_nonsequential/DYNAPCNNNETWORK_EXAMPLES/DynapcnnNetwork-example_5.ipynb b/tests/test_nonsequential/DYNAPCNNNETWORK_EXAMPLES/DynapcnnNetwork-example_5.ipynb deleted file mode 100644 index 4b3fcddb..00000000 --- a/tests/test_nonsequential/DYNAPCNNNETWORK_EXAMPLES/DynapcnnNetwork-example_5.ipynb +++ /dev/null @@ -1,400 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": { - "metadata": {} - }, - "outputs": [], - "source": [ - "import torch\n", - "import torch.nn as nn\n", - "from sinabs.backend.dynapcnn import DynapcnnNetworkGraph\n", - "from sinabs.layers import Merge, IAFSqueeze" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": { - "metadata": {} - }, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "torch.manual_seed(0)" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": { - "metadata": {} - }, - "outputs": [], - "source": [ - "channels = 2\n", - "height = 34\n", - "width = 34\n", - "\n", - "input_shape = (channels, height, width)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Network Module\n", - "\n", - "We need to define a `nn.Module` implementing the network we want the chip to reproduce." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": { - "metadata": {} - }, - "outputs": [], - "source": [ - "class SNN(nn.Module):\n", - " def __init__(self) -> None:\n", - " super().__init__()\n", - "\n", - " self.conv1 = nn.Conv2d(2, 10, 2, 1, bias=False)\n", - " self.conv1_iaf = IAFSqueeze(batch_size=1)\n", - " self.pool1 = nn.AvgPool2d(3,3)\n", - " self.pool1a = nn.AvgPool2d(4,4)\n", - "\n", - " self.conv2 = nn.Conv2d(10, 10, 4, 1, bias=False)\n", - " self.conv2_iaf = IAFSqueeze(batch_size=1)\n", - "\n", - " self.conv3 = nn.Conv2d(10, 10, 2, 1, bias=False)\n", - " self.conv3_iaf = IAFSqueeze(batch_size=1)\n", - "\n", - " self.conv4 = nn.Conv2d(10, 1, 2, 1, bias=False)\n", - " self.conv4_iaf = IAFSqueeze(batch_size=1)\n", - "\n", - " self.flat = nn.Flatten()\n", - "\n", - " self.fc1 = nn.Linear(36, 100, bias=False)\n", - " self.fc1_iaf = IAFSqueeze(batch_size=1)\n", - " \n", - " self.fc2 = nn.Linear(100, 100, bias=False)\n", - " self.fc2_iaf = IAFSqueeze(batch_size=1)\n", - "\n", - " self.fc3 = nn.Linear(100, 100, bias=False)\n", - " self.fc3_iaf = IAFSqueeze(batch_size=1)\n", - "\n", - " self.fc4 = nn.Linear(100, 10, bias=False)\n", - " self.fc4_iaf = IAFSqueeze(batch_size=1)\n", - "\n", - " self.merge1 = Merge()\n", - " self.merge2 = Merge()\n", - " self.merge3 = Merge()\n", - "\n", - " def forward(self, x):\n", - " # -- conv. block 0 --\n", - " con1_out = self.conv1(x)\n", - " conv1_iaf_out = self.conv1_iaf(con1_out)\n", - " pool1_out = self.pool1(conv1_iaf_out)\n", - " pool1a_out = self.pool1a(conv1_iaf_out)\n", - " # -- conv. block 1 --\n", - " conv2_out = self.conv2(pool1_out)\n", - " conv2_iaf_out = self.conv2_iaf(conv2_out)\n", - " # -- conv. block 2 --\n", - " merge1_out = self.merge1(pool1a_out, conv2_iaf_out)\n", - " conv3_out = self.conv3(merge1_out)\n", - " conv3_iaf_out = self.conv3_iaf(conv3_out)\n", - " # -- conv. block 3 --\n", - " conv4_out = self.conv4(conv3_iaf_out)\n", - " conv4_iaf_out = self.conv4_iaf(conv4_out)\n", - " flat_out = self.flat(conv4_iaf_out)\n", - " # -- fc clock 4 --\n", - " fc1_out = self.fc1(flat_out)\n", - " fc1_iaf_out = self.fc1_iaf(fc1_out)\n", - " # -- fc clock 5 --\n", - " fc2_out = self.fc2(fc1_iaf_out)\n", - " fc2_iaf_out = self.fc2_iaf(fc2_out)\n", - " # -- fc clock 6 --\n", - " merge2_out = self.merge2(fc1_iaf_out, fc2_iaf_out)\n", - " fc3_out = self.fc3(merge2_out)\n", - " fc3_iaf_out = self.fc3_iaf(fc3_out)\n", - " # -- fc clock 7 --\n", - " merge3_out = self.merge3(fc2_iaf_out, fc3_iaf_out)\n", - " fc4_out = self.fc4(merge3_out)\n", - " fc4_iaf_out = self.fc4_iaf(fc4_out)\n", - "\n", - " return fc4_iaf_out" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": { - "metadata": {} - }, - "outputs": [], - "source": [ - "snn = SNN()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The following exemplifies how each of the layers in the SNN should be grouped together to form a `DynapcnnLayer` instance. Let's check the shapes of the tensors each of the (original) layers in the model inputs and outputs by feeding a fake input through the model:" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": { - "metadata": {} - }, - "outputs": [], - "source": [ - "x = torch.randn((1, *input_shape))\n", - "\n", - "# -- conv. block 0 --\n", - "con1_out = snn.conv1(x)\n", - "conv1_iaf_out = snn.conv1_iaf(con1_out)\n", - "pool1_out = snn.pool1(conv1_iaf_out)\n", - "pool1a_out = snn.pool1a(conv1_iaf_out)\n", - "# -- conv. block 1 --\n", - "conv2_out = snn.conv2(pool1_out)\n", - "conv2_iaf_out = snn.conv2_iaf(conv2_out)\n", - "# -- conv. block 2 --\n", - "merge1_out = snn.merge1(pool1a_out, conv2_iaf_out)\n", - "conv3_out = snn.conv3(merge1_out)\n", - "conv3_iaf_out = snn.conv3_iaf(conv3_out)\n", - "# -- conv. block 3 --\n", - "conv4_out = snn.conv4(conv3_iaf_out)\n", - "conv4_iaf_out = snn.conv4_iaf(conv4_out)\n", - "flat_out = snn.flat(conv4_iaf_out)\n", - "# -- fc clock 4 --\n", - "fc1_out = snn.fc1(flat_out)\n", - "fc1_iaf_out = snn.fc1_iaf(fc1_out)\n", - "# -- fc clock 5 --\n", - "fc2_out = snn.fc2(fc1_iaf_out)\n", - "fc2_iaf_out = snn.fc2_iaf(fc2_out)\n", - "# -- fc clock 6 --\n", - "merge2_out = snn.merge2(fc1_iaf_out, fc2_iaf_out)\n", - "fc3_out = snn.fc3(merge2_out)\n", - "fc3_iaf_out = snn.fc3_iaf(fc3_out)\n", - "# -- fc clock 7 --\n", - "merge3_out = snn.merge3(fc2_iaf_out, fc3_iaf_out)\n", - "fc4_out = snn.fc4(merge3_out)\n", - "fc4_iaf_out = snn.fc4_iaf(fc4_out)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## DynapcnnNetwork Class\n", - "\n", - "In the constructor of `DynapcnnNetworkGraph` the SNN passed as argument (defined as a `nn.Module`) will be parsed such that each layer is represented in a computational graph (using `nirtorch.extract_torch_graph`). \n", - "\n", - "The layers are the `nodes` of the graph, while their connectivity (how the outputs from a layer are sent to other layers) is represented as `edges`, represented in a `list` of `tuples`.\n", - "\n", - "Once the constructor finishes its initialization, the `hw_model.dynapcnn_layers` property is a dictionary where each entry represents the ID of a `DynapcnnLayer` instance (an `int` from `0` to `L`), with this entry containing a `DynapcnnLayer` instance where a subset of the layers in the original SNN has been incorporated into, the core such instance has been assigned to, and the list of `DynapcnnLayer` instances (their IDs) the layer targets." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": { - "metadata": {} - }, - "outputs": [], - "source": [ - "hw_model = DynapcnnNetworkGraph(\n", - " snn,\n", - " discretize=True,\n", - " input_shape=input_shape\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The `hw_model.to()` call will figure out into which core eac `DynapcnnLayer` instance will be assigned to. Once this assingment is made the instance itself is used to configure the `CNNLayerConfig` instance representing the core's configuration.\n", - "\n", - "If the cores' configuration is valid, each `DynapcnnLayer` instance and their respective destinations will be used to create a computational graph that encodes how the `forward` method of `hw_model.network` (a `nn.Module` using the `DynapcnnLayer` instances) propagates that through the network." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": { - "metadata": {} - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Network is valid\n", - "(0, 1)\n", - "(0, 2)\n", - "(1, 2)\n", - "(2, 3)\n", - "(3, 4)\n", - "(4, 5)\n", - "(4, 6)\n", - "(5, 6)\n", - "(5, 7)\n", - "(6, 7)\n" - ] - }, - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "hw_model.to(device=\"speck2fmodule:0\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The layers comprising our `hw_model` and their respective metadata can be inspected by calling `print` on a `DynapcnnNetworkGraph` instance." - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": { - "metadata": {} - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "---- DynapcnnLayer 0 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 0): Conv2d(2, 10, kernel_size=(2, 2), stride=(1, 1), bias=False)\n", - "(node 1): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1.), min_v_mem=Parameter containing:\n", - "tensor(-32768.), batch_size=1, num_timesteps=-1)\n", - "(node 2): SumPool2d(norm_type=1, kernel_size=(3, 3), stride=None, ceil_mode=False)\n", - "(node 3): SumPool2d(norm_type=1, kernel_size=(4, 4), stride=None, ceil_mode=False)\n", - "> layer destinations: [1, 2]\n", - "> assigned core: 0\n", - "\n", - "---- DynapcnnLayer 1 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 4): Conv2d(10, 10, kernel_size=(4, 4), stride=(1, 1), bias=False)\n", - "(node 6): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1.), min_v_mem=Parameter containing:\n", - "tensor(-32768.), batch_size=1, num_timesteps=-1)\n", - "> layer destinations: [2]\n", - "> assigned core: 1\n", - "\n", - "---- DynapcnnLayer 2 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 7): Conv2d(10, 10, kernel_size=(2, 2), stride=(1, 1), bias=False)\n", - "(node 8): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1.), min_v_mem=Parameter containing:\n", - "tensor(-32768.), batch_size=1, num_timesteps=-1)\n", - "> layer destinations: [3]\n", - "> assigned core: 2\n", - "\n", - "---- DynapcnnLayer 3 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 9): Conv2d(10, 1, kernel_size=(2, 2), stride=(1, 1), bias=False)\n", - "(node 10): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1.), min_v_mem=Parameter containing:\n", - "tensor(-32768.), batch_size=1, num_timesteps=-1)\n", - "> layer destinations: [4]\n", - "> assigned core: 3\n", - "\n", - "---- DynapcnnLayer 4 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 11): Conv2d(1, 100, kernel_size=(6, 6), stride=(1, 1), bias=False)\n", - "(node 12): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1.), min_v_mem=Parameter containing:\n", - "tensor(-32768.), batch_size=1, num_timesteps=-1)\n", - "> layer destinations: [5, 6]\n", - "> assigned core: 4\n", - "\n", - "---- DynapcnnLayer 5 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 13): Conv2d(100, 100, kernel_size=(1, 1), stride=(1, 1), bias=False)\n", - "(node 15): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1.), min_v_mem=Parameter containing:\n", - "tensor(-32768.), batch_size=1, num_timesteps=-1)\n", - "> layer destinations: [6, 7]\n", - "> assigned core: 5\n", - "\n", - "---- DynapcnnLayer 6 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 17): Conv2d(100, 100, kernel_size=(1, 1), stride=(1, 1), bias=False)\n", - "(node 18): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1.), min_v_mem=Parameter containing:\n", - "tensor(-32768.), batch_size=1, num_timesteps=-1)\n", - "> layer destinations: [7]\n", - "> assigned core: 6\n", - "\n", - "---- DynapcnnLayer 7 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 19): Conv2d(100, 10, kernel_size=(1, 1), stride=(1, 1), bias=False)\n", - "(node 20): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1.), min_v_mem=Parameter containing:\n", - "tensor(-32768.), batch_size=1, num_timesteps=-1)\n", - "> layer destinations: []\n", - "> assigned core: 7\n", - "\n", - "\n" - ] - } - ], - "source": [ - "print(hw_model)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "speck-rescnn", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.3" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/tests/test_nonsequential/DYNAPCNNNETWORK_EXAMPLES/DynapcnnNetwork-example_5a.ipynb b/tests/test_nonsequential/DYNAPCNNNETWORK_EXAMPLES/DynapcnnNetwork-example_5a.ipynb deleted file mode 100644 index 991e48fa..00000000 --- a/tests/test_nonsequential/DYNAPCNNNETWORK_EXAMPLES/DynapcnnNetwork-example_5a.ipynb +++ /dev/null @@ -1,390 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": { - "metadata": {} - }, - "outputs": [], - "source": [ - "import torch\n", - "import torch.nn as nn\n", - "from sinabs.backend.dynapcnn import DynapcnnNetworkGraph\n", - "from sinabs.layers import Merge, IAFSqueeze, SumPool2d" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": { - "metadata": {} - }, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "torch.manual_seed(0)" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": { - "metadata": {} - }, - "outputs": [], - "source": [ - "channels = 2\n", - "height = 34\n", - "width = 34\n", - "\n", - "input_shape = (channels, height, width)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Network Module\n", - "\n", - "We need to define a `nn.Module` implementing the network we want the chip to reproduce." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": { - "metadata": {} - }, - "outputs": [], - "source": [ - "class SNN(nn.Module):\n", - " def __init__(self) -> None:\n", - " super().__init__()\n", - "\n", - " self.conv1 = nn.Conv2d(2, 10, 2, 1, bias=False)\n", - " self.conv1_iaf = IAFSqueeze(batch_size=1)\n", - " self.pool1 = SumPool2d(3,3)\n", - " self.pool1a = SumPool2d(4,4)\n", - "\n", - " self.conv2 = nn.Conv2d(10, 10, 4, 1, bias=False)\n", - " self.conv2_iaf = IAFSqueeze(batch_size=1)\n", - "\n", - " self.conv3 = nn.Conv2d(10, 10, 2, 1, bias=False)\n", - " self.conv3_iaf = IAFSqueeze(batch_size=1)\n", - "\n", - " self.conv4 = nn.Conv2d(10, 1, 2, 1, bias=False)\n", - " self.conv4_iaf = IAFSqueeze(batch_size=1)\n", - "\n", - " self.flat = nn.Flatten()\n", - "\n", - " self.fc1 = nn.Linear(36, 100, bias=False)\n", - " self.fc1_iaf = IAFSqueeze(batch_size=1)\n", - " \n", - " self.fc2 = nn.Linear(100, 100, bias=False)\n", - " self.fc2_iaf = IAFSqueeze(batch_size=1)\n", - "\n", - " self.fc3 = nn.Linear(100, 100, bias=False)\n", - " self.fc3_iaf = IAFSqueeze(batch_size=1)\n", - "\n", - " self.fc4 = nn.Linear(100, 10, bias=False)\n", - " self.fc4_iaf = IAFSqueeze(batch_size=1)\n", - "\n", - " self.merge1 = Merge()\n", - " self.merge2 = Merge()\n", - " self.merge3 = Merge()\n", - "\n", - " def forward(self, x):\n", - " # -- conv. block 0 --\n", - " con1_out = self.conv1(x)\n", - " conv1_iaf_out = self.conv1_iaf(con1_out)\n", - " pool1_out = self.pool1(conv1_iaf_out)\n", - " pool1a_out = self.pool1a(conv1_iaf_out)\n", - " # -- conv. block 1 --\n", - " conv2_out = self.conv2(pool1_out)\n", - " conv2_iaf_out = self.conv2_iaf(conv2_out)\n", - " # -- conv. block 2 --\n", - " merge1_out = self.merge1(pool1a_out, conv2_iaf_out)\n", - " conv3_out = self.conv3(merge1_out)\n", - " conv3_iaf_out = self.conv3_iaf(conv3_out)\n", - " # -- conv. block 3 --\n", - " conv4_out = self.conv4(conv3_iaf_out)\n", - " conv4_iaf_out = self.conv4_iaf(conv4_out)\n", - " flat_out = self.flat(conv4_iaf_out)\n", - " # -- fc clock 4 --\n", - " fc1_out = self.fc1(flat_out)\n", - " fc1_iaf_out = self.fc1_iaf(fc1_out)\n", - " # -- fc clock 5 --\n", - " fc2_out = self.fc2(fc1_iaf_out)\n", - " fc2_iaf_out = self.fc2_iaf(fc2_out)\n", - " # -- fc clock 6 --\n", - " merge2_out = self.merge2(fc1_iaf_out, fc2_iaf_out)\n", - " fc3_out = self.fc3(merge2_out)\n", - " fc3_iaf_out = self.fc3_iaf(fc3_out)\n", - " # -- fc clock 7 --\n", - " merge3_out = self.merge3(fc2_iaf_out, fc3_iaf_out)\n", - " fc4_out = self.fc4(merge3_out)\n", - " fc4_iaf_out = self.fc4_iaf(fc4_out)\n", - "\n", - " return fc4_iaf_out" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": { - "metadata": {} - }, - "outputs": [], - "source": [ - "snn = SNN()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The following exemplifies how each of the layers in the SNN should be grouped together to form a `DynapcnnLayer` instance. Let's check the shapes of the tensors each of the (original) layers in the model inputs and outputs by feeding a fake input through the model:" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": { - "metadata": {} - }, - "outputs": [], - "source": [ - "x = torch.randn((1, *input_shape))\n", - "\n", - "# -- conv. block 0 --\n", - "con1_out = snn.conv1(x)\n", - "conv1_iaf_out = snn.conv1_iaf(con1_out)\n", - "pool1_out = snn.pool1(conv1_iaf_out)\n", - "pool1a_out = snn.pool1a(conv1_iaf_out)\n", - "# -- conv. block 1 --\n", - "conv2_out = snn.conv2(pool1_out)\n", - "conv2_iaf_out = snn.conv2_iaf(conv2_out)\n", - "# -- conv. block 2 --\n", - "merge1_out = snn.merge1(pool1a_out, conv2_iaf_out)\n", - "conv3_out = snn.conv3(merge1_out)\n", - "conv3_iaf_out = snn.conv3_iaf(conv3_out)\n", - "# -- conv. block 3 --\n", - "conv4_out = snn.conv4(conv3_iaf_out)\n", - "conv4_iaf_out = snn.conv4_iaf(conv4_out)\n", - "flat_out = snn.flat(conv4_iaf_out)\n", - "# -- fc clock 4 --\n", - "fc1_out = snn.fc1(flat_out)\n", - "fc1_iaf_out = snn.fc1_iaf(fc1_out)\n", - "# -- fc clock 5 --\n", - "fc2_out = snn.fc2(fc1_iaf_out)\n", - "fc2_iaf_out = snn.fc2_iaf(fc2_out)\n", - "# -- fc clock 6 --\n", - "merge2_out = snn.merge2(fc1_iaf_out, fc2_iaf_out)\n", - "fc3_out = snn.fc3(merge2_out)\n", - "fc3_iaf_out = snn.fc3_iaf(fc3_out)\n", - "# -- fc clock 7 --\n", - "merge3_out = snn.merge3(fc2_iaf_out, fc3_iaf_out)\n", - "fc4_out = snn.fc4(merge3_out)\n", - "fc4_iaf_out = snn.fc4_iaf(fc4_out)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## DynapcnnNetwork Class\n", - "\n", - "In the constructor of `DynapcnnNetworkGraph` the SNN passed as argument (defined as a `nn.Module`) will be parsed such that each layer is represented in a computational graph (using `nirtorch.extract_torch_graph`). \n", - "\n", - "The layers are the `nodes` of the graph, while their connectivity (how the outputs from a layer are sent to other layers) is represented as `edges`, represented in a `list` of `tuples`.\n", - "\n", - "Once the constructor finishes its initialization, the `hw_model.dynapcnn_layers` property is a dictionary where each entry represents the ID of a `DynapcnnLayer` instance (an `int` from `0` to `L`), with this entry containing a `DynapcnnLayer` instance where a subset of the layers in the original SNN has been incorporated into, the core such instance has been assigned to, and the list of `DynapcnnLayer` instances (their IDs) the layer targets." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": { - "metadata": {} - }, - "outputs": [], - "source": [ - "hw_model = DynapcnnNetworkGraph(\n", - " snn,\n", - " discretize=True,\n", - " input_shape=input_shape\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The `hw_model.to()` call will figure out into which core eac `DynapcnnLayer` instance will be assigned to. Once this assingment is made the instance itself is used to configure the `CNNLayerConfig` instance representing the core's configuration.\n", - "\n", - "If the cores' configuration is valid, each `DynapcnnLayer` instance and their respective destinations will be used to create a computational graph that encodes how the `forward` method of `hw_model.network` (a `nn.Module` using the `DynapcnnLayer` instances) propagates that through the network." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": { - "metadata": {} - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Network is valid\n" - ] - }, - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "hw_model.to(device=\"speck2fmodule:0\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The layers comprising our `hw_model` and their respective metadata can be inspected by calling `print` on a `DynapcnnNetworkGraph` instance." - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": { - "metadata": {} - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "---- DynapcnnLayer 0 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 0): Conv2d(2, 10, kernel_size=(2, 2), stride=(1, 1), bias=False)\n", - "(node 1): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1.), min_v_mem=Parameter containing:\n", - "tensor(-32768.), batch_size=1, num_timesteps=-1)\n", - "(node 2): SumPool2d(norm_type=1, kernel_size=3, stride=3, ceil_mode=False)\n", - "(node 3): SumPool2d(norm_type=1, kernel_size=4, stride=4, ceil_mode=False)\n", - "> layer destinations: [1, 2]\n", - "> assigned core: 0\n", - "\n", - "---- DynapcnnLayer 1 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 4): Conv2d(10, 10, kernel_size=(4, 4), stride=(1, 1), bias=False)\n", - "(node 6): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1.), min_v_mem=Parameter containing:\n", - "tensor(-32768.), batch_size=1, num_timesteps=-1)\n", - "> layer destinations: [2]\n", - "> assigned core: 1\n", - "\n", - "---- DynapcnnLayer 2 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 7): Conv2d(10, 10, kernel_size=(2, 2), stride=(1, 1), bias=False)\n", - "(node 8): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1.), min_v_mem=Parameter containing:\n", - "tensor(-32768.), batch_size=1, num_timesteps=-1)\n", - "> layer destinations: [3]\n", - "> assigned core: 2\n", - "\n", - "---- DynapcnnLayer 3 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 9): Conv2d(10, 1, kernel_size=(2, 2), stride=(1, 1), bias=False)\n", - "(node 10): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1.), min_v_mem=Parameter containing:\n", - "tensor(-32768.), batch_size=1, num_timesteps=-1)\n", - "> layer destinations: [4]\n", - "> assigned core: 3\n", - "\n", - "---- DynapcnnLayer 4 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 11): Conv2d(1, 100, kernel_size=(6, 6), stride=(1, 1), bias=False)\n", - "(node 12): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1.), min_v_mem=Parameter containing:\n", - "tensor(-32768.), batch_size=1, num_timesteps=-1)\n", - "> layer destinations: [5, 6]\n", - "> assigned core: 4\n", - "\n", - "---- DynapcnnLayer 5 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 13): Conv2d(100, 100, kernel_size=(1, 1), stride=(1, 1), bias=False)\n", - "(node 15): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1.), min_v_mem=Parameter containing:\n", - "tensor(-32768.), batch_size=1, num_timesteps=-1)\n", - "> layer destinations: [6, 7]\n", - "> assigned core: 5\n", - "\n", - "---- DynapcnnLayer 6 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 17): Conv2d(100, 100, kernel_size=(1, 1), stride=(1, 1), bias=False)\n", - "(node 18): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1.), min_v_mem=Parameter containing:\n", - "tensor(-32768.), batch_size=1, num_timesteps=-1)\n", - "> layer destinations: [7]\n", - "> assigned core: 6\n", - "\n", - "---- DynapcnnLayer 7 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 19): Conv2d(100, 10, kernel_size=(1, 1), stride=(1, 1), bias=False)\n", - "(node 20): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1.), min_v_mem=Parameter containing:\n", - "tensor(-32768.), batch_size=1, num_timesteps=-1)\n", - "> layer destinations: []\n", - "> assigned core: 7\n", - "\n", - "\n" - ] - } - ], - "source": [ - "print(hw_model)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "speck-rescnn", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.3" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/tests/test_nonsequential/DYNAPCNNNETWORK_EXAMPLES/DynapcnnNetwork-example_6.ipynb b/tests/test_nonsequential/DYNAPCNNNETWORK_EXAMPLES/DynapcnnNetwork-example_6.ipynb deleted file mode 100644 index 9a8dc655..00000000 --- a/tests/test_nonsequential/DYNAPCNNNETWORK_EXAMPLES/DynapcnnNetwork-example_6.ipynb +++ /dev/null @@ -1,422 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": { - "metadata": {} - }, - "outputs": [], - "source": [ - "import torch\n", - "import torch.nn as nn\n", - "from sinabs.backend.dynapcnn import DynapcnnNetworkGraph\n", - "from sinabs.layers import Merge, IAFSqueeze, SumPool2d\n", - "import sinabs.layers as sl\n", - "from sinabs.activation.surrogate_gradient_fn import PeriodicExponential" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": { - "metadata": {} - }, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "torch.manual_seed(0)" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": { - "metadata": {} - }, - "outputs": [], - "source": [ - "channels = 2\n", - "height = 34\n", - "width = 34\n", - "\n", - "input_shape = (channels, height, width)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Network Module\n", - "\n", - "We need to define a `nn.Module` implementing the network we want the chip to reproduce." - ] - }, - { - "cell_type": "code", - "execution_count": 67, - "metadata": { - "metadata": {} - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "torch.Size([8, 128])\n" - ] - }, - { - "data": { - "text/plain": [ - "tensor([[0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],\n", - " [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],\n", - " [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],\n", - " [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],\n", - " [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],\n", - " [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],\n", - " [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],\n", - " [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]], grad_fn=)" - ] - }, - "execution_count": 67, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "class SNN(nn.Module):\n", - " def __init__(self, nb_classes, batch_size, surrogate_fn, min_v_mem=-0.313, spk_thr=2.0) -> None:\n", - " super().__init__()\n", - "\n", - " self.conv1 = nn.Conv2d(2, 1, 2, 1, bias=False)\n", - " self.iaf1 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr)\n", - " self.pool1 = sl.SumPool2d(2,2)\n", - "\n", - " self.conv2 = nn.Conv2d(1, 8, 2, 1, bias=False)\n", - " self.iaf2 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr)\n", - " self.pool2 = sl.SumPool2d(2,2)\n", - "\n", - " self.conv3 = nn.Conv2d(8, 16, 2, 1, bias=False)\n", - " self.iaf3 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr)\n", - " self.pool3 = sl.SumPool2d(2,2)\n", - "\n", - " self.conv4 = nn.Conv2d(16, 32, 2, 1, bias=False)\n", - " self.iaf4 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr)\n", - "\n", - " self.flat = nn.Flatten()\n", - "\n", - " self.fc1 = nn.Linear(128, 1024, bias=False)\n", - " self.iaf1_fc = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr)\n", - "\n", - " self.fc2 = nn.Linear(1024, 512, bias=False)\n", - " self.iaf2_fc = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr)\n", - "\n", - " self.fc3 = nn.Linear(512, 256, bias=False)\n", - " self.iaf3_fc = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr)\n", - "\n", - " self.fc4 = nn.Linear(256, 128, bias=False)\n", - " self.iaf4_fc = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr)\n", - "\n", - " self.fc5 = nn.Linear(128, nb_classes, bias=False)\n", - " self.iaf5_fc = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr)\n", - "\n", - " def forward(self, x):\n", - " # conv 1\n", - " con1_out = self.conv1(x)\n", - " iaf1_out = self.iaf1(con1_out)\n", - " pool1_out = self.pool1(iaf1_out)\n", - "\n", - " # conv 2\n", - " conv2_out = self.conv2(pool1_out)\n", - " iaf2_out = self.iaf2(conv2_out)\n", - " pool2_out = self.pool2(iaf2_out)\n", - "\n", - " # conv 3\n", - " conv3_out = self.conv3(pool2_out)\n", - " iaf3_out = self.iaf3(conv3_out)\n", - " pool3_out = self.pool3(iaf3_out)\n", - "\n", - " # conv 4\n", - " conv4_out = self.conv4(pool3_out)\n", - " iaf4_out = self.iaf4(conv4_out)\n", - "\n", - " flat_out = self.flat(iaf4_out)\n", - " \n", - " # fc 1\n", - " print(flat_out.shape)\n", - " fc1_out = self.fc1(flat_out)\n", - " iaf1_fc_out = self.iaf1_fc(fc1_out)\n", - "\n", - " # fc 2\n", - " fc2_out = self.fc2(iaf1_fc_out)\n", - " iaf2_fc_out = self.iaf2_fc(fc2_out)\n", - "\n", - " # fc 3\n", - " fc3_out = self.fc3(iaf2_fc_out)\n", - " iaf3_fc_out = self.iaf3_fc(fc3_out)\n", - "\n", - " # fc 4\n", - " fc4_out = self.fc4(iaf3_fc_out)\n", - " iaf4_fc_out = self.iaf4_fc(fc4_out)\n", - "\n", - " # fc 5\n", - " fc5_out = self.fc5(iaf4_fc_out)\n", - " iaf5_fc_out = self.iaf5_fc(fc5_out)\n", - "\n", - " return iaf5_fc_out\n", - " \n", - "snn = SNN(11, 8, PeriodicExponential())\n", - "\n", - "x = torch.randn((8, *input_shape))\n", - "\n", - "snn(x)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The following exemplifies how each of the layers in the SNN should be grouped together to form a `DynapcnnLayer` instance. Let's check the shapes of the tensors each of the (original) layers in the model inputs and outputs by feeding a fake input through the model:" - ] - }, - { - "cell_type": "code", - "execution_count": 30, - "metadata": { - "metadata": {} - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "torch.Size([8, 8, 17, 17])\n", - "torch.Size([8, 8, 16, 16])\n", - "torch.Size([8, 8, 1, 1])\n", - "torch.Size([8, 8])\n" - ] - }, - { - "ename": "RuntimeError", - "evalue": "mat1 and mat2 shapes cannot be multiplied (8x8 and 800x11)", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mRuntimeError\u001b[0m Traceback (most recent call last)", - "Cell \u001b[0;32mIn[30], line 3\u001b[0m\n\u001b[1;32m 1\u001b[0m x \u001b[38;5;241m=\u001b[39m torch\u001b[38;5;241m.\u001b[39mrandn((\u001b[38;5;241m8\u001b[39m, \u001b[38;5;241m*\u001b[39minput_shape))\n\u001b[0;32m----> 3\u001b[0m snn(x)\n", - "File \u001b[0;32m~/.local/lib/python3.11/site-packages/torch/nn/modules/module.py:1511\u001b[0m, in \u001b[0;36mModule._wrapped_call_impl\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m 1509\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_compiled_call_impl(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs) \u001b[38;5;66;03m# type: ignore[misc]\u001b[39;00m\n\u001b[1;32m 1510\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m-> 1511\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_call_impl(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n", - "File \u001b[0;32m~/.local/lib/python3.11/site-packages/torch/nn/modules/module.py:1520\u001b[0m, in \u001b[0;36mModule._call_impl\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m 1515\u001b[0m \u001b[38;5;66;03m# If we don't have any hooks, we want to skip the rest of the logic in\u001b[39;00m\n\u001b[1;32m 1516\u001b[0m \u001b[38;5;66;03m# this function, and just call forward.\u001b[39;00m\n\u001b[1;32m 1517\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m (\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_backward_hooks \u001b[38;5;129;01mor\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_backward_pre_hooks \u001b[38;5;129;01mor\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_forward_hooks \u001b[38;5;129;01mor\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_forward_pre_hooks\n\u001b[1;32m 1518\u001b[0m \u001b[38;5;129;01mor\u001b[39;00m _global_backward_pre_hooks \u001b[38;5;129;01mor\u001b[39;00m _global_backward_hooks\n\u001b[1;32m 1519\u001b[0m \u001b[38;5;129;01mor\u001b[39;00m _global_forward_hooks \u001b[38;5;129;01mor\u001b[39;00m _global_forward_pre_hooks):\n\u001b[0;32m-> 1520\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m forward_call(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n\u001b[1;32m 1522\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m 1523\u001b[0m result \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m\n", - "Cell \u001b[0;32mIn[28], line 74\u001b[0m, in \u001b[0;36mSNN.forward\u001b[0;34m(self, x)\u001b[0m\n\u001b[1;32m 72\u001b[0m flat \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mflat(iaf8_out)\n\u001b[1;32m 73\u001b[0m \u001b[38;5;28mprint\u001b[39m(flat\u001b[38;5;241m.\u001b[39mshape)\n\u001b[0;32m---> 74\u001b[0m fc_out \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mfc_out(flat)\n\u001b[1;32m 75\u001b[0m iaf_fc_out \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39miaf_fc_out(fc_out)\n\u001b[1;32m 78\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m iaf_fc_out\n", - "File \u001b[0;32m~/.local/lib/python3.11/site-packages/torch/nn/modules/module.py:1511\u001b[0m, in \u001b[0;36mModule._wrapped_call_impl\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m 1509\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_compiled_call_impl(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs) \u001b[38;5;66;03m# type: ignore[misc]\u001b[39;00m\n\u001b[1;32m 1510\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m-> 1511\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_call_impl(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n", - "File \u001b[0;32m~/.local/lib/python3.11/site-packages/torch/nn/modules/module.py:1520\u001b[0m, in \u001b[0;36mModule._call_impl\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m 1515\u001b[0m \u001b[38;5;66;03m# If we don't have any hooks, we want to skip the rest of the logic in\u001b[39;00m\n\u001b[1;32m 1516\u001b[0m \u001b[38;5;66;03m# this function, and just call forward.\u001b[39;00m\n\u001b[1;32m 1517\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m (\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_backward_hooks \u001b[38;5;129;01mor\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_backward_pre_hooks \u001b[38;5;129;01mor\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_forward_hooks \u001b[38;5;129;01mor\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_forward_pre_hooks\n\u001b[1;32m 1518\u001b[0m \u001b[38;5;129;01mor\u001b[39;00m _global_backward_pre_hooks \u001b[38;5;129;01mor\u001b[39;00m _global_backward_hooks\n\u001b[1;32m 1519\u001b[0m \u001b[38;5;129;01mor\u001b[39;00m _global_forward_hooks \u001b[38;5;129;01mor\u001b[39;00m _global_forward_pre_hooks):\n\u001b[0;32m-> 1520\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m forward_call(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n\u001b[1;32m 1522\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m 1523\u001b[0m result \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m\n", - "File \u001b[0;32m~/.local/lib/python3.11/site-packages/torch/nn/modules/linear.py:116\u001b[0m, in \u001b[0;36mLinear.forward\u001b[0;34m(self, input)\u001b[0m\n\u001b[1;32m 115\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mforward\u001b[39m(\u001b[38;5;28mself\u001b[39m, \u001b[38;5;28minput\u001b[39m: Tensor) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m Tensor:\n\u001b[0;32m--> 116\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m F\u001b[38;5;241m.\u001b[39mlinear(\u001b[38;5;28minput\u001b[39m, \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mweight, \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mbias)\n", - "\u001b[0;31mRuntimeError\u001b[0m: mat1 and mat2 shapes cannot be multiplied (8x8 and 800x11)" - ] - } - ], - "source": [ - "x = torch.randn((8, *input_shape))\n", - "\n", - "snn(x)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## DynapcnnNetwork Class\n", - "\n", - "In the constructor of `DynapcnnNetworkGraph` the SNN passed as argument (defined as a `nn.Module`) will be parsed such that each layer is represented in a computational graph (using `nirtorch.extract_torch_graph`). \n", - "\n", - "The layers are the `nodes` of the graph, while their connectivity (how the outputs from a layer are sent to other layers) is represented as `edges`, represented in a `list` of `tuples`.\n", - "\n", - "Once the constructor finishes its initialization, the `hw_model.dynapcnn_layers` property is a dictionary where each entry represents the ID of a `DynapcnnLayer` instance (an `int` from `0` to `L`), with this entry containing a `DynapcnnLayer` instance where a subset of the layers in the original SNN has been incorporated into, the core such instance has been assigned to, and the list of `DynapcnnLayer` instances (their IDs) the layer targets." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": { - "metadata": {} - }, - "outputs": [], - "source": [ - "hw_model = DynapcnnNetworkGraph(\n", - " snn,\n", - " discretize=True,\n", - " input_shape=input_shape\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The `hw_model.to()` call will figure out into which core eac `DynapcnnLayer` instance will be assigned to. Once this assingment is made the instance itself is used to configure the `CNNLayerConfig` instance representing the core's configuration.\n", - "\n", - "If the cores' configuration is valid, each `DynapcnnLayer` instance and their respective destinations will be used to create a computational graph that encodes how the `forward` method of `hw_model.network` (a `nn.Module` using the `DynapcnnLayer` instances) propagates that through the network." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": { - "metadata": {} - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Network is valid\n" - ] - }, - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "hw_model.to(device=\"speck2fmodule:0\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The layers comprising our `hw_model` and their respective metadata can be inspected by calling `print` on a `DynapcnnNetworkGraph` instance." - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": { - "metadata": {} - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "---- DynapcnnLayer 0 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 0): Conv2d(2, 10, kernel_size=(2, 2), stride=(1, 1), bias=False)\n", - "(node 1): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1.), min_v_mem=Parameter containing:\n", - "tensor(-32768.), batch_size=1, num_timesteps=-1)\n", - "(node 2): SumPool2d(norm_type=1, kernel_size=3, stride=3, ceil_mode=False)\n", - "(node 3): SumPool2d(norm_type=1, kernel_size=4, stride=4, ceil_mode=False)\n", - "> layer destinations: [1, 2]\n", - "> assigned core: 0\n", - "\n", - "---- DynapcnnLayer 1 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 4): Conv2d(10, 10, kernel_size=(4, 4), stride=(1, 1), bias=False)\n", - "(node 6): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1.), min_v_mem=Parameter containing:\n", - "tensor(-32768.), batch_size=1, num_timesteps=-1)\n", - "> layer destinations: [2]\n", - "> assigned core: 1\n", - "\n", - "---- DynapcnnLayer 2 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 7): Conv2d(10, 10, kernel_size=(2, 2), stride=(1, 1), bias=False)\n", - "(node 8): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1.), min_v_mem=Parameter containing:\n", - "tensor(-32768.), batch_size=1, num_timesteps=-1)\n", - "> layer destinations: [3]\n", - "> assigned core: 2\n", - "\n", - "---- DynapcnnLayer 3 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 9): Conv2d(10, 1, kernel_size=(2, 2), stride=(1, 1), bias=False)\n", - "(node 10): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1.), min_v_mem=Parameter containing:\n", - "tensor(-32768.), batch_size=1, num_timesteps=-1)\n", - "> layer destinations: [4]\n", - "> assigned core: 3\n", - "\n", - "---- DynapcnnLayer 4 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 11): Conv2d(1, 100, kernel_size=(6, 6), stride=(1, 1), bias=False)\n", - "(node 12): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1.), min_v_mem=Parameter containing:\n", - "tensor(-32768.), batch_size=1, num_timesteps=-1)\n", - "> layer destinations: [5, 6]\n", - "> assigned core: 4\n", - "\n", - "---- DynapcnnLayer 5 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 13): Conv2d(100, 100, kernel_size=(1, 1), stride=(1, 1), bias=False)\n", - "(node 15): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1.), min_v_mem=Parameter containing:\n", - "tensor(-32768.), batch_size=1, num_timesteps=-1)\n", - "> layer destinations: [6, 7]\n", - "> assigned core: 5\n", - "\n", - "---- DynapcnnLayer 6 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 17): Conv2d(100, 100, kernel_size=(1, 1), stride=(1, 1), bias=False)\n", - "(node 18): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1.), min_v_mem=Parameter containing:\n", - "tensor(-32768.), batch_size=1, num_timesteps=-1)\n", - "> layer destinations: [7]\n", - "> assigned core: 6\n", - "\n", - "---- DynapcnnLayer 7 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 19): Conv2d(100, 10, kernel_size=(1, 1), stride=(1, 1), bias=False)\n", - "(node 20): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1.), min_v_mem=Parameter containing:\n", - "tensor(-32768.), batch_size=1, num_timesteps=-1)\n", - "> layer destinations: []\n", - "> assigned core: 7\n", - "\n", - "\n" - ] - } - ], - "source": [ - "print(hw_model)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "speck-rescnn", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.3" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/tests/test_nonsequential/DYNAPCNNNETWORK_EXAMPLES/complex_network_structure.ipynb b/tests/test_nonsequential/DYNAPCNNNETWORK_EXAMPLES/complex_network_structure.ipynb deleted file mode 100644 index 4494924e..00000000 --- a/tests/test_nonsequential/DYNAPCNNNETWORK_EXAMPLES/complex_network_structure.ipynb +++ /dev/null @@ -1,337 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": { - "metadata": {} - }, - "outputs": [], - "source": [ - "import torch\n", - "import torch.nn as nn\n", - "from sinabs.backend.dynapcnn import DynapcnnNetworkGraph\n", - "from sinabs.layers import Merge, IAFSqueeze, SumPool2d\n", - "import sinabs.layers as sl\n", - "from sinabs.activation.surrogate_gradient_fn import PeriodicExponential" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": { - "metadata": {} - }, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "torch.manual_seed(0)" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": { - "metadata": {} - }, - "outputs": [], - "source": [ - "channels = 2\n", - "height = 34\n", - "width = 34\n", - "\n", - "input_shape = (channels, height, width)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Network Module\n", - "\n", - "We need to define a `nn.Module` implementing the network we want the chip to reproduce." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "```mermaid\n", - "stateDiagram\n", - " [*] --> A\n", - " A --> B\n", - " A --> C\n", - " C --> D\n", - " C --> E\n", - " B --> D\n", - " D --> F\n", - " E --> F\n", - " F --> [*]\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": { - "metadata": {} - }, - "outputs": [], - "source": [ - "class SNN(nn.Module):\n", - " def __init__(self, nb_classes, batch_size, surrogate_fn, min_v_mem=-0.313, spk_thr=2.0) -> None:\n", - " super().__init__()\n", - "\n", - " self.conv1 = nn.Conv2d(2, 8, 2, 1, bias=False)\n", - " self.iaf1 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr)\n", - "\n", - " self.conv2 = nn.Conv2d(8, 8, 2, 1, bias=False)\n", - " self.iaf2 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr)\n", - " self.pool2 = sl.SumPool2d(2,2)\n", - "\n", - " self.conv3 = nn.Conv2d(8, 8, 2, 1, bias=False)\n", - " self.iaf3 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr)\n", - " self.pool3 = sl.SumPool2d(2,2)\n", - " self.pool3a = sl.SumPool2d(6,6)\n", - "\n", - " self.conv4 = nn.Conv2d(8, 8, 2, 1, bias=False)\n", - " self.iaf4 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr)\n", - " self.pool4 = sl.SumPool2d(3,3)\n", - "\n", - " self.flat = nn.Flatten()\n", - " self.flat_a = nn.Flatten()\n", - "\n", - " self.fc1 = nn.Linear(200, 200, bias=False)\n", - " self.iaf1_fc = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr)\n", - "\n", - " self.fc2 = nn.Linear(200, nb_classes, bias=False)\n", - " self.iaf2_fc = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr)\n", - "\n", - " # -- merges --\n", - " self.merge1 = Merge()\n", - " self.merge2 = Merge()\n", - "\n", - " def forward(self, x):\n", - " # conv 1 - A\n", - " con1_out = self.conv1(x)\n", - " iaf1_out = self.iaf1(con1_out)\n", - "\n", - " # conv 2 - B\n", - " conv2_out = self.conv2(iaf1_out)\n", - " iaf2_out = self.iaf2(conv2_out)\n", - " pool2_out = self.pool2(iaf2_out)\n", - "\n", - " # conv 3 - C\n", - " conv3_out = self.conv3(iaf1_out)\n", - " iaf3_out = self.iaf3(conv3_out)\n", - " pool3_out = self.pool3(iaf3_out)\n", - " pool3a_out = self.pool3a(iaf3_out)\n", - "\n", - " # conv 4 - D\n", - " merge1_out = self.merge1(pool2_out, pool3_out)\n", - " conv4_out = self.conv4(merge1_out)\n", - " iaf4_out = self.iaf4(conv4_out)\n", - " pool4_out = self.pool4(iaf4_out)\n", - " flat_out = self.flat(pool4_out)\n", - " \n", - " # fc 1 - E\n", - " flat_a_out = self.flat_a(pool3a_out)\n", - " fc1_out = self.fc1(flat_a_out)\n", - " iaf1_fc_out = self.iaf1_fc(fc1_out)\n", - "\n", - " # fc 2 - F\n", - " merge2_out = self.merge2(iaf1_fc_out, flat_out)\n", - " fc2_out = self.fc2(merge2_out)\n", - " iaf2_fc_out = self.iaf2_fc(fc2_out)\n", - "\n", - " return iaf2_fc_out\n", - " \n", - "snn = SNN(11, 1, PeriodicExponential())" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## DynapcnnNetwork Class\n", - "\n", - "In the constructor of `DynapcnnNetworkGraph` the SNN passed as argument (defined as a `nn.Module`) will be parsed such that each layer is represented in a computational graph (using `nirtorch.extract_torch_graph`). \n", - "\n", - "The layers are the `nodes` of the graph, while their connectivity (how the outputs from a layer are sent to other layers) is represented as `edges`, represented in a `list` of `tuples`.\n", - "\n", - "Once the constructor finishes its initialization, the `hw_model.dynapcnn_layers` property is a dictionary where each entry represents the ID of a `DynapcnnLayer` instance (an `int` from `0` to `L`), with this entry containing a `DynapcnnLayer` instance where a subset of the layers in the original SNN has been incorporated into, the core such instance has been assigned to, and the list of `DynapcnnLayer` instances (their IDs) the layer targets." - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": { - "metadata": {} - }, - "outputs": [], - "source": [ - "hw_model = DynapcnnNetworkGraph(\n", - " snn,\n", - " discretize=True,\n", - " input_shape=input_shape\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The `hw_model.to()` call will figure out into which core eac `DynapcnnLayer` instance will be assigned to. Once this assingment is made the instance itself is used to configure the `CNNLayerConfig` instance representing the core's configuration.\n", - "\n", - "If the cores' configuration is valid, each `DynapcnnLayer` instance and their respective destinations will be used to create a computational graph that encodes how the `forward` method of `hw_model.network` (a `nn.Module` using the `DynapcnnLayer` instances) propagates that through the network." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": { - "metadata": {} - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Network is valid\n" - ] - }, - { - "ename": "RuntimeError", - "evalue": "Device is already opened!", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mRuntimeError\u001b[0m Traceback (most recent call last)", - "Cell \u001b[0;32mIn[6], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m hw_model\u001b[38;5;241m.\u001b[39mto(device\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mspeck2fmodule:0\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n", - "File \u001b[0;32m~/Documents/github/sinabs/sinabs/backend/dynapcnn/dynapcnn_network_graph.py:172\u001b[0m, in \u001b[0;36mDynapcnnNetworkGraph.to\u001b[0;34m(self, device, chip_layers_ordering, monitor_layers, config_modifier, slow_clk_frequency)\u001b[0m\n\u001b[1;32m 163\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m device_name \u001b[38;5;129;01min\u001b[39;00m ChipFactory\u001b[38;5;241m.\u001b[39msupported_devices: \u001b[38;5;66;03m# pragma: no cover\u001b[39;00m\n\u001b[1;32m 165\u001b[0m config \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mmake_config( \u001b[38;5;66;03m# generate config.\u001b[39;00m\n\u001b[1;32m 166\u001b[0m chip_layers_ordering\u001b[38;5;241m=\u001b[39mchip_layers_ordering,\n\u001b[1;32m 167\u001b[0m device\u001b[38;5;241m=\u001b[39mdevice,\n\u001b[1;32m 168\u001b[0m monitor_layers\u001b[38;5;241m=\u001b[39mmonitor_layers,\n\u001b[1;32m 169\u001b[0m config_modifier\u001b[38;5;241m=\u001b[39mconfig_modifier,\n\u001b[1;32m 170\u001b[0m )\n\u001b[0;32m--> 172\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39msamna_device \u001b[38;5;241m=\u001b[39m open_device(device) \u001b[38;5;66;03m# apply configuration to device.\u001b[39;00m\n\u001b[1;32m 173\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39msamna_device\u001b[38;5;241m.\u001b[39mget_model()\u001b[38;5;241m.\u001b[39mapply_configuration(config)\n\u001b[1;32m 174\u001b[0m time\u001b[38;5;241m.\u001b[39msleep(\u001b[38;5;241m1\u001b[39m)\n", - "File \u001b[0;32m~/Documents/github/sinabs/sinabs/backend/dynapcnn/io.py:256\u001b[0m, in \u001b[0;36mopen_device\u001b[0;34m(device_id)\u001b[0m\n\u001b[1;32m 254\u001b[0m device_map \u001b[38;5;241m=\u001b[39m get_device_map()\n\u001b[1;32m 255\u001b[0m device_info \u001b[38;5;241m=\u001b[39m device_map[device_id]\n\u001b[0;32m--> 256\u001b[0m device_handle \u001b[38;5;241m=\u001b[39m samna\u001b[38;5;241m.\u001b[39mdevice\u001b[38;5;241m.\u001b[39mopen_device(device_info)\n\u001b[1;32m 258\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m device_handle \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m 259\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m device_handle\n", - "\u001b[0;31mRuntimeError\u001b[0m: Device is already opened!" - ] - } - ], - "source": [ - "hw_model.to(device=\"speck2fmodule:0\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The layers comprising our `hw_model` and their respective metadata can be inspected by calling `print` on a `DynapcnnNetworkGraph` instance." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "metadata": {} - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "---- DynapcnnLayer 0 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 0): Conv2d(2, 8, kernel_size=(2, 2), stride=(1, 1), bias=False)\n", - "(node 1): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(723.), min_v_mem=Parameter containing:\n", - "tensor(-113.), batch_size=1, num_timesteps=-1)\n", - "> layer destinations: [1, 2]\n", - "> assigned core: 0\n", - "\n", - "---- DynapcnnLayer 1 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 2): Conv2d(8, 8, kernel_size=(2, 2), stride=(1, 1), bias=False)\n", - "(node 4): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1452.), min_v_mem=Parameter containing:\n", - "tensor(-227.), batch_size=1, num_timesteps=-1)\n", - "(node 5): SumPool2d(norm_type=1, kernel_size=2, stride=2, ceil_mode=False)\n", - "> layer destinations: [3]\n", - "> assigned core: 1\n", - "\n", - "---- DynapcnnLayer 2 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 3): Conv2d(8, 8, kernel_size=(2, 2), stride=(1, 1), bias=False)\n", - "(node 7): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1437.), min_v_mem=Parameter containing:\n", - "tensor(-225.), batch_size=1, num_timesteps=-1)\n", - "(node 8): SumPool2d(norm_type=1, kernel_size=2, stride=2, ceil_mode=False)\n", - "(node 9): SumPool2d(norm_type=1, kernel_size=6, stride=6, ceil_mode=False)\n", - "> layer destinations: [3, 4]\n", - "> assigned core: 2\n", - "\n", - "---- DynapcnnLayer 3 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 10): Conv2d(8, 8, kernel_size=(2, 2), stride=(1, 1), bias=False)\n", - "(node 11): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1439.), min_v_mem=Parameter containing:\n", - "tensor(-225.), batch_size=1, num_timesteps=-1)\n", - "(node 12): SumPool2d(norm_type=1, kernel_size=3, stride=3, ceil_mode=False)\n", - "> layer destinations: [5]\n", - "> assigned core: 3\n", - "\n", - "---- DynapcnnLayer 4 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 14): Conv2d(8, 200, kernel_size=(5, 5), stride=(1, 1), bias=False)\n", - "(node 15): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(3592.), min_v_mem=Parameter containing:\n", - "tensor(-562.), batch_size=1, num_timesteps=-1)\n", - "> layer destinations: [5]\n", - "> assigned core: 5\n", - "\n", - "---- DynapcnnLayer 5 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 16): Conv2d(200, 11, kernel_size=(1, 1), stride=(1, 1), bias=False)\n", - "(node 17): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(3592.), min_v_mem=Parameter containing:\n", - "tensor(-562.), batch_size=1, num_timesteps=-1)\n", - "> layer destinations: []\n", - "> assigned core: 4\n", - "\n", - "\n" - ] - } - ], - "source": [ - "print(hw_model)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "speck-rescnn", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.3" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/tests/test_nonsequential/DYNAPCNNNETWORK_EXAMPLES/split_and_merge.ipynb b/tests/test_nonsequential/DYNAPCNNNETWORK_EXAMPLES/split_and_merge.ipynb deleted file mode 100644 index 4ce4ffc8..00000000 --- a/tests/test_nonsequential/DYNAPCNNNETWORK_EXAMPLES/split_and_merge.ipynb +++ /dev/null @@ -1,359 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": { - "metadata": {} - }, - "outputs": [], - "source": [ - "import torch\n", - "import torch.nn as nn\n", - "from sinabs.backend.dynapcnn import DynapcnnNetworkGraph\n", - "from sinabs.layers import Merge, IAFSqueeze, SumPool2d\n", - "import sinabs.layers as sl\n", - "from sinabs.activation.surrogate_gradient_fn import PeriodicExponential" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": { - "metadata": {} - }, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "torch.manual_seed(0)" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": { - "metadata": {} - }, - "outputs": [], - "source": [ - "channels = 2\n", - "height = 34\n", - "width = 34\n", - "\n", - "input_shape = (channels, height, width)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Network Module\n", - "\n", - "We need to define a `nn.Module` implementing the network we want the chip to reproduce." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "```mermaid\n", - "stateDiagram\n", - " [*] --> A\n", - " A --> B\n", - " B --> C\n", - " C --> D\n", - " B --> E\n", - " E --> F\n", - " D --> G\n", - " F --> G\n", - " G --> [*]\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": { - "metadata": {} - }, - "outputs": [], - "source": [ - "class SNN(nn.Module):\n", - " def __init__(self, nb_classes, batch_size, surrogate_fn, min_v_mem=-0.313, spk_thr=2.0) -> None:\n", - " super().__init__()\n", - "\n", - " self.conv1 = nn.Conv2d(2, 4, 2, 1, bias=False)\n", - " self.iaf1 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr)\n", - "\n", - " self.conv2 = nn.Conv2d(4, 4, 2, 1, bias=False)\n", - " self.iaf2 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr)\n", - " self.pool2 = sl.SumPool2d(2,2)\n", - " self.pool2a = sl.SumPool2d(5,5)\n", - "\n", - " self.conv3 = nn.Conv2d(4, 4, 2, 1, bias=False)\n", - " self.iaf3 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr)\n", - " self.pool3 = sl.SumPool2d(2,2)\n", - "\n", - " self.conv4 = nn.Conv2d(4, 4, 2, 1, bias=False)\n", - " self.iaf4 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr)\n", - "\n", - " self.flat = nn.Flatten()\n", - " self.flat_a = nn.Flatten()\n", - "\n", - " self.fc1 = nn.Linear(144, 144, bias=False)\n", - " self.iaf1_fc = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr)\n", - "\n", - " self.fc2 = nn.Linear(144, 144, bias=False)\n", - " self.iaf2_fc = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr)\n", - "\n", - " self.fc3 = nn.Linear(144, nb_classes, bias=False)\n", - " self.iaf3_fc = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr)\n", - "\n", - " # -- merges --\n", - " self.merge1 = Merge()\n", - "\n", - " def forward(self, x):\n", - " # conv 1 - A\n", - " con1_out = self.conv1(x)\n", - " iaf1_out = self.iaf1(con1_out)\n", - "\n", - " # conv 2 - B\n", - " conv2_out = self.conv2(iaf1_out)\n", - " iaf2_out = self.iaf2(conv2_out)\n", - " pool2_out = self.pool2(iaf2_out)\n", - " pool2a_out = self.pool2a(iaf2_out)\n", - "\n", - " # conv 3 - C\n", - " conv3_out = self.conv3(pool2_out)\n", - " iaf3_out = self.iaf3(conv3_out)\n", - " pool3_out = self.pool3(iaf3_out)\n", - "\n", - " # conv 4 - D\n", - " conv4_out = self.conv4(pool3_out)\n", - " iaf4_out = self.iaf4(conv4_out)\n", - " flat_out = self.flat(iaf4_out)\n", - " \n", - " # fc 1 - E\n", - " flat_a_out = self.flat_a(pool2a_out)\n", - " print(flat_a_out.shape)\n", - " fc1_out = self.fc1(flat_a_out)\n", - " iaf1_fc_out = self.iaf1_fc(fc1_out)\n", - "\n", - " # fc 2 - F\n", - " fc2_out = self.fc2(iaf1_fc_out)\n", - " iaf2_fc_out = self.iaf2_fc(fc2_out)\n", - "\n", - " # fc 2 - G\n", - " print(flat_out.shape, iaf2_fc_out.shape)\n", - " merge1_out = self.merge1(flat_out, iaf2_fc_out)\n", - " fc3_out = self.fc3(merge1_out)\n", - " iaf3_fc_out = self.iaf3_fc(fc3_out)\n", - "\n", - " return iaf3_fc_out\n", - " \n", - "snn = SNN(11, 1, PeriodicExponential())" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## DynapcnnNetwork Class\n", - "\n", - "In the constructor of `DynapcnnNetworkGraph` the SNN passed as argument (defined as a `nn.Module`) will be parsed such that each layer is represented in a computational graph (using `nirtorch.extract_torch_graph`). \n", - "\n", - "The layers are the `nodes` of the graph, while their connectivity (how the outputs from a layer are sent to other layers) is represented as `edges`, represented in a `list` of `tuples`.\n", - "\n", - "Once the constructor finishes its initialization, the `hw_model.dynapcnn_layers` property is a dictionary where each entry represents the ID of a `DynapcnnLayer` instance (an `int` from `0` to `L`), with this entry containing a `DynapcnnLayer` instance where a subset of the layers in the original SNN has been incorporated into, the core such instance has been assigned to, and the list of `DynapcnnLayer` instances (their IDs) the layer targets." - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": { - "metadata": {} - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "torch.Size([1, 144])\n", - "torch.Size([1, 144]) torch.Size([1, 144])\n" - ] - } - ], - "source": [ - "hw_model = DynapcnnNetworkGraph(\n", - " snn,\n", - " discretize=True,\n", - " input_shape=input_shape\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The `hw_model.to()` call will figure out into which core eac `DynapcnnLayer` instance will be assigned to. Once this assingment is made the instance itself is used to configure the `CNNLayerConfig` instance representing the core's configuration.\n", - "\n", - "If the cores' configuration is valid, each `DynapcnnLayer` instance and their respective destinations will be used to create a computational graph that encodes how the `forward` method of `hw_model.network` (a `nn.Module` using the `DynapcnnLayer` instances) propagates that through the network." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": { - "metadata": {} - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Network is valid\n" - ] - }, - { - "ename": "RuntimeError", - "evalue": "Device is already opened!", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mRuntimeError\u001b[0m Traceback (most recent call last)", - "Cell \u001b[0;32mIn[6], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m hw_model\u001b[38;5;241m.\u001b[39mto(device\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mspeck2fmodule:0\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n", - "File \u001b[0;32m~/Documents/github/sinabs/sinabs/backend/dynapcnn/dynapcnn_network_graph.py:172\u001b[0m, in \u001b[0;36mDynapcnnNetworkGraph.to\u001b[0;34m(self, device, chip_layers_ordering, monitor_layers, config_modifier, slow_clk_frequency)\u001b[0m\n\u001b[1;32m 163\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m device_name \u001b[38;5;129;01min\u001b[39;00m ChipFactory\u001b[38;5;241m.\u001b[39msupported_devices: \u001b[38;5;66;03m# pragma: no cover\u001b[39;00m\n\u001b[1;32m 165\u001b[0m config \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mmake_config( \u001b[38;5;66;03m# generate config.\u001b[39;00m\n\u001b[1;32m 166\u001b[0m chip_layers_ordering\u001b[38;5;241m=\u001b[39mchip_layers_ordering,\n\u001b[1;32m 167\u001b[0m device\u001b[38;5;241m=\u001b[39mdevice,\n\u001b[1;32m 168\u001b[0m monitor_layers\u001b[38;5;241m=\u001b[39mmonitor_layers,\n\u001b[1;32m 169\u001b[0m config_modifier\u001b[38;5;241m=\u001b[39mconfig_modifier,\n\u001b[1;32m 170\u001b[0m )\n\u001b[0;32m--> 172\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39msamna_device \u001b[38;5;241m=\u001b[39m open_device(device) \u001b[38;5;66;03m# apply configuration to device.\u001b[39;00m\n\u001b[1;32m 173\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39msamna_device\u001b[38;5;241m.\u001b[39mget_model()\u001b[38;5;241m.\u001b[39mapply_configuration(config)\n\u001b[1;32m 174\u001b[0m time\u001b[38;5;241m.\u001b[39msleep(\u001b[38;5;241m1\u001b[39m)\n", - "File \u001b[0;32m~/Documents/github/sinabs/sinabs/backend/dynapcnn/io.py:256\u001b[0m, in \u001b[0;36mopen_device\u001b[0;34m(device_id)\u001b[0m\n\u001b[1;32m 254\u001b[0m device_map \u001b[38;5;241m=\u001b[39m get_device_map()\n\u001b[1;32m 255\u001b[0m device_info \u001b[38;5;241m=\u001b[39m device_map[device_id]\n\u001b[0;32m--> 256\u001b[0m device_handle \u001b[38;5;241m=\u001b[39m samna\u001b[38;5;241m.\u001b[39mdevice\u001b[38;5;241m.\u001b[39mopen_device(device_info)\n\u001b[1;32m 258\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m device_handle \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m 259\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m device_handle\n", - "\u001b[0;31mRuntimeError\u001b[0m: Device is already opened!" - ] - } - ], - "source": [ - "hw_model.to(device=\"speck2fmodule:0\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The layers comprising our `hw_model` and their respective metadata can be inspected by calling `print` on a `DynapcnnNetworkGraph` instance." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "metadata": {} - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "---- DynapcnnLayer 0 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 0): Conv2d(2, 4, kernel_size=(2, 2), stride=(1, 1), bias=False)\n", - "(node 1): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(758.), min_v_mem=Parameter containing:\n", - "tensor(-119.), batch_size=1, num_timesteps=-1)\n", - "> layer destinations: [1]\n", - "> assigned core: 0\n", - "\n", - "---- DynapcnnLayer 1 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 2): Conv2d(4, 4, kernel_size=(2, 2), stride=(1, 1), bias=False)\n", - "(node 3): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1022.), min_v_mem=Parameter containing:\n", - "tensor(-160.), batch_size=1, num_timesteps=-1)\n", - "(node 4): SumPool2d(norm_type=1, kernel_size=2, stride=2, ceil_mode=False)\n", - "(node 5): SumPool2d(norm_type=1, kernel_size=5, stride=5, ceil_mode=False)\n", - "> layer destinations: [2, 3]\n", - "> assigned core: 1\n", - "\n", - "---- DynapcnnLayer 2 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 6): Conv2d(4, 4, kernel_size=(2, 2), stride=(1, 1), bias=False)\n", - "(node 7): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1062.), min_v_mem=Parameter containing:\n", - "tensor(-166.), batch_size=1, num_timesteps=-1)\n", - "(node 8): SumPool2d(norm_type=1, kernel_size=2, stride=2, ceil_mode=False)\n", - "> layer destinations: [4]\n", - "> assigned core: 2\n", - "\n", - "---- DynapcnnLayer 3 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 12): Conv2d(4, 144, kernel_size=(6, 6), stride=(1, 1), bias=False)\n", - "(node 13): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(3048.), min_v_mem=Parameter containing:\n", - "tensor(-477.), batch_size=1, num_timesteps=-1)\n", - "> layer destinations: [6]\n", - "> assigned core: 5\n", - "\n", - "---- DynapcnnLayer 4 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 9): Conv2d(4, 4, kernel_size=(2, 2), stride=(1, 1), bias=False)\n", - "(node 10): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1027.), min_v_mem=Parameter containing:\n", - "tensor(-161.), batch_size=1, num_timesteps=-1)\n", - "> layer destinations: [5]\n", - "> assigned core: 3\n", - "\n", - "---- DynapcnnLayer 5 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 16): Conv2d(4, 11, kernel_size=(6, 6), stride=(1, 1), bias=False)\n", - "(node 17): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(3054.), min_v_mem=Parameter containing:\n", - "tensor(-478.), batch_size=1, num_timesteps=-1)\n", - "> layer destinations: []\n", - "> assigned core: 4\n", - "\n", - "---- DynapcnnLayer 6 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 14): Conv2d(144, 144, kernel_size=(1, 1), stride=(1, 1), bias=False)\n", - "(node 15): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(3048.), min_v_mem=Parameter containing:\n", - "tensor(-477.), batch_size=1, num_timesteps=-1)\n", - "> layer destinations: [5]\n", - "> assigned core: 6\n", - "\n", - "\n" - ] - } - ], - "source": [ - "print(hw_model)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "speck-rescnn", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.3" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/tests/test_nonsequential/DYNAPCNNNETWORK_EXAMPLES/two_networks_merging_outputs.ipynb b/tests/test_nonsequential/DYNAPCNNNETWORK_EXAMPLES/two_networks_merging_outputs.ipynb deleted file mode 100644 index 8f1e2be3..00000000 --- a/tests/test_nonsequential/DYNAPCNNNETWORK_EXAMPLES/two_networks_merging_outputs.ipynb +++ /dev/null @@ -1,378 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": { - "metadata": {} - }, - "outputs": [], - "source": [ - "import torch\n", - "import torch.nn as nn\n", - "from sinabs.backend.dynapcnn import DynapcnnNetworkGraph\n", - "from sinabs.layers import Merge, IAFSqueeze, SumPool2d\n", - "import sinabs.layers as sl\n", - "from sinabs.activation.surrogate_gradient_fn import PeriodicExponential" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": { - "metadata": {} - }, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "torch.manual_seed(0)" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": { - "metadata": {} - }, - "outputs": [], - "source": [ - "channels = 2\n", - "height = 34\n", - "width = 34\n", - "\n", - "input_shape = (channels, height, width)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Network Module\n", - "\n", - "We need to define a `nn.Module` implementing the network we want the chip to reproduce." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "```mermaid\n", - "stateDiagram\n", - " [*] --> A\n", - " A --> B\n", - " B --> C\n", - " D --> E\n", - " E --> F\n", - " C --> G\n", - " F --> G\n", - " G --> H\n", - " H --> I\n", - " I --> [*]\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": { - "metadata": {} - }, - "outputs": [], - "source": [ - "class SNN(nn.Module):\n", - " def __init__(self, nb_classes, batch_size, surrogate_fn, min_v_mem=-0.313, spk_thr=2.0) -> None:\n", - " super().__init__()\n", - "\n", - " self.conv_A = nn.Conv2d(2, 4, 2, 1, bias=False)\n", - " self.iaf_A = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr)\n", - "\n", - " self.conv_B = nn.Conv2d(4, 4, 2, 1, bias=False)\n", - " self.iaf_B = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr)\n", - " self.pool_B = sl.SumPool2d(2,2)\n", - "\n", - " self.conv_C = nn.Conv2d(4, 4, 2, 1, bias=False)\n", - " self.iaf_C = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr)\n", - " self.pool_C = sl.SumPool2d(2,2)\n", - "\n", - " self.conv_D = nn.Conv2d(2, 4, 2, 1, bias=False)\n", - " self.iaf_D = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr)\n", - "\n", - " self.conv_E = nn.Conv2d(4, 4, 2, 1, bias=False)\n", - " self.iaf_E = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr)\n", - " self.pool_E = sl.SumPool2d(2,2)\n", - "\n", - " self.conv_F = nn.Conv2d(4, 4, 2, 1, bias=False)\n", - " self.iaf_F = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr)\n", - " self.pool_F = sl.SumPool2d(2,2)\n", - "\n", - " self.flat_brach1 = nn.Flatten()\n", - " self.flat_brach2 = nn.Flatten()\n", - " self.merge = Merge()\n", - "\n", - " self.fc1 = nn.Linear(196, 200, bias=False)\n", - " self.iaf1_fc = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr)\n", - "\n", - " self.fc2 = nn.Linear(200, 200, bias=False)\n", - " self.iaf2_fc = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr)\n", - "\n", - " self.fc3 = nn.Linear(200, nb_classes, bias=False)\n", - " self.iaf3_fc = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr)\n", - "\n", - " def forward(self, x):\n", - " # conv 1 - A\n", - " conv_A_out = self.conv_A(x)\n", - " iaf_A_out = self.iaf_A(conv_A_out)\n", - " # conv 2 - B\n", - " conv_B_out = self.conv_B(iaf_A_out)\n", - " iaf_B_out = self.iaf_B(conv_B_out)\n", - " pool_B_out = self.pool_B(iaf_B_out)\n", - " # conv 3 - C\n", - " conv_C_out = self.conv_C(pool_B_out)\n", - " iaf_C_out = self.iaf_C(conv_C_out)\n", - " pool_C_out = self.pool_C(iaf_C_out)\n", - "\n", - " # ---\n", - "\n", - " # conv 4 - D\n", - " conv_D_out = self.conv_D(x)\n", - " iaf_D_out = self.iaf_D(conv_D_out)\n", - " # conv 5 - E\n", - " conv_E_out = self.conv_E(iaf_D_out)\n", - " iaf_E_out = self.iaf_E(conv_E_out)\n", - " pool_E_out = self.pool_E(iaf_E_out)\n", - " # conv 6 - F\n", - " conv_F_out = self.conv_F(pool_E_out)\n", - " iaf_F_out = self.iaf_F(conv_F_out)\n", - " pool_F_out = self.pool_F(iaf_F_out)\n", - "\n", - " # ---\n", - "\n", - " flat_brach1_out = self.flat_brach1(pool_C_out)\n", - " flat_brach2_out = self.flat_brach2(pool_F_out)\n", - " merge_out = self.merge(flat_brach1_out, flat_brach2_out)\n", - "\n", - " # FC 7 - G\n", - " fc1_out = self.fc1(merge_out)\n", - " iaf1_fc_out = self.iaf1_fc(fc1_out)\n", - " # FC 8 - H\n", - " fc2_out = self.fc2(iaf1_fc_out)\n", - " iaf2_fc_out = self.iaf2_fc(fc2_out)\n", - " # FC 9 - I\n", - " fc3_out = self.fc3(iaf2_fc_out)\n", - " iaf3_fc_out = self.iaf3_fc(fc3_out)\n", - "\n", - " return iaf3_fc_out\n", - " \n", - "snn = SNN(11, 1, PeriodicExponential())" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## DynapcnnNetwork Class\n", - "\n", - "In the constructor of `DynapcnnNetworkGraph` the SNN passed as argument (defined as a `nn.Module`) will be parsed such that each layer is represented in a computational graph (using `nirtorch.extract_torch_graph`). \n", - "\n", - "The layers are the `nodes` of the graph, while their connectivity (how the outputs from a layer are sent to other layers) is represented as `edges`, represented in a `list` of `tuples`.\n", - "\n", - "Once the constructor finishes its initialization, the `hw_model.dynapcnn_layers` property is a dictionary where each entry represents the ID of a `DynapcnnLayer` instance (an `int` from `0` to `L`), with this entry containing a `DynapcnnLayer` instance where a subset of the layers in the original SNN has been incorporated into, the core such instance has been assigned to, and the list of `DynapcnnLayer` instances (their IDs) the layer targets." - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": { - "metadata": {} - }, - "outputs": [], - "source": [ - "hw_model = DynapcnnNetworkGraph(\n", - " snn,\n", - " discretize=True,\n", - " input_shape=input_shape\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The `hw_model.to()` call will figure out into which core eac `DynapcnnLayer` instance will be assigned to. Once this assingment is made the instance itself is used to configure the `CNNLayerConfig` instance representing the core's configuration.\n", - "\n", - "If the cores' configuration is valid, each `DynapcnnLayer` instance and their respective destinations will be used to create a computational graph that encodes how the `forward` method of `hw_model.network` (a `nn.Module` using the `DynapcnnLayer` instances) propagates that through the network." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": { - "metadata": {} - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Network is valid\n" - ] - }, - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "hw_model.to(device=\"speck2fmodule:0\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The layers comprising our `hw_model` and their respective metadata can be inspected by calling `print` on a `DynapcnnNetworkGraph` instance." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": { - "metadata": {} - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "---- DynapcnnLayer 0 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 0): Conv2d(2, 4, kernel_size=(2, 2), stride=(1, 1), bias=False)\n", - "(node 1): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(758.), min_v_mem=Parameter containing:\n", - "tensor(-119.), batch_size=1, num_timesteps=-1)\n", - "> layer destinations: [1]\n", - "> assigned core: 0\n", - "\n", - "---- DynapcnnLayer 1 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 2): Conv2d(4, 4, kernel_size=(2, 2), stride=(1, 1), bias=False)\n", - "(node 3): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1022.), min_v_mem=Parameter containing:\n", - "tensor(-160.), batch_size=1, num_timesteps=-1)\n", - "(node 4): SumPool2d(norm_type=1, kernel_size=2, stride=2, ceil_mode=False)\n", - "> layer destinations: [2]\n", - "> assigned core: 1\n", - "\n", - "---- DynapcnnLayer 2 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 5): Conv2d(4, 4, kernel_size=(2, 2), stride=(1, 1), bias=False)\n", - "(node 6): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1062.), min_v_mem=Parameter containing:\n", - "tensor(-166.), batch_size=1, num_timesteps=-1)\n", - "(node 7): SumPool2d(norm_type=1, kernel_size=2, stride=2, ceil_mode=False)\n", - "> layer destinations: [3]\n", - "> assigned core: 2\n", - "\n", - "---- DynapcnnLayer 3 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 17): Conv2d(4, 200, kernel_size=(7, 7), stride=(1, 1), bias=False)\n", - "(node 18): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(3556.), min_v_mem=Parameter containing:\n", - "tensor(-557.), batch_size=1, num_timesteps=-1)\n", - "> layer destinations: [7]\n", - "> assigned core: 5\n", - "\n", - "---- DynapcnnLayer 4 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 8): Conv2d(2, 4, kernel_size=(2, 2), stride=(1, 1), bias=False)\n", - "(node 9): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(796.), min_v_mem=Parameter containing:\n", - "tensor(-125.), batch_size=1, num_timesteps=-1)\n", - "> layer destinations: [5]\n", - "> assigned core: 3\n", - "\n", - "---- DynapcnnLayer 5 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 10): Conv2d(4, 4, kernel_size=(2, 2), stride=(1, 1), bias=False)\n", - "(node 11): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1027.), min_v_mem=Parameter containing:\n", - "tensor(-161.), batch_size=1, num_timesteps=-1)\n", - "(node 12): SumPool2d(norm_type=1, kernel_size=2, stride=2, ceil_mode=False)\n", - "> layer destinations: [6]\n", - "> assigned core: 4\n", - "\n", - "---- DynapcnnLayer 6 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 13): Conv2d(4, 4, kernel_size=(2, 2), stride=(1, 1), bias=False)\n", - "(node 14): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1033.), min_v_mem=Parameter containing:\n", - "tensor(-162.), batch_size=1, num_timesteps=-1)\n", - "(node 15): SumPool2d(norm_type=1, kernel_size=2, stride=2, ceil_mode=False)\n", - "> layer destinations: [3]\n", - "> assigned core: 8\n", - "\n", - "---- DynapcnnLayer 7 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 19): Conv2d(200, 200, kernel_size=(1, 1), stride=(1, 1), bias=False)\n", - "(node 20): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(3592.), min_v_mem=Parameter containing:\n", - "tensor(-562.), batch_size=1, num_timesteps=-1)\n", - "> layer destinations: [8]\n", - "> assigned core: 6\n", - "\n", - "---- DynapcnnLayer 8 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 21): Conv2d(200, 11, kernel_size=(1, 1), stride=(1, 1), bias=False)\n", - "(node 22): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(3592.), min_v_mem=Parameter containing:\n", - "tensor(-562.), batch_size=1, num_timesteps=-1)\n", - "> layer destinations: []\n", - "> assigned core: 7\n", - "\n", - "\n" - ] - } - ], - "source": [ - "print(hw_model)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "speck-rescnn", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.3" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/tests/test_nonsequential/DynapcnnNetwork-example_1.ipynb b/tests/test_nonsequential/DynapcnnNetwork-example_1.ipynb deleted file mode 100644 index a294325f..00000000 --- a/tests/test_nonsequential/DynapcnnNetwork-example_1.ipynb +++ /dev/null @@ -1,679 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 22, - "metadata": {}, - "outputs": [], - "source": [ - "import torch\n", - "import torch.nn as nn\n", - "from sinabs.backend.dynapcnn import DynapcnnNetworkGraph\n", - "from sinabs.layers import Merge, IAFSqueeze\n", - "import matplotlib.pyplot as plt" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "torch.manual_seed(0)" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "channels = 2\n", - "height = 34\n", - "width = 34\n", - "\n", - "input_shape = (channels, height, width)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Network Module\n", - "\n", - "We need to define a `nn.Module` implementing the network we want the chip to reproduce." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "class SNN(nn.Module):\n", - " def __init__(self) -> None:\n", - " super().__init__()\n", - "\n", - " self.conv1 = nn.Conv2d(2, 10, 2, 1, bias=False) # node 0\n", - " self.iaf1 = IAFSqueeze(batch_size=1) # node 1\n", - " self.pool1 = nn.AvgPool2d(3,3) # node 2\n", - " self.pool1a = nn.AvgPool2d(4,4) # node 3\n", - "\n", - " self.conv2 = nn.Conv2d(10, 10, 4, 1, bias=False)# node 4\n", - " self.iaf2 = IAFSqueeze(batch_size=1) # node 6\n", - " # self.pool2 = nn.AvgPool2d(3,3) # node 7\n", - "\n", - " self.conv3 = nn.Conv2d(10, 1, 2, 1, bias=False) # node 8\n", - " self.iaf3 = IAFSqueeze(batch_size=1) # node 9\n", - "\n", - " self.flat = nn.Flatten()\n", - "\n", - " self.fc1 = nn.Linear(49, 500, bias=False) # node 10\n", - " self.iaf4 = IAFSqueeze(batch_size=1) # node 11\n", - " \n", - " self.fc2 = nn.Linear(500, 10, bias=False) # node 12\n", - " self.iaf5 = IAFSqueeze(batch_size=1) # node 13\n", - "\n", - " self.adder = Merge()\n", - "\n", - " def forward(self, x):\n", - " \n", - " con1_out = self.conv1(x)\n", - " iaf1_out = self.iaf1(con1_out)\n", - " pool1_out = self.pool1(iaf1_out)\n", - " pool1a_out = self.pool1a(iaf1_out)\n", - "\n", - " conv2_out = self.conv2(pool1_out)\n", - " iaf2_out = self.iaf2(conv2_out)\n", - " # pool2_out = self.pool2(iaf2_out)\n", - "\n", - " conv3_out = self.conv3(self.adder(pool1a_out, iaf2_out))\n", - " iaf3_out = self.iaf3(conv3_out)\n", - "\n", - " flat_out = self.flat(iaf3_out)\n", - " \n", - " fc1_out = self.fc1(flat_out)\n", - " iaf4_out = self.iaf4(fc1_out)\n", - " fc2_out = self.fc2(iaf4_out)\n", - " iaf5_out = self.iaf5(fc2_out)\n", - "\n", - " return iaf5_out" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "snn = SNN()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The following exemplifies how each of the layers in the SNN should be grouped together to form a `DynapcnnLayer` instance. Let's check the shapes of the tensors each of the (original) layers in the model inputs and outputs by feeding a fake input through the model:" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "DynapcnnLayer 0: ... [1, 2, 34, 34]\n", - " conv1: [1, 10, 33, 33]\n", - " iaf1: [1, 10, 33, 33]\n", - " pool1: [1, 10, 11, 11]\n", - " pool1a: [1, 10, 8, 8]\n", - "\n", - "DynapcnnLayer 1: ... [1, 10, 11, 11]\n", - " conv2: [1, 10, 8, 8]\n", - " iaf2: [1, 10, 8, 8]\n", - "\n", - "DynapcnnLayer 2: ... [1, 10, 8, 8] [ Merge(pool1a, iaf2_out) ]\n", - " conv3: [1, 1, 7, 7]\n", - " iaf3: [1, 1, 7, 7]\n", - "\n", - "DynapcnnLayer 3: ... [1, 49]\n", - " fc1: [1, 500]\n", - " iaf4: [1, 500]\n", - "\n", - "DynapcnnLayer 4: ... [1, 500]\n", - " fc2: [1, 10]\n", - " iaf5: [1, 10]\n", - "\n" - ] - } - ], - "source": [ - "x = torch.randn((1, *input_shape))\n", - "\n", - "print(f'DynapcnnLayer 0: ... {list(x.shape)}')\n", - "con1_out = snn.conv1(x)\n", - "print(f' conv1: {list(con1_out.shape)}')\n", - "iaf1_out = snn.iaf1(con1_out)\n", - "print(f' iaf1: {list(iaf1_out.shape)}')\n", - "pool1_out = snn.pool1(iaf1_out)\n", - "print(f' pool1: {list(pool1_out.shape)}')\n", - "pool1a_out = snn.pool1a(iaf1_out)\n", - "print(f' pool1a: {list(pool1a_out.shape)}\\n')\n", - "\n", - "print(f'DynapcnnLayer 1: ... {list(pool1_out.shape)}')\n", - "conv2_out = snn.conv2(pool1_out)\n", - "print(f' conv2: {list(conv2_out.shape)}')\n", - "iaf2_out = snn.iaf2(conv2_out)\n", - "print(f' iaf2: {list(iaf2_out.shape)}\\n')\n", - "# pool2_out = snn.pool2(iaf2_out)\n", - "# print(f' pool2: {list(pool2_out.shape)}\\n')\n", - "\n", - "added = snn.adder(pool1a_out, iaf2_out)\n", - "\n", - "print(f'DynapcnnLayer 2: ... {list(added.shape)} [ Merge(pool1a, iaf2_out) ]')\n", - "conv3_out = snn.conv3(added)\n", - "print(f' conv3: {list(conv3_out.shape)}')\n", - "iaf3_out = snn.iaf3(conv3_out)\n", - "print(f' iaf3: {list(iaf3_out.shape)}\\n')\n", - "\n", - "flat_out = snn.flat(iaf3_out)\n", - "\n", - "print(f'DynapcnnLayer 3: ... {list(flat_out.shape)}')\n", - "fc1_out = snn.fc1(flat_out)\n", - "print(f' fc1: {list(fc1_out.shape)}')\n", - "iaf4_out = snn.iaf4(fc1_out)\n", - "print(f' iaf4: {list(iaf4_out.shape)}\\n')\n", - "\n", - "\n", - "print(f'DynapcnnLayer 4: ... {list(iaf4_out.shape)}')\n", - "fc2_out = snn.fc2(iaf4_out)\n", - "print(f' fc2: {list(fc2_out.shape)}')\n", - "iaf5_out = snn.iaf5(fc2_out)\n", - "print(f' iaf5: {list(iaf5_out.shape)}\\n')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## DynapcnnNetwork Class\n", - "\n", - "In the constructor of `DynapcnnNetworkGraph` the SNN passed as argument (defined as a `nn.Module`) will be parsed such that each layer is represented in a computational graph (using `nirtorch.extract_torch_graph`). \n", - "\n", - "The layers are the `nodes` of the graph, while their connectivity (how the outputs from a layer are sent to other layers) is represented as `edges`, represented in a `list` of `tuples`.\n", - "\n", - "Once the constructor finishes its initialization, the `hw_model.dynapcnn_layers` property is a dictionary where each entry represents the ID of a `DynapcnnLayer` instance (an `int` from `0` to `L`), with this entry containing a `DynapcnnLayer` instance where a subset of the layers in the original SNN has been incorporated into, the core such instance has been assigned to, and the list of `DynapcnnLayer` instances (their IDs) the layer targets." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [], - "source": [ - "hw_model = DynapcnnNetworkGraph(\n", - " snn,\n", - " discretize=True,\n", - " input_shape=input_shape\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The `hw_model.to()` call will figure out into which core eac `DynapcnnLayer` instance will be assigned to. Once this assingment is made the instance itself is used to configure the `CNNLayerConfig` instance representing the core's configuration.\n", - "\n", - "If the cores' configuration is valid, each `DynapcnnLayer` instance and their respective destinations will be used to create a computational graph that encodes how the `forward` method of `hw_model.network` (a `nn.Module` using the `DynapcnnLayer` instances) propagates that through the network." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Network is valid\n" - ] - }, - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "hw_model.to(device=\"speck2fmodule:0\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The layers comprising our `hw_model` and their respective metadata can be inspected by calling `print` on a `DynapcnnNetworkGraph` instance." - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "---- DynapcnnLayer 0 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 0): Conv2d(2, 10, kernel_size=(2, 2), stride=(1, 1), bias=False)\n", - "(node 1): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1.), min_v_mem=Parameter containing:\n", - "tensor(-32768.), batch_size=1, num_timesteps=-1)\n", - "(node 2): SumPool2d(norm_type=1, kernel_size=(3, 3), stride=None, ceil_mode=False)\n", - "(node 3): SumPool2d(norm_type=1, kernel_size=(4, 4), stride=None, ceil_mode=False)\n", - "> layer destinations: [1, 2]\n", - "> assigned core: 0\n", - "\n", - "---- DynapcnnLayer 1 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 4): Conv2d(10, 10, kernel_size=(4, 4), stride=(1, 1), bias=False)\n", - "(node 6): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1.), min_v_mem=Parameter containing:\n", - "tensor(-32768.), batch_size=1, num_timesteps=-1)\n", - "> layer destinations: [2]\n", - "> assigned core: 1\n", - "\n", - "---- DynapcnnLayer 2 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 7): Conv2d(10, 1, kernel_size=(2, 2), stride=(1, 1), bias=False)\n", - "(node 8): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1.), min_v_mem=Parameter containing:\n", - "tensor(-32768.), batch_size=1, num_timesteps=-1)\n", - "> layer destinations: [3]\n", - "> assigned core: 2\n", - "\n", - "---- DynapcnnLayer 3 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 9): Conv2d(1, 500, kernel_size=(7, 7), stride=(1, 1), bias=False)\n", - "(node 10): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1.), min_v_mem=Parameter containing:\n", - "tensor(-32768.), batch_size=1, num_timesteps=-1)\n", - "> layer destinations: [4]\n", - "> assigned core: 3\n", - "\n", - "---- DynapcnnLayer 4 ----------------------------------------------------------\n", - "> layer modules: \n", - "(node 11): Conv2d(500, 10, kernel_size=(1, 1), stride=(1, 1), bias=False)\n", - "(node 12): IAFSqueeze(spike_threshold=Parameter containing:\n", - "tensor(1.), min_v_mem=Parameter containing:\n", - "tensor(-32768.), batch_size=1, num_timesteps=-1)\n", - "> layer destinations: []\n", - "> assigned core: 4\n", - "\n", - "\n" - ] - } - ], - "source": [ - "print(hw_model)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Training our DynapcnnNetwork\n", - "\n", - "Preparing the data..." - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [], - "source": [ - "# https://synsense.gitlab.io/sinabs-dynapcnn/getting_started/notebooks/nmnist_quick_start.html\n", - "\n", - "from tonic.datasets.nmnist import NMNIST\n", - "from tonic.transforms import ToFrame\n", - "from torch.utils.data import DataLoader\n", - "from torch.nn import CrossEntropyLoss\n", - "from torch.optim import SGD\n", - "from tqdm.notebook import tqdm\n", - " \n", - "# download dataset\n", - "root_dir = \"./NMNIST\"\n", - "_ = NMNIST(save_to=root_dir, train=True)\n", - "_ = NMNIST(save_to=root_dir, train=False)" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "type of data is: \n", - "(4686,)\n", - "time length of sample data is: 300760 micro seconds\n", - "there are 4686 events in the sample data\n", - "the label of the sample data is: 5\n" - ] - } - ], - "source": [ - "sample_data, label = NMNIST(save_to=root_dir, train=False)[0]\n", - "\n", - "print(f\"type of data is: {type(sample_data)}\")\n", - "print(sample_data.shape)\n", - "print(f\"time length of sample data is: {sample_data['t'][-1] - sample_data['t'][0]} micro seconds\")\n", - "print(f\"there are {len(sample_data)} events in the sample data\")\n", - "print(f\"the label of the sample data is: {label}\")" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The transformed array is in shape [Time-Step, Channel, Height, Width] --> (50, 2, 34, 34)\n" - ] - } - ], - "source": [ - "n_time_steps = 50\n", - "to_raster = ToFrame(sensor_size=NMNIST.sensor_size, n_time_bins=n_time_steps)\n", - "\n", - "snn_train_dataset = NMNIST(save_to=root_dir, train=True, transform=to_raster)\n", - "snn_test_dataset = NMNIST(save_to=root_dir, train=False, transform=to_raster)\n", - "\n", - "# check the transformed data\n", - "sample_data, label = snn_train_dataset[0]\n", - "print(f\"The transformed array is in shape [Time-Step, Channel, Height, Width] --> {sample_data.shape}\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Setting the training hyperparameters..." - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "device: NVIDIA GeForce RTX 3070 Ti\n" - ] - } - ], - "source": [ - "if torch.cuda.is_available():\n", - " device = torch.device('cuda:0')\n", - " print('device: ', torch.cuda.get_device_name(0))\n", - "else:\n", - " device = torch.device('cpu')" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [], - "source": [ - "epochs = 1\n", - "lr = 1e-4\n", - "batch_size = 64\n", - "num_workers = 4\n", - "shuffle = True" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [], - "source": [ - "snn_train_dataloader = DataLoader(snn_train_dataset, batch_size=batch_size, num_workers=num_workers, drop_last=True, shuffle=True)\n", - "snn_test_dataloader = DataLoader(snn_test_dataset, batch_size=batch_size, num_workers=num_workers, drop_last=True, shuffle=False)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Initializing our weights..." - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [], - "source": [ - "hw_cnn = hw_model.network" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [], - "source": [ - "hw_cnn.to(device)" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [], - "source": [ - "hw_cnn.init_weights()" - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "metadata": {}, - "outputs": [], - "source": [ - "optimizer = SGD(params=hw_cnn.parameters(), lr=lr)\n", - "criterion = CrossEntropyLoss()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The training loop..." - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "metadata": {}, - "outputs": [], - "source": [ - "losses = []\n", - "batches = []\n", - "batch_count = 0" - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "0a2474dc5d01479ead00063a63022136", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - " 0%| | 0/937 [00:00" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "plt.plot(batches, losses)\n", - "plt.ylabel('loss')\n", - "plt.xlabel('batches')\n", - "plt.show()" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "speck-rescnn", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.3" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/tests/test_nonsequential/NNI-test/main.ipynb b/tests/test_nonsequential/NNI-test/main.ipynb deleted file mode 100644 index 553c1170..00000000 --- a/tests/test_nonsequential/NNI-test/main.ipynb +++ /dev/null @@ -1,136 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "from nni.experiment import Experiment\n", - "experiment = Experiment('local')" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "search_space = {\n", - " 'lr': {'_type': 'loguniform', '_value': [0.001, 0.0001]},\n", - "}" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "experiment.config.trial_command = 'python model.py'\n", - "experiment.config.trial_code_directory = '.'" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "experiment.config.search_space = search_space" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "experiment.config.tuner.name = 'TPE'\n", - "experiment.config.tuner.class_args['optimize_mode'] = 'maximize'" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], - "source": [ - "experiment.config.max_trial_number = 5\n", - "experiment.config.trial_concurrency = 2" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[2024-04-26 17:05:41] \u001b[32mCreating experiment, Experiment ID: \u001b[36mda0h79xv\u001b[0m\n", - "[2024-04-26 17:05:41] \u001b[32mStarting web server...\u001b[0m\n", - "[2024-04-26 17:05:42] \u001b[32mSetting up...\u001b[0m\n", - "[2024-04-26 17:05:42] \u001b[32mWeb portal URLs: \u001b[36mhttp://127.0.0.1:8080 http://192.168.11.68:8080 http://172.17.0.1:8080\u001b[0m\n" - ] - }, - { - "data": { - "text/plain": [ - "True" - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "experiment.run(8080)" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[2024-04-26 17:05:52] \u001b[32mStopping experiment, please wait...\u001b[0m\n", - "[2024-04-26 17:05:52] \u001b[32mSaving experiment checkpoint...\u001b[0m\n", - "[2024-04-26 17:05:52] \u001b[32mStopping NNI manager, if any...\u001b[0m\n", - "[2024-04-26 17:05:54] \u001b[32mExperiment stopped.\u001b[0m\n" - ] - } - ], - "source": [ - "#input('Press enter to quit')\n", - "experiment.stop()" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "speck-rescnn", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.3" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/tests/test_nonsequential/NNI-test/model.py b/tests/test_nonsequential/NNI-test/model.py deleted file mode 100644 index 2ba97930..00000000 --- a/tests/test_nonsequential/NNI-test/model.py +++ /dev/null @@ -1,175 +0,0 @@ -import torch -import torch.nn as nn -import sinabs.layers as sl -import nni - -from tonic.datasets.nmnist import NMNIST -from tonic.transforms import ToFrame -from torch.utils.data import DataLoader -from torch.nn import CrossEntropyLoss -from torch.optim import SGD - -params = { - 'lr': 0.001, -} - -optimized_params = nni.get_next_parameter() -params.update(optimized_params) -print(params) - -###### Loading Data ###### - -batch_size = 32 -num_workers = 4 -epochs = 1 - -root_dir = "./NMNIST" -_ = NMNIST(save_to=root_dir, train=True) -_ = NMNIST(save_to=root_dir, train=False) - -n_time_steps = 50 -to_raster = ToFrame(sensor_size=NMNIST.sensor_size, n_time_bins=n_time_steps) - -snn_train_dataset = NMNIST(save_to=root_dir, train=True, transform=to_raster) -snn_test_dataset = NMNIST(save_to=root_dir, train=False, transform=to_raster) - -snn_train_dataloader = DataLoader(snn_train_dataset, batch_size=batch_size, num_workers=num_workers, drop_last=True, shuffle=True) -snn_test_dataloader = DataLoader(snn_test_dataset, batch_size=batch_size, num_workers=num_workers, drop_last=True, shuffle=False) - -###### Defining the Model ###### - -if torch.cuda.is_available(): - device = torch.device('cuda:0') - print('device: ', torch.cuda.get_device_name(0)) -else: - device = torch.device('cpu') - -class SNN(nn.Module): - def __init__(self) -> None: - super().__init__() - - self.conv1 = nn.Conv2d(2, 10, 2, 1, bias=False) - self.iaf1 = sl.IAFSqueeze(batch_size=1) - self.pool1 = sl.SumPool2d(3,3) - self.pool1a = sl.SumPool2d(4,4) - - self.conv2 = nn.Conv2d(10, 10, 4, 1, bias=False) - self.iaf2 = sl.IAFSqueeze(batch_size=1) - - self.conv3 = nn.Conv2d(10, 1, 2, 1, bias=False) - self.iaf3 = sl.IAFSqueeze(batch_size=1) - - self.flat = nn.Flatten() - - self.fc1 = nn.Linear(49, 100, bias=False) - self.iaf4 = sl.IAFSqueeze(batch_size=1) - - self.fc2 = nn.Linear(100, 10, bias=False) - self.iaf5 = sl.IAFSqueeze(batch_size=1) - - - def detach_neuron_states(self): - for name, layer in self.named_modules(): - if name != '': - if isinstance(layer, sl.StatefulLayer): - for name, buffer in layer.named_buffers(): - buffer.detach_() - - def init_weights(self): - for name, layer in self.named_modules(): - if isinstance(layer, nn.Conv2d) or isinstance(layer, nn.Linear): - nn.init.xavier_normal_(layer.weight.data) - - def forward(self, x): - - con1_out = self.conv1(x) - iaf1_out = self.iaf1(con1_out) - pool1_out = self.pool1(iaf1_out) - - conv2_out = self.conv2(pool1_out) - iaf2_out = self.iaf2(conv2_out) - - conv3_out = self.conv3(iaf2_out) - iaf3_out = self.iaf3(conv3_out) - - flat_out = self.flat(iaf3_out) - - fc1_out = self.fc1(flat_out) - iaf4_out = self.iaf4(fc1_out) - fc2_out = self.fc2(iaf4_out) - iaf5_out = self.iaf5(fc2_out) - - return iaf5_out - -snn = SNN().to(device) - -snn.init_weights() - -optimizer = SGD(snn.parameters(), lr=params['lr']) -loss_fn = CrossEntropyLoss() - -###### Defining Train/Test ###### - -def train(dataloader, model, loss_fn, optimizer): - size = len(dataloader.dataset) - model.train() - for batch, (X, y) in enumerate(dataloader): - # reshape the input from [Batch, Time, Channel, Height, Width] into [Batch*Time, Channel, Height, Width] - X = X.reshape(-1, 2, 34, 34).to(dtype=torch.float, device=device) - y = y.to(dtype=torch.long, device=device) - - # forward - pred = model(X) - - # reshape the output from [Batch*Time,num_classes] into [Batch, Time, num_classes] - pred = pred.reshape(batch_size, n_time_steps, -1) - - # accumulate all time-steps output for final prediction - pred = pred.sum(dim = 1) - loss = loss_fn(pred, y) - - # gradient update - optimizer.zero_grad() - loss.backward() - optimizer.step() - - # detach the neuron states and activations from current computation graph(necessary) - model.detach_neuron_states() - - break - -def test(dataloader, model): - correct_predictions = [] - with torch.no_grad(): - for X, y in dataloader: - # reshape the input from [Batch, Time, Channel, Height, Width] into [Batch*Time, Channel, Height, Width] - X = X.reshape(-1, 2, 34, 34).to(dtype=torch.float, device=device) - y = y.to(dtype=torch.long, device=device) - - # forward - output = model(X) - - # reshape the output from [Batch*Time,num_classes] into [Batch, Time, num_classes] - output = output.reshape(batch_size, n_time_steps, -1) - - # accumulate all time-steps output for final prediction - output = output.sum(dim=1) - - # calculate accuracy - pred = output.argmax(dim=1, keepdim=True) - - # compute the total correct predictions - correct_predictions.append(pred.eq(y.view_as(pred))) - - break - - return correct_predictions.sum().item()/(len(correct_predictions))*100 - -###### Training loop (HPO) ###### - -for t in range(epochs): - print(f"Epoch {t+1}\n-------------------------------") - train(snn_train_dataloader, snn, loss_fn, optimizer) - accuracy = test(snn_test_dataloader, snn) - nni.report_intermediate_result(accuracy) -nni.report_final_result(accuracy) \ No newline at end of file diff --git a/tests/test_nonsequential/baseline-SCNN-example_1-NNI.ipynb b/tests/test_nonsequential/baseline-SCNN-example_1-NNI.ipynb deleted file mode 100644 index 90889ea7..00000000 --- a/tests/test_nonsequential/baseline-SCNN-example_1-NNI.ipynb +++ /dev/null @@ -1,613 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [], - "source": [ - "import torch\n", - "import torch.nn as nn\n", - "import sinabs.layers as sl\n", - "from tqdm.notebook import tqdm\n", - "\n", - "from tonic.datasets.nmnist import NMNIST\n", - "from tonic.transforms import ToFrame\n", - "from torch.utils.data import DataLoader\n", - "from torch.nn import CrossEntropyLoss\n", - "from torch.optim import Adam\n", - "\n", - "from sinabs.activation.surrogate_gradient_fn import PeriodicExponential\n", - "\n", - "import matplotlib.pyplot as plt\n", - "import numpy as np" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "torch.manual_seed(0)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Loading Data" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "batch_size = 64\n", - "num_workers = 4\n", - "epochs = 5\n", - "lr = 1e-3" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "root_dir = \"./NMNIST\"\n", - "_ = NMNIST(save_to=root_dir, train=True)\n", - "_ = NMNIST(save_to=root_dir, train=False)" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "n_time_steps = 50\n", - "to_raster = ToFrame(sensor_size=NMNIST.sensor_size, n_time_bins=n_time_steps)\n", - "\n", - "snn_train_dataset = NMNIST(save_to=root_dir, train=True, transform=to_raster)\n", - "snn_test_dataset = NMNIST(save_to=root_dir, train=False, transform=to_raster)" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], - "source": [ - "snn_train_dataloader = DataLoader(snn_train_dataset, batch_size=batch_size, num_workers=num_workers, drop_last=True, shuffle=True)\n", - "snn_test_dataloader = DataLoader(snn_test_dataset, batch_size=batch_size, num_workers=num_workers, drop_last=True, shuffle=False)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Network Module\n", - "\n", - "We need to define a `nn.Module` implementing the network we want the chip to reproduce." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "device: NVIDIA GeForce RTX 3070 Ti\n" - ] - } - ], - "source": [ - "if torch.cuda.is_available():\n", - " device = torch.device('cuda:0')\n", - " print('device: ', torch.cuda.get_device_name(0))\n", - "else:\n", - " device = torch.device('cpu')" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [], - "source": [ - "class SNN(nn.Module):\n", - " def __init__(self) -> None:\n", - " super().__init__()\n", - "\n", - " self.conv1 = nn.Conv2d(2, 10, 2, 1, bias=False)\n", - " self.iaf1 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - " self.pool1 = nn.AvgPool2d(2,2)\n", - " self.pool1a = nn.AvgPool2d(6,6)\n", - "\n", - " self.conv2 = nn.Conv2d(10, 10, 2, 1, bias=False)\n", - " self.iaf2 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - " self.pool2 = nn.AvgPool2d(3,3)\n", - "\n", - " self.conv3 = nn.Conv2d(10, 10, 3, 1, bias=False)\n", - " self.iaf3 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - " self.pool3 = nn.AvgPool2d(2,2)\n", - "\n", - " self.flat = nn.Flatten()\n", - "\n", - " self.fc1 = nn.Linear(10, 10, bias=False)\n", - " self.iaf4 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - "\n", - " def detach_neuron_states(self):\n", - " for name, layer in self.named_modules():\n", - " if name != '':\n", - " if isinstance(layer, sl.StatefulLayer):\n", - " for name, buffer in layer.named_buffers():\n", - " buffer.detach_()\n", - "\n", - " def init_weights(self):\n", - " for name, layer in self.named_modules():\n", - " if isinstance(layer, nn.Conv2d) or isinstance(layer, nn.Linear):\n", - " nn.init.xavier_normal_(layer.weight.data)\n", - "\n", - " def forward(self, x):\n", - " \n", - " con1_out = self.conv1(x)\n", - " iaf1_out = self.iaf1(con1_out)\n", - " pool1_out = self.pool1(iaf1_out)\n", - "\n", - " conv2_out = self.conv2(pool1_out)\n", - " iaf2_out = self.iaf2(conv2_out)\n", - " pool2_out = self.pool2(iaf2_out)\n", - "\n", - " conv3_out = self.conv3(pool2_out)\n", - " iaf3_out = self.iaf3(conv3_out)\n", - " pool3_out = self.pool3(iaf3_out)\n", - "\n", - " flat_out = self.flat(pool3_out)\n", - " \n", - " fc1_out = self.fc1(flat_out)\n", - " iaf4_out = self.iaf4(fc1_out)\n", - "\n", - " return iaf4_out" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [], - "source": [ - "snn = SNN().to(device)" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [], - "source": [ - "snn.init_weights()" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [], - "source": [ - "optimizer = Adam(snn.parameters(), lr=lr, betas=(0.9, 0.999), eps=1e-8)\n", - "loss_fn = CrossEntropyLoss()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Define train and test" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [], - "source": [ - "def train(dataloader, model, loss_fn, optimizer, epochs, test_func, dataloader_test):\n", - " epochs_y = []\n", - " epochs_x = []\n", - " epochs_acc = []\n", - " model.train()\n", - "\n", - " for e in range(epochs):\n", - " losses = []\n", - " batches = []\n", - " batch_count = 0\n", - " train_p_bar = tqdm(snn_train_dataloader)\n", - "\n", - " for X, y in train_p_bar:\n", - " # reshape the input from [Batch, Time, Channel, Height, Width] into [Batch*Time, Channel, Height, Width]\n", - " X = X.reshape(-1, 2, 34, 34).to(dtype=torch.float, device=device)\n", - " y = y.to(dtype=torch.long, device=device)\n", - "\n", - " # forward\n", - " pred = model(X)\n", - "\n", - " # reshape the output from [Batch*Time,num_classes] into [Batch, Time, num_classes]\n", - " pred = pred.reshape(batch_size, n_time_steps, -1)\n", - "\n", - " # accumulate all time-steps output for final prediction\n", - " pred = pred.sum(dim = 1)\n", - " loss = loss_fn(pred, y)\n", - "\n", - " # gradient update\n", - " optimizer.zero_grad()\n", - " loss.backward()\n", - " optimizer.step()\n", - "\n", - " # detach the neuron states and activations from current computation graph(necessary)\n", - " model.detach_neuron_states()\n", - "\n", - " train_p_bar.set_description(f\"Epoch {e} - BPTT Training Loss: {round(loss.item(), 4)}\")\n", - "\n", - " batch_count += 1\n", - " losses.append(loss.item())\n", - " batches.append(batch_count)\n", - "\n", - " epochs_y.append(losses)\n", - " epochs_x.append(batches)\n", - "\n", - " acc = test_func(dataloader_test, model)\n", - " print(f'Epoch {e} accuracy: {acc}')\n", - " epochs_acc.append(acc)\n", - "\n", - " return epochs_x, epochs_y, epochs_acc\n" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [], - "source": [ - "def test(dataloader, model):\n", - " correct_predictions = []\n", - " with torch.no_grad():\n", - " test_p_bar = tqdm(dataloader)\n", - " for X, y in test_p_bar:\n", - " # reshape the input from [Batch, Time, Channel, Height, Width] into [Batch*Time, Channel, Height, Width]\n", - " X = X.reshape(-1, 2, 34, 34).to(dtype=torch.float, device=device)\n", - " y = y.to(dtype=torch.long, device=device)\n", - "\n", - " # forward\n", - " output = model(X)\n", - "\n", - " # reshape the output from [Batch*Time,num_classes] into [Batch, Time, num_classes]\n", - " output = output.reshape(batch_size, n_time_steps, -1)\n", - "\n", - " # accumulate all time-steps output for final prediction\n", - " output = output.sum(dim=1)\n", - "\n", - " # calculate accuracy\n", - " pred = output.argmax(dim=1, keepdim=True)\n", - "\n", - " # compute the total correct predictions\n", - " correct_predictions.append(pred.eq(y.view_as(pred)))\n", - "\n", - " test_p_bar.set_description(f\"Testing Model...\")\n", - " \n", - " correct_predictions = torch.cat(correct_predictions)\n", - " return correct_predictions.sum().item()/(len(correct_predictions))*100" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Training loop (HPO)" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "0cd81220753e46039b5cac482961c5c5", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - " 0%| | 0/937 [00:00" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "plt.plot(epochs_x[-1], epochs_y[-1])\n", - "plt.xlabel('batches')\n", - "plt.ylabel('loss')\n", - "plt.ylim(0,)\n", - "plt.show()" - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "y_avg = []\n", - "for y in epochs_y:\n", - " y_avg.append(np.mean(y))\n", - "\n", - "plt.plot(np.arange(len(epochs_x)), y_avg, marker = '.')\n", - "plt.xlabel('epoch')\n", - "plt.ylabel('average loss')\n", - "plt.ylim(0,)\n", - "for i, txt in enumerate(y_avg):\n", - " plt.text(i, txt, f'{txt:.2f}', ha='center', va='bottom')\n", - "plt.show()" - ] - }, - { - "cell_type": "code", - "execution_count": 24, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "plt.plot(np.arange(len(epochs_x)), epochs_acc, marker = '.')\n", - "plt.xlabel('epoch')\n", - "plt.ylabel('test accuracy')\n", - "plt.ylim(80, 100)\n", - "for i, txt in enumerate(epochs_acc):\n", - " plt.text(i, txt, f'{txt:.2f}', ha='center', va='bottom')\n", - "plt.show()" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "speck-rescnn", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.3" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/tests/test_nonsequential/baseline-SCNN-example_2.ipynb b/tests/test_nonsequential/baseline-SCNN-example_2.ipynb deleted file mode 100644 index 893b5e79..00000000 --- a/tests/test_nonsequential/baseline-SCNN-example_2.ipynb +++ /dev/null @@ -1,630 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "import torch\n", - "import torch.nn as nn\n", - "import sinabs.layers as sl\n", - "from tqdm.notebook import tqdm\n", - "\n", - "from tonic.datasets.nmnist import NMNIST\n", - "from tonic.transforms import ToFrame\n", - "from torch.utils.data import DataLoader\n", - "from torch.nn import CrossEntropyLoss\n", - "from torch.optim import Adam\n", - "\n", - "from sinabs.activation.surrogate_gradient_fn import PeriodicExponential\n", - "\n", - "import matplotlib.pyplot as plt\n", - "import numpy as np" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "torch.manual_seed(0)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Loading Data" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "batch_size = 64\n", - "num_workers = 4\n", - "epochs = 5\n", - "lr = 1e-3" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "root_dir = \"./NMNIST\"\n", - "_ = NMNIST(save_to=root_dir, train=True)\n", - "_ = NMNIST(save_to=root_dir, train=False)" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "n_time_steps = 50\n", - "to_raster = ToFrame(sensor_size=NMNIST.sensor_size, n_time_bins=n_time_steps)\n", - "\n", - "snn_train_dataset = NMNIST(save_to=root_dir, train=True, transform=to_raster)\n", - "snn_test_dataset = NMNIST(save_to=root_dir, train=False, transform=to_raster)" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], - "source": [ - "snn_train_dataloader = DataLoader(snn_train_dataset, batch_size=batch_size, num_workers=num_workers, drop_last=True, shuffle=True)\n", - "snn_test_dataloader = DataLoader(snn_test_dataset, batch_size=batch_size, num_workers=num_workers, drop_last=True, shuffle=False)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Network Module\n", - "\n", - "We need to define a `nn.Module` implementing the network we want the chip to reproduce." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "device: NVIDIA GeForce RTX 3070 Ti\n" - ] - } - ], - "source": [ - "if torch.cuda.is_available():\n", - " device = torch.device('cuda:0')\n", - " print('device: ', torch.cuda.get_device_name(0))\n", - "else:\n", - " device = torch.device('cpu')" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [], - "source": [ - "class SNN(nn.Module):\n", - " def __init__(self) -> None:\n", - " super().__init__()\n", - "\n", - " self.conv1 = nn.Conv2d(2, 10, 2, 1, bias=False)\n", - " self.iaf1 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - " self.pool1 = nn.AvgPool2d(2,2)\n", - "\n", - " self.conv2 = nn.Conv2d(10, 10, 2, 1, bias=False)\n", - " self.iaf2 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - " self.pool2 = nn.AvgPool2d(3,3)\n", - "\n", - " self.conv3 = nn.Conv2d(10, 10, 3, 1, bias=False)\n", - " self.iaf3 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - " self.pool3 = nn.AvgPool2d(2,2)\n", - "\n", - " self.flat = nn.Flatten()\n", - "\n", - " self.fc1 = nn.Linear(10, 100, bias=False)\n", - " self.iaf4 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - "\n", - " self.fc2 = nn.Linear(100, 100, bias=False)\n", - " self.iaf5 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - "\n", - " self.fc3 = nn.Linear(100, 100, bias=False)\n", - " self.iaf6 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - "\n", - " self.fc4 = nn.Linear(100, 10, bias=False)\n", - " self.iaf7 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - "\n", - " def detach_neuron_states(self):\n", - " for name, layer in self.named_modules():\n", - " if name != '':\n", - " if isinstance(layer, sl.StatefulLayer):\n", - " for name, buffer in layer.named_buffers():\n", - " buffer.detach_()\n", - "\n", - " def init_weights(self):\n", - " for name, layer in self.named_modules():\n", - " if isinstance(layer, nn.Conv2d) or isinstance(layer, nn.Linear):\n", - " nn.init.xavier_normal_(layer.weight.data)\n", - "\n", - " def forward(self, x):\n", - " \n", - " con1_out = self.conv1(x)\n", - " iaf1_out = self.iaf1(con1_out)\n", - " pool1_out = self.pool1(iaf1_out)\n", - "\n", - " conv2_out = self.conv2(pool1_out)\n", - " iaf2_out = self.iaf2(conv2_out)\n", - " pool2_out = self.pool2(iaf2_out)\n", - "\n", - " conv3_out = self.conv3(pool2_out)\n", - " iaf3_out = self.iaf3(conv3_out)\n", - " pool3_out = self.pool3(iaf3_out)\n", - "\n", - " flat_out = self.flat(pool3_out)\n", - " \n", - " fc1_out = self.fc1(flat_out)\n", - " iaf4_out = self.iaf4(fc1_out)\n", - "\n", - " fc2_out = self.fc2(iaf4_out)\n", - " iaf5_out = self.iaf5(fc2_out)\n", - "\n", - " fc3_out = self.fc3(iaf5_out)\n", - " iaf6_out = self.iaf6(fc3_out)\n", - "\n", - " fc4_out = self.fc4(iaf6_out)\n", - " iaf7_out = self.iaf7(fc4_out)\n", - "\n", - " return iaf7_out" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [], - "source": [ - "snn = SNN().to(device)" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [], - "source": [ - "snn.init_weights()" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [], - "source": [ - "optimizer = Adam(snn.parameters(), lr=lr, betas=(0.9, 0.999), eps=1e-8)\n", - "loss_fn = CrossEntropyLoss()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Define train and test" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [], - "source": [ - "def train(dataloader, model, loss_fn, optimizer, epochs, test_func, dataloader_test):\n", - " epochs_y = []\n", - " epochs_x = []\n", - " epochs_acc = []\n", - " model.train()\n", - "\n", - " for e in range(epochs):\n", - " losses = []\n", - " batches = []\n", - " batch_count = 0\n", - " train_p_bar = tqdm(snn_train_dataloader)\n", - "\n", - " for X, y in train_p_bar:\n", - " # reshape the input from [Batch, Time, Channel, Height, Width] into [Batch*Time, Channel, Height, Width]\n", - " X = X.reshape(-1, 2, 34, 34).to(dtype=torch.float, device=device)\n", - " y = y.to(dtype=torch.long, device=device)\n", - "\n", - " # forward\n", - " pred = model(X)\n", - "\n", - " # reshape the output from [Batch*Time,num_classes] into [Batch, Time, num_classes]\n", - " pred = pred.reshape(batch_size, n_time_steps, -1)\n", - "\n", - " # accumulate all time-steps output for final prediction\n", - " pred = pred.sum(dim = 1)\n", - " loss = loss_fn(pred, y)\n", - "\n", - " # gradient update\n", - " optimizer.zero_grad()\n", - " loss.backward()\n", - " optimizer.step()\n", - "\n", - " # detach the neuron states and activations from current computation graph(necessary)\n", - " model.detach_neuron_states()\n", - "\n", - " train_p_bar.set_description(f\"Epoch {e} - BPTT Training Loss: {round(loss.item(), 4)}\")\n", - "\n", - " batch_count += 1\n", - " losses.append(loss.item())\n", - " batches.append(batch_count)\n", - "\n", - " epochs_y.append(losses)\n", - " epochs_x.append(batches)\n", - "\n", - " acc = test_func(dataloader_test, model)\n", - " print(f'Epoch {e} accuracy: {acc}')\n", - " epochs_acc.append(acc)\n", - "\n", - " return epochs_x, epochs_y, epochs_acc\n" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [], - "source": [ - "def test(dataloader, model):\n", - " correct_predictions = []\n", - " with torch.no_grad():\n", - " test_p_bar = tqdm(dataloader)\n", - " for X, y in test_p_bar:\n", - " # reshape the input from [Batch, Time, Channel, Height, Width] into [Batch*Time, Channel, Height, Width]\n", - " X = X.reshape(-1, 2, 34, 34).to(dtype=torch.float, device=device)\n", - " y = y.to(dtype=torch.long, device=device)\n", - "\n", - " # forward\n", - " output = model(X)\n", - "\n", - " # reshape the output from [Batch*Time,num_classes] into [Batch, Time, num_classes]\n", - " output = output.reshape(batch_size, n_time_steps, -1)\n", - "\n", - " # accumulate all time-steps output for final prediction\n", - " output = output.sum(dim=1)\n", - "\n", - " # calculate accuracy\n", - " pred = output.argmax(dim=1, keepdim=True)\n", - "\n", - " # compute the total correct predictions\n", - " correct_predictions.append(pred.eq(y.view_as(pred)))\n", - "\n", - " test_p_bar.set_description(f\"Testing Model...\")\n", - " \n", - " correct_predictions = torch.cat(correct_predictions)\n", - " return correct_predictions.sum().item()/(len(correct_predictions))*100" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Training loop (HPO)" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "392406a27a8146319e1aab0a40fe2f59", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - " 0%| | 0/937 [00:00" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "plt.plot(epochs_x[-1], epochs_y[-1])\n", - "plt.xlabel('batches')\n", - "plt.ylabel('loss')\n", - "plt.ylim(0,)\n", - "plt.show()" - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjcAAAGwCAYAAABVdURTAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy81sbWrAAAACXBIWXMAAA9hAAAPYQGoP6dpAABTAElEQVR4nO3de1xUZf4H8M/MwDCgMIhc5C4o4g1NQREVlRRMXVe7rJSu1qa/1rL1QmqirWu2vygvZW6pWZo/dxMpRXNXNsVU0CAvBOUVSRAQQQRluAk4zPn9gU6NXGSQ4TDD5/16zevVPPOcM9/HU83H55zzHIkgCAKIiIiITIRU7AKIiIiIWhPDDREREZkUhhsiIiIyKQw3REREZFIYboiIiMikMNwQERGRSWG4ISIiIpNiJnYBbU2j0eDGjRuwtraGRCIRuxwiIiJqBkEQUFZWBhcXF0ilTc/NdLhwc+PGDbi7u4tdBhEREbVAbm4u3NzcmuzT4cKNtbU1gLo/HBsbG5GrISIiouYoLS2Fu7u79ne8KR0u3Dw4FWVjY8NwQ0REZGSac0kJLyhuRGJiIiZPngwXFxdIJBLs37+/yf6xsbEIDQ2Fg4MDbGxsEBQUhEOHDtXrV1JSgnnz5sHZ2RkKhQJ9+vRBXFycgUZBRETU8TDcNKKiogIDBw7Exx9/3Kz+iYmJCA0NRVxcHFJSUhASEoLJkycjNTVV26empgahoaG4du0a9uzZg/T0dHz22WdwdXU11DCIiIg6nA53Wqq5JkyYgAkTJjS7/4YNG3Tev/vuu/jmm2/w73//G4MGDQIAbN++Hbdv30ZSUhLMzc0BAJ6enq1WMxEREXHmxmA0Gg3KyspgZ2enbTtw4ACCgoIwb948ODk5oX///nj33XdRW1srYqVERESmhTM3BrJ+/XpUVFRg2rRp2rbMzEwcPXoUM2bMQFxcHDIyMjBv3jyo1WqsXLlSxGqJiIhMB8ONAURHR2PVqlX45ptv4OjoqG3XaDRwdHTE1q1bIZPJ4O/vjxs3bmDt2rUMN0RERK2E4aaVxcTEYPbs2fj6668xbtw4nc+cnZ1hbm4OmUymbevTpw8KCgpQU1MDuVze1uUSERGZHF5z04qio6Px0ksvYdeuXZg0aVK9z0eMGIFffvkFGo1G23blyhU4Ozsz2BAREbUShptGlJeXIy0tDWlpaQCArKwspKWlIScnBwAQGRmJWbNmaftHR0dj1qxZWL9+PYYNG4aCggIUFBRApVJp+7z66qsoLi7GggULcOXKFRw8eBDvvvsu5s2b16ZjIyIiMmUSQRAEsYtoS6WlpVAqlVCpVE2uUHz8+HGEhITUa3/xxRexY8cOvPTSS7h27RqOHz8OABgzZgwSEhIa7f9AcnIyFi1ahLS0NLi6umL27Nl48803dU5VERERka7m/n4DDDettt/dp3MQGXsOAgCpBIh6xg/hQzxabf9EREQdmT6/3zwt1QryVXcRua8u2ACARgCWx55HvuquqHURERF1RAw3rSCrqAIPz3/VCgKuFVWKUxAREVEHxnDTCrzsO0H60ENKpRKgu72VOAURERF1YAw3rcBZaYmoZ/wg+81j2Ae628JZaSliVURERB0Tw00rCR/igZPLQvDu1P4AgLTcEqQXlIlcFRERUcfDcNOKnJWWmD7MExP6d4MgAOsOp4tdEhERUYfDcGMAb4T1glQCxF+8iR9z7ohdDhERUYfCcGMAPR2t8exgNwDA2m/T0cGWEiIiIhIVw42BLBjnA7lMiuTMYnz/S7HY5RAREXUYDDcG4tbFCtMD61YoXnvoMmdviIiI2gjDjQG9/mRPWMll+Om6CocuFIhdDhERUYfAcGNA9p0tMHukFwBg3eErqNVw9oaIiMjQGG4M7H9GecPWyhy/FJYj9sfrYpdDRERk8hhuDMxGYY5XR/cAAGw4koFqda3IFREREZk2UcNNYmIiJk+eDBcXF0gkEuzfv7/J/rGxsQgNDYWDgwNsbGwQFBSEQ4cOtU2xj2FWUHc4Wlsgr+Quok/liF0OERGRSRM13FRUVGDgwIH4+OOPm9U/MTERoaGhiIuLQ0pKCkJCQjB58mSkpqYauNLHYymXYf5YHwDAx8d+QUW1WuSKiIiITJdEaCf3KEskEuzbtw9Tp07Va7t+/fohPDwcK1eubPDz6upqVFdXa9+XlpbC3d0dKpUKNjY2j1OyXu7VajDugwRkF1dicVgvvP6kT5t9NxERkbErLS2FUqls1u+3UV9zo9FoUFZWBjs7u0b7REVFQalUal/u7u5tWOGvzGVSRIT2AgB8mpiJksoaUeogIiIydUYdbtavX4+KigpMmzat0T6RkZFQqVTaV25ubhtWqGvyABf07maNsio1tiRkilYHERGRKTPacBMdHY1Vq1YhJiYGjo6OjfazsLCAjY2NzkssUqkEi8N8AQA7krJQWFolWi1ERESmyijDTUxMDGbPno2vvvoK48aNE7scvYzt44jBHraouqfBxqMZYpdDRERkcowu3ERHR+Oll17Crl27MGnSJLHL0ZtEIsHSp3oDAHafzkVOcaXIFREREZkWUcNNeXk50tLSkJaWBgDIyspCWloacnLq1oKJjIzErFmztP2jo6Mxa9YsrF+/HsOGDUNBQQEKCgqgUqnEKL/Fhnl3RbCPPdQaAR8euSJ2OURERCZF1HBz9uxZDBo0CIMGDQIAREREYNCgQdrbuvPz87VBBwA+/fRTqNVqzJs3D87OztrXggULRKn/cSwdXzd7sz8tD5cLSkWuhoiIyHS0m3Vu2oo+98kb2mtfpiDuXAHG9XHC5y8GiFoLERFRe9Zh1rkxdhGhvpBKgCOXbuLHnDtil0NERGQSGG5E1NOxM54d7AYAWPttOjrYJBoREZFBMNyIbGFoL8hlUiRnFuPkL0Vil0NERGT0GG5E5mpriRnDPAAAaw9x9oaIiOhxMdy0A/NCesJKLsPP11U4dKFA7HKIiIiMGsNNO2Df2QKzR3oBANYdvoJaDWdviIiIWorhpp34n1HesLUyxy+F5Yj98brY5RARERkthpt2wkZhjldH9wAAbDiSgWp1rcgVERERGSeGm3bkxeHd4WRjgbySu4g+lfPoDYiIiKgehpt2RGEuw1+e9AEAfHzsF1RUq0WuiIiIyPgw3LQz4UPc4dnVCkXlNfji+yyxyyEiIjI6DDftjLlMiojQXgCATxMzUVJZI3JFRERExoXhph2aPMAFvbtZo6xKjS0JmWKXQ0REZFQYbtohqVSCxWG+AIAdSVkoLK0SuSIiIiLjwXDTTo3t44jBHraouqfBxqMZYpdDRERkNBhu2imJRIKlT/UGAOw+nYvs4gqRKyIiIjIODDft2DDvrhjVywFqjYANRzh7Q0RE1BwMN+3ckvvX3uxPy8PlglKRqyEiImr/GG7aOT83JSb6dYMgAOsOXRG7HCIionaP4cYIRIT6QioBjly6iZTsO2KXQ0RE1K4x3BiBno6d8Zy/GwBg7aHLEARB5IqIiIjaL4YbI7FgXC/IZVL8kHkbJ38pErscIiKidovhxki42lpixjAPAMDaQ+mcvSEiImoEw40RmRfSE1ZyGX6+rsK35wvELoeIiKhdYrgxIvadLTBnpBcAYN3hdNRqOHtDRET0MIYbIzNnlDdsrcxx9VYFYn+8LnY5RERE7Q7DjZGxUZjj1dE9AAAbjmSgWl0rckVERETtC8ONEXpxeHc42Vggr+Qudp3KEbscIiKidoXhxggpzGWYP9YHAPDJsV9QUa0WuSIiIqL2g+HGSE0LcIdnVysUldfgi++zxC6HiIio3WC4MVLmMikiQnsBAD5NzERJZY3IFREREbUPDDdGbPIAF/TuZo2yKjU2J1wVuxwiIqJ2geHGiEmlEiwZ7wsA+L+ka7hZWiVyRUREROJjuDFyT/Z2hL9nF1Td0+AfRzPELoeIiEh0DDdGTiL5dfZm9+lcZBdXiFwRERGRuBhuTMAw764Y1csBao2AD+OviF0OERGRqBhuTMTS+7M33/x0A5cLSkWuhoiISDwMNyaiv6sSk/ycIQjAukOcvSEioo6L4caELArtBakEOHLpJlKy74hdDhERkSgYbkxIT8fOeM7fDQCw9tBlCIIgckVERERtj+HGxCwY1wtymRQ/ZN7GyV+KxC6HiIiozTHcmBhXW0v8cZgnAGDtoXTO3hARUYfDcGOCXgvpASu5DD9fV+Hb8wVil0NERNSmGG5MkH1nC8wZ6QUAWHc4HepajcgVERERtR2GGxM1Z5Q3bK3McfVWBfal5oldDhERUZsRNdwkJiZi8uTJcHFxgUQiwf79+x+5TUJCAvz9/aFQKODt7Y0tW7YYvlAjZKMwx2tjegAANhzJQLW6VuSKiIiI2oao4aaiogIDBw7Exx9/3Kz+WVlZmDhxIoKDg5Gamorly5dj/vz52Lt3r4ErNU6zgrrDycYCeSV3setUjtjlEBERtQmJ0E5up5FIJNi3bx+mTp3aaJ8333wTBw4cwKVLl7Rtc+fOxU8//YTk5ORmfU9paSmUSiVUKhVsbGwet+x278tT2Vix7zy6dpIjcWkIOlmYiV0SERGR3vT5/Taqa26Sk5MRFham0zZ+/HicPXsW9+7da3Cb6upqlJaW6rw6kmkB7uje1QrFFTX44vssscshIiIyOKMKNwUFBXByctJpc3JyglqtRlFRwwvWRUVFQalUal/u7u5tUWq7YS6TYlFoLwDAp4mZKKmsEbkiIiIiwzKqcAPUnb76rQdn1R5ufyAyMhIqlUr7ys3NNXiN7c3kAS7o3c0aZVVqbE64KnY5REREBmVU4aZbt24oKNBdlK6wsBBmZmbo2rVrg9tYWFjAxsZG59XRSKUSLBnvCwDY8f013CytErkiIiIiwzGqcBMUFIT4+HidtsOHDyMgIADm5uYiVWUcnuztCH/PLqhWa/CPoxlil0NERGQwooab8vJypKWlIS0tDUDdrd5paWnIyam7bTkyMhKzZs3S9p87dy6ys7MRERGBS5cuYfv27di2bRsWL14sRvlGRSKRYOn92Zvdp3ORXVwhckVERESGIWq4OXv2LAYNGoRBgwYBACIiIjBo0CCsXLkSAJCfn68NOgDg5eWFuLg4HD9+HE888QTeeecdbNy4Ec8++6wo9RubQO+uGN3LAWqNgA/jr4hdDhERkUG0m3Vu2kpHW+fmYefzVPjdP05CIgH+uyAYvbt1vD8DIiIyPia7zg09vv6uSkzyc4YgAOsOcfaGiIhMD8NNBxQR1gsyqQRHLt1ESvYdscshIiJqVQw3HVAPh854brAbAGDtocvoYGcmiYjIxDHcdFDzx/lALpPih8zbOJHR8OrORERExojhpoNytbXEH4d5AgDWHkrn7A0REZkMhpsObF5ID3SSy3AuT4Vvzxc8egMiIiIjwHDTgXXtbIHZwd4AgHWH06Gu1YhcERER0eNjuOng5gR7wdbKHFdvVSA2NU/scoiIiB4bw00HZ6Mwx2tjegAAPjqSgWp1rcgVERERPR6GG8KsoO7oZqNAXsld7DqV8+gNiIiI2jGGG4LCXIb5Y30AAB8f/QUV1WqRKyIiImo5hhsCAPwhwA3du1qhuKIG209miV0OERFRizHcEADAXCbFotBeAICtiZkoqawRuSIiIqKWYbghrckDXNDH2QZl1WpsTrgqdjlEREQtwnBDWlKpBEvG183e7Pj+Gm6WVolcERERkf4YbkhHiK8j/D27oFqtwcbvMsQuh4iISG8MN6RDIpFg6XhfAEDMmVxkF1eIXBEREZF+GG6onkDvrhjdywFqjYAP46+IXQ4REZFeGG6oQUvuz95889MNXC4oFbkaIiKi5mO4oQb1d1Vikp8zBAFYdyhd7HKIiIiajeGGGhUR1gsyqQRHLhUiJfuO2OUQERE1C8MNNaqHQ2c8N9gNALD20GUIgiByRURERI/GcENNWjDOB3IzKX7IvI0TGUVil0NERPRIDDfUJBdbS8wc5gkAWHsonbM3RETU7jHc0CO9NqYHOsllOJenwrfnC8Quh4iIqEkMN/RIXTtbYHawNwBg3eF0qGs1IldERETUOIYbapb/CfZCFytzXL1VgdjUPLHLISIiahTDDTWLtcIcr43pCQD46EgGqtW1IldERETUMIYbaraZQZ7oZqNAXsldfPlDjtjlEBERNYjhhppNYS7D/LE+AIBPjv2Cimq1yBURERHVx3BDevlDgBu6d7VCcUUNtp/MErscIiKiehhuSC/mMikiwuoeqrk1MRN3KmpEroiIiEgXww3p7Xd+zujjbIOyajW2JFwVuxwiIiIdDDekN6lUgiXjewEAdiRdw83SKpErIiIi+hXDDbVIiK8jAjy7oFqtwcbvMsQuh4iISIvhhlpEIpFg6VO9AQAxZ3KRXVwhckVERER1GG6oxYZ62WF0LweoNQI+iL8idjlEREQAGG7oMS0ZX3fn1IGfbuBSfqnI1RARETHc0GPq76rEpAHOEARg/eF0scshIiJiuKHH90ZoL8ikEhy5VIiU7Ntil0NERB0cww09Nm+HznhusBsAYM236RAEQeSKiIioI2O4oVaxYJwP5GZSnMq6jRMZRWKXQ0REHRjDDbUKF1tLzBzmCQBYe4izN0REJB6GG2o1r43pgU5yGc7lqfDf8wVil0NERB0Uww21mq6dLTA72BsAsO5wOtS1GpErIiKijojhhlrV/wR7oYuVOTJvVSA2NU/scoiIqAMSPdxs2rQJXl5eUCgU8Pf3x4kTJ5rs/+WXX2LgwIGwsrKCs7Mz/vSnP6G4uLiNqqVHsVaY47UxPQEAHx3JQLW6VuSKiIiooxE13MTExGDhwoVYsWIFUlNTERwcjAkTJiAnJ6fB/idPnsSsWbMwe/ZsXLhwAV9//TXOnDmDOXPmtHHl1JSZQZ7oZqNAXsldfPlDw8eSiIjIUPQON3fv3kVlZaX2fXZ2NjZs2IDDhw/r/eUffPABZs+ejTlz5qBPnz7YsGED3N3dsXnz5gb7//DDD+jevTvmz58PLy8vjBw5En/+859x9uzZRr+juroapaWlOi8yLIW5DPPH+gAAPjn2C8qr1SJXREREHYne4WbKlCnYuXMnAKCkpASBgYFYv349pkyZ0mgoaUhNTQ1SUlIQFham0x4WFoakpKQGtxk+fDiuX7+OuLg4CIKAmzdvYs+ePZg0aVKj3xMVFQWlUql9ubu7N7tGark/BLihe1crFFfU4IuTWWKXQ0REHYje4ebHH39EcHAwAGDPnj1wcnJCdnY2du7ciY0bNzZ7P0VFRaitrYWTk5NOu5OTEwoKGr6NePjw4fjyyy8RHh4OuVyObt26wdbWFv/4xz8a/Z7IyEioVCrtKzc3t9k1UsuZy6SICKt7qObWxEzcqagRuSIiIuoo9A43lZWVsLa2BgAcPnwYzzzzDKRSKYYNG4bs7Gy9C5BIJDrvBUGo1/bAxYsXMX/+fKxcuRIpKSn49ttvkZWVhblz5za6fwsLC9jY2Oi8qG38zs8ZfZ1tUFatxpaEq2KXQ0REHYTe4aZnz57Yv38/cnNzcejQIe1ppcLCQr2Cg729PWQyWb1ZmsLCwnqzOQ9ERUVhxIgRWLJkCQYMGIDx48dj06ZN2L59O/Lz8/UdChmYVCrBkvF1szc7kq6hQFUlckVERNQR6B1uVq5cicWLF6N79+4IDAxEUFAQgLpZnEGDBjV7P3K5HP7+/oiPj9dpj4+Px/DhwxvcprKyElKpbskymQwAuNx/OzXG1wEBnl1QrdbgH0czxC6HiIg6AL3DzXPPPYecnBycPXsW3377rbZ97Nix+PDDD/XaV0REBD7//HNs374dly5dwqJFi5CTk6M9zRQZGYlZs2Zp+0+ePBmxsbHYvHkzMjMz8f3332P+/PkYOnQoXFxc9B0KtQGJRIKlT/UGAMScyUV2cYXIFRERkakza8lG3bp1Q7du3QAApaWlOHr0KHx9fdG7d2+99hMeHo7i4mKsXr0a+fn56N+/P+Li4uDpWfcAxvz8fJ01b1566SWUlZXh448/xhtvvAFbW1s8+eSTeP/991syDGojQ73sMMbXAcfTb+GD+Cv46Pnmz/ARERHpSyLoeT5n2rRpGDVqFF5//XXcvXsXAwcOxLVr1yAIAnbv3o1nn33WULW2itLSUiiVSqhUKl5c3IbO56nwu3+chEQCxM0PRh9n/tkTEVHz6fP7rfdpqcTERO2t4Pv27YMgCCgpKcHGjRvx97//vWUVk8nr76rEpAHOEARg/eF0scshIiITpne4UalUsLOzAwB8++23ePbZZ2FlZYVJkyYhI4MXjFLj3gjtBZlUgiOXCpGSfVvscoiIyETpHW7c3d2RnJyMiooKfPvtt9pbwe/cuQOFQtHqBZLp8HbojD/4uwEA1nybzjvciIjIIPQONwsXLsSMGTPg5uYGFxcXjBkzBkDd6So/P7/Wro9MzPyxPpCbSXEq6zYSM4rELoeIiEyQ3uHmtddeQ3JyMrZv346TJ09q153x9vbmNTf0SC62lpg5rO5uuLWHLnP2hoiIWp3ed0v91oNNG3tcQnvEu6XEV1xejVFrjqGiphabZgzGRD9nsUsiIqJ2zqB3SwHAzp074efnB0tLS1haWmLAgAH45z//2aJiqePp2tkCc4K9AQDrDqdDXasRuSIiIjIleoebDz74AK+++iomTpyIr776CjExMXjqqacwd+5cvVcopo5rTrAXuliZI/NWBWJ/zBO7HCIiMiF6n5by8vLC22+/rfNYBAD4v//7P6xatQpZWVmtWmBr42mp9uOzxEz8b9wluCgVOLZkDCzMZGKXRERE7ZRBT0vl5+c3+GDL4cOH88ncpJeZQZ7oZqPADVUVvvwh59EbEBERNYPe4aZnz5746quv6rXHxMTAx8enVYqijkFhLsOCcXX/znxy7BeUV6tFroiIiEyB3g/OfPvttxEeHo7ExESMGDECEokEJ0+exHfffddg6CFqynP+btiamImsogpsP5mF+WMZkImI6PHoPXPz7LPP4tSpU7C3t8f+/fsRGxsLe3t7nD59Gk8//bQhaiQTZi6TYlFoLwB11+DcqagRuSIiIjJ2j7XOjTHiBcXtj0Yj4Hf/OImL+aX48yhvRE7sI3ZJRETUzrT6BcWlpaXNfhHpSyqVYMl4XwDAjqRrKFBViVwREREZs2Zdc2Nra/vIVYgFQYBEIkFtbW2rFEYdyxhfBwzp3gVnrt3BxqMZePdpPqeMiIhaplnh5tixY4augzo4iUSCJeN7Y9qnyfjqTC5eCfZGd/tOYpdFRERGqFnhZvTo0YaugwhDvewwxtcBx9Nv4cMjV/DR84PELomIiIxQi54tRWQoi8Pqrr058NMNXMrnNVxERKQ/hhtqV/q7KvG7Ac4QBGDdoXSxyyEiIiPEcEPtTkRoL8ikEnx3uRAp2bfFLoeIiIwMww21O94OnfEHfzcAwJpv09HBlmIiIqLH1KJwo1arceTIEXz66acoKysDANy4cQPl5eWtWhx1XAvG+UBuJsWprNtIzCgSuxwiIjIieoeb7Oxs+Pn5YcqUKZg3bx5u3boFAFizZg0WL17c6gVSx+SstMSsYZ4AgLWHLkOj4ewNERE1j97hZsGCBQgICMCdO3dgaWmpbX/66afx3XfftWpx1LG9FtITneQynM8rxbcXCsQuh4iIjITe4ebkyZN46623IJfLddo9PT2Rl5fXaoUR2XWSY06wNwBg3eF0qGs1IldERETGQO9wo9FoGnzEwvXr12Ftbd0qRRE9MCfYC12szJF5qwKxPzI8ExHRo+kdbkJDQ7Fhwwbte4lEgvLycvztb3/DxIkTW7M2IlgrzDEvpCcAYMORK6i6x2eXERFR0/QONx9++CESEhLQt29fVFVVYfr06ejevTvy8vLw/vvvG6JG6uD+OMwTzkoFbqiqsOtUjtjlEBFROycRWrCIyN27dxEdHY0ff/wRGo0GgwcPxowZM3QuMG6vSktLoVQqoVKpYGNjI3Y51EzRp3MQGXsOXTvJkbA0BJ0tmvVYNCIiMhH6/H63KNwYM4Yb46Su1SD0w0RkFVUgIrQX5o/1EbskIiJqQ/r8fuv9198DBw402C6RSKBQKNCzZ094eXnpu1uiJpnJpIgI7YW/RKfis8RMzBzmiS6d5I/ekIiIOhy9w83UqVMhkUjqLYn/oE0ikWDkyJHYv38/unTp0mqFEk3yc8bm41dxMb8UWxKuInJiH7FLIiKidkjvC4rj4+MxZMgQxMfHQ6VSQaVSIT4+HkOHDsV//vMfJCYmori4mKsVU6uTSiVYMt4XALAj6RoKVFUiV0RERO2R3jM3CxYswNatWzF8+HBt29ixY6FQKPDKK6/gwoUL2LBhA15++eVWLZQIAMb4OmBI9y44c+0ONh7NwLtP+4ldEhERtTN6z9xcvXq1wQt5bGxskJmZCQDw8fFBUREfdkitTyKRYOlTvQEAX53JxbWiCpErIiKi9kbvcOPv748lS5ZoH5gJALdu3cLSpUsxZMgQAEBGRgbc3Nxar0qi3xjS3Q4hvg5QawR8eOSK2OUQEVE7o3e42bZtG7KysuDm5oaePXvCx8cHbm5uuHbtGj7//HMAQHl5Of7617+2erFED7wRVnftzYGfbuBSfqnI1RARUXvSonVuBEHAoUOHcOXKFQiCgN69eyM0NBRSqd5Zqc1xnRvT8fquH/Gfn/Mxtrcjtr00ROxyiIjIgLiIXxMYbkxHVlEFxn2QgFqNgD1zgxDQ3U7skoiIyEAMuogfAFRUVCAhIQE5OTmoqanR+Wz+/Pkt2SWR3rzsO2FagBuiT+dizaF0xLwyDBKJROyyiIhIZHqHm9TUVEycOBGVlZWoqKiAnZ0dioqKYGVlBUdHR4YbalPzx/pg7495OJ11G4kZRRjdy0HskoiISGR6XySzaNEiTJ48Gbdv34alpSV++OEHZGdnw9/fH+vWrTNEjUSNclZaYtYwTwDA2kOXodF0qLOsRETUAL3DTVpaGt544w3IZDLIZDJUV1fD3d0da9aswfLlyw1RI1GTXgvpic4WZjifV4r/ni8QuxwiIhKZ3uHG3Nxce12Dk5MTcnJyAABKpVL7z0Rtya6THHOC6x7Wuj4+HepajcgVERGRmPQON4MGDcLZs2cBACEhIVi5ciW+/PJLLFy4EH5++i+Fv2nTJnh5eUGhUMDf3x8nTpxosn91dTVWrFgBT09PWFhYoEePHti+fbve30umZfZIL3SxMkfmrQrE/pgndjlERCQivcPNu+++C2dnZwDAO++8g65du+LVV19FYWEhtm7dqte+YmJisHDhQqxYsQKpqakIDg7GhAkTmpwBmjZtGr777jts27YN6enpiI6ORu/evfUdBpkYa4U55oX0BABsOHIFVfdqRa6IiIjEotc6N4IgICcnB46OjrC0tHzsLw8MDMTgwYOxefNmbVufPn0wdepUREVF1ev/7bff4vnnn0dmZibs7Fq2pgnXuTFdVfdqEbLuOPJVVfjr7/pi9kgvsUsiIqJWos/vt14zN4IgwMfHB9evX3+sAgGgpqYGKSkpCAsL02kPCwtDUlJSg9scOHAAAQEBWLNmDVxdXdGrVy8sXrwYd+/ebfR7qqurUVpaqvMi06Qwl2HBWB8AwKZjv6C8Wi1yRUREJAa9wo1UKoWPjw+Ki4sf+4uLiopQW1sLJycnnXYnJycUFDR8x0tmZiZOnjyJ8+fPY9++fdiwYQP27NmDefPmNfo9UVFRUCqV2pe7u/tj107t13P+bvCy74TiihpsP5kldjlERCQCva+5WbNmDZYsWYLz58+3SgEPrygrCEKjq8xqNBpIJBJ8+eWXGDp0KCZOnIgPPvgAO3bsaHT2JjIyEiqVSvvKzc1tlbqpfTKTSRER2gsA8FliJu5U1DxiCyIiMjV6h5s//vGPOH36NAYOHAhLS0vY2dnpvJrL3t4eMpms3ixNYWFhvdmcB5ydneHq6gqlUqlt69OnDwRBaPRUmYWFBWxsbHReZNom+Tmjr7MNyqrV2JxwVexyiIiojen9+IUNGza0yhfL5XL4+/sjPj4eTz/9tLY9Pj4eU6ZMaXCbESNG4Ouvv0Z5eTk6d+4MALhy5QqkUinc3NxapS4yflKpBEue8sWfvjiD/0u6hpdHeKGbUiF2WURE1EZEfSp4TEwMZs6ciS1btiAoKAhbt27FZ599hgsXLsDT0xORkZHIy8vDzp07AQDl5eXo06cPhg0bhrfffhtFRUWYM2cORo8ejc8++6xZ38m7pToGQRAQ/ukPOH3tNqYHeuDdp/Vfg4mIiNoPg90t9cDVq1fx1ltv4YUXXkBhYSGAutu0L1y4oNd+wsPDsWHDBqxevRpPPPEEEhMTERcXB0/PumcF5efn66x507lzZ8THx6OkpAQBAQGYMWMGJk+ejI0bN7ZkGGTCJJK62RsA+OpMLq4VVYhcERERtRW9Z24SEhIwYcIEjBgxAomJibh06RK8vb2xZs0anD59Gnv27DFUra2CMzcdy5++OI1j6bfw+4Eu2PjCILHLISKiFjLozM2yZcvw97//HfHx8ZDL5dr2kJAQJCcn618tkQEtHl83e3Pgpxu4eINrHBERdQR6h5tz587pXAD8gIODQ6usf0PUmvq5KDF5oAsAYP3hdJGrISKitqB3uLG1tUV+fn699tTUVLi6urZKUUStKSK0F2RSCb67XIiz126LXQ4RERmY3uFm+vTpePPNN1FQUACJRAKNRoPvv/8eixcvxqxZswxRI9Fj8bLvhGkBdUsFrDmUDhFvECQiojagd7j53//9X3h4eMDV1RXl5eXo27cvRo0aheHDh+Ott94yRI1Ej23+WB/IzaQ4nXUbiRlFYpdDREQG1OJ1bq5evYrU1FRoNBoMGjQIPj4+rV2bQfBuqY7rfw9exGcnstDf1QYH5o2EVNrwYz6IiKj90ef3W+8VihMSEjB69Gj06NEDPXr0aHGRRG3t1TE9EX06F+fzSvHf8wWYNMBZ7JKIiMgA9D4tFRoaCg8PDyxbtqzVHp5J1BbsOskxJ9gLALA+Ph3qWo3IFRERkSHoHW5u3LiBpUuX4sSJExgwYAAGDBiANWvWNPrgSqL2ZE6wN+w6yZF5qwKxP+aJXQ4RERmA3uHG3t4er7/+Or7//ntcvXoV4eHh2LlzJ7p3744nn3zSEDUStdimTZvg5eUFhUIBf39/pJ5Oxmtj6k6nbjhyBVX3arV9jx8/DolEUu91+fJlnX3u3bsXffv2hYWFBfr27Yt9+/a16ZiIiKhpLXq21ANeXl5YtmwZ3nvvPfj5+SEhIaG16iJ6bDExMVi4cCFWrFiB1NRUBAcHY8KECRjlIoGzUoEbqip8eSqn3nbp6enIz8/Xvn57sXxycjLCw8Mxc+ZM/PTTT5g5cyamTZuGU6dOteXQiIioCS2+W+r777/Hl19+iT179qCqqgq///3vMWPGDEyYMKG1a2xVvFuq4wgMDMTgwYOxefNmbVufPn0wdepUDHz6VSyLPQe7TnIkLg1BZwszHD9+HCEhIbhz5w5sbW0b3Gd4eDhKS0vx3//+V9v21FNPoUuXLoiOjjb0kIiIOiyDPltq+fLl8PLywpNPPons7Gxs2LABBQUF+Ne//tXugw11HDU1NUhJSUFYWJhOe1hYGJKSkvCcvxu87TvhdkUNtp/M0ukzaNAgODs7Y+zYsTh27JjOZ8nJyfX2OX78eCQlJRlmIEREpDe9w83x48exePFi5OXl4eDBg5g+fTqsrKwMURtRixUVFaG2thZOTk467U5OTigoKICZTIqIsF4AgM8SM3GnogbOzs7YunUr9u7di9jYWPj6+mLs2LFITEzUbl9QUNDoPomIqH3Qe50b/g2VjIlEortQnyAI2raJ/Z3R1/kqLuaXYnPCVSyf2Ae+vr7avkFBQcjNzcW6deswatSoZu2TiIjEp3e4eeDixYvIyclBTU2NTvvvf//7xy6K6HHZ29tDJpPVm1EpLCzUzrxIpRIsecoXf/riDP4v6RpeHuGFbkqFTv9hw4bhX//6l/Z9t27dmtwnERGJT+9wk5mZiaeffhrnzp2DRCLRPoTwwd9ca2trm9qcqE3I5XL4+/sjPj4eTz/9tLY9Pj4eU6ZM0b4f08sBQ7vb4fS12/jouwxEPeOns5/U1FQ4O/+6knFQUBDi4+OxaNEibdvhw4cxfPhwA46GiIj0oXe4WbBgAby8vHDkyBF4e3vj9OnTKC4uxhtvvIF169YZokaiFomIiMDMmTMREBCAoKAgbN26FTk5OZg7dy4AIDIyEnl5eViyegP+sCUZn236B7zKn0RIkD9qamrwr3/9C3v37sXevXu1+1ywYAFGjRqF999/H1OmTME333yDI0eO4OTJk2INk4iIHqJ3uElOTsbRo0fh4OAAqVQKqVSKkSNHIioqCvPnz0dqaqoh6iTSW3h4OIqLi7F69Wrk5+ejf//+iIuLg6enJwAgPz8fOTk5GNLdDiG+Dth/6h6WLFmCKlURrCwt0b9/Pxw8eBATJ07U7nP48OHYvXs33nrrLfz1r39Fjx49EBMTg8DAQLGGSURED9F7nZsuXbogJSUF3t7e6NGjBz7//HOEhITg6tWr8PPzQ2VlpaFqbRVc54YacuGGCpM2/jr7IpUAUc/4IXyIh4hVERHRAwZ9Knj//v3x888/w9vbG4GBgVizZg3kcjm2bt0Kb2/vFhdNJCa7TnKd9xoBiIw9h1G9HOCstBSpKiIiagm917l56623oNHUPU3573//O7KzsxEcHIy4uDhs3Lix1QskagtZRRX12jQCMP2zU4g+nYOKarUIVRERUUu0+PELv3X79m106dLFKNb64Gkpaki+6i5GvHcUmkb+a+hsYYapg1wwfagn+rrw3xsioramz+93q4QbY8JwQ42JOZOD5bHnUSsIkEkkWDGpD9QaDaJP5+rM7DzhbosZgR743QAXWMplIlZMRNRxMNw0geGGmpKvuotrRZXobm+lvdZGEAQkXy3Gl6dzcOh8AdT3p3esFWZ4drAbpgd6oJeTtZhlExGZPIabJjDc0OO4VVaNr1NyEX06B7m372rbh3TvgumBHpjQ3xkKc87mEBG1NoabJjDcUGvQaASc+KUIu05l48ilQtTen82xtTLHc4Pd8EKgB3o4dBa5SiIi08Fw0wSGG2ptN0urEHMmF7tP5+CGqkrbPszbDjMCPTG+XzfIzfS+MZGIiH6D4aYJDDdkKLUaAQlXCvHlDzk4ll6ovfOqayc5/hDgjheGusOzaydxiyQiMlIMN01guKG2kFdyFzFnchFzJgc3S6u17cE+9pgR6IGxfZxgLuNsDhFRczHcNIHhhtqSulaD7y4XYtepHCRm3MKD/9ocrC0QHuCO54e6w62LlbhFEhEZAYabJjDckFhyb1ci+nQOvjp7HUXldbM5EgkwppcDpgd6IsTXAWaczSEiahDDTRMYbkhsNWoN4i/exK7T2fj+l2Jtu7NSgfAh7ggf4s7nWRERPYThpgkMN9SeZBVVIPp0DvakXMftihoAdU8kf7K3E2YM88AoHwfIpO3/sSZERIbGcNMEhhtqj6rVtfj2fAF2ncrBqazb2nZXW0u8MNQd0wLc4WijELFCIiJxMdw0geGG2rtfCsuw61Qu9qTkorSq7mnkZlIJQvs6YXqgB0b0sIeUszlE1MEw3DSB4YaMRdW9Whz8OR+7TucgJfuOtt2zqxVeGOqB5/zdYN/ZQsQKiYjaDsNNExhuyBhdLijFrlM52PdjHsqq62ZzzGUSjO/XDTMCPTHM2w4SCWdziMh0Mdw0geGGjFlljRr/+SkfX57Kxk/XVdp2b4dOmH5/NsfWSi5ihUREhsFw0wSGGzIV5/NU2HU6B9+k5qGiphYAIDeTYpKfM6YHeiDAswtnc4jIZDDcNIHhhkxNebUa36TlYdepHFy4Uapt7+XUGdOHeuDpwW5QWpqLWCER0eNjuGkCww2ZKkEQ8NN1FXadysaBn26g6p4GAKAwl2LyABdMD/TAE+62nM0hIqPEcNMEhhvqCFR372F/at1sTvrNMm17H2cbTA/0wNQnXGCt4GwOERkPhpsmMNxQRyIIAn7MuYMvf8jBf87lo0ZdN5tjJZdhyhMumD7UE35uSpGrJCJ6NIabJjDcUEdVUlmDvT/mYdepbFy9VaFtH+CmxPShHvj9Ey6wkpuJWCERUeP0+f0W/RHEmzZtgpeXFxQKBfz9/XHixIlmbff999/DzMwMTzzxhGELJDIRtlZyzB7phSMRo7H7lWH4/UAXmMsk+Pm6CstizyHwf7/DX/efx6X80kfvjIioHRN15iYmJgYzZ87Epk2bMGLECHz66af4/PPPcfHiRXh4eDS6nUqlwuDBg9GzZ0/cvHkTaWlpzf5OztwQ/aq4vBp7Uq4j+nQOrhVXatsHedhiRqAnfjfAGQpzmYgVEhHVMZrTUoGBgRg8eDA2b96sbevTpw+mTp2KqKioRrd7/vnn4ePjA5lMhv379zPcED0mjUZA0tVi7DqdjcMXbkKtqfvfgo3CDM8MdsOMQA/4OFmLXCURdWRGcVqqpqYGKSkpCAsL02kPCwtDUlJSo9t98cUXuHr1Kv72t78163uqq6tRWlqq8yIiXVKpBCN97LFphj+SIp/EkvG+cOtiidIqNXYkXUPoh4mYtiUZ36TloVpdK3a5RERNEu3qwaKiItTW1sLJyUmn3cnJCQUFBQ1uk5GRgWXLluHEiRMwM2te6VFRUXj77bcfu16ijsLRWoF5IT3x6ugeSMy4hV2ncvDd5UKcvnYbp6/dRhcrczzn74YXhnrA26Gz2OUSEdUj+q0RDy8oJghCg4uM1dbWYvr06Xj77bfRq1evZu8/MjISERER2velpaVwd3dvecFEHYRUKsEYX0eM8XVEgaoKMWdysftMDvJVVfjsRBY+O5GF4T26YnqgB8L6doPcTPT7E4iIAIgYbuzt7SGTyerN0hQWFtabzQGAsrIynD17FqmpqXj99dcBABqNBoIgwMzMDIcPH8aTTz5ZbzsLCwtYWFgYZhBEHUQ3pQILxvlgXkgPHE+/hV2nc3AsvRBJV4uRdLUY9p3l+EOAO14Y4gGPrlZil0tEHZzoFxT7+/tj06ZN2ra+fftiypQp9S4o1mg0uHjxok7bpk2bcPToUezZswdeXl7o1KnTI7+TFxQTtY7rdyoRcyYXMWdyUVhWrW0P9rHHjEAPjO3jBHMZZ3OIqHXo8/st6mmpiIgIzJw5EwEBAQgKCsLWrVuRk5ODuXPnAqg7pZSXl4edO3dCKpWif//+Ots7OjpCoVDUayciw3PrYoU3wnwxf6wPvrtUiC9PZeNERpH25WhtgfAh7nh+qAdcbS3FLpeIOhBR/1oVHh6ODRs2YPXq1XjiiSeQmJiIuLg4eHp6AgDy8/ORk5MjZolE9AjmMime6t8N/5wdiMQlIXh1TA/Yd5ajsKwa/zj6C4LfP4qXd5zBkYs3UavRf6JYn4U+T548iREjRqBr166wtLRE79698eGHHzbaf/fu3ZBIJJg6daredRFR+8XHLxBRq6tRa3D4YgF2ncpB0tVibbuLUoHwIR4IH+KObkrFI/ej70KfqampuHz5MgYMGIBOnTrh5MmT+POf/4wPP/wQr7zyik7f7OxsjBgxAt7e3rCzs8P+/fsfe9xEZDhGs4ifGBhuiNpW5q1yRJ/OwZ6U67hTeQ8AIJNK8GRvR8wI9MAoHwdIpfXvkARavtDnbz3zzDPo1KkT/vnPf2rbamtrMXr0aPzpT3/CiRMnUFJSwnBD1M4ZxSJ+RNQxeDt0xopJfZEcORYbwp/A0O52qNUIiL94Ey99cQaj1h7DJ8d+QWFZlc52LV3o87dSU1ORlJSE0aNH67SvXr0aDg4OmD179uMNjojaJdHXuSGijkFhLsPUQa6YOsgVGTfLsOt0DvamXMf1O3ex9lA6Poy/grB+Tpg+1BPDe3Rt0UKfD7i5ueHWrVtQq9VYtWoV5syZo/3s+++/x7Zt2/R6bAsRGReGGyJqcz5O1vjb5H5YOr43Dp7Lx65T2fgxpwRx5woQd64A3btaYYJ33fpUzV3o87dOnDiB8vJy/PDDD1i2bBl69uyJF154AWVlZfjjH/+Izz77DPb29gYbHxGJi+GGiERjKZfhOX83POfvhkv5pdh1Kgf7UvNwrbgSmwpVgESKv3+dhL869UKglx0kEkmjC33+lpeXFwDAz88PN2/exKpVq/DCCy/g6tWruHbtGiZPnqztq9FoAABmZmZIT09Hjx49DDdgImoTDDdE1C70cbbBO1P7Y9mE3vj3Tzew63QOCrr1ROLxo3he3hs9HDrhhaEeOHT4MJ7W49ZtQRBQXV23yGDv3r1x7tw5nc/feustlJWV4aOPPuKjWYhMBMMNEbUrnSzM8PxQDzw/1ANrpcuwbMErsHbrhcuOvojYvQHlV6/hlmswzl67jT1b1uDGjRvYuXMnAOCTTz6Bh4cHevfuDaBu3Zt169bhL3/5CwA0uOinra0tAHAxUCITwnBDRO3Wktf+hE64i/ffX4Mb+fmwcuoOxz+swpHrAo5sSca9oz/BWn0HpVX3YKMwx52Kaqx/YykK8nJgbmaGHj164L333sOf//xnsYdCRG2I69wQkdEQBAFpuSXYdSoH//75Bqru1V0vozCXor+LEik5dyAIgFQCRD3jh/Ah9Rf6IyLjxEX8msBwQ2QaVHfvYd+P17HrdA6u3Cyv97lEAkT/zzAM7W7X6CKBRGQ8GG6awHBDZFoEQcCOpGt4+98XG/zc2sIM/V2VGOCmxAA3WwxwU8Kti+UjbycnovbFaJ4KTkT0uCQSCZ7q3w3v/OciHn4up1wmQVm1GsmZxUjO/PUZV12szOHnZosBvwk9TjYWDDxEJoIzN0RkEmLO5GB57HnUCgJkEgnefaY/nh3shozCcvx8vQQ/X1fh5+sqXC4oxb3a+v/bc7C2wEA3Jfxcbe8HHiW6drYQYSRE1BCelmoCww2R6cpX3cW1okp0t7eCs9KywT7V6lqkF5Thp+sqnLsfejIKy1H78LQPAFdbSwxwU8LPTYkBrrbwc1NCaWlu6GEQUQMYbprAcENED7tbU4uL+Sr8lKvCuTwVfr5egsyiCjT0f8fuXa201+74uSrR31WJThY8w09kaAw3TWC4IaLmKKu6h/N5pXWntPJUOHddhZzblfX6SSRAT4fOvwYeNyX6OttAYS4ToWoi08Vw0wSGGyJqqTsVNdqZnZ+v183y5Kuq6vUzk0rQy8kaA91/vYbHt5s1zGVSEaomMg0MN01guCGi1lRYWoVzeSqda3iKK2rq9ZObSdHH2eb+Rct1d2j1dOwMGdfgIWoWhpsmMNwQkSEJgoAbqiqcu15yP/DUzfSUVqnr9bU0l6G/q43ONTzdu3biooNEDWC4aQLDDRG1NUEQkF1cef/anbrQcz5Phcqa2np9rRVm2pmdB4GHiw4SMdw0ieGGiNqDWo2AzFvl2mt3frpegos3SlGt1tTra9dJDj9XZd0prfuhx8lGIULVROJhuGkCww0RtVf3ajW4crOs7lTW/QuXL+eXQd3AGjxONhbwc7W9H3jqZnrsOslFqPrRNm3ahLVr1yI/Px/9+vXDhg0bEBwc3GDf2NhYbN68GWlpaaiurka/fv2watUqjB8/XqdfSUkJVqxYgdjYWNy5cwdeXl5Yv349Jk6c2BZDIhHw8QtEREbIXCZFPxcl+rko8fz9tqp7tbhcUKa9WLlu0cEy3Cytxs3Smzhy6aZ2e7cu9xcdvB96+rspYaMQd9HBmJgYLFy4EJs2bcKIESPw6aefYsKECbh48SI8POo/tT0xMRGhoaF49913YWtriy+++AKTJ0/GqVOnMGjQIABATU0NQkND4ejoiD179sDNzQ25ubmwtrZu6+FRO8WZGyIiI1NZo8bFG6U6d2hlFlU02NfbvhP87l+7M9DdFv1cbGAlb7u/1wYGBmLw4MHYvHmztq1Pnz6YOnUqoqKimrWPfv36ITw8HCtXrgQAbNmyBWvXrsXly5dhbs4VozsKztwQEZkwK7kZArrbIaC7nbattOoezufVzeycu153Dc/1O3eRWVSBzKIKfJN2AwAglQA+jtbwc/v1Gp7e3awNsuhgTU0NUlJSsGzZMp32sLAwJCUlNWsfGo0GZWVlsLP7dawHDhxAUFAQ5s2bh2+++QYODg6YPn063nzzTchkXDyRGG6IiEyCjcIcw3vYY3gPe23b7Yoa/Hy9ROcanpul1Ui/WYb0m2XYk3IdAGAuk8C3m7XOQ0N7OT3+ooNFRUWora2Fk5OTTruTkxMKCgqatY/169ejoqIC06ZN07ZlZmbi6NGjmDFjBuLi4pCRkYF58+ZBrVZrZ3eoY2O4ISIyUXad5Bjj64gxvo7atpulVdq1d36+P9Nzu6IG5/NKcT6vFNGn6/pZmEnR18UGA1zrZncGuinh7dCyRQcfvo1dEIRm3doeHR2NVatW4ZtvvoGj469j0Gg0cHR0xNatWyGTyeDv748bN25g7dq1DDcEgOGGiKhDcbJRwKmvAuP61s2mCIKAvJK7909lqXAur+4anrIqNVJzSpCaUwIgGwDQSS5DP1fl/cCjxEA3W3h2tWo0qNjb20Mmk9WbpSksLKw3m/OwmJgYzJ49G19//TXGjRun85mzszPMzc11TkH16dMHBQUFqKmpgVzePu8ao7bDcENE1IFJJBK4dbGCWxcrTPBzBgBoNAKyb1f++gyt6yqcv6FCRU0tTmfdxums29rtbRRmGOBmW3c7uqsSA9xt4aJUQCKRQC6Xw9/fH/Hx8Xj66ae128THx2PKlCmN1hQdHY2XX34Z0dHRmDRpUr3PR4wYgV27dkGj0UAqrTt1duXKFTg7OzPYEADeLSV2OURERqFWI+Dq/UUHH4Sei/mlqGlg0cGuneT3n5Bui9s/H8OayL9gy5YtCAoKwtatW/HZZ5/hwoUL8PT0RGRkJPLy8rBz504AdcFm1qxZ+Oijj/DMM89o92lpaQmlUgkAyM3NRd++ffHSSy/hL3/5CzIyMvDyyy9j/vz5WLFiRdv8gXQgrb1OUWxsLN5991388ssvuHfvHnx8fPDGG29g5syZTdbBRfyawHBDRNQ67tVqkF5QpvOk9PSC+osOlv14EOVnYqEuvw1Xr15Y/Ld3MXPqU+jSSY6XXnoJ165dw/HjxwEAw0eOQvL3J+p914svvogdO3Zo3ycnJ2PRokVIS0uDq6srZs+ezbulDCAmJgYzZ87UWafo888/b3SdooULF8LFxQUhISHadYrWrVuns07R8ePHcefOHfTu3RtyuRz/+c9/8MYbb+DgwYP1Fmv8LYabJjDcEBEZTtW9WlzKL617pERu3TU8vxSWo4FFluFuZ4kB9+/Q8nNTIuNmGd7+90VohLpb1qOe8UP4kPo/oNR2DLFOUUMGDx6MSZMm4Z133mm0D9e5ISIiUSjMZRjk0QWDPLoAQXVtFdVqXLhR+us1PHkqZBVVIPf2XeTevouD5/Lr7UcjAMv2nkNWUQXculjB1socSkvdl7XCvEV3b1HzGGqdot8SBAFHjx5Feno63n///ceu+QGGGyIiMqhOFmYY6mWHoV6//sCp7v666ODP10twJus2iipqdLYTAGxJyGx0vxIJ0NnCTBt2fhuAbCzrhyGlpTlsLeX3g5EZpAxGTTLUOkUAoFKp4OrqiurqashkMmzatAmhoaGtVjvDDRERtTmlpTlG9LTHiJ51iw7mq+5ixHtHdU5fSQBM8OuGe7UCVHfvofTuPajuvypraiEIQFmVGmVValy/c1ev75dIAGsLMygbmBGy+U0IaujV0YJRa69TBADW1tZIS0tDeXk5vvvuO0RERMDb2xtjxoxplZoZboiISHTOSktEPeOH5bHnUSsIkEkkePeZ/o1ec1Oj1miDzsPBp96rUvf93Xt1wai0So3SKjVy0bJgZGslrxeKGpwtsvr1c2sL4wlGhlqnCACkUil69uwJAHjiiSdw6dIlREVFMdwQEZFpCR/igVG9HHCtqBLd7a3grLRstK/cTAoHaws4WFvo/T2NBaOSyhqo7qqbDE0PByN9SSWAtaKBENTADNLDwamtg5Gh1ilqiCAIqK6ufuyaH2C4ISKidsNZadlkqGkNjxOMqtW1Dc8UVd7TBqOSuzUNziRV3dNAI0D7Xl9SCerNDjU0W2T78GdWdcGoOaeSHhYREYGZM2ciICBAu05RTk4O5s6dCwBNrlM0bNgw7azPb9cpioqKQkBAAHr06IGamhrExcVh586dOndkPS6GGyIiomayMJPB0VoGR2uF3ts+HIxKKhs+jfbbYPSgT7W6LhiVVNa16auhYPSomSJbK3NMnPIMPvywCKtXr0Z+fj769++PuLg4eHp6AgDy8/ORk5Oj/Z5PP/0UarUa8+bNw7x587Ttv12nqKKiAq+99hquX78OS0tL9O7dG//6178QHh6u97gaw3VuiIiI2rmqe7VNXldUUtn4dUfVDawirQ+ZVAIbhVmjs0W/vUstJfsOPj+ZBcEAaxVxnRsiIiITojCXQWEug6ON/jNGD4JRSSMXWNebLfrNP9eoNajVCLhTeQ939Jwx0gjA8tjzGNXLweCnGh/GcENERGTCHjcYNXTnWUkDoej6nUpcuVmus32tIOBaUSXDDREREbUPD4KRUzOCUUNrFckkEnS3tzJghQ2Ttvk3EhERkcl5sFaR7P5dWQ/WKmrrWRuAMzdERETUSvRZq8iQGG6IiIio1bTFWkWPIvppqU2bNsHLywsKhQL+/v44ceJEo31jY2MRGhoKBwcH2NjYICgoCIcOHWrDaomIiKi9EzXcxMTEYOHChVixYgVSU1MRHByMCRMm6CwI9FuJiYkIDQ1FXFwcUlJSEBISgsmTJyM1NbWNKyciIqL2StRF/AIDAzF48GCdJZf79OmDqVOnIioqqln76NevH8LDw7Fy5coGP6+urtZ5XkVpaSnc3d25iB8REZER0WcRP9FmbmpqapCSkoKwsDCd9rCwMCQlJTVrHxqNBmVlZbCzs2u0T1RUFJRKpfbl7u7+WHUTERFR+yZauCkqKkJtbW29x6Y7OTnVe7x6Y9avX4+KigpMmzat0T6RkZFQqVTaV25u7mPVTURERO2b6HdLPfyUUkEQmvXk0ujoaKxatQrffPMNHB0dG+1nYWEBCwv9n/xKRERExkm0cGNvbw+ZTFZvlqawsLDebM7DYmJiMHv2bHz99dcYN26cIcskIiIiIyPaaSm5XA5/f3/Ex8frtMfHx2P48OGNbhcdHY2XXnoJu3btwqRJkwxdJhERERkZUU9LRUREYObMmQgICEBQUBC2bt2KnJwczJ07F0Dd9TJ5eXnYuXMngLpgM2vWLHz00UcYNmyYdtbH0tISSqVStHEQERFR+yFquAkPD0dxcTFWr16N/Px89O/fH3FxcfD09AQA5Ofn66x58+mnn0KtVmPevHmYN2+etv3FF1/Ejh072rp8IiIiaodEXedGDPrcJ09ERETtg1Gsc0NERERkCAw3REREZFIYboiIiMikMNwQERGRSWG4ISIiIpPCcENEREQmheGGiIiITArDDREREZkUhhsiIiIyKQw3REREZFIYboiIiMikMNwQERGRSWG4ISIiIpPCcENEREQmheGGiIiITArDDREREZkUhhsiIiIyKQw3REREZFIYboiIiMikMNwQERGRSWG4ISIiIpPCcENEREQmheGGiIiITArDDREREZkUhhsiIiIyKQw3REREZFIYboiIiMikMNwQERGRSWG4ISIiIpPCcENEREQmheGGiIiITArDDREREZkUhhsiIiIyKQw3REREZFIYboiIiMikMNwQERGRSWG4ISIiIpPCcENEREQmheGGiIiITArDDREREZkUhhsiIiIyKQw3REREZFIYboiIiMikMNwQERGRSWG4ISIiIpMierjZtGkTvLy8oFAo4O/vjxMnTjTZPyEhAf7+/lAoFPD29saWLVvaqFIiIiIyBqKGm5iYGCxcuBAr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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "y_avg = []\n", - "for y in epochs_y:\n", - " y_avg.append(np.mean(y))\n", - "\n", - "plt.plot(np.arange(len(epochs_x)), y_avg, marker = '.')\n", - "plt.xlabel('epoch')\n", - "plt.ylabel('average loss')\n", - "plt.ylim(0,)\n", - "for i, txt in enumerate(y_avg):\n", - " plt.text(i, txt, f'{txt:.2f}', ha='center', va='bottom')\n", - "plt.show()" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "plt.plot(np.arange(len(epochs_x)), epochs_acc, marker = '.')\n", - "plt.xlabel('epoch')\n", - "plt.ylabel('test accuracy')\n", - "plt.ylim(80, 100)\n", - "for i, txt in enumerate(epochs_acc):\n", - " plt.text(i, txt, f'{txt:.2f}', ha='center', va='bottom')\n", - "plt.show()" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "speck-rescnn", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.3" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/tests/test_nonsequential/baseline-SCNN-example_3.ipynb b/tests/test_nonsequential/baseline-SCNN-example_3.ipynb deleted file mode 100644 index dc53313a..00000000 --- a/tests/test_nonsequential/baseline-SCNN-example_3.ipynb +++ /dev/null @@ -1,1500 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "import torch, random\n", - "import torch.nn as nn\n", - "import sinabs.layers as sl\n", - "from tqdm.notebook import tqdm\n", - "\n", - "from tonic.datasets.dvsgesture import DVSGesture\n", - "from tonic.transforms import ToFrame\n", - "from torch.utils.data import DataLoader\n", - "from torch.nn import CrossEntropyLoss\n", - "from torch.optim import Adam\n", - "\n", - "from sinabs.activation.surrogate_gradient_fn import PeriodicExponential\n", - "\n", - "import matplotlib.pyplot as plt\n", - "import numpy as np" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "torch.backends.cudnn.deterministic = True\n", - "random.seed(1)\n", - "torch.manual_seed(1)\n", - "torch.cuda.manual_seed(1)\n", - "np.random.seed(1)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Loading Data" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "batch_size = 3\n", - "num_workers = 1\n", - "epochs = 30\n", - "lr = 1e-3" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "root_dir = \"./DVSGESTURE\"\n", - "_ = DVSGesture(save_to=root_dir, train=True)\n", - "_ = DVSGesture(save_to=root_dir, train=False)" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "n_time_steps = 50\n", - "to_raster = ToFrame(sensor_size=DVSGesture.sensor_size, n_time_bins=n_time_steps)\n", - "\n", - "snn_train_dataset = DVSGesture(save_to=root_dir, train=True, transform=to_raster)\n", - "snn_test_dataset = DVSGesture(save_to=root_dir, train=False, transform=to_raster)" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The transformed array is in shape [Time-Step, Channel, Height, Width] --> (50, 2, 128, 128)\n" - ] - } - ], - "source": [ - "sample_data, label = snn_train_dataset[0]\n", - "print(f\"The transformed array is in shape [Time-Step, Channel, Height, Width] --> {sample_data.shape}\")" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [], - "source": [ - "snn_train_dataloader = DataLoader(snn_train_dataset, batch_size=batch_size, num_workers=num_workers, drop_last=True, shuffle=True)\n", - "snn_test_dataloader = DataLoader(snn_test_dataset, batch_size=batch_size, num_workers=num_workers, drop_last=True, shuffle=False)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Network Module\n", - "\n", - "We need to define a `nn.Module` implementing the network we want the chip to reproduce." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "device: NVIDIA RTX A4000\n" - ] - } - ], - "source": [ - "if torch.cuda.is_available():\n", - " device = torch.device('cuda:0')\n", - " print('device: ', torch.cuda.get_device_name(0))\n", - "else:\n", - " device = torch.device('cpu')" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [], - "source": [ - "class SNN(nn.Module):\n", - " def __init__(self) -> None:\n", - " super().__init__()\n", - "\n", - " self.conv1 = nn.Conv2d(2, 10, 2, 1, bias=False)\n", - " self.iaf1 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - " self.pool1 = nn.AvgPool2d(2,2)\n", - "\n", - " self.conv2 = nn.Conv2d(10, 10, 2, 1, bias=False)\n", - " self.iaf2 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - " self.pool2 = nn.AvgPool2d(3,3)\n", - "\n", - " self.conv3 = nn.Conv2d(10, 10, 3, 1, bias=False)\n", - " self.iaf3 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - " self.pool3 = nn.AvgPool2d(2,2)\n", - "\n", - " self.flat = nn.Flatten()\n", - "\n", - " self.fc1 = nn.Linear(810, 100, bias=False)\n", - " self.iaf4 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - "\n", - " self.fc2 = nn.Linear(100, 100, bias=False)\n", - " self.iaf5 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - "\n", - " self.fc3 = nn.Linear(100, 100, bias=False)\n", - " self.iaf6 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - "\n", - " self.fc4 = nn.Linear(100, 11, bias=False)\n", - " self.iaf7 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - "\n", - " def detach_neuron_states(self):\n", - " for name, layer in self.named_modules():\n", - " if name != '':\n", - " if isinstance(layer, sl.StatefulLayer):\n", - " for name, buffer in layer.named_buffers():\n", - " buffer.detach_()\n", - "\n", - " def init_weights(self):\n", - " for name, layer in self.named_modules():\n", - " if isinstance(layer, nn.Conv2d) or isinstance(layer, nn.Linear):\n", - " nn.init.xavier_normal_(layer.weight.data)\n", - "\n", - " def forward(self, x):\n", - " \n", - " con1_out = self.conv1(x)\n", - " iaf1_out = self.iaf1(con1_out)\n", - " pool1_out = self.pool1(iaf1_out)\n", - "\n", - " conv2_out = self.conv2(pool1_out)\n", - " iaf2_out = self.iaf2(conv2_out)\n", - " pool2_out = self.pool2(iaf2_out)\n", - "\n", - " conv3_out = self.conv3(pool2_out)\n", - " iaf3_out = self.iaf3(conv3_out)\n", - " pool3_out = self.pool3(iaf3_out)\n", - "\n", - " flat_out = self.flat(pool3_out)\n", - " \n", - " fc1_out = self.fc1(flat_out)\n", - " iaf4_out = self.iaf4(fc1_out)\n", - "\n", - " fc2_out = self.fc2(iaf4_out)\n", - " iaf5_out = self.iaf5(fc2_out)\n", - "\n", - " fc3_out = self.fc3(iaf5_out)\n", - " iaf6_out = self.iaf6(fc3_out)\n", - "\n", - " fc4_out = self.fc4(iaf6_out)\n", - " iaf7_out = self.iaf7(fc4_out)\n", - "\n", - " return iaf7_out" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [], - "source": [ - "snn = SNN().to(device)" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [], - "source": [ - "snn.init_weights()" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [], - "source": [ - "optimizer = Adam(snn.parameters(), lr=lr, betas=(0.9, 0.999), eps=1e-8)\n", - "loss_fn = CrossEntropyLoss()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Define train and test" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [], - "source": [ - "def train(dataloader, model, loss_fn, optimizer, epochs, test_func, dataloader_test):\n", - " epochs_y = []\n", - " epochs_x = []\n", - " epochs_acc = []\n", - " model.train()\n", - "\n", - " for e in range(epochs):\n", - " losses = []\n", - " batches = []\n", - " batch_count = 0\n", - " train_p_bar = tqdm(snn_train_dataloader)\n", - "\n", - " for X, y in train_p_bar:\n", - " # reshape the input from [Batch, Time, Channel, Height, Width] into [Batch*Time, Channel, Height, Width]\n", - " X = X.reshape(-1, 2, 128, 128).to(dtype=torch.float, device=device)\n", - " y = y.to(dtype=torch.long, device=device)\n", - "\n", - " # forward\n", - " pred = model(X)\n", - "\n", - " # reshape the output from [Batch*Time,num_classes] into [Batch, Time, num_classes]\n", - " pred = pred.reshape(batch_size, n_time_steps, -1)\n", - "\n", - " # accumulate all time-steps output for final prediction\n", - " pred = pred.sum(dim = 1)\n", - " loss = loss_fn(pred, y)\n", - "\n", - " # gradient update\n", - " optimizer.zero_grad()\n", - " loss.backward()\n", - " optimizer.step()\n", - "\n", - " # detach the neuron states and activations from current computation graph(necessary)\n", - " model.detach_neuron_states()\n", - "\n", - " train_p_bar.set_description(f\"Epoch {e} - BPTT Training Loss: {round(loss.item(), 4)}\")\n", - "\n", - " batch_count += 1\n", - " losses.append(loss.item())\n", - " batches.append(batch_count)\n", - "\n", - " epochs_y.append(losses)\n", - " epochs_x.append(batches)\n", - "\n", - " acc = test_func(dataloader_test, model)\n", - " print(f'Epoch {e} accuracy: {acc}')\n", - " epochs_acc.append(acc)\n", - "\n", - " return epochs_x, epochs_y, epochs_acc\n" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [], - "source": [ - "def test(dataloader, model):\n", - " correct_predictions = []\n", - " with torch.no_grad():\n", - " test_p_bar = tqdm(dataloader)\n", - " for X, y in test_p_bar:\n", - " # reshape the input from [Batch, Time, Channel, Height, Width] into [Batch*Time, Channel, Height, Width]\n", - " X = X.reshape(-1, 2, 128, 128).to(dtype=torch.float, device=device)\n", - " y = y.to(dtype=torch.long, device=device)\n", - "\n", - " # forward\n", - " output = model(X)\n", - "\n", - " # reshape the output from [Batch*Time,num_classes] into [Batch, Time, num_classes]\n", - " output = output.reshape(batch_size, n_time_steps, -1)\n", - "\n", - " # accumulate all time-steps output for final prediction\n", - " output = output.sum(dim=1)\n", - "\n", - " # calculate accuracy\n", - " pred = output.argmax(dim=1, keepdim=True)\n", - "\n", - " # compute the total correct predictions\n", - " correct_predictions.append(pred.eq(y.view_as(pred)))\n", - "\n", - " test_p_bar.set_description(f\"Testing Model...\")\n", - " \n", - " correct_predictions = torch.cat(correct_predictions)\n", - " return correct_predictions.sum().item()/(len(correct_predictions))*100" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Training loop" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "ebf2bea3d0124365abf1f2aa248ceab6", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - " 0%| | 0/359 [00:00" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "y_avg = []\n", - "for y in epochs_y:\n", - " y_avg.append(np.mean(y))\n", - "\n", - "plt.plot(np.arange(len(epochs_x)), y_avg, marker = '.')\n", - "plt.xlabel('epoch')\n", - "plt.ylabel('average loss')\n", - "plt.ylim(0,)\n", - "plt.xticks(np.arange(len(epochs_x)))\n", - "for i, txt in enumerate(y_avg):\n", - " if i%2 == 0:\n", - " pass\n", - " else:\n", - " plt.text(i, txt, f'{txt:.2f}', ha='center', va='bottom', color = 'k')\n", - "plt.show()" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjsAAAG2CAYAAACZEEfAAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8fJSN1AAAACXBIWXMAAA9hAAAPYQGoP6dpAAB9HElEQVR4nO3dd1RUx98G8GfpRUB6kaqg2HvB3oIt9qiJJjHGWH5irLFgYkw0ETWJJsbE9ipqrDGxG3vBhgiKXSmKglQLLL3uvH8QNq60XYrg+nzO2XNk7p07c3evu987d4pECCFAREREpKY0qroCRERERJWJwQ4RERGpNQY7REREpNYY7BAREZFaY7BDREREao3BDhEREak1BjtERESk1hjsEBERkVpjsENERERqjcEOERERqbUqDXbOnTuH/v37w87ODhKJBPv27VPYLoTA119/DVtbW+jr66Nnz54ICwtT2OfFixcYNWoUjI2NUbNmTYwdOxapqamv8SyIiIioOqvSYCctLQ1NmzbFb7/9VuT2ZcuWYeXKlVizZg0CAgJgaGiIXr16ITMzU77PqFGjcOfOHZw4cQKHDh3CuXPnMH78+Nd1CkRERFTNSarLQqASiQR79+7FoEGDAOS36tjZ2WHmzJn44osvAABSqRTW1tbYtGkT3n//fdy7dw8NGjRAYGAgWrVqBQA4evQo+vbtiydPnsDOzq6qToeIiIiqCa2qrkBxIiIiEBcXh549e8rTTExM0LZtW/j7++P999+Hv78/atasKQ90AKBnz57Q0NBAQEAABg8eXOSxs7KykJWVJf9bJpPhxYsXMDc3h0QiqbyTIiIiogojhEBKSgrs7OygoVH8w6pqG+zExcUBAKytrRXSra2t5dvi4uJgZWWlsF1LSwtmZmbyfYri4+ODb7/9toJrTERERFUhKioK9vb2xW6vtsFOZfL29saMGTPkf0ulUjg6OiIqKgrGxsZVWDMiIiJSVnJyMhwcHGBkZFTiftU22LGxsQEAxMfHw9bWVp4eHx+PZs2ayfdJSEhQyJebm4sXL17I8xdFV1cXurq6hdKNjY0Z7BAREb1hSuuCUm3n2XFxcYGNjQ1OnTolT0tOTkZAQAA8PDwAAB4eHkhKSsLVq1fl+5w+fRoymQxt27Z97XUmIiKi6qdKW3ZSU1MRHh4u/zsiIgLXr1+HmZkZHB0dMW3aNHz33Xdwc3ODi4sL5s+fDzs7O/mIrfr166N3794YN24c1qxZg5ycHEyePBnvv/8+R2IRERERgCoOdoKCgtCtWzf53wX9aEaPHo1NmzZh9uzZSEtLw/jx45GUlISOHTvi6NGj0NPTk+fZtm0bJk+ejB49ekBDQwNDhw7FypUrX/u5EBERUfVUbebZqUrJyckwMTGBVCplnx0iIqI3hLK/39W2zw4RERFRRWCwQ0RERGqNwQ4RERGpNQY7REREpNYY7BAREZFaY7BDREREao3BDhEREak1BjtERESk1hjsEBERkVpjsENERERqjcEOERERqTUGO0RERKTWGOwQERGRWmOwQ0RERGqNwQ4RERGpNQY7REREpNYY7BAREZFaY7BDREREao3BDhEREak1BjtERESk1hjsEBERkVpjsENERERqjcEOERERqTUGO0RERKTWGOwQERGRWmOwQ0RERGqNwQ4RERGpNQY7REREpNYY7BAREZFaY7BDREREao3BDhEREak1BjtERESk1hjsEBERkVpjsENERERqjcEOERERqTUGO0RERKTWGOwQERGRWmOwQ0RERGqNwQ4RERGpNQY7REREpNYY7BAREZFaY7BDREREao3BDhEREak1BjtERESk1hjsEBERkVpjsENERERqjcEOERERqTUGO0RERKTWGOwQERGRWmOwQ0RERGqNwQ4RERGpNQY7REREpNYY7BAREZFaY7BDREREao3BDhEREak1BjtERESk1hjsEBERkVpjsENERERqjcEOERERqTUGO0RERKTWGOwQERGRWmOwQ0RERGqNwQ4RERGptWod7OTl5WH+/PlwcXGBvr4+6tSpg0WLFkEIId9HCIGvv/4atra20NfXR8+ePREWFlaFtSYiIqLqpFoHO0uXLsXq1auxatUq3Lt3D0uXLsWyZcvw66+/yvdZtmwZVq5ciTVr1iAgIACGhobo1asXMjMzq7DmREREVF1IxMvNJNXMu+++C2tra2zYsEGeNnToUOjr62Pr1q0QQsDOzg4zZ87EF198AQCQSqWwtrbGpk2b8P777ytVTnJyMkxMTCCVSmFsbFwp50JEREQVS9nf72rdstO+fXucOnUKoaGhAIAbN27gwoUL6NOnDwAgIiICcXFx6NmzpzyPiYkJ2rZtC39//2KPm5WVheTkZIUXERERqSetqq5ASebO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Li4OOjo6qFmzpsK+1tbWiIuLK/ZYPj4+MDExkb8cHBwqs+pERERUhd6YYMfLywu3b9/Gzp07y30sb29vSKVS+SsqKqoCakhERETVkVZVV0AZkydPxqFDh3Du3DnY29vL021sbJCdnY2kpCSF1p34+HjY2NgUezxdXV3o6upWZpWJiIiomqjWLTtCCEyePBl79+7F6dOn4eLiorC9ZcuW0NbWxqlTp+RpISEhiIyMhIeHx+uuLhEREVVD1bplx8vLC9u3b8f+/fthZGQk74djYmICfX19mJiYYOzYsZgxYwbMzMxgbGyMzz//HB4eHkqPxCIiIiL1Vq2HnkskkiLTfX198cknnwDIn1Rw5syZ2LFjB7KystCrVy/8/vvvJT7GehWHnhMREb15lP39rtbBzuvCYIeIiOjNo5bz7BARERGpisEOERERqTUGO0RERKTWGOwQERGRWmOwQ0RERGqNwQ4RERGpNQY7REREpNYY7BAREZFaY7BDREREao3BDhEREak1BjtERESk1hjsEBERkVpjsENERERqjcEOERERqTUGO0RERKTWGOwQERGRWmOwQ0RERGqNwQ4RERGpNQY7REREpNYY7BAREZFaY7BDREREao3BDhEREak1BjtERESk1hjsEBERkVpjsENERERqjcEOERERqTUGO0RERKTWGOwQERGRWmOwQ0RERGqNwQ4RERGpNQY7REREpNYY7BAREZFaY7BDREREao3BDhEREak1BjtERESk1hjsEBERkVpjsENERERqjcEOERERqTUGO0RERKTWGOwQERGRWmOwQ0RERGqNwQ4RERGpNQY7REREpNYY7BAREZFaY7BDREREao3BDhEREak1BjtERESk1hjsEBERkVpjsENERERqjcEOERERqTUGO0RERKTWGOwQERGRWmOwQ0RERGqNwQ4RERGpNQY7REREpNYY7BAREZFaY7BDREREao3BDhEREak1BjtERESk1hjsEBERkVpjsENERERqjcEOERERqTUGO0RERKTW1CbY+e233+Ds7Aw9PT20bdsWV65cqeoqERERUTWgFsHOrl27MGPGDCxYsADXrl1D06ZN0atXLyQkJFR11YiIiKiKqUWws3z5cowbNw5jxoxBgwYNsGbNGhgYGGDjxo1VXTUiIiKqYlpVXYHyys7OxtWrV+Ht7S1P09DQQM+ePeHv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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "plt.plot(np.arange(len(epochs_x)), epochs_acc, marker = '.')\n", - "plt.xlabel('epoch')\n", - "plt.ylabel('test accuracy')\n", - "plt.ylim(0, 100)\n", - "plt.xticks(np.arange(len(epochs_x)))\n", - "for i, txt in enumerate(epochs_acc):\n", - " if i%2 == 0:\n", - " pass\n", - " else:\n", - " plt.text(i, txt, f'{txt:.2f}', ha='center', va='bottom', color = 'k')\n", - "plt.show()" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "speck-rescnn", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.3" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/tests/test_nonsequential/exp_set_A/baseline-SCNN-example_3.ipynb b/tests/test_nonsequential/exp_set_A/baseline-SCNN-example_3.ipynb deleted file mode 100644 index dc53313a..00000000 --- a/tests/test_nonsequential/exp_set_A/baseline-SCNN-example_3.ipynb +++ /dev/null @@ -1,1500 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "import torch, random\n", - "import torch.nn as nn\n", - "import sinabs.layers as sl\n", - "from tqdm.notebook import tqdm\n", - "\n", - "from tonic.datasets.dvsgesture import DVSGesture\n", - "from tonic.transforms import ToFrame\n", - "from torch.utils.data import DataLoader\n", - "from torch.nn import CrossEntropyLoss\n", - "from torch.optim import Adam\n", - "\n", - "from sinabs.activation.surrogate_gradient_fn import PeriodicExponential\n", - "\n", - "import matplotlib.pyplot as plt\n", - "import numpy as np" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "torch.backends.cudnn.deterministic = True\n", - "random.seed(1)\n", - "torch.manual_seed(1)\n", - "torch.cuda.manual_seed(1)\n", - "np.random.seed(1)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Loading Data" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "batch_size = 3\n", - "num_workers = 1\n", - "epochs = 30\n", - "lr = 1e-3" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "root_dir = \"./DVSGESTURE\"\n", - "_ = DVSGesture(save_to=root_dir, train=True)\n", - "_ = DVSGesture(save_to=root_dir, train=False)" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "n_time_steps = 50\n", - "to_raster = ToFrame(sensor_size=DVSGesture.sensor_size, n_time_bins=n_time_steps)\n", - "\n", - "snn_train_dataset = DVSGesture(save_to=root_dir, train=True, transform=to_raster)\n", - "snn_test_dataset = DVSGesture(save_to=root_dir, train=False, transform=to_raster)" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The transformed array is in shape [Time-Step, Channel, Height, Width] --> (50, 2, 128, 128)\n" - ] - } - ], - "source": [ - "sample_data, label = snn_train_dataset[0]\n", - "print(f\"The transformed array is in shape [Time-Step, Channel, Height, Width] --> {sample_data.shape}\")" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [], - "source": [ - "snn_train_dataloader = DataLoader(snn_train_dataset, batch_size=batch_size, num_workers=num_workers, drop_last=True, shuffle=True)\n", - "snn_test_dataloader = DataLoader(snn_test_dataset, batch_size=batch_size, num_workers=num_workers, drop_last=True, shuffle=False)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Network Module\n", - "\n", - "We need to define a `nn.Module` implementing the network we want the chip to reproduce." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "device: NVIDIA RTX A4000\n" - ] - } - ], - "source": [ - "if torch.cuda.is_available():\n", - " device = torch.device('cuda:0')\n", - " print('device: ', torch.cuda.get_device_name(0))\n", - "else:\n", - " device = torch.device('cpu')" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [], - "source": [ - "class SNN(nn.Module):\n", - " def __init__(self) -> None:\n", - " super().__init__()\n", - "\n", - " self.conv1 = nn.Conv2d(2, 10, 2, 1, bias=False)\n", - " self.iaf1 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - " self.pool1 = nn.AvgPool2d(2,2)\n", - "\n", - " self.conv2 = nn.Conv2d(10, 10, 2, 1, bias=False)\n", - " self.iaf2 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - " self.pool2 = nn.AvgPool2d(3,3)\n", - "\n", - " self.conv3 = nn.Conv2d(10, 10, 3, 1, bias=False)\n", - " self.iaf3 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - " self.pool3 = nn.AvgPool2d(2,2)\n", - "\n", - " self.flat = nn.Flatten()\n", - "\n", - " self.fc1 = nn.Linear(810, 100, bias=False)\n", - " self.iaf4 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - "\n", - " self.fc2 = nn.Linear(100, 100, bias=False)\n", - " self.iaf5 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - "\n", - " self.fc3 = nn.Linear(100, 100, bias=False)\n", - " self.iaf6 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - "\n", - " self.fc4 = nn.Linear(100, 11, bias=False)\n", - " self.iaf7 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - "\n", - " def detach_neuron_states(self):\n", - " for name, layer in self.named_modules():\n", - " if name != '':\n", - " if isinstance(layer, sl.StatefulLayer):\n", - " for name, buffer in layer.named_buffers():\n", - " buffer.detach_()\n", - "\n", - " def init_weights(self):\n", - " for name, layer in self.named_modules():\n", - " if isinstance(layer, nn.Conv2d) or isinstance(layer, nn.Linear):\n", - " nn.init.xavier_normal_(layer.weight.data)\n", - "\n", - " def forward(self, x):\n", - " \n", - " con1_out = self.conv1(x)\n", - " iaf1_out = self.iaf1(con1_out)\n", - " pool1_out = self.pool1(iaf1_out)\n", - "\n", - " conv2_out = self.conv2(pool1_out)\n", - " iaf2_out = self.iaf2(conv2_out)\n", - " pool2_out = self.pool2(iaf2_out)\n", - "\n", - " conv3_out = self.conv3(pool2_out)\n", - " iaf3_out = self.iaf3(conv3_out)\n", - " pool3_out = self.pool3(iaf3_out)\n", - "\n", - " flat_out = self.flat(pool3_out)\n", - " \n", - " fc1_out = self.fc1(flat_out)\n", - " iaf4_out = self.iaf4(fc1_out)\n", - "\n", - " fc2_out = self.fc2(iaf4_out)\n", - " iaf5_out = self.iaf5(fc2_out)\n", - "\n", - " fc3_out = self.fc3(iaf5_out)\n", - " iaf6_out = self.iaf6(fc3_out)\n", - "\n", - " fc4_out = self.fc4(iaf6_out)\n", - " iaf7_out = self.iaf7(fc4_out)\n", - "\n", - " return iaf7_out" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [], - "source": [ - "snn = SNN().to(device)" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [], - "source": [ - "snn.init_weights()" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [], - "source": [ - "optimizer = Adam(snn.parameters(), lr=lr, betas=(0.9, 0.999), eps=1e-8)\n", - "loss_fn = CrossEntropyLoss()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Define train and test" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [], - "source": [ - "def train(dataloader, model, loss_fn, optimizer, epochs, test_func, dataloader_test):\n", - " epochs_y = []\n", - " epochs_x = []\n", - " epochs_acc = []\n", - " model.train()\n", - "\n", - " for e in range(epochs):\n", - " losses = []\n", - " batches = []\n", - " batch_count = 0\n", - " train_p_bar = tqdm(snn_train_dataloader)\n", - "\n", - " for X, y in train_p_bar:\n", - " # reshape the input from [Batch, Time, Channel, Height, Width] into [Batch*Time, Channel, Height, Width]\n", - " X = X.reshape(-1, 2, 128, 128).to(dtype=torch.float, device=device)\n", - " y = y.to(dtype=torch.long, device=device)\n", - "\n", - " # forward\n", - " pred = model(X)\n", - "\n", - " # reshape the output from [Batch*Time,num_classes] into [Batch, Time, num_classes]\n", - " pred = pred.reshape(batch_size, n_time_steps, -1)\n", - "\n", - " # accumulate all time-steps output for final prediction\n", - " pred = pred.sum(dim = 1)\n", - " loss = loss_fn(pred, y)\n", - "\n", - " # gradient update\n", - " optimizer.zero_grad()\n", - " loss.backward()\n", - " optimizer.step()\n", - "\n", - " # detach the neuron states and activations from current computation graph(necessary)\n", - " model.detach_neuron_states()\n", - "\n", - " train_p_bar.set_description(f\"Epoch {e} - BPTT Training Loss: {round(loss.item(), 4)}\")\n", - "\n", - " batch_count += 1\n", - " losses.append(loss.item())\n", - " batches.append(batch_count)\n", - "\n", - " epochs_y.append(losses)\n", - " epochs_x.append(batches)\n", - "\n", - " acc = test_func(dataloader_test, model)\n", - " print(f'Epoch {e} accuracy: {acc}')\n", - " epochs_acc.append(acc)\n", - "\n", - " return epochs_x, epochs_y, epochs_acc\n" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [], - "source": [ - "def test(dataloader, model):\n", - " correct_predictions = []\n", - " with torch.no_grad():\n", - " test_p_bar = tqdm(dataloader)\n", - " for X, y in test_p_bar:\n", - " # reshape the input from [Batch, Time, Channel, Height, Width] into [Batch*Time, Channel, Height, Width]\n", - " X = X.reshape(-1, 2, 128, 128).to(dtype=torch.float, device=device)\n", - " y = y.to(dtype=torch.long, device=device)\n", - "\n", - " # forward\n", - " output = model(X)\n", - "\n", - " # reshape the output from [Batch*Time,num_classes] into [Batch, Time, num_classes]\n", - " output = output.reshape(batch_size, n_time_steps, -1)\n", - "\n", - " # accumulate all time-steps output for final prediction\n", - " output = output.sum(dim=1)\n", - "\n", - " # calculate accuracy\n", - " pred = output.argmax(dim=1, keepdim=True)\n", - "\n", - " # compute the total correct predictions\n", - " correct_predictions.append(pred.eq(y.view_as(pred)))\n", - "\n", - " test_p_bar.set_description(f\"Testing Model...\")\n", - " \n", - " correct_predictions = torch.cat(correct_predictions)\n", - " return correct_predictions.sum().item()/(len(correct_predictions))*100" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Training loop" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "ebf2bea3d0124365abf1f2aa248ceab6", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - " 0%| | 0/359 [00:00" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "y_avg = []\n", - "for y in epochs_y:\n", - " y_avg.append(np.mean(y))\n", - "\n", - "plt.plot(np.arange(len(epochs_x)), y_avg, marker = '.')\n", - "plt.xlabel('epoch')\n", - "plt.ylabel('average loss')\n", - "plt.ylim(0,)\n", - "plt.xticks(np.arange(len(epochs_x)))\n", - "for i, txt in enumerate(y_avg):\n", - " if i%2 == 0:\n", - " pass\n", - " else:\n", - " plt.text(i, txt, f'{txt:.2f}', ha='center', va='bottom', color = 'k')\n", - "plt.show()" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjsAAAG2CAYAAACZEEfAAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8fJSN1AAAACXBIWXMAAA9hAAAPYQGoP6dpAAB9HElEQVR4nO3dd1RUx98G8GfpRUB6kaqg2HvB3oIt9qiJJjHGWH5irLFgYkw0ETWJJsbE9ipqrDGxG3vBhgiKXSmKglQLLL3uvH8QNq60XYrg+nzO2XNk7p07c3evu987d4pECCFAREREpKY0qroCRERERJWJwQ4RERGpNQY7REREpNYY7BAREZFaY7BDREREao3BDhEREak1BjtERESk1hjsEBERkVpjsENERERqjcEOERERqbUqDXbOnTuH/v37w87ODhKJBPv27VPYLoTA119/DVtbW+jr66Nnz54ICwtT2OfFixcYNWoUjI2NUbNmTYwdOxapqamv8SyIiIioOqvSYCctLQ1NmzbFb7/9VuT2ZcuWYeXKlVizZg0CAgJgaGiIXr16ITMzU77PqFGjcOfOHZw4cQKHDh3CuXPnMH78+Nd1CkRERFTNSarLQqASiQR79+7FoEGDAOS36tjZ2WHmzJn44osvAABSqRTW1tbYtGkT3n//fdy7dw8NGjRAYGAgWrVqBQA4evQo+vbtiydPnsDOzq6qToeIiIiqCa2qrkBxIiIiEBcXh549e8rTTExM0LZtW/j7++P999+Hv78/atasKQ90AKBnz57Q0NBAQEAABg8eXOSxs7KykJWVJf9bJpPhxYsXMDc3h0QiqbyTIiIiogojhEBKSgrs7OygoVH8w6pqG+zExcUBAKytrRXSra2t5dvi4uJgZWWlsF1LSwtmZmbyfYri4+ODb7/9toJrTERERFUhKioK9vb2xW6vtsFOZfL29saMGTPkf0ulUjg6OiIqKgrGxsZVWDMiIiJSVnJyMhwcHGBkZFTiftU22LGxsQEAxMfHw9bWVp4eHx+PZs2ayfdJSEhQyJebm4sXL17I8xdFV1cXurq6hdKNjY0Z7BAREb1hSuuCUm3n2XFxcYGNjQ1OnTolT0tOTkZAQAA8PDwAAB4eHkhKSsLVq1fl+5w+fRoymQxt27Z97XUmIiKi6qdKW3ZSU1MRHh4u/zsiIgLXr1+HmZkZHB0dMW3aNHz33Xdwc3ODi4sL5s+fDzs7O/mIrfr166N3794YN24c1qxZg5ycHEyePBnvv/8+R2IRERERgCoOdoKCgtCtWzf53wX9aEaPHo1NmzZh9uzZSEtLw/jx45GUlISOHTvi6NGj0NPTk+fZtm0bJk+ejB49ekBDQwNDhw7FypUrX/u5EBERUfVUbebZqUrJyckwMTGBVCplnx0iIqI3hLK/39W2zw4RERFRRWCwQ0RERGqNwQ4RERGpNQY7REREpNYY7BAREZFaY7BDREREao3BDhEREak1BjtERESk1hjsEBERkVpjsENERERqjcEOERERqTUGO0RERKTWGOwQERGRWmOwQ0RERGqNwQ4RERGpNQY7REREpNYY7BAREZFaY7BDREREao3BDhEREak1BjtERESk1hjsEBERkVpjsENERERqjcEOERERqTUGO0RERKTWGOwQERGRWmOwQ0RERGqNwQ4RERGpNQY7REREpNYY7BAREZFaY7BDREREao3BDhEREak1BjtERESk1hjsEBERkVpjsENERERqjcEOERERqTUGO0RERKTWGOwQERGRWmOwQ0RERGqNwQ4RERGpNQY7REREpNYY7BAREZFaY7BDREREao3BDhEREak1BjtERESk1hjsEBERkVpjsENERERqjcEOERERqTUGO0RERKTWGOwQERGRWmOwQ0RERGqNwQ4RERGpNQY7REREpNYY7BAREZFaY7BDREREao3BDhEREak1BjtERESk1hjsEBERkVpjsENERERqjcEOERERqTUGO0RERKTWGOwQERGRWmOwQ0RERGqNwQ4RERGptWod7OTl5WH+/PlwcXGBvr4+6tSpg0WLFkEIId9HCIGvv/4atra20NfXR8+ePREWFlaFtSYiIqLqpFoHO0uXLsXq1auxatUq3Lt3D0uXLsWyZcvw66+/yvdZtmwZVq5ciTVr1iAgIACGhobo1asXMjMzq7DmREREVF1IxMvNJNXMu+++C2tra2zYsEGeNnToUOjr62Pr1q0QQsDOzg4zZ87EF198AQCQSqWwtrbGpk2b8P777ytVTnJyMkxMTCCVSmFsbFwp50JEREQVS9nf72rdstO+fXucOnUKoaGhAIAbN27gwoUL6NOnDwAgIiICcXFx6NmzpzyPiYkJ2rZtC39//2KPm5WVheTkZIUXERERqSetqq5ASebO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Li4OOjo6qFmzpsK+1tbWiIuLK/ZYPj4+MDExkb8cHBwqs+pERERUhd6YYMfLywu3b9/Gzp07y30sb29vSKVS+SsqKqoCakhERETVkVZVV0AZkydPxqFDh3Du3DnY29vL021sbJCdnY2kpCSF1p34+HjY2NgUezxdXV3o6upWZpWJiIiomqjWLTtCCEyePBl79+7F6dOn4eLiorC9ZcuW0NbWxqlTp+RpISEhiIyMhIeHx+uuLhEREVVD1bplx8vLC9u3b8f+/fthZGQk74djYmICfX19mJiYYOzYsZgxYwbMzMxgbGyMzz//HB4eHkqPxCIiIiL1Vq2HnkskkiLTfX198cknnwDIn1Rw5syZ2LFjB7KystCrVy/8/vvvJT7GehWHnhMREb15lP39rtbBzuvCYIeIiOjNo5bz7BARERGpisEOERERqTUGO0RERKTWGOwQERGRWmOwQ0RERGqNwQ4RERGpNQY7REREpNYY7BAREZFaY7BDREREao3BDhEREak1BjtERESk1hjsEBERkVpjsENERERqjcEOERERqTUGO0RERKTWGOwQERGRWmOwQ0RERGqNwQ4RERGpNQY7REREpNYY7BAREZFaY7BDREREao3BDhEREak1BjtERESk1hjsEBERkVpjsENERERqjcEOERERqTUGO0RERKTWGOwQERGRWmOwQ0RERGqNwQ4RERGpNQY7REREpNYY7BAREZFaY7BDREREao3BDhEREak1BjtERESk1hjsEBERkVpjsENERERqjcEOERERqTUGO0RERKTWGOwQERGRWmOwQ0RERGqNwQ4RERGpNQY7REREpNYY7BAREZFaY7BDREREao3BDhEREak1BjtERESk1hjsEBERkVpjsENERERqjcEOERERqTUGO0RERKTWGOwQERGRWmOwQ0RERGqNwQ4RERGpNQY7REREpNYY7BAREZFaY7BDREREao3BDhEREak1BjtERESk1hjsEBERkVpjsENERERqjcEOERERqTUGO0RERKTW1CbY+e233+Ds7Aw9PT20bdsWV65cqeoqERERUTWgFsHOrl27MGPGDCxYsADXrl1D06ZN0atXLyQkJFR11YiIiKiKqUWws3z5cowbNw5jxoxBgwYNsGbNGhgYGGDjxo1VXTUiIiKqYlpVXYHyys7OxtWrV+Ht7S1P09DQQM+ePeHv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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "plt.plot(np.arange(len(epochs_x)), epochs_acc, marker = '.')\n", - "plt.xlabel('epoch')\n", - "plt.ylabel('test accuracy')\n", - "plt.ylim(0, 100)\n", - "plt.xticks(np.arange(len(epochs_x)))\n", - "for i, txt in enumerate(epochs_acc):\n", - " if i%2 == 0:\n", - " pass\n", - " else:\n", - " plt.text(i, txt, f'{txt:.2f}', ha='center', va='bottom', color = 'k')\n", - "plt.show()" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "speck-rescnn", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.3" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/tests/test_nonsequential/exp_set_A/non-sequential-SCNN-example_3.ipynb b/tests/test_nonsequential/exp_set_A/non-sequential-SCNN-example_3.ipynb deleted file mode 100644 index 956dfb88..00000000 --- a/tests/test_nonsequential/exp_set_A/non-sequential-SCNN-example_3.ipynb +++ /dev/null @@ -1,1509 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "import torch, random\n", - "import torch.nn as nn\n", - "import sinabs.layers as sl\n", - "from tqdm.notebook import tqdm\n", - "\n", - "from tonic.datasets.dvsgesture import DVSGesture\n", - "from tonic.transforms import ToFrame\n", - "from torch.utils.data import DataLoader\n", - "from torch.nn import CrossEntropyLoss\n", - "from torch.optim import Adam\n", - "\n", - "from sinabs.activation.surrogate_gradient_fn import PeriodicExponential\n", - "\n", - "import matplotlib.pyplot as plt\n", - "import numpy as np" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "torch.backends.cudnn.deterministic = True\n", - "random.seed(1)\n", - "torch.manual_seed(1)\n", - "torch.cuda.manual_seed(1)\n", - "np.random.seed(1)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Loading Data" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "batch_size = 3\n", - "num_workers = 1\n", - "epochs = 30\n", - "lr = 1e-3" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "root_dir = \"./DVSGESTURE\"\n", - "_ = DVSGesture(save_to=root_dir, train=True)\n", - "_ = DVSGesture(save_to=root_dir, train=False)" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "n_time_steps = 50\n", - "to_raster = ToFrame(sensor_size=DVSGesture.sensor_size, n_time_bins=n_time_steps)\n", - "\n", - "snn_train_dataset = DVSGesture(save_to=root_dir, train=True, transform=to_raster)\n", - "snn_test_dataset = DVSGesture(save_to=root_dir, train=False, transform=to_raster)" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The transformed array is in shape [Time-Step, Channel, Height, Width] --> (50, 2, 128, 128)\n" - ] - } - ], - "source": [ - "sample_data, label = snn_train_dataset[0]\n", - "print(f\"The transformed array is in shape [Time-Step, Channel, Height, Width] --> {sample_data.shape}\")" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [], - "source": [ - "snn_train_dataloader = DataLoader(snn_train_dataset, batch_size=batch_size, num_workers=num_workers, drop_last=True, shuffle=True)\n", - "snn_test_dataloader = DataLoader(snn_test_dataset, batch_size=batch_size, num_workers=num_workers, drop_last=True, shuffle=False)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Network Module\n", - "\n", - "We need to define a `nn.Module` implementing the network we want the chip to reproduce." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "device: NVIDIA RTX A4000\n" - ] - } - ], - "source": [ - "if torch.cuda.is_available():\n", - " device = torch.device('cuda:0')\n", - " print('device: ', torch.cuda.get_device_name(0))\n", - "else:\n", - " device = torch.device('cpu')" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [], - "source": [ - "class SNN(nn.Module):\n", - " def __init__(self) -> None:\n", - " super().__init__()\n", - "\n", - " self.conv1 = nn.Conv2d(2, 10, 2, 1, bias=False)\n", - " self.iaf1 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - " self.pool1 = nn.AvgPool2d(2,2)\n", - " self.pool1a = nn.AvgPool2d(6,6)\n", - "\n", - " self.conv2 = nn.Conv2d(10, 10, 2, 1, bias=False)\n", - " self.iaf2 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - " self.pool2 = nn.AvgPool2d(3,3)\n", - "\n", - " self.conv3 = nn.Conv2d(10, 10, 3, 1, bias=False)\n", - " self.iaf3 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - " self.pool3 = nn.AvgPool2d(2,2)\n", - "\n", - " self.flat = nn.Flatten()\n", - "\n", - " self.fc1 = nn.Linear(810, 100, bias=False)\n", - " self.iaf4 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - "\n", - " self.fc2 = nn.Linear(100, 100, bias=False)\n", - " self.iaf5 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - "\n", - " self.fc3 = nn.Linear(100, 100, bias=False)\n", - " self.iaf6 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - "\n", - " self.fc4 = nn.Linear(100, 11, bias=False)\n", - " self.iaf7 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - "\n", - " self.merge_fc = sl.Merge()\n", - " self.merge_conv = sl.Merge()\n", - "\n", - " def detach_neuron_states(self):\n", - " for name, layer in self.named_modules():\n", - " if name != '':\n", - " if isinstance(layer, sl.StatefulLayer):\n", - " for name, buffer in layer.named_buffers():\n", - " buffer.detach_()\n", - "\n", - " def init_weights(self):\n", - " for name, layer in self.named_modules():\n", - " if isinstance(layer, nn.Conv2d) or isinstance(layer, nn.Linear):\n", - " nn.init.xavier_normal_(layer.weight.data)\n", - "\n", - " def forward(self, x):\n", - " \n", - " con1_out = self.conv1(x)\n", - " iaf1_out = self.iaf1(con1_out)\n", - " pool1_out = self.pool1(iaf1_out)\n", - " pool1a_out = self.pool1a(iaf1_out)\n", - "\n", - " conv2_out = self.conv2(pool1_out)\n", - " iaf2_out = self.iaf2(conv2_out)\n", - " pool2_out = self.pool2(iaf2_out)\n", - "\n", - " merged_conv_out = self.merge_conv(pool1a_out, pool2_out)\n", - "\n", - " conv3_out = self.conv3(merged_conv_out)\n", - " iaf3_out = self.iaf3(conv3_out)\n", - " pool3_out = self.pool3(iaf3_out)\n", - "\n", - " flat_out = self.flat(pool3_out)\n", - " \n", - " fc1_out = self.fc1(flat_out)\n", - " iaf4_out = self.iaf4(fc1_out)\n", - "\n", - " fc2_out = self.fc2(iaf4_out)\n", - " iaf5_out = self.iaf5(fc2_out)\n", - "\n", - " fc3_out = self.fc3(iaf5_out)\n", - " iaf6_out = self.iaf6(fc3_out)\n", - "\n", - " merge_fc_out = self.merge_fc(iaf4_out, iaf6_out)\n", - "\n", - " fc4_out = self.fc4(merge_fc_out)\n", - " iaf7_out = self.iaf7(fc4_out)\n", - "\n", - " return iaf7_out" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [], - "source": [ - "snn = SNN().to(device)" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [], - "source": [ - "snn.init_weights()" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [], - "source": [ - "optimizer = Adam(snn.parameters(), lr=lr, betas=(0.9, 0.999), eps=1e-8)\n", - "loss_fn = CrossEntropyLoss()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Define train and test" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [], - "source": [ - "def train(dataloader, model, loss_fn, optimizer, epochs, test_func, dataloader_test):\n", - " epochs_y = []\n", - " epochs_x = []\n", - " epochs_acc = []\n", - " model.train()\n", - "\n", - " for e in range(epochs):\n", - " losses = []\n", - " batches = []\n", - " batch_count = 0\n", - " train_p_bar = tqdm(snn_train_dataloader)\n", - "\n", - " for X, y in train_p_bar:\n", - " # reshape the input from [Batch, Time, Channel, Height, Width] into [Batch*Time, Channel, Height, Width]\n", - " X = X.reshape(-1, 2, 128, 128).to(dtype=torch.float, device=device)\n", - " y = y.to(dtype=torch.long, device=device)\n", - "\n", - " # forward\n", - " pred = model(X)\n", - "\n", - " # reshape the output from [Batch*Time,num_classes] into [Batch, Time, num_classes]\n", - " pred = pred.reshape(batch_size, n_time_steps, -1)\n", - "\n", - " # accumulate all time-steps output for final prediction\n", - " pred = pred.sum(dim = 1)\n", - " loss = loss_fn(pred, y)\n", - "\n", - " # gradient update\n", - " optimizer.zero_grad()\n", - " loss.backward()\n", - " optimizer.step()\n", - "\n", - " # detach the neuron states and activations from current computation graph(necessary)\n", - " model.detach_neuron_states()\n", - "\n", - " train_p_bar.set_description(f\"Epoch {e} - BPTT Training Loss: {round(loss.item(), 4)}\")\n", - "\n", - " batch_count += 1\n", - " losses.append(loss.item())\n", - " batches.append(batch_count)\n", - "\n", - " epochs_y.append(losses)\n", - " epochs_x.append(batches)\n", - "\n", - " acc = test_func(dataloader_test, model)\n", - " print(f'Epoch {e} accuracy: {acc}')\n", - " epochs_acc.append(acc)\n", - "\n", - " return epochs_x, epochs_y, epochs_acc\n" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [], - "source": [ - "def test(dataloader, model):\n", - " correct_predictions = []\n", - " with torch.no_grad():\n", - " test_p_bar = tqdm(dataloader)\n", - " for X, y in test_p_bar:\n", - " # reshape the input from [Batch, Time, Channel, Height, Width] into [Batch*Time, Channel, Height, Width]\n", - " X = X.reshape(-1, 2, 128, 128).to(dtype=torch.float, device=device)\n", - " y = y.to(dtype=torch.long, device=device)\n", - "\n", - " # forward\n", - " output = model(X)\n", - "\n", - " # reshape the output from [Batch*Time,num_classes] into [Batch, Time, num_classes]\n", - " output = output.reshape(batch_size, n_time_steps, -1)\n", - "\n", - " # accumulate all time-steps output for final prediction\n", - " output = output.sum(dim=1)\n", - "\n", - " # calculate accuracy\n", - " pred = output.argmax(dim=1, keepdim=True)\n", - "\n", - " # compute the total correct predictions\n", - " correct_predictions.append(pred.eq(y.view_as(pred)))\n", - "\n", - " test_p_bar.set_description(f\"Testing Model...\")\n", - " \n", - " correct_predictions = torch.cat(correct_predictions)\n", - " return correct_predictions.sum().item()/(len(correct_predictions))*100" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Training loop (HPO)" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "12d134e3b89e41888c9c47892b8e6491", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - " 0%| | 0/359 [00:00" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "y_avg = []\n", - "for y in epochs_y:\n", - " y_avg.append(np.mean(y))\n", - "\n", - "plt.plot(np.arange(len(epochs_x)), y_avg, marker = '.')\n", - "plt.xlabel('epoch')\n", - "plt.ylabel('average loss')\n", - "plt.ylim(0,)\n", - "plt.xticks(np.arange(len(epochs_x)))\n", - "for i, txt in enumerate(y_avg):\n", - " if i%5 == 0:\n", - " plt.text(i, txt, f'{txt:.2f}', ha='center', va='bottom', color = 'k')\n", - " else:\n", - " pass\n", - "plt.show()" - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjsAAAG2CAYAAACZEEfAAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8fJSN1AAAACXBIWXMAAA9hAAAPYQGoP6dpAABq60lEQVR4nO3dd1hT1+MG8DfsHUW2TAfixK3gqqO46q6jtVWr1bZi62idraPVFrWt7dfROn5urauOOloXrqqooOBEBERBZYhI2DPn9weaGlmJBIH4fp4nT8vNPfecQMx9c+6550iEEAJEREREWkqnohtAREREVJ4YdoiIiEirMewQERGRVmPYISIiIq3GsENERERajWGHiIiItBrDDhEREWk1hh0iIiLSagw7REREpNUYdoiIiEirVWjYOXPmDPr06QMHBwdIJBLs27dP6XkhBObMmQN7e3sYGxujW7duCA8PV9onKSkJw4cPh4WFBapVq4YxY8YgLS3tNb4KIiIiqswqNOykp6fD09MTK1asKPL5xYsXY+nSpVi5ciUuXrwIU1NTdO/eHVlZWYp9hg8fjps3b+LYsWM4ePAgzpw5g3Hjxr2ul0BERESVnKSyLAQqkUiwd+9e9O/fH0BBr46DgwO+/PJLfPXVVwAAmUwGW1tbbNiwAcOGDUNoaCgaNGiAwMBAtGzZEgBw+PBh9OrVCw8ePICDg0NFvRwiIiKqJPQqugHFiYqKQlxcHLp166bYJpVK0aZNGwQEBGDYsGEICAhAtWrVFEEHALp16wYdHR1cvHgRAwYMKPLY2dnZyM7OVvwsl8uRlJSEGjVqQCKRlN+LIiIiIo0RQiA1NRUODg7Q0Sn+YlWlDTtxcXEAAFtbW6Xttra2iufi4uJgY2Oj9Lyenh4sLS0V+xTFz88P3377rYZbTERERBUhJiYGjo6OxT5facNOeZo5cyamTJmi+Fkmk8HZ2RkxMTGwsLCowJYRERGRqlJSUuDk5ARzc/MS96u0YcfOzg4AEB8fD3t7e8X2+Ph4NG3aVLFPQkKCUrm8vDwkJSUpyhfF0NAQhoaGhbZbWFgw7BAREVUxpQ1BqbTz7Li5ucHOzg7+/v6KbSkpKbh48SK8vLwAAF5eXkhOTsbly5cV+5w4cQJyuRxt2rR57W0mIiKiyqdCe3bS0tIQERGh+DkqKgohISGwtLSEs7MzJk2ahAULFqBu3bpwc3PD7Nmz4eDgoLhjq379+ujRowfGjh2LlStXIjc3FxMmTMCwYcN4JxYREREBqOCwExQUhM6dOyt+fj6OZuTIkdiwYQOmTZuG9PR0jBs3DsnJyWjfvj0OHz4MIyMjRZmtW7diwoQJ6Nq1K3R0dDBo0CAsXbr0tb8WIiIiqpwqzTw7FSklJQVSqRQymYxjdoiIiKoIVc/flXbMDhEREZEmMOwQERGRVmPYISIiIq3GsENERERajWGHiIiItBrDDhEREWk1hh0iIiLSagw7REREpNUYdoiIiEirMewQERGRVmPYISIiIq3GsENERERajWGHiIiItBrDDhEREWk1hh0iIiLSagw7REREpNUYdoiIiEirMewQERGRVmPYISIiIq3GsENERERajWGHiIiItBrDDhEREWk1hh0iIiLSagw7REREpNUYdoiIiEirMewQERGRVmPYISIiIq3GsENERERajWGHiIiItBrDDhEREWk1hh0iIiLSagw7REREpNUYdoiIiEqQn5+P2bNnw83NDcbGxqhduzbmz58PIYRin1GjRkEikSg9evToUeJxU1NTMWnSJLi4uMDY2Bje3t4IDAxU2ictLQ0TJkyAo6MjjI2N0aBBA6xcubJcXqc206voBhAREVVmixYtwu+//46NGzeiYcOGCAoKwkcffQSpVIovvvhCsV+PHj2wfv16xc+GhoYlHvfjjz/GjRs3sHnzZjg4OGDLli3o1q0bbt26hZo1awIApkyZghMnTmDLli1wdXXF0aNHMX78eDg4OKBv377l84K1EHt2iIiISnD+/Hn069cPvXv3hqurK9599134+Pjg0qVLSvsZGhrCzs5O8ahevXqxx8zMzMTu3buxePFidOzYEXXq1MG8efNQp04d/P7770p1jxw5Em+99RZcXV0xbtw4eHp6FqqbSsawQ0T0hiivyzF+fn5o1aoVzM3NYWNjg/79+yMsLExpn08++QS1a9eGsbExalhZo0O3njgTGFIeL1PjvL294e/vjzt37gAArl69irNnz6Jnz55K+506dQo2NjaoV68ePvvsMzx58qTYY+bl5SE/Px9GRkZK242NjXH27Fmluvfv34+HDx9CCIGTJ0/izp078PHx0eArfAMIEjKZTAAQMpmsoptCRFRuvv/+e1GjRg1x8OBBERUVJXbt2iXMzMzE//73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DBTPGRgYwNPTE1999ZXmW0hERERUBiqHnZMnTwIouPX7f//7H8e2EBERUZWg9t1Y69evL492EBEREZULtQcoExEREVUlDDtERESk1Rh2iIiISKsx7BAREZFWY9ghIiIircawQ0RERFqNYYeIiIi0GsMOERERaTWGHSIiItJqDDtERESk1Rh2iIiISKsx7BAREZFWY9ghIiIircawQ0RERFqNYYeIiIi0GsMOERERaTWGHSIiItJqDDtERESk1Rh2iIiISKsx7BAREZFWY9ghIiIircawQ0RERFqNYYeIiIi0GsMOERERaTWGHSIiItJqDDtERESk1Rh2iIiISKsx7BAREZFWY9ghIiIircawQ0RERFqNYYeIiIi0GsMOERERaTWGHSIiItJqDDtERESk1Rh2iIiISKsx7BAREZFWY9ghIiIircawQ0RERFqNYYeIiIi0GsMOERERaTWGHSIiItJqDDtERESk1Rh2iIiISKsx7BAREZFWY9ghIiIircawQ0RERFqNYYeIiIi0GsMOERERaTWGHSIiItJqDDtERESk1Rh2iIiISKsx7BAREZFWY9ghIiIircawQ0RERFqNYYeIiIi0GsMOERERaTWGHSIiItJqDDtERESk1Sp12PHz80OrVq1gbm4OGxsb9O/fH2FhYUr7ZGVlwdfXFzVq1ICZmRkGDRqE+Pj4CmoxERERVTaVOuycPn0avr6+uHDhAo4dO4bc3Fz4+PggPT1dsc/kyZNx4MAB7Nq1C6dPn8ajR48wcODACmw1ERERVSYSIYSo6Eao6vHjx7CxscHp06fRsWNHyGQyWFtb448//sC7774LALh9+zbq16+PgIAAtG3bVqXjpqSkQCqVQiaTwcLCojxfAhEREWmIqufvSt2z8zKZTAYAsLS0BABcvnwZubm56Natm2IfDw8PODs7IyAgoNjjZGdnIyUlRelBRERE2qnKhB25XI5JkyahXbt2aNSoEQAgLi4OBgYGqFatmtK+tra2iIuLK/ZYfn5+kEqlioeTk1N5Np2IiIgqUJUJO76+vrhx4wa2b99e5mPNnDkTMplM8YiJidFAC4mIiKgy0qvoBqhiwoQJOHjwIM6cOQNHR0fFdjs7O+Tk5CA5OVmpdyc+Ph52dnbFHs/Q0BCGhobl2WQiIiKqJCp1z44QAhMmTMDevXtx4sQJuLm5KT3fokUL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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "plt.plot(np.arange(len(epochs_x)), epochs_acc, marker = '.')\n", - "plt.xlabel('epoch')\n", - "plt.ylabel('test accuracy')\n", - "plt.ylim(0, 100)\n", - "plt.xticks(np.arange(len(epochs_x)))\n", - "for i, txt in enumerate(epochs_acc):\n", - " if i%5 == 0:\n", - " plt.text(i, txt, f'{txt:.2f}', ha='center', va='bottom', color = 'k')\n", - " else:\n", - " pass\n", - "plt.show()" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "speck-rescnn", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.3" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/tests/test_nonsequential/exp_set_B/baseline-SCNN-example_3.ipynb b/tests/test_nonsequential/exp_set_B/baseline-SCNN-example_3.ipynb deleted file mode 100644 index a29b616b..00000000 --- a/tests/test_nonsequential/exp_set_B/baseline-SCNN-example_3.ipynb +++ /dev/null @@ -1,1512 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "import torch, random\n", - "import torch.nn as nn\n", - "import sinabs.layers as sl\n", - "from tqdm.notebook import tqdm\n", - "\n", - "from tonic.datasets.dvsgesture import DVSGesture\n", - "from tonic.transforms import ToFrame\n", - "from torch.utils.data import DataLoader\n", - "from torch.nn import CrossEntropyLoss\n", - "from torch.optim import Adam\n", - "\n", - "from sinabs.activation.surrogate_gradient_fn import PeriodicExponential\n", - "\n", - "import matplotlib.pyplot as plt\n", - "import numpy as np" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "torch.backends.cudnn.deterministic = True\n", - "random.seed(1)\n", - "torch.manual_seed(1)\n", - "torch.cuda.manual_seed(1)\n", - "np.random.seed(1)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Loading Data" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "batch_size = 3\n", - "num_workers = 1\n", - "epochs = 30\n", - "lr = 5e-4" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "root_dir = \"../DVSGESTURE\"\n", - "_ = DVSGesture(save_to=root_dir, train=True)\n", - "_ = DVSGesture(save_to=root_dir, train=False)" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "n_time_steps = 50\n", - "to_raster = ToFrame(sensor_size=DVSGesture.sensor_size, n_time_bins=n_time_steps)\n", - "\n", - "snn_train_dataset = DVSGesture(save_to=root_dir, train=True, transform=to_raster)\n", - "snn_test_dataset = DVSGesture(save_to=root_dir, train=False, transform=to_raster)" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The transformed array is in shape [Time-Step, Channel, Height, Width] --> (50, 2, 128, 128)\n" - ] - } - ], - "source": [ - "sample_data, label = snn_train_dataset[0]\n", - "print(f\"The transformed array is in shape [Time-Step, Channel, Height, Width] --> {sample_data.shape}\")" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [], - "source": [ - "snn_train_dataloader = DataLoader(snn_train_dataset, batch_size=batch_size, num_workers=num_workers, drop_last=True, shuffle=True)\n", - "snn_test_dataloader = DataLoader(snn_test_dataset, batch_size=batch_size, num_workers=num_workers, drop_last=True, shuffle=False)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Network Module\n", - "\n", - "We need to define a `nn.Module` implementing the network we want the chip to reproduce." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "device: NVIDIA GeForce RTX 3070 Ti\n" - ] - } - ], - "source": [ - "if torch.cuda.is_available():\n", - " device = torch.device('cuda:0')\n", - " print('device: ', torch.cuda.get_device_name(0))\n", - "else:\n", - " device = torch.device('cpu')" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [], - "source": [ - "class SNN(nn.Module):\n", - " def __init__(self) -> None:\n", - " super().__init__()\n", - "\n", - " self.conv1 = nn.Conv2d(2, 10, 2, 1, bias=False)\n", - " self.iaf1 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - " self.pool1 = nn.AvgPool2d(2,2)\n", - "\n", - " self.conv2 = nn.Conv2d(10, 10, 2, 1, bias=False)\n", - " self.iaf2 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - " self.pool2 = nn.AvgPool2d(3,3)\n", - "\n", - " self.conv3 = nn.Conv2d(10, 10, 3, 1, bias=False)\n", - " self.iaf3 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - " self.pool3 = nn.AvgPool2d(2,2)\n", - "\n", - " self.flat = nn.Flatten()\n", - "\n", - " self.fc1 = nn.Linear(810, 100, bias=False)\n", - " self.iaf4 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - "\n", - " self.fc2 = nn.Linear(100, 100, bias=False)\n", - " self.iaf5 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - "\n", - " self.fc3 = nn.Linear(100, 100, bias=False)\n", - " self.iaf6 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - "\n", - " self.fc4 = nn.Linear(100, 11, bias=False)\n", - " self.iaf7 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - "\n", - " def detach_neuron_states(self):\n", - " for name, layer in self.named_modules():\n", - " if name != '':\n", - " if isinstance(layer, sl.StatefulLayer):\n", - " for name, buffer in layer.named_buffers():\n", - " buffer.detach_()\n", - "\n", - " def init_weights(self):\n", - " for name, layer in self.named_modules():\n", - " if isinstance(layer, nn.Conv2d) or isinstance(layer, nn.Linear):\n", - " nn.init.xavier_normal_(layer.weight.data)\n", - "\n", - " def forward(self, x):\n", - " \n", - " con1_out = self.conv1(x)\n", - " iaf1_out = self.iaf1(con1_out)\n", - " pool1_out = self.pool1(iaf1_out)\n", - "\n", - " conv2_out = self.conv2(pool1_out)\n", - " iaf2_out = self.iaf2(conv2_out)\n", - " pool2_out = self.pool2(iaf2_out)\n", - "\n", - " conv3_out = self.conv3(pool2_out)\n", - " iaf3_out = self.iaf3(conv3_out)\n", - " pool3_out = self.pool3(iaf3_out)\n", - "\n", - " flat_out = self.flat(pool3_out)\n", - " \n", - " fc1_out = self.fc1(flat_out)\n", - " iaf4_out = self.iaf4(fc1_out)\n", - "\n", - " fc2_out = self.fc2(iaf4_out)\n", - " iaf5_out = self.iaf5(fc2_out)\n", - "\n", - " fc3_out = self.fc3(iaf5_out)\n", - " iaf6_out = self.iaf6(fc3_out)\n", - "\n", - " fc4_out = self.fc4(iaf6_out)\n", - " iaf7_out = self.iaf7(fc4_out)\n", - "\n", - " return iaf7_out" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [], - "source": [ - "snn = SNN().to(device)" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [], - "source": [ - "snn.init_weights()" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [], - "source": [ - "optimizer = Adam(snn.parameters(), lr=lr, betas=(0.9, 0.999), eps=1e-8)\n", - "loss_fn = CrossEntropyLoss()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Define train and test" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [], - "source": [ - "def train(dataloader, model, loss_fn, optimizer, epochs, test_func, dataloader_test):\n", - " epochs_y = []\n", - " epochs_x = []\n", - " epochs_acc = []\n", - " model.train()\n", - "\n", - " for e in range(epochs):\n", - " losses = []\n", - " batches = []\n", - " batch_count = 0\n", - " train_p_bar = tqdm(snn_train_dataloader)\n", - "\n", - " for X, y in train_p_bar:\n", - " # reshape the input from [Batch, Time, Channel, Height, Width] into [Batch*Time, Channel, Height, Width]\n", - " X = X.reshape(-1, 2, 128, 128).to(dtype=torch.float, device=device)\n", - " y = y.to(dtype=torch.long, device=device)\n", - "\n", - " # forward\n", - " pred = model(X)\n", - "\n", - " # reshape the output from [Batch*Time,num_classes] into [Batch, Time, num_classes]\n", - " pred = pred.reshape(batch_size, n_time_steps, -1)\n", - "\n", - " # accumulate all time-steps output for final prediction\n", - " pred = pred.sum(dim = 1)\n", - " loss = loss_fn(pred, y)\n", - "\n", - " # gradient update\n", - " optimizer.zero_grad()\n", - " loss.backward()\n", - " optimizer.step()\n", - "\n", - " # detach the neuron states and activations from current computation graph(necessary)\n", - " model.detach_neuron_states()\n", - "\n", - " train_p_bar.set_description(f\"Epoch {e} - BPTT Training Loss: {round(loss.item(), 4)}\")\n", - "\n", - " batch_count += 1\n", - " losses.append(loss.item())\n", - " batches.append(batch_count)\n", - "\n", - " epochs_y.append(losses)\n", - " epochs_x.append(batches)\n", - "\n", - " acc = test_func(dataloader_test, model)\n", - " print(f'Epoch {e} accuracy: {acc}')\n", - " epochs_acc.append(acc)\n", - "\n", - " return epochs_x, epochs_y, epochs_acc\n" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [], - "source": [ - "def test(dataloader, model):\n", - " correct_predictions = []\n", - " with torch.no_grad():\n", - " test_p_bar = tqdm(dataloader)\n", - " for X, y in test_p_bar:\n", - " # reshape the input from [Batch, Time, Channel, Height, Width] into [Batch*Time, Channel, Height, Width]\n", - " X = X.reshape(-1, 2, 128, 128).to(dtype=torch.float, device=device)\n", - " y = y.to(dtype=torch.long, device=device)\n", - "\n", - " # forward\n", - " output = model(X)\n", - "\n", - " # reshape the output from [Batch*Time,num_classes] into [Batch, Time, num_classes]\n", - " output = output.reshape(batch_size, n_time_steps, -1)\n", - "\n", - " # accumulate all time-steps output for final prediction\n", - " output = output.sum(dim=1)\n", - "\n", - " # calculate accuracy\n", - " pred = output.argmax(dim=1, keepdim=True)\n", - "\n", - " # compute the total correct predictions\n", - " correct_predictions.append(pred.eq(y.view_as(pred)))\n", - "\n", - " test_p_bar.set_description(f\"Testing Model...\")\n", - " \n", - " correct_predictions = torch.cat(correct_predictions)\n", - " return correct_predictions.sum().item()/(len(correct_predictions))*100" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Training loop" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "a1826a7c572749a4ae111dcc8af0ec3b", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - " 0%| | 0/359 [00:00" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "y_avg = []\n", - "for y in epochs_y:\n", - " y_avg.append(np.mean(y))\n", - "\n", - "plt.plot(np.arange(len(epochs_x)), y_avg, marker = '.')\n", - "plt.xlabel('epoch')\n", - "plt.ylabel('average loss')\n", - "plt.ylim(0,)\n", - "plt.xticks(np.arange(len(epochs_x)))\n", - "for i, txt in enumerate(y_avg):\n", - " if i%2 == 0:\n", - " pass\n", - " else:\n", - " plt.text(i, txt, f'{txt:.2f}', ha='center', va='bottom', color = 'k')\n", - "plt.show()" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjsAAAG2CAYAAACZEEfAAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy81sbWrAAAACXBIWXMAAA9hAAAPYQGoP6dpAAB7hklEQVR4nO3deXhM1/8H8PdkskeE7DNJJEESBLEWsRdRVUupXe2qpSXUvrSqJGiptoryU2uLllhqj5bYiSVEBCEhEYkIyWTfz++PfDM1ss2QiIz363nmaXPvPcuNY+7HuWeRCCEEiIiIiLSUTkVXgIiIiKg8MdghIiIircZgh4iIiLQagx0iIiLSagx2iIiISKsx2CEiIiKtxmCHiIiItBqDHSIiItJqDHaIiIhIqzHYISIiIq1WocHOyZMn0aNHD8jlckgkEuzZs0flvBAC8+fPh1wuh5GRETp06ICQkBCVazIzM/HFF1/A0tISJiYm6NmzJx4+fPga74KIiIjeZBUa7KSmpsLDwwMrV64s8vzSpUuxfPlyrFy5EoGBgbC1tUWXLl2QnJysvMbb2xu7d+/G9u3bcfr0aaSkpOCDDz5Abm7u67oNIiIieoNJ3pSNQCUSCXbv3o3evXsDyO/Vkcvl8Pb2xowZMwDk9+LY2NhgyZIlGDduHBQKBaysrLBlyxYMGDAAAPDo0SM4ODjg4MGD6Nq1a0XdDhEREb0hdCu6AsWJiIhAbGwsvLy8lMcMDAzQvn17nD17FuPGjcPly5eRnZ2tco1cLkf9+vVx9uzZYoOdzMxMZGZmKn/Oy8vDs2fPYGFhAYlEUn43RURERGVGCIHk5GTI5XLo6BT/suqNDXZiY2MBADY2NirHbWxs8ODBA+U1+vr6qF69eqFrCtIXxdfXF998800Z15iIiIgqQlRUFOzt7Ys9/8YGOwVe7GkRQpTa+1LaNbNmzcKUKVOUPysUCtSoUQNRUVGoWrXqq1WYiIiIXoukpCQ4ODjA1NS0xOve2GDH1tYWQH7vjUwmUx6Pi4tT9vbY2toiKysLCQkJKr07cXFx8PT0LDZvAwMDGBgYFDpetWpVBjtERESVTGmdIG/sOjvOzs6wtbWFv7+/8lhWVhYCAgKUgUzTpk2hp6enck1MTAxu3LhRYrBDREREb48K7dlJSUnB3bt3lT9HREQgKCgI5ubmqFGjBry9veHj4wMXFxe4uLjAx8cHxsbGGDx4MADAzMwMo0ePxpdffgkLCwuYm5tj6tSpaNCgATp37lxRt0VERERvkAoNdi5duoSOHTsqfy4YRzN8+HBs3LgR06dPR3p6OsaPH4+EhAS0aNECR48eVXk398MPP0BXVxf9+/dHeno6OnXqhI0bN0Iqlb72+yEiIqI3zxuzzk5FSkpKgpmZGRQKBcfsEBERVRLqPr/f2DE7RERERGWBwQ4RERFpNQY7REREpNUY7BAREZFWY7BDREREWo3BDhEREWk1BjtERESk1RjsEBERkVZjsENERERajcEOERERaTUGO0RERKTVGOwQERGRVmOwQ0RERFqNwQ4RERFpNQY7REREpNUY7BAREZFWY7BDREREWo3BDhEREWk1BjtERESk1RjsEBERkVZjsENERERajcEOERERaTUGO0RERKTVGOwQERGRVmOwQ0RERFqNwQ4RERFpNQY7REREpNUY7BAREZFWY7BDREREWo3BDhEREWk1BjtERESk1RjsEBERkVZjsENERERajcEOERERaTUGO0RERKTVGOwQERGRVmOwQ0RERFqNwQ4RERFpNQY7REREpNUY7BAREZFWY7BDREREWo3BDhEREWk1BjtERESk1RjsEBERkVZjsENERERajcEOERERaTUGO0RERKTVGOwQERGRVmOwQ0RERFqNwQ4RERFpNQY7REREpNUY7BAREZFWY7BDREREWo3BDhERERWSk5ODuXPnwtnZGUZGRqhZsyYWLFiAvLw85TVCCMyfPx9yuRxGRkbo0KEDQkJCSszXz88PzZo1Q7Vq1WBiYoJGjRphy5Ytha5btWoVnJ2dYWhoiKZNm+LUqVMvfS8MdoiIiKiQJUuWYM2aNVi5ciVCQ0OxdOlSfPfdd/j555+V1yxduhTLly/HypUrERgYCFtbW3Tp0gXJycnF5mtubo45c+bg3LlzuH79OkaOHImRI0fiyJEjymt27NgBb29vzJkzB1evXkXbtm3RrVs3REZGvtS9SIQQ4qVSapGkpCSYmZlBoVCgatWqFV0dIiKiCvfBBx/AxsYG69evVx7r27cvjI2NsWXLFgghIJfL4e3tjRkzZgAAMjMzYWNjgyVLlmDcuHFql9WkSRN0794d3377LQCgRYsWaNKkCVavXq28pm7duujduzd8fX2Vx9R9frNnh4iIiApp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cnEznVJSUkqcMUVERERUEdR+jTVlyhQA+bOv5s2bpzL9PDc3FxcuXECjRo3KvIJEREREr0LtYOfq1asA8nt2goODoa+vrzynr68PDw8PTJ06texrSERERPQK1A52jh8/DiB/6vePP/7IsS1ERERUKWg8G2vDhg3lUQ8iIiKicqHxAGUiIiKiyoTBDhEREWk1BjtERESk1RjsEBERkVZjsENERERajcEOERERaTUGO0RERKTVGOwQERGRVmOwQ0RERFqNwQ4RERFpNQY7REREpNUY7BAREZFWY7BDREREWo3BDhEREWk1BjtERESk1RjsEBERkVZjsENERERajcEOERERaTUGO0RERKTVGOwQERGRVmOwQ0RERFqNwQ4RERFpNQY7REREpNUY7BAREZFWY7BDREREWo3BDhEREWk1BjtERESk1RjsEBERkVZjsENERERajcEOERERaTUGO0RERKTVGOwQERGRVmOwQ0RERFqNwQ4RERFpNQY7REREpNUY7BAREZFWY7BDREREWo3BDhEREWk1BjtERESk1RjsEBERkVZjsENERERajcEOERERaTUGO0RERKTVGOwQERGRVmOwQ0RERFqNwQ4RERFpNQY7REREpNUY7BAREZFWY7BDREREWo3BDhEREWk1BjtERESk1RjsEBERkVZjsENERERajcEOERERaTUGO0RERKTVGOwQERGRVmOwQ0RERFqNwQ4RERFptTc62PH19UXz5s1hamoKa2tr9O7dG7dv31a5RgiB+fPnQy6Xw8jICB06dEBISEgF1ZiIiIjeNG90sBMQEIAJEybg/Pnz8Pf3R05ODry8vJCamqq8ZunSpVi+fDlWrlyJwMBA2NraokuXLkhOTq7AmhMREdGbQiKEEBVdCXU9efIE1tbWCAgIQLt27SCEgFwuh7e3N2bMmAEAyMzMhI2NDZYsWYJx48aplW9SUhLMzMygUChQtWrV8rwFIiIiKiPqPr/f6J6dFykUCgCAubk5ACAiIgKxsbHw8vJSXmNgYID27dvj7NmzxeaTmZmJpKQklQ8RERFpp0oT7AghMGXKFLRp0wb169cHAMTGxgIAbGxsVK61sbFRniuKr68vzMzMlB8HB4fyqzgRERFVqEoT7Hz++ee4fv06tm3bVuicRCJR+VkIUejY82bNmgWFQqH8REVFlXl9iYiI6M2gW9EV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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "plt.plot(np.arange(len(epochs_x)), epochs_acc, marker = '.')\n", - "plt.xlabel('epoch')\n", - "plt.ylabel('test accuracy')\n", - "plt.ylim(0, 100)\n", - "plt.xticks(np.arange(len(epochs_x)))\n", - "for i, txt in enumerate(epochs_acc):\n", - " if i%2 == 0:\n", - " pass\n", - " else:\n", - " plt.text(i, txt, f'{txt:.2f}', ha='center', va='bottom', color = 'k')\n", - "plt.show()" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [], - "source": [ - "with open('baseline_exp_set_B_training_metrics.npy', 'wb') as f:\n", - " np.save(f, np.array(epochs_x))\n", - " np.save(f, np.array(epochs_y))\n", - " np.save(f, np.array(epochs_acc))" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "speck-rescnn", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.3" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/tests/test_nonsequential/exp_set_B/baseline_exp_set_B_training_metrics.npy b/tests/test_nonsequential/exp_set_B/baseline_exp_set_B_training_metrics.npy deleted file mode 100644 index eafbf40a061d3e9f1e60476b58a21fd33ee6d88e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 172944 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%0AGU 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 TX)JW3|G6fy(A@U9n#KMf7dXz^ diff --git a/tests/test_nonsequential/exp_set_B/non-sequential-SCNN-example_3.ipynb b/tests/test_nonsequential/exp_set_B/non-sequential-SCNN-example_3.ipynb deleted file mode 100644 index f8b7f3ff..00000000 --- a/tests/test_nonsequential/exp_set_B/non-sequential-SCNN-example_3.ipynb +++ /dev/null @@ -1,1521 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "import torch, random\n", - "import torch.nn as nn\n", - "import sinabs.layers as sl\n", - "from tqdm.notebook import tqdm\n", - "\n", - "from tonic.datasets.dvsgesture import DVSGesture\n", - "from tonic.transforms import ToFrame\n", - "from torch.utils.data import DataLoader\n", - "from torch.nn import CrossEntropyLoss\n", - "from torch.optim import Adam\n", - "\n", - "from sinabs.activation.surrogate_gradient_fn import PeriodicExponential\n", - "\n", - "import matplotlib.pyplot as plt\n", - "import numpy as np" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "torch.backends.cudnn.deterministic = True\n", - "random.seed(1)\n", - "torch.manual_seed(1)\n", - "torch.cuda.manual_seed(1)\n", - "np.random.seed(1)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Loading Data" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "batch_size = 3\n", - "num_workers = 1\n", - "epochs = 30\n", - "lr = 5e-4" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "root_dir = \"../DVSGESTURE\"\n", - "_ = DVSGesture(save_to=root_dir, train=True)\n", - "_ = DVSGesture(save_to=root_dir, train=False)" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "n_time_steps = 50\n", - "to_raster = ToFrame(sensor_size=DVSGesture.sensor_size, n_time_bins=n_time_steps)\n", - "\n", - "snn_train_dataset = DVSGesture(save_to=root_dir, train=True, transform=to_raster)\n", - "snn_test_dataset = DVSGesture(save_to=root_dir, train=False, transform=to_raster)" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The transformed array is in shape [Time-Step, Channel, Height, Width] --> (50, 2, 128, 128)\n" - ] - } - ], - "source": [ - "sample_data, label = snn_train_dataset[0]\n", - "print(f\"The transformed array is in shape [Time-Step, Channel, Height, Width] --> {sample_data.shape}\")" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [], - "source": [ - "snn_train_dataloader = DataLoader(snn_train_dataset, batch_size=batch_size, num_workers=num_workers, drop_last=True, shuffle=True)\n", - "snn_test_dataloader = DataLoader(snn_test_dataset, batch_size=batch_size, num_workers=num_workers, drop_last=True, shuffle=False)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Network Module\n", - "\n", - "We need to define a `nn.Module` implementing the network we want the chip to reproduce." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "device: NVIDIA RTX A4000\n" - ] - } - ], - "source": [ - "if torch.cuda.is_available():\n", - " device = torch.device('cuda:0')\n", - " print('device: ', torch.cuda.get_device_name(0))\n", - "else:\n", - " device = torch.device('cpu')" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [], - "source": [ - "class SNN(nn.Module):\n", - " def __init__(self) -> None:\n", - " super().__init__()\n", - "\n", - " self.conv1 = nn.Conv2d(2, 10, 2, 1, bias=False)\n", - " self.iaf1 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - " self.pool1 = nn.AvgPool2d(2,2)\n", - " self.pool1a = nn.AvgPool2d(6,6)\n", - "\n", - " self.conv2 = nn.Conv2d(10, 10, 2, 1, bias=False)\n", - " self.iaf2 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - " self.pool2 = nn.AvgPool2d(3,3)\n", - "\n", - " self.conv3 = nn.Conv2d(10, 10, 3, 1, bias=False)\n", - " self.iaf3 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - " self.pool3 = nn.AvgPool2d(2,2)\n", - "\n", - " self.flat = nn.Flatten()\n", - "\n", - " self.fc1 = nn.Linear(810, 100, bias=False)\n", - " self.iaf4 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - "\n", - " self.fc2 = nn.Linear(100, 100, bias=False)\n", - " self.iaf5 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - "\n", - " self.fc3 = nn.Linear(100, 100, bias=False)\n", - " self.iaf6 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - "\n", - " self.fc4 = nn.Linear(100, 11, bias=False)\n", - " self.iaf7 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - "\n", - " self.merge_fc = sl.Merge()\n", - " self.merge_conv = sl.Merge()\n", - "\n", - " def detach_neuron_states(self):\n", - " for name, layer in self.named_modules():\n", - " if name != '':\n", - " if isinstance(layer, sl.StatefulLayer):\n", - " for name, buffer in layer.named_buffers():\n", - " buffer.detach_()\n", - "\n", - " def init_weights(self):\n", - " for name, layer in self.named_modules():\n", - " if isinstance(layer, nn.Conv2d) or isinstance(layer, nn.Linear):\n", - " nn.init.xavier_normal_(layer.weight.data)\n", - "\n", - " def forward(self, x):\n", - " \n", - " con1_out = self.conv1(x)\n", - " iaf1_out = self.iaf1(con1_out)\n", - " pool1_out = self.pool1(iaf1_out)\n", - " pool1a_out = self.pool1a(iaf1_out)\n", - "\n", - " conv2_out = self.conv2(pool1_out)\n", - " iaf2_out = self.iaf2(conv2_out)\n", - " pool2_out = self.pool2(iaf2_out)\n", - "\n", - " merged_conv_out = self.merge_conv(pool1a_out, pool2_out)\n", - "\n", - " conv3_out = self.conv3(merged_conv_out)\n", - " iaf3_out = self.iaf3(conv3_out)\n", - " pool3_out = self.pool3(iaf3_out)\n", - "\n", - " flat_out = self.flat(pool3_out)\n", - " \n", - " fc1_out = self.fc1(flat_out)\n", - " iaf4_out = self.iaf4(fc1_out)\n", - "\n", - " fc2_out = self.fc2(iaf4_out)\n", - " iaf5_out = self.iaf5(fc2_out)\n", - "\n", - " fc3_out = self.fc3(iaf5_out)\n", - " iaf6_out = self.iaf6(fc3_out)\n", - "\n", - " merge_fc_out = self.merge_fc(iaf4_out, iaf6_out)\n", - "\n", - " fc4_out = self.fc4(merge_fc_out)\n", - " iaf7_out = self.iaf7(fc4_out)\n", - "\n", - " return iaf7_out" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [], - "source": [ - "snn = SNN().to(device)" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [], - "source": [ - "snn.init_weights()" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [], - "source": [ - "optimizer = Adam(snn.parameters(), lr=lr, betas=(0.9, 0.999), eps=1e-8)\n", - "loss_fn = CrossEntropyLoss()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Define train and test" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [], - "source": [ - "def train(dataloader, model, loss_fn, optimizer, epochs, test_func, dataloader_test):\n", - " epochs_y = []\n", - " epochs_x = []\n", - " epochs_acc = []\n", - " model.train()\n", - "\n", - " for e in range(epochs):\n", - " losses = []\n", - " batches = []\n", - " batch_count = 0\n", - " train_p_bar = tqdm(snn_train_dataloader)\n", - "\n", - " for X, y in train_p_bar:\n", - " # reshape the input from [Batch, Time, Channel, Height, Width] into [Batch*Time, Channel, Height, Width]\n", - " X = X.reshape(-1, 2, 128, 128).to(dtype=torch.float, device=device)\n", - " y = y.to(dtype=torch.long, device=device)\n", - "\n", - " # forward\n", - " pred = model(X)\n", - "\n", - " # reshape the output from [Batch*Time,num_classes] into [Batch, Time, num_classes]\n", - " pred = pred.reshape(batch_size, n_time_steps, -1)\n", - "\n", - " # accumulate all time-steps output for final prediction\n", - " pred = pred.sum(dim = 1)\n", - " loss = loss_fn(pred, y)\n", - "\n", - " # gradient update\n", - " optimizer.zero_grad()\n", - " loss.backward()\n", - " optimizer.step()\n", - "\n", - " # detach the neuron states and activations from current computation graph(necessary)\n", - " model.detach_neuron_states()\n", - "\n", - " train_p_bar.set_description(f\"Epoch {e} - BPTT Training Loss: {round(loss.item(), 4)}\")\n", - "\n", - " batch_count += 1\n", - " losses.append(loss.item())\n", - " batches.append(batch_count)\n", - "\n", - " epochs_y.append(losses)\n", - " epochs_x.append(batches)\n", - "\n", - " acc = test_func(dataloader_test, model)\n", - " print(f'Epoch {e} accuracy: {acc}')\n", - " epochs_acc.append(acc)\n", - "\n", - " return epochs_x, epochs_y, epochs_acc\n" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [], - "source": [ - "def test(dataloader, model):\n", - " correct_predictions = []\n", - " with torch.no_grad():\n", - " test_p_bar = tqdm(dataloader)\n", - " for X, y in test_p_bar:\n", - " # reshape the input from [Batch, Time, Channel, Height, Width] into [Batch*Time, Channel, Height, Width]\n", - " X = X.reshape(-1, 2, 128, 128).to(dtype=torch.float, device=device)\n", - " y = y.to(dtype=torch.long, device=device)\n", - "\n", - " # forward\n", - " output = model(X)\n", - "\n", - " # reshape the output from [Batch*Time,num_classes] into [Batch, Time, num_classes]\n", - " output = output.reshape(batch_size, n_time_steps, -1)\n", - "\n", - " # accumulate all time-steps output for final prediction\n", - " output = output.sum(dim=1)\n", - "\n", - " # calculate accuracy\n", - " pred = output.argmax(dim=1, keepdim=True)\n", - "\n", - " # compute the total correct predictions\n", - " correct_predictions.append(pred.eq(y.view_as(pred)))\n", - "\n", - " test_p_bar.set_description(f\"Testing Model...\")\n", - " \n", - " correct_predictions = torch.cat(correct_predictions)\n", - " return correct_predictions.sum().item()/(len(correct_predictions))*100" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Training loop (HPO)" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "81911e3a7aa94b6299e5943b8f751b65", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - " 0%| | 0/359 [00:00" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "y_avg = []\n", - "for y in epochs_y:\n", - " y_avg.append(np.mean(y))\n", - "\n", - "plt.plot(np.arange(len(epochs_x)), y_avg, marker = '.')\n", - "plt.xlabel('epoch')\n", - "plt.ylabel('average loss')\n", - "plt.ylim(0,)\n", - "plt.xticks(np.arange(len(epochs_x)))\n", - "for i, txt in enumerate(y_avg):\n", - " if i%5 == 0:\n", - " plt.text(i, txt, f'{txt:.2f}', ha='center', va='bottom', color = 'k')\n", - " else:\n", - " pass\n", - "plt.show()" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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JkzArFmzNN5AAEhNTcWIESOwYcMG1KhRQ7FdKpXit99+w8qVK9G1a1e0bNkS/v7++Pfff3Hp0qUyaQsRERG9WdQOOzNmzIC+vj6ioqJgYmKi2D506FAcPXpUo43L5+Pjgz59+qB79+5K20NCQpCTk6O03cPDAy4uLggICCjyeFlZWUhOTlZ6ERERkXZSebmIfMePH8exY8fg5OSktL1u3bpl8uj5zp07ceXKFQQFBRV4LzY2FgYGBqhevbrSdjs7O8TGxhZ5TD8/P3z99deabioRERFVQmr37KSlpSn16ORLTExUWgldEx4/foxp06Zh+/btMDIy0thxfX19IZVKFa/Hjx9r7NhERERUuagddt566y3FchEAIJFIIJfLsXz5cnTp0kWjjQsJCUF8fDxatGgBPT096Onp4dy5c/j555+hp6cHOzs7ZGdnIykpSalcXFwc7O3tizyuoaEhzM3NlV5ERESkndS+jbV8+XJ069YNwcHByM7Oxpw5c3Dr1i0kJibi4sWLGm1ct27dcOPGDaVt48aNg4eHB+bOnQtnZ2fo6+vj1KlTGDRoEAAgLCwMUVFRivl/iIiIqGpTO+x4enri3r17WL16NczMzJCamoqBAwfCx8cHDg4OGm2cmZkZPD09lbaZmprCyspKsX3ChAmYOXMmLC0tYW5ujk8//RReXl5o166dRttCREREbya1w05UVBScnZ3x+eefF/qei4uLRhqmqh9++AE6OjoYNGgQsrKy0KNHD/z666/l2gYiIiKqvCRCCKFOAV1dXcTExMDW1lZp+/Pnz2FrawuZTKbRBpaH5ORkWFhYQCqVcvwOERHRG0LV67faA5SFEJBIJAW2p6amavSJKSIiIiJNUPk21syZMwHkPX21YMECpcfPZTIZAgMD0axZM403kIiIiKg0VA47V69eBZDXs3Pjxg0YGBgo3jMwMEDTpk3x2Wefab6FRERERKWgctg5c+YMgLxHv3/66SeObSEiIqI3gtpPY/n7+5dFO4iIiIjKhNoDlImIiIjeJAw7REREpNUYdoiIiEirMewQERGRVmPYISIiIq3GsENERERajWGHiIiItBrDDhEREWk1hh0iIiLSagw7REREpNUYdoiIiEirMewQERGRVmPYISIiIq3GsENERERajWGHiIiItBrDDhEREWk1hh0iIiLSagw7REREpNUYdoiIiEirMewQERGRVmPYISIiIq3GsENERERajWGHiIiItBrDDhEREWk1hh0iIiLSagw7REREpNUYdoiIiEirMewQERGRVmPYISIiIq3GsENERERajWGHiIiItBrDDhEREWk1hh0iIiLSagw7REREpNUYdoiIiEirMewQERGRVmPYISIiIq3GsENERERajWGHiIiItBrDDhEREWk1hh0iIiLSagw7REREpNUYdoiIiEirMewQERGRVmPYISIiIq3GsENERERajWGHiIiItBrDDhEREWk1hh0iIiLSagw7REREpNUYdoiIiEirMewQERGRVmPYISIiIq3GsENERERajWGHiIiItBrDDhEREWk1hh0iIiLSagw7REREpNUqddjx8/ND69atYWZmBltbW/Tv3x9hYWFK+2RmZsLHxwdWVlaoVq0aBg0ahLi4uApqMREREVU2lTrsnDt3Dj4+Prh06RJOnDiBnJwceHt7Iy0tTbHPjBkzcPDgQezZswfnzp3D06dPMXDgwApsNREREVUmEiGEqOhGqOrZs2ewtbXFuXPn0KlTJ0ilUtjY2OD333/H+++/DwC4e/cuGjRogICAALRr106l4yYnJ8PCwgJSqRTm5uZleQpERESkIapevyt1z86rpFIpAMDS0hIAEBISgpycHHTv3l2xj4eHB1xcXBAQEFDkcbKyspCcnKz0IiIiIu30xoQduVyO6dOno0OHDvD09AQAxMbGwsDAANWrV1fa187ODrGxsUUey8/PDxYWFoqXs7NzWTadiIiIKtAbE3Z8fHxw8+ZN7Ny5s9TH8vX1hVQqVbweP36sgRYSERFRZaRX0Q1QxZQpU3Do0CGcP38eTk5Oiu329vbIzs5GUlKSUu9OXFwc7O3tizyeoaEhDA0Ny7LJREREVElU6p4dIQSmTJmCffv24fTp03B3d1d6v2XLltDX18epU6cU28LCwhAVFQUvL6/ybi4RERFVQpW6Z8fHxwe///47/vrrL5iZmSnG4VhYWMDY2BgWFhaYMGECZs6cCUtLS5ibm+PTTz+Fl5eXyk9iERERkXar1I+eSySSQrf7+/tj7NixAPImFZw1axZ27NiBrKws9OjRA7/++muxt7FexUfPiYiI3jyqXr8rddgpLww7REREbx6tnGeHiIiISF0MO0RERKTVGHaIiIhIqzHsEBERkVZj2CEiIiKtxrBDREREWo1hh4iIiLQaww4RERFpNYYdIiIi0moMO0RERKTVGHaIiIhIqzHsEBERkVZj2CEiIiKtxrBDREREWo1hh4iIiLQaww4RERFpNYYdIiIi0moMO0RERKTVGHaIiIhIqzHsEBERkVZj2CEiIiKtxrBDREREWo1hh4iIiLQaww4RERFpNYYdIiIi0moMO0RERKTVGHaIiIhIqzHsEBERkVZj2CEiIiKtxrBDREREWo1hh4iIiLQaww4RERFpNYYdIiIi0moMO0RERKTVGHaIiIhIqzHsEBERkVZj2CEiIiKtxrBDREREWo1hh4iIiLQaww4RERFpNYYdIiIi0moMO0RERKTVGHaIiIhIqzHsEBERkVZj2CEiIiKtxrBDREREWo1hh4iIiLQaww4RERFpNYYdIiIi0moMO0RERKTVGHaIiIhIqzHsEBERkVZj2CEiIiKtxrBDREREWo1hh4iIiLQaww4RERFpNYYdIiIi0moMO0RERKTVGHaIiIhIqzHsEBERkVZj2CEiIiKtxrBDREREWo1hh4iIiLSa1oSdX375BW5ubjAyMkLbtm1x+fLlim4SERERVQJaEXZ27dqFmTNn4quvvsKVK1fQtGlT9OjRA/Hx8RXdNCIiIqpgWhF2Vq5ciYkTJ2LcuHFo2LAh1q5dCxMTE2zcuLGim0ZEREQVTK+iG1Ba2dnZCAkJga+vr2Kbjo4OunfvjoCAgELLZGVlISsrS/GzVCoFACQnJ5dtY4mIiEhj8q/bQohi93vjw05CQgJkMhns7OyUttvZ2eHu3buFlvHz88PXX39dYLuzs3OZtJGIiIjKTkpKCiwsLIp8/40PO6/D19cXM2fOVPwsl8uRmJgIKysrSCQSjdWTnJwMZ2dnPH78GObm5uVannWXf92lLc+6q1bdpS3Puln3m1K+tHUXRwiBlJQUODo6FrvfGx92rK2toauri7i4OKXtcXFxsLe3L7SMoaEhDA0NlbZVr169rJoIc3PzUv0Dl6Y86y7/uktbnnVXrbpLW551s+43pXxp6y5KcT06+d74AcoGBgZo2bIlTp06pdgml8tx6tQpeHl5VWDLiIiIqDJ443t2AGDmzJkYM2YMWrVqhTZt2uDHH39EWloaxo0bV9FNIyIiogqmFWFn6NChePbsGb788kvExsaiWbNmOHr0aIFBy+XN0NAQX331VYFbZuVRnnWXf92lLc+6q1bdpS3Puln3m1K+tHVrgkSU9LwWERER0RvsjR+zQ0RERFQchh0iIiLSagw7REREpNUYdoiIiEirMeyUoV9++QVubm4wMjJC27ZtcfnyZZXKnT9/Hn379oWjoyMkEgn279+vcp1+fn5o3bo1zMzMYGtri/79+yMsLEzl8mvWrEGTJk0Ukz95eXnhyJEjKpd/2dKlSyGRSDB9+nSV9l+4cCEkEonSy8PDQ+X6oqOjMXLkSFhZWcHY2BiNGzdGcHCwSmXd3NwK1C2RSODj41NiWZlMhgULFsDd3R3GxsaoXbs2Fi1aVOJaLS9LSUnB9OnT4erqCmNjY7Rv3x5BQUEF9ivpsyGEwJdffgkHBwcYGxuje/fuCA8PV7n83r174e3trZhNPDQ0VOX6c3JyMHfuXDRu3BimpqZwdHTE6NGj8fTpU5XqXrhwITw8PGBqaooaNWqge/fuCAwMVLntL5s8eTIkEgl+/PFHlcqOHTu2wL99z5491ar7zp07eO+992BhYQFTU1O0bt0aUVFRJZYt7HMnkUjw3XffqVR3amoqpkyZAicnJxgbGysWQ1albFxcHMaOHQtHR0eYmJigZ8+eis+LKt8lmZmZ8PHxgZWVFapVq4ZBgwYpJnhVpfz69evx9ttvw9zcHBKJBElJSYr3SiqfmJiITz/9FPXr14exsTFcXFwwdepUSKVSler+6KOPULt2bRgbG8PGxgb9+vVTLDGkzveoEAK9evVS/H5VKfv2228X+PeePHmyWnUHBASga9euMDU1hbm5OTp16oRvvvmm2LIPHz4s8vO2Z88eleqOjY3FqFGjYG9vD1NTU7Ro0QJ//vmnSmUjIyMxYMAA2NjYwNzcHEOGDCkwIXBZYdgpI7t27cLMmTPx1Vdf4cqVK2jatCl69OiB+Pj4EsumpaWhadOm+OWXX9Su99y5c/Dx8cGlS5dw4sQJ5OTkwNvbG2lpaSqVd3JywtKlSxESEoLg4GB07doV/fr1w61bt9RqR1BQENatW4cmTZqoVa5Ro0aIiYlRvC5cuKBSuRcvXqBDhw7Q19fHkSNHcPv2baxYsQI1atRQub0v13vixAkAwODBg0ssu2zZMqxZswarV6/GnTt3sGzZMixfvhyrVq1SqW4A+PDDD3HixAls3boVN27cgLe3N7p3747o6Gil/Ur6bCxfvhw///wz1q5di8DAQJiamqJHjx7IzMxUqXxaWho6duyIZcuWFfl+UeXT09Nx5coVLFiwAFeuXMHevXsRFhaG9957T6W669Wrh9WrV+PGjRu4cOEC3Nzc4O3tjWfPnqlUPt++fftw6dIlpenjVSnbs2dPpc/Ajh07VC4fGRmJjh07wsPDA2fPnsX169exYMECGBkZlVj25TpjYmKwceNGSCQSDBo0SKW6Z86ciaNHj2Lbtm24c+cOpk+fjilTpuDAgQPFlhVCoH///rh//z7++usvXL16Fa6urujevTvS0tJU+i6ZMWMGDh48iD179uDcuXN4+vQpBg4cCEC176L09HT07NkT8+fPL9C+kso/ffoUT58+xffff4+bN29i06ZNOHr0KCZMmKBS3S1btoS/vz/u3LmDY8eOQQgBb29vyGQytb5Hf/zxR6VlhlQtO3HiRKV/9+XLl6tcPiAgAD179oS3tzcuX76MoKAgTJkyBRcuXCi2rLOzc4HP29dff41q1aqhV69eKtU9evRohIWF4cCBA7hx4wYGDhyIIUOG4ODBg8WWTUtLg7e3NyQSCU6fPo2LFy8iOzsbffv2hVwuL/B71ThBZaJNmzbCx8dH8bNMJhOOjo7Cz89PreMAEPv27XvtdsTHxwsA4ty5c699jBo1aoj/+7//U3n/lJQUUbduXXHixAnRuXNnMW3aNJXKffXVV6Jp06av1ca5c+eKjh07vlbZwkybNk3Url1byOXyEvft06ePGD9+vNK2gQMHihEjRqhUV3p6utDV1RWHDh1S2t6iRQvx+eefF1nu1c+GXC4X9vb24rvvvlNsS0pKEoaGhmLHjh0lln/ZgwcPBABx9epVlesvzOXLlwUA8ejRI7XLSqVSAUCcPHlS5bqfPHkiatasKW7evClcXV3FDz/8oFLZMWPGiH79+hXbnuLKDx06VIwcOfK1yr6qX79+omvXriqXb9Sokfjmm2+UthX22Xm1bFhYmAAgbt68qdgmk8mEjY2N2LBhQ4G6X/0uSUpKEvr6+mLPnj2Kfe7cuSMAiICAgBLLv+zMmTMCgHjx4kWh511S+Xy7d+8WBgYGIicnR+2y165dEwBERESEynVfvXpV1KxZU8TExBT5b1tYWXW+Fwsr37ZtW/HFF1+8VtlXNWvWrMD3V3HlTU1NxZYtW5T2s7S0LPCZebXssWPHhI6OjpBKpYp9kpKShEQiESdOnCjxXEqLPTtlIDs7GyEhIejevbtim46ODrp3746AgIBybYtUKgUAWFpaql1WJpNh586dSEtLU2vpDR8fH/Tp00fp/FUVHh4OR0dH1KpVCyNGjEBUVJRK5Q4cOIBWrVph8ODBsLW1RfPmzbFhwwa16wfy/v22bduG8ePHq7QwbPv27XHq1Cncu3cPAHDt2jVcuHABvXr1Uqm+3NxcyGQyGBkZKW03NjZWuWcLAB48eIDY2Fil37uFhQXatm1b7p+7fFKpFBKJRO2157Kzs7F+/XpYWFigadOmKpWRy+UYNWoUZs+ejUaNGqnd1rNnz8LW1hb169fHxx9/jOfPn6tc7+HDh1GvXj306NEDtra2aNu2rVq3n/PFxcXh8OHDmDBhgspl2rdvjwMHDiA6OhpCCJw5cwb37t2Dt7d3seWysrIAQOlzp6OjA0NDw0I/d69+l4SEhCAnJ0fp8+bh4QEXF5dCP2+l+S5StbxUKoW5uTn09PQKbC+ubFpaGvz9/eHu7g5nZ2eV6k5PT8fw4cPxyy+/FLkOY3F1b9++HdbW1vD09ISvry/S09NVKh8fH4/AwEDY2tqiffv2sLOzQ+fOnVX6N3tVSEgIQkNDi/y8FVa+ffv22LVrFxITEyGXy7Fz505kZmbi7bffLrZsVlYWJBKJ0sSCRkZG0NHRUet77rWVeZyqgqKjowUA8e+//yptnz17tmjTpo1ax0IpenZkMpno06eP6NChg1rlrl+/LkxNTYWurq6wsLAQhw8fVrnsjh07hKenp8jIyBBCqPcXzN9//y12794trl27Jo4ePSq8vLyEi4uLSE5OLrGsoaGhMDQ0FL6+vuLKlSti3bp1wsjISGzatEnltufbtWuX0NXVFdHR0SrtL5PJxNy5c4VEIhF6enpCIpGIJUuWqFWnl5eX6Ny5s4iOjha5ubli69atQkdHR9SrV6/IMq9+Ni5evCgAiKdPnyrtN3jwYDFkyJASy79MEz07GRkZokWLFmL48OEqlz148KAwNTUVEolEODo6isuXL6tc95IlS8Q777yj6I1Tp2dnx44d4q+//hLXr18X+/btEw0aNBCtW7cWubm5JZbP/6vexMRErFy5Uly9elX4+fkJiUQizp49q9J551u2bJmoUaOG4v8fVdqemZkpRo8eLQAIPT09YWBgIDZv3lxi2ezsbOHi4iIGDx4sEhMTRVZWlli6dKkAILy9vZXKFvZdsn37dmFgYFCgntatW4s5c+aUWP5lJfXsqPJd9uzZM+Hi4iLmz5+vctlffvlFmJqaCgCifv36hfbqFFV+0qRJYsKECYqfC/u3KarsunXrxNGjR8X169fFtm3bRM2aNcWAAQNUqjsgIEAAEJaWlmLjxo3iypUrYvr06cLAwEDcu3dPpfPO9/HHH4sGDRoU+l5R5V+8eCG8vb0Vnzdzc3Nx7NixEsvGx8cLc3NzMW3aNJGWliZSU1PFlClTBAAxadKkItuoKQw7ZaCyhJ3JkycLV1dX8fjxY7XKZWVlifDwcBEcHCzmzZsnrK2txa1bt0osFxUVJWxtbcW1a9cU29QJO6968eKFMDc3V+kWmr6+vvDy8lLa9umnn4p27dqpXa+3t7d49913Vd5/x44dwsnJSezYsUNcv35dbNmyRVhaWqoVtCIiIkSnTp0EAKGrqytat24tRowYITw8PIosU5nDTnZ2tujbt69o3ry5Urd1SWVTU1NFeHi4CAgIEOPHjxdubm4iLi6uxPLBwcHCzs5OKaCqE3ZeFRkZqfIttPz/3z/44AOl/fr27SuGDRumVt3169cXU6ZMKfL9wsp/9913ol69euLAgQPi2rVrYtWqVaJatWoFbg0UVjY4OFg0bdpU8bnr0aOH6NWrl+jZs6fSfoV9l6gTdkr6Liop7JRUXiqVijZt2oiePXuK7OxslcsmJSWJe/fuiXPnzom+ffuKFi1aFAiahZX/66+/RJ06dURKSopiW2G/X1W/g0+dOlXoLbTCyuf/f+7r66u0b+PGjcW8efNUrjs9PV1YWFiI77//vtD3iyo/ZcoU0aZNG3Hy5EkRGhoqFi5cKCwsLMT169dLLHvs2DFRq1YtIZFIhK6urhg5cqRo0aKFmDx5cjG/Hc1g2CkDWVlZQldXt8AHf/To0eK9995T61ivG3Z8fHyEk5OTuH//vtplX9WtWzeVkve+ffsUX5r5LwCKD3ZhfyWXpFWrVkr/AxfFxcVF6a8sIYT49ddfhaOjo1r1PXz4UOjo6Ij9+/erXMbJyUmsXr1aaduiRYtE/fr11apbiLyLfX5YGTJkiOjdu3eR+7762ci/QL8aUDp16iSmTp1aYvmXlSbsZGdni/79+4smTZqIhIQEtcq+qk6dOoX2kr1a/ocfflB8zl7+7Ono6AhXV9fXqtva2lqsXbu2xLqzsrKEnp6eWLRokdJ+c+bMEe3bt1e57vPnzwsAIjQ0tMg2vVo+PT1d6OvrFxjvNWHCBNGjRw+V605KShLx8fFCiLzxhp988onivaK+S/Iv0K8GFBcXF7Fy5coSy7+suLBTUvnk5GTh5eUlunXrViCoqPM9mJWVJUxMTMTvv/9eYvlp06YV+Xnr3Lmz2nWnpqYKAOLo0aMl1n3//n0BQGzdulVp+5AhQxS9qKrUvWXLFqGvr6/4d39ZUeUjIiIKjPMSIu8a8dFHH6lc97NnzxT/1nZ2dmL58uVF7qspHLNTBgwMDNCyZUucOnVKsU0ul+PUqVNqjX15HUIITJkyBfv27cPp06fh7u5e6mPK5XLF/f3idOvWDTdu3EBoaKji1apVK4wYMQKhoaHQ1dVVq97U1FRERkbCwcGhxH07dOhQ4DHHe/fuwdXVVa06/f39YWtriz59+qhcJj09HTo6yv8r6erqvtYTBqampnBwcMCLFy9w7Ngx9OvXT+Wy7u7usLe3V/rcJScnIzAwsMw/d/lycnIwZMgQhIeH4+TJk7CysirV8VT97I0aNQrXr19X+uw5Ojpi9uzZOHbsmNr1PnnyBM+fP1fps2dgYIDWrVuX+vP322+/oWXLliqPUQLyft85OTml/vxZWFjAxsYG4eHhCA4ORr9+/Ur8LmnZsiX09fWVPm9hYWGIioqCl5dXqb+LVCmfnJwMb29vGBgY4MCBA4rxR69Tt8j74x9ZWVkllp83b16BzxsA/PDDD9i4caPadeeXd3BwKLFuNzc3ODo6Fvp5c3FxUbnu3377De+99x5sbGyUfgfFlc8fV1TY500mk6lct7W1NapXr47Tp08jPj5e8cRmmSrzOFVF7dy5UxgaGopNmzaJ27dvi0mTJonq1auL2NjYEsumpKSIq1eviqtXrwoAinEArz7RUpiPP/5YWFhYiLNnz4qYmBjFKz09XaV2z5s3T5w7d048ePBAXL9+XcybN09IJBJx/Phxlcq/Sp3bWLNmzRJnz54VDx48EBcvXhTdu3cX1tbWhf7l8arLly8LPT09sXjxYhEeHi62b98uTExMxLZt21Ruq0wmEy4uLmLu3LkqlxEi70memjVrikOHDokHDx6IvXv3Cmtr6wJd+cU5evSoOHLkiLh//744fvy4aNq0qWjbtm2BLvmSPhtLly4V1atXV4w/6devn3B3d1f8xVtS+efPn4urV6+Kw4cPCwBi586d4urVqyImJqbE8tnZ2eK9994TTk5OIjQ0VOnzl5WVVWzZ1NRU4evrKwICAsTDhw9FcHCwGDdunDA0NFT8Fanu/xcv38YqrmxKSor47LPPREBAgHjw4IE4efKkaNGihahbt67IzMxUqe69e/cKfX19sX79ehEeHi5WrVoldHV1xT///KNSu6VSqTAxMRFr1qwpcB4lle/cubNo1KiROHPmjLh//77w9/cXRkZG4tdffy2x7O7du8WZM2dEZGSk2L9/v3B1dRUDBw4UQqj2XTJ58mTh4uIiTp8+LYKDg4WXl5fidrIq5WNiYsTVq1fFhg0bBABx/vx5cfXqVfH8+fMSy0ulUtG2bVvRuHFjERERobTP5MmTiy0bGRkplixZIoKDg8WjR4/ExYsXRd++fYWlpaWIi4t7re9R/K/nrKSyERER4ptvvhHBwcHiwYMH4q+//hK1atUSnTp1Uvn39sMPPwhzc3OxZ88eER4eLr744gthZGQkhg8frlK7w8PDhUQiEUeOHFHaXlLd2dnZok6dOuKtt94SgYGBIiIiQnz//fdCIpGI3r17l1j3xo0bRUBAgIiIiBBbt24VlpaWYubMmUX+TjWJYacMrVq1Sri4uAgDAwPRpk0bcenSJZXK5XfpvvoaM2ZMiWULKwdA+Pv7q1T3+PHjhaurqzAwMBA2NjaiW7durx10hFAv7AwdOlQ4ODgIAwMDUbNmTTF06NBCBwwW5eDBg8LT01MYGhoKDw8PsX79erXaeuzYMQFAhIWFqVUuOTlZTJs2Tbi4uAgjIyNRq1Yt8fnnn4usrCyVj7Fr1y5Rq1YtYWBgIOzt7YWPj49ISkoqsF9Jnw25XC4WLFgg7OzshKGhoejWrZvS+ZRU3t/fv9D3v/rqqxLL59/6Kux15syZYstmZGSIAQMGCEdHR2FgYCAcHBzEe++9pzRAWd3/L14OO8WVTU9PF97e3sLGxkbo6+sLV1dXMXHiRKU/TFSp+7fffhN16tQRRkZGomnTpopboaqUXbdunTA2Nn6tf/OYmBgxduxY4ejoKIyMjET9+vXFihUrhFwuL7HsTz/9JJycnIS+vr5wcXERX3zxheJzq8p3SUZGhvjkk09EjRo1hImJiRgwYIAiGKtS/quvvipyn5LKF3Vuxb3yy0ZHR4tevXoJW1tboa+vL5ycnMTw4cPF3bt3VW77q/LDTkllo6KiRKdOnYSlpaUwNDQUderUEbNnz1aMbVO1bj8/P+Hk5CRMTEyEl5eX+Oeff1Qu6+vrK5ydnYVMJitwDiWVv3fvnhg4cKCwtbUVJiYmokmTJmLLli0qlZ07d66ws7MT+vr6om7duorPaXmQ/O8EiYiIiLQSx+wQERGRVmPYISIiIq3GsENERERajWGHiIiItBrDDhEREWk1hh0iIiLSagw7REREpNUYdoiIXnH27FlIJBIkJSVVdFOISAMYdoiIiEirMewQERGRVmPYIaJKRy6Xw8/PD+7u7jA2NkbTpk3xxx9/APjvFtPhw4fRpEkTGBkZoV27drh586bSMf788080atQIhoaGcHNzw4oVK5Tez8rKwty5c+Hs7AxDQ0PUqVMHv/32m9I+ISEhaNWqFUxMTNC+ffsCK00T0ZuBYYeIKh0/Pz9s2bIFa9euxa1btzBjxgyMHDkS586dU+wze/ZsrFixAkFBQbCxsUHfvn2Rk5MDIC+kDBkyBMOGDcONGzewcOFCLFiwAJs2bVKUHz16NHbs2IGff/4Zd+7cwbp161CtWjWldnz++edYsWIFgoODoaenh/Hjx5fL+RORZnEhUCKqVLKysmBpaYmTJ0/Cy8tLsf3DDz9Eeno6Jk2ahC5dumDnzp0YOnQoACAxMRFOTk7YtGkThgwZghEjRuDZs2c4fvy4ovycOXNw+PBh3Lp1C/fu3UP9+vVx4sQJdO/evUAbzp49iy5duuDkyZPo1q0bAODvv/9Gnz59kJGRASMjozL+LRCRJrFnh4gqlYiICKSnp+Odd95BtWrVFK8tW7YgMjJSsd/LQcjS0hL169fHnTt3AAB37txBhw4dlI7boUMHhIeHQyaTITQ0FLq6uujcuXOxbWnSpInivx0cHAAA8fHxpT5HIipfehXdACKil6WmpgIADh8+jJo1ayq9Z2hoqBR4XpexsbFK++nr6yv+WyKRAMgbT0REbxb27BBRpdKwYUMYGhoiKioKderUUXo5Ozsr9rt06ZLiv1+8eIF79+6hQYMGAIAGDRrg4sWLSse9ePEi6tWrB11dXTRu3BhyuVxpDBARaS/27BBRpWJmZobPPvsMM2bMgFwuR8eOHSGVSnHx4kWYm5vD1dUVAPDNN9/AysoKdnZ2+Pzzz2FtbY3+/fsDAGbNmoXWrVtj0aJFGDp0KAICArB69Wr8+uuvAAA3NzeMGTMG48ePx88//4ymTZvi0aNHiI+Px5AhQyrq1ImojDDsEFGls2jRItjY2MDPzw/3799H9erV0aJFC8yfP19xG2np0qWYNm0awsPD0axZMxw8eBAGBgYAgBYtWmD37t348ssvsWjRIjg4OOCbb77B2LFjFXWsWbMG8+fPxyeffILnz5/DxcUF8+fPr4jTJaIyxqexiOiNkv+k1IsXL1C9evWKbg4RvQE4ZoeIiIi0GsMOERERaTXexiIiIiKtxp4dIiIi0moMO0RERKTVGHaIiIhIqzHsEBERkVZj2CEiIiKtxrBDREREWo1hh4iIiLQaww4RERFpNYYdIiIi0mr/DyhqLZkmhFwSAAAAAElFTkSuQmCC", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "plt.plot(np.arange(len(epochs_x)), epochs_acc, marker = '.')\n", - "plt.xlabel('epoch')\n", - "plt.ylabel('test accuracy')\n", - "plt.ylim(0, 100)\n", - "plt.xticks(np.arange(len(epochs_x)))\n", - "for i, txt in enumerate(epochs_acc):\n", - " if i%5 == 0:\n", - " plt.text(i, txt, f'{txt:.2f}', ha='center', va='bottom', color = 'k')\n", - " else:\n", - " pass\n", - "plt.show()" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [], - "source": [ - "with open('nonseq_exp_set_B_training_metrics.npy', 'wb') as f:\n", - " np.save(f, np.array(epochs_x))\n", - " np.save(f, np.array(epochs_y))\n", - " np.save(f, np.array(epochs_acc))" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "speck-rescnn", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.3" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/tests/test_nonsequential/exp_set_B1/baseline-SCNN-example_3.ipynb b/tests/test_nonsequential/exp_set_B1/baseline-SCNN-example_3.ipynb deleted file mode 100644 index 2eb99dfc..00000000 --- a/tests/test_nonsequential/exp_set_B1/baseline-SCNN-example_3.ipynb +++ /dev/null @@ -1,1071 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "import torch, random\n", - "import torch.nn as nn\n", - "import sinabs.layers as sl\n", - "from tqdm.notebook import tqdm\n", - "\n", - "from tonic.datasets.dvsgesture import DVSGesture\n", - "from tonic.transforms import ToFrame\n", - "from torch.utils.data import DataLoader\n", - "from torch.nn import CrossEntropyLoss\n", - "from torch.optim import Adam\n", - "\n", - "from sinabs.activation.surrogate_gradient_fn import PeriodicExponential\n", - "\n", - "import matplotlib.pyplot as plt\n", - "import numpy as np" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "torch.backends.cudnn.deterministic = True\n", - "random.seed(1)\n", - "torch.manual_seed(1)\n", - "torch.cuda.manual_seed(1)\n", - "np.random.seed(1)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Loading Data" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "batch_size = 3\n", - "num_workers = 1\n", - "epochs = 30\n", - "lr = 5e-4" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "root_dir = \"../DVSGESTURE\"\n", - "_ = DVSGesture(save_to=root_dir, train=True)\n", - "_ = DVSGesture(save_to=root_dir, train=False)" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "n_time_steps = 50\n", - "to_raster = ToFrame(sensor_size=DVSGesture.sensor_size, n_time_bins=n_time_steps)\n", - "\n", - "snn_train_dataset = DVSGesture(save_to=root_dir, train=True, transform=to_raster)\n", - "snn_test_dataset = DVSGesture(save_to=root_dir, train=False, transform=to_raster)" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The transformed array is in shape [Time-Step, Channel, Height, Width] --> (50, 2, 128, 128)\n" - ] - } - ], - "source": [ - "sample_data, label = snn_train_dataset[0]\n", - "print(f\"The transformed array is in shape [Time-Step, Channel, Height, Width] --> {sample_data.shape}\")" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [], - "source": [ - "snn_train_dataloader = DataLoader(snn_train_dataset, batch_size=batch_size, num_workers=num_workers, drop_last=True, shuffle=True)\n", - "snn_test_dataloader = DataLoader(snn_test_dataset, batch_size=batch_size, num_workers=num_workers, drop_last=True, shuffle=False)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Network Module\n", - "\n", - "We need to define a `nn.Module` implementing the network we want the chip to reproduce." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "device: NVIDIA GeForce RTX 3070 Ti\n" - ] - } - ], - "source": [ - "if torch.cuda.is_available():\n", - " device = torch.device('cuda:0')\n", - " print('device: ', torch.cuda.get_device_name(0))\n", - "else:\n", - " device = torch.device('cpu')" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [], - "source": [ - "class SNN(nn.Module):\n", - " def __init__(self) -> None:\n", - " super().__init__()\n", - "\n", - " self.conv1 = nn.Conv2d(2, 10, 2, 1, bias=False)\n", - " self.iaf1 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential(), spike_threshold=0.5)\n", - " self.pool1 = nn.AvgPool2d(2,2)\n", - "\n", - " self.conv2 = nn.Conv2d(10, 10, 2, 1, bias=False)\n", - " self.iaf2 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential(), spike_threshold=0.5)\n", - " self.pool2 = nn.AvgPool2d(3,3)\n", - "\n", - " self.conv3 = nn.Conv2d(10, 10, 3, 1, bias=False)\n", - " self.iaf3 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential(), spike_threshold=0.5)\n", - " self.pool3 = nn.AvgPool2d(2,2)\n", - "\n", - " self.flat = nn.Flatten()\n", - "\n", - " self.fc1 = nn.Linear(810, 100, bias=False)\n", - " self.iaf4 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential(), spike_threshold=0.5)\n", - "\n", - " self.fc2 = nn.Linear(100, 100, bias=False)\n", - " self.iaf5 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential(), spike_threshold=0.5)\n", - "\n", - " self.fc3 = nn.Linear(100, 100, bias=False)\n", - " self.iaf6 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential(), spike_threshold=0.5)\n", - "\n", - " self.fc4 = nn.Linear(100, 11, bias=False)\n", - " self.iaf7 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential(), spike_threshold=0.5)\n", - "\n", - " def detach_neuron_states(self):\n", - " for name, layer in self.named_modules():\n", - " if name != '':\n", - " if isinstance(layer, sl.StatefulLayer):\n", - " for name, buffer in layer.named_buffers():\n", - " buffer.detach_()\n", - "\n", - " def init_weights(self):\n", - " for name, layer in self.named_modules():\n", - " if isinstance(layer, nn.Conv2d) or isinstance(layer, nn.Linear):\n", - " nn.init.xavier_normal_(layer.weight.data)\n", - "\n", - " def forward(self, x):\n", - " \n", - " con1_out = self.conv1(x)\n", - " iaf1_out = self.iaf1(con1_out)\n", - " pool1_out = self.pool1(iaf1_out)\n", - "\n", - " conv2_out = self.conv2(pool1_out)\n", - " iaf2_out = self.iaf2(conv2_out)\n", - " pool2_out = self.pool2(iaf2_out)\n", - "\n", - " conv3_out = self.conv3(pool2_out)\n", - " iaf3_out = self.iaf3(conv3_out)\n", - " pool3_out = self.pool3(iaf3_out)\n", - "\n", - " flat_out = self.flat(pool3_out)\n", - " \n", - " fc1_out = self.fc1(flat_out)\n", - " iaf4_out = self.iaf4(fc1_out)\n", - "\n", - " fc2_out = self.fc2(iaf4_out)\n", - " iaf5_out = self.iaf5(fc2_out)\n", - "\n", - " fc3_out = self.fc3(iaf5_out)\n", - " iaf6_out = self.iaf6(fc3_out)\n", - "\n", - " fc4_out = self.fc4(iaf6_out)\n", - " iaf7_out = self.iaf7(fc4_out)\n", - "\n", - " return iaf7_out" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [], - "source": [ - "snn = SNN().to(device)" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [], - "source": [ - "snn.init_weights()" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [], - "source": [ - "optimizer = Adam(snn.parameters(), lr=lr, betas=(0.9, 0.999), eps=1e-8)\n", - "loss_fn = CrossEntropyLoss()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Define train and test" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [], - "source": [ - "def train(dataloader, model, loss_fn, optimizer, epochs, test_func, dataloader_test):\n", - " epochs_y = []\n", - " epochs_x = []\n", - " epochs_acc = []\n", - " model.train()\n", - "\n", - " for e in range(epochs):\n", - " losses = []\n", - " batches = []\n", - " batch_count = 0\n", - " train_p_bar = tqdm(snn_train_dataloader)\n", - "\n", - " for X, y in train_p_bar:\n", - " # reshape the input from [Batch, Time, Channel, Height, Width] into [Batch*Time, Channel, Height, Width]\n", - " X = X.reshape(-1, 2, 128, 128).to(dtype=torch.float, device=device)\n", - " y = y.to(dtype=torch.long, device=device)\n", - "\n", - " # forward\n", - " pred = model(X)\n", - "\n", - " # reshape the output from [Batch*Time,num_classes] into [Batch, Time, num_classes]\n", - " pred = pred.reshape(batch_size, n_time_steps, -1)\n", - "\n", - " # accumulate all time-steps output for final prediction\n", - " pred = pred.sum(dim = 1)\n", - " loss = loss_fn(pred, y)\n", - "\n", - " # gradient update\n", - " optimizer.zero_grad()\n", - " loss.backward()\n", - " optimizer.step()\n", - "\n", - " # detach the neuron states and activations from current computation graph(necessary)\n", - " model.detach_neuron_states()\n", - "\n", - " train_p_bar.set_description(f\"Epoch {e} - BPTT Training Loss: {round(loss.item(), 4)}\")\n", - "\n", - " batch_count += 1\n", - " losses.append(loss.item())\n", - " batches.append(batch_count)\n", - "\n", - " epochs_y.append(losses)\n", - " epochs_x.append(batches)\n", - "\n", - " acc = test_func(dataloader_test, model)\n", - " print(f'Epoch {e} accuracy: {acc}')\n", - " epochs_acc.append(acc)\n", - "\n", - " return epochs_x, epochs_y, epochs_acc\n" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [], - "source": [ - "def test(dataloader, model):\n", - " correct_predictions = []\n", - " with torch.no_grad():\n", - " test_p_bar = tqdm(dataloader)\n", - " for X, y in test_p_bar:\n", - " # reshape the input from [Batch, Time, Channel, Height, Width] into [Batch*Time, Channel, Height, Width]\n", - " X = X.reshape(-1, 2, 128, 128).to(dtype=torch.float, device=device)\n", - " y = y.to(dtype=torch.long, device=device)\n", - "\n", - " # forward\n", - " output = model(X)\n", - "\n", - " # reshape the output from [Batch*Time,num_classes] into [Batch, Time, num_classes]\n", - " output = output.reshape(batch_size, n_time_steps, -1)\n", - "\n", - " # accumulate all time-steps output for final prediction\n", - " output = output.sum(dim=1)\n", - "\n", - " # calculate accuracy\n", - " pred = output.argmax(dim=1, keepdim=True)\n", - "\n", - " # compute the total correct predictions\n", - " correct_predictions.append(pred.eq(y.view_as(pred)))\n", - "\n", - " test_p_bar.set_description(f\"Testing Model...\")\n", - " \n", - " correct_predictions = torch.cat(correct_predictions)\n", - " return correct_predictions.sum().item()/(len(correct_predictions))*100" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Training loop" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "7c174908d3784728bf9706cd7683230e", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - " 0%| | 0/359 [00:00" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "y_avg = []\n", - "for y in epochs_y:\n", - " y_avg.append(np.mean(y))\n", - "\n", - "plt.plot(np.arange(len(epochs_x)), y_avg, marker = '.')\n", - "plt.xlabel('epoch')\n", - "plt.ylabel('average loss')\n", - "plt.ylim(0,)\n", - "plt.xticks(np.arange(len(epochs_x)))\n", - "for i, txt in enumerate(y_avg):\n", - " if i%2 == 0:\n", - " pass\n", - " else:\n", - " plt.text(i, txt, f'{txt:.2f}', ha='center', va='bottom', color = 'k')\n", - "plt.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjsAAAG2CAYAAACZEEfAAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy81sbWrAAAACXBIWXMAAA9hAAAPYQGoP6dpAAB7hklEQVR4nO3deXhM1/8H8PdkskeE7DNJJEESBLEWsRdRVUupXe2qpSXUvrSqJGiptoryU2uLllhqj5bYiSVEBCEhEYkIyWTfz++PfDM1ss2QiIz363nmaXPvPcuNY+7HuWeRCCEEiIiIiLSUTkVXgIiIiKg8MdghIiIircZgh4iIiLQagx0iIiLSagx2iIiISKsx2CEiIiKtxmCHiIiItBqDHSIiItJqDHaIiIhIqzHYISIiIq1WocHOyZMn0aNHD8jlckgkEuzZs0flvBAC8+fPh1wuh5GRETp06ICQkBCVazIzM/HFF1/A0tISJiYm6NmzJx4+fPga74KIiIjeZBUa7KSmpsLDwwMrV64s8vzSpUuxfPlyrFy5EoGBgbC1tUWXLl2QnJysvMbb2xu7d+/G9u3bcfr0aaSkpOCDDz5Abm7u67oNIiIieoNJ3pSNQCUSCXbv3o3evXsDyO/Vkcvl8Pb2xowZMwDk9+LY2NhgyZIlGDduHBQKBaysrLBlyxYMGDAAAPDo0SM4ODjg4MGD6Nq1a0XdDhEREb0hdCu6AsWJiIhAbGwsvLy8lMcMDAzQvn17nD17FuPGjcPly5eRnZ2tco1cLkf9+vVx9uzZYoOdzMxMZGZmKn/Oy8vDs2fPYGFhAYlEUn43RURERGVGCIHk5GTI5XLo6BT/suqNDXZiY2MBADY2NirHbWxs8ODBA+U1+vr6qF69eqFrCtIXxdfXF998800Z15iIiIgqQlRUFOzt7Ys9/8YGOwVe7GkRQpTa+1LaNbNmzcKUKVOUPysUCtSoUQNRUVGoWrXqq1WYiIiIXoukpCQ4ODjA1NS0xOve2GDH1tYWQH7vjUwmUx6Pi4tT9vbY2toiKysLCQkJKr07cXFx8PT0LDZvAwMDGBgYFDpetWpVBjtERESVTGmdIG/sOjvOzs6wtbWFv7+/8lhWVhYCAgKUgUzTpk2hp6enck1MTAxu3LhRYrBDREREb48K7dlJSUnB3bt3lT9HREQgKCgI5ubmqFGjBry9veHj4wMXFxe4uLjAx8cHxsbGGDx4MADAzMwMo0ePxpdffgkLCwuYm5tj6tSpaNCgATp37lxRt0VERERvkAoNdi5duoSOHTsqfy4YRzN8+HBs3LgR06dPR3p6OsaPH4+EhAS0aNECR48eVXk398MPP0BXVxf9+/dHeno6OnXqhI0bN0Iqlb72+yEiIqI3zxuzzk5FSkpKgpmZGRQKBcfsEBERVRLqPr/f2DE7RERERGWBwQ4RERFpNQY7REREpNUY7BAREZFWY7BDREREWo3BDhEREWk1BjtERESk1RjsEBERkVZjsENERERajcEOERERaTUGO0RERKTVGOwQERGRVmOwQ0RERFqNwQ4RERFpNQY7REREpNUY7BAREZFWY7BDREREWo3BDhEREWk1BjtERESk1RjsEBERkVZjsENERERajcEOERERaTUGO0RERKTVGOwQERGRVmOwQ0RERFqNwQ4RERFpNQY7REREpNUY7BAREZFWY7BDREREWo3BDhEREWk1BjtERESk1RjsEBERkVZjsENERERajcEOERERaTUGO0RERKTVGOwQERGRVmOwQ0RERFqNwQ4RERFpNQY7REREpNUY7BAREZFWY7BDREREWo3BDhEREWk1BjtERESk1RjsEBERkVZjsENERERajcEOERERaTUGO0RERKTVGOwQERGRVmOwQ0RERFqNwQ4RERFpNQY7REREpNUY7BAREZFWY7BDREREWo3BDhERERWSk5ODuXPnwtnZGUZGRqhZsyYWLFiAvLw85TVCCMyfPx9yuRxGRkbo0KEDQkJCSszXz88PzZo1Q7Vq1WBiYoJGjRphy5Ytha5btWoVnJ2dYWhoiKZNm+LUqVMvfS8MdoiIiKiQJUuWYM2aNVi5ciVCQ0OxdOlSfPfdd/j555+V1yxduhTLly/HypUrERgYCFtbW3Tp0gXJycnF5mtubo45c+bg3LlzuH79OkaOHImRI0fiyJEjymt27NgBb29vzJkzB1evXkXbtm3RrVs3REZGvtS9SIQQ4qVSapGkpCSYmZlBoVCgatWqFV0dIiKiCvfBBx/AxsYG69evVx7r27cvjI2NsWXLFgghIJfL4e3tjRkzZgAAMjMzYWNjgyVLlmDcuHFql9WkSRN0794d3377LQCgRYsWaNKkCVavXq28pm7duujduzd8fX2Vx9R9frNnh4iIiApp06YN/vnnH9y5cwcAcO3aNZw+fRrvv/8+ACAiIgKxsbHw8vJSpjEwMED79u1x9uxZtcoQQuCff/7B7du30a5dOwBAVlYWLl++rJIvAHh5eamd74t0XyoVERERabUZM2ZAoVCgTp06kEqlyM3NxaJFizBo0CAAQGxsLADAxsZGJZ2NjQ0ePHhQYt4KhQJ2dnbIzMyEVCrFqlWr0KVLFwBAfHw8cnNzi8y3oExNsWeHiIioBE5OTpBIJIU+EyZMAAA8fvwYI0aMgFwuh7GxMd577z2EhYWVmGdISAj69u2rzHvFihUal1veduzYga1bt+KPP/7AlStXsGnTJnz//ffYtGmTynUSiUTlZyFEoWMvMjU1RVBQEAIDA7Fo0SJMmTIFJ06ceOV8i8Ngh4iIqASBgYGIiYlRfvz9/QEA/fr1gxACvXv3Rnh4OPbu3YurV6/C0dERnTt3RmpqarF5pqWloWbNmli8eDFsbW2LLdfe3r7Q8VWrVikDnpSUFHz++eewt7eHkZER6tatqzLOpSgdOnQoMojq3r278prk5GSMHTsWqampGDlyJMaNG4c6depg8uTJyjEzBfV+sbclLi6uUK/Mi3R0dFC7dm00atQIX375JT766CNlvpaWlpBKpS+Vb7HlvVQqIiJ6a8Uo0nH2XjxiFOkVXZXXwsrKCra2tsrP/v37UatWLbRv3x5hYWE4f/48Vq9ejebNm8PNzQ2rVq1CSkoKtm3bVmyezZs3x3fffYeBAwfCwMCg2HKvXLmiDLLGjBkDmUwGID/QAoDJkyfj8OHD2Lp1K0JDQzF58mR88cUX2Lt3b7Fl+/n5qQRvN27cgFQqVeYJAGPGjEF6ejpGjBiB4OBgeHl5KQO4gqnnzs7OsLW1VQZ/QP54m4CAAHh6eqr/C0Z+r01mZiYAQF9fH02bNlXJFwD8/f01zvf5At56CoVCABAKhaKiq0JE9EbbfvGBcJ65XzjO2C+cZ+4X2y8+qOgqvVaZmZnCwsJCLFq0SAghxPXr1wUAcffuXZXrbG1txfDhw9XK09HRUfzwww9qlevp6Slq1aol8vLyhBBCuLu7iwULFqhc26RJEzF37lz1bkgI8cMPPwhTU1ORkpIihBAiLS1NSKVS0alTJ2FnZyf2798vIiIihJOTkzA2NhbTp09Xpl28eLEwMzMTfn5+Ijg4WAwaNEjIZDKRlJSkvObjjz8WM2fOVP7s4+Mjjh49Ku7duydCQ0PFsmXLhK6urli3bp3ymu3btws9PT2xfv16cfPmTeHt7S1MTEzE/fv3Vequ7vObA5SJiEgtMYp0zPILRt7/FizJE8Bsvxto52oFmZlRxVbuNdmzZw8SExMxYsQIAECdOnXg6OiIWbNm4ddff4WJiQmWL1+O2NhYxMTElGm5CQkJCA0NxdSpU5VjV9q0aYN9+/Zh1KhRkMvlOHHiBO7cuYMff/xR7bzXr1+PgQMHwsTEBED+YoK5ubmYNGkS/vnnH4wfPx5xcXEQQsDGxkY5PRwApk+fjvT0dIwfPx4JCQlo0aIFjh49ClNTU+U1kZGR0NH570VSamoqxo8fj4cPH8LIyAh16tTB1q1bMWDAAOU1AwYMwNOnT7FgwQLExMSgfv36OHjwIBwdHV/uF6h26FcBsrOzxZw5c4STk5MwNDQUzs7O4ptvvhG5ubnKa/Ly8sTXX38tZDKZMDQ0FO3btxc3btzQqBz27BARle7M3SfCccb+Qp+zd+PLvWxHR0cBoNBn/PjxQghR5DkAYunSpSXmm5CQIMaPHy9sbW2FgYGBqFOnjjhw4IDy/Ndff10oT319fZU8Ll26JDw8PAQAIZVKRdeuXUW3bt1Et27d1L630np2vLy8RJMmTYRUKhXR0dHK45mZmWLYsGECgNDV1RX6+vpi8+bNapUrhBAXLlwQAMSFCxdUjrdq1Uq0b99eREdHi5ycHLFlyxYhkUiEq6ur2nkXeJSYJs7cfSIeJaZpnLY0WtGzU7B646ZNm+Du7o5Lly5h5MiRMDMzw6RJkwD8t3rjxo0b4erqioULF6JLly64ffu2SmRJRESvxtnSBBLkP/Gfdz8+Fa1qWZRr2YGBgcjNzVX+fOPGDXTp0kU5zuTFXpRDhw5h9OjR6Nu3b7F5ZmVloUuXLrC2tsbOnTthb2+PqKioQs8Od3d3HDt2DFFRUWjZsiXWrVuncr5p06YICgqCQqFAVlYWrKys0KJFCzRr1uxVbxsA8ODBAxw7dgwNGzZEt27dIJfLled++uknnD9/Hvv27YOjoyNOnjyJ8ePHQyaToXPnzqXmvX79etSvXx/vvPOOyvEtW7Zg1KhRsLOzg1QqRZMmTTB48GBcuXJFo7rvCIxU9gbqSADfPg0woHkNjfIoC290sHPu3Dn06tVLOULcyckJ27Ztw6VLlwDkD2hasWIF5syZgz59+gAANm3aBBsbG/zxxx8ard5IREQls6xiADMjPSSmZwOAMvCZt/cGqhnroVsDWbmVbWVlpfLz4sWLlYOEARSa0bR371507NgRNWvWLDbP3377Dc+ePcPZs2ehp6cHAEW+JtHV1YWtrS3WrFkDa2trDB48uMj8zMzMAABhYWG4dOmSyuueV7FhwwZYWFjg+vXrmD9/vvJ4eno6Zs+ejd27dyufkw0bNkRQUBC+//77UoOdtLQ0bN++HQsWLCh0rlatWggICEBqaiqSkpIgk8kwYMAAODs7q13vN+m15xs9G6u8Vm/MzMxEUlKSyoeIiEpm5+CIa/O74sGSD/BgyQe4/7//Pj68Cp9vu4oD12MQGhqKnj17wszMDKampmjZsmWp+xmtWLECbm5uMDIygoODAyZPnoyMjAzl+eTkZHh7e8PR0RFGRkZo2bIlNm7ciFGjRhW57srjx49x4MABjB49usRy9+3bh1atWmHChAmwsbFB/fr14ePjo9KDBOQHLzKZDAsXLkS1atUK3c9ff/2FEydOKKefd+nSBb1791Z5Ng0bNgyzZs1S/pyVlYWgoCAEBQUhKysL0dHRCAoKwt27d1XyzsvLw4YNG+Dq6gpra2uV6eHZ2dnIzs5WGQ8DAFKpVGWzzuL8+eefyMzMxNChQ4u9xsTEBDKZDAkJCThy5Ah69epVar4FIp6kKgOdArlC4H58mtp5lJkyf4FWhvLy8sTMmTOFRCIRurq6QiKRCB8fH+X5M2fOCAAq7y+FEGLs2LHCy8ur2HyLegcLjtkhIipWTm6eaP31bmE/YYtYvOuciImJEf7+/gKA+GjeOuE4Y79w+PT/hKlZNTFt2jRx5coVce/ePbF//37x+PHjYvPdunWrMDAwEL///ruIiIgQR44cETKZTHh7eyuv6d+/v6hXr54ICAgQYWFh4qOPPhIAxKVLl4rMc8mSJaJ69eoiPT29xHtyc3MTBgYGYtSoUeLSpUti27ZtwtzcXHzzzTfKaw4ePCh27twp1qxZIwCI5s2bCxsbGxEf/984pR9//FHY29sLPT09UaNGDTF37lyRmZmpUlb79u1F/0FDlWNXIiIiinwOtW/fXiXdkSNHBAAhl8vFjBkzCt1D+/bthbu7uzh+/LgIDw8XGzZsEIaGhmLVqlXKa16cDVWgTZs2YsCAAUX+bg4fPiwOHTokwsPDxdGjR4WHh4d45513RFZWVom/0+fN3R1caHxXzZkHynTsjrpjdt7oYGfbtm3C3t5ebNu2TVy/fl1s3rxZmJubi40bNwoh/gt2Hj16pJJuzJgxomvXrsXmm5GRIRQKhfITFRXFYIeIqAR/X4sWjjP2i4bzj4jkjGwhhBCTJk0StWrVEtk5uWLKjiBhXKetMHHvKPZcfah2vhMmTBDvvvuuyrEpU6aINm3aCCH+mwa9f/9+5XkvLy9RtWpVMWfOnCLzdHNzE59//nmpZbu4uAgHBweRk5OjPLZs2TJha2tbbJqUlBRhY2Mjli1bVmr+z3uVKfsFAc/t27cLnYuJiREjRowQcrlcGBoaCjc3N7Fs2TLl1HQh8gOiF6fB3759WwAQR48eLbLMHTt2iJo1awp9fX1ha2srJkyYIBITE9Wu868Bd5UBjtPM/wKdsl6qQCsGKE+bNg0zZ87EwIEDAQANGjTAgwcP4Ovri+HDh6us3liw0BJQ+iqLBgYGxS7iREREqvLyBFb+m/96ZWRrJ1Qx0EVWVha2bt2KKVOmQFeqg8V96uPn4Zdh3OxDDOrTA/qJkXBzqYVZs2ahd+/exebdpk0bbN26FRcvXsQ777yD8PBwHDx4EMOHDwfw3zRoQ0NDAP8N1q1duzZOnz5dKL9Tp07h9u3b2LFjR6n3JZPJoKenB6lUqjxWt25dxMbGIisrC/r6+oXSmJiYoEGDBqVuB1EgKycPx27GYuauYOXAbk3Hrnh5eUGIF4eF57O1tcWGDRtKTH/ixAnlQpDOliaQmRnB1dW12DwBoH///ujfv3+pdSvKn5ei4HPwFgBgxnt10LuxHPfj0+BkaVxhSxS80cFOWlpaie8in1+9sXHjxgD+W71xyZIlr72+RETa6J9bcbgVm4wqBroY4ekEoPB6M0/jnyA7Iw1pgbtQpfVQGDmOhGuVR+jTpw+OHz+uHEj8ooEDB+LJkydo06YNhBDIycnBZ599hpkzZwLI30OpVatW+Pbbb1G3bl2sX78epqamyrGcL1q/fj2aNm0KDw+PUu+rdevW+OOPP5CXl6d81ty5cwcymazIQAfIH/MZGhqKtm3bFnleCIF7T1JwKiwep8PicT78KVKzcgtdVzB25XU8/F/njKjDN2Ixc9d1AMC4djXxWYdaAFDh6zC90cFOjx49sGjRItSoUQPu7u64evUqli9fjlGjRgHI3yTM29sbPj4+cHFxgYuLC3x8fGBsbFzsaHkiIlKfEAIrj+f36gxt6YhqxvlBwPr161WmQRf8I7Tvhx/Cqd8X2HYxCqclNdGkzSWsWbOm2GDnxIkTWLRoEVatWoUWLVrg7t27mDRpEmQyGebNmwdAdRo0kN+b8cEHHxSaBp2UlIS//voLy5YtK7KsYcOGwc7OTrkH02effYaff/4ZkyZNwhdffIGwsDD4+Phg4sSJyjRTp05Fjx49UKNGDcTFxWHu198gIVGBbh/+twBefEomztyNVwY4sUkZKuVWe24GWwEJACdL42J+62WnqBlRs/yCy2VG1Nm78Zi47SryBDCgmQNmdqtTpvm/ijc62Pn5558xb9485eqNcrkc48aNw1dffaW8Rp3VG4mI6OWcvhuPa1GJMNTTwZi2+dOOC14l+fn5Ka+ztLSErq4u3N3rYXbvBtCRSPD7hUiEZZkh+Wbxr3zmzZuHjz/+GGPGjAGQP1whNTUVn3zyCebMmQMdHR3lNOh9+/ahV69eCAgIwLx58wpNg96+fTuEEBg0aFCRZb24kq+DgwOOHj2KyZMno2HDhrCzs8OkSZMwY8YM5TUPHz7EoEGDEB8fjyrVzJFZvRbMBi5F/z/uol3tRMSlZCE0RnVGr76uDt5xMkcbF0u0qW2JerKq+OtyFGb73UDuc6+OHiakl3uPx+2Y5EIzovIEsObEPczv6f7Su4i/6FpUIsZuvoSs3Dy8526LRR/WL7O8y4JElPTS7i2RlJQEMzMzKBQKVK1ataKrQ0T0xhjw6zlciHiGka2d8HUPdwDA/Pnz8euvvyIqKgq6uv/9m9nT0xO1atXCli1bIITAV3tDsGz6WOjoGWD9xs1Fvjpp2rQpOnfurDL0YNu2bRg1ahRSUlJUxtMUSEhIgLOzM5YuXYpPPvlEo/uJUaQjIj5VOXblRbl5AglpWYhPyUR8cv5/nyRn4v7TVPx+ofgp9HVlVdHOxRJtXCzR3MkchnqF6x2jSMf9+FRsOvsAh0NiITMzxMGJbVHdpOhXZq9KCIFPt1zGkZuPizzf0c0K3/XzgGWVVxvDejcuGf3WnENCWjY8a1ngtxHNi7z/8qDu8/uN7tkhIqKKczHiGS5EPIOeVIJP2uUvzlew7svw4cNVAh0gf1LJgAED0K5dO3Ts2BHWUceRcS8Q1oN8MGNX/quUQyvnqrxK6tGjB5YvX47GjRsrX2PNmzcPPXv2VAY6R44cgRACbm5uuHv3LqZNmwY3NzeMHDlSo/t5fuyKBEAbF0tYVjFQBjTxKVl4lppZqCekJJ93rIXhns6wMi09YJCZGUFmZoSG9tVw5+dkhMenYupf1/B/w5uVSy/IhjP3ceTmY0gk+febJwCpBOjeUI7DIbE4fvsJ3ltxCsv7e6Cdq1Wp+RUlOjEdH6+/iIS0bHjYm2HtsGavLdDRBIMdIiIqUsFYnY+aOih7QY4dO4bIyEjl2Mnnffjhh1izZg18fX0xceJEuLm5wW/XTlyTumDDmfuY5RcMoxt3VF4lzZ07FxKJBHPnzkV0dDSsrKyU4zULKBQKzJo1Cw8fPoS5uTn69u2LRYsWKVc9VsfVyATM2BWs/FkAOBUWX+z15ib6sKyiD8sqBrCsYgAjPSn+vBSlslWGVCLBkJaOagU6zzMx0MXPgxvjw1Vn8c+tOPx25j5Gt1F/ZWJ1nA9/ikUHQwEA87rXQ7cGtiozom7FJmHitqu48zgFw367iLFtnTG1qxsMdNUPVOJTMvHx/11AjCIDta2rYMPId1DF4M0MK/gaC3yNRUT0ousPE9Fz5RlIdSQ4/mUH1LB4+cG0QggsPBCK9acjAABTvVzRxLF6sa+SypIiLRurTtzF+tMRyCmiy2bQOw5o6mgOyyr6sDI1gFUVA5ib6ENXWniDgR2BkcpxN1KJBD596r/SrKYt5+5j3t4Q6Ekl2PWZJxraV3vpvJ73KDEdPX4+jaepWejdSI4fBjQqsucoIzsXiw6EYsv5BwAAd3lV/DSoMWpZVSm1jOSMbAxadx43opNgV80IOz9rVSEzrtR9fjPYAYMdIqIXfbL5Eo7efIw+je2wfECjV85PCAGfg6FYdypCeaw8p0FnZOdi09n7+OX4XSRl5BR5jVQiwemZHTV6SOePuymbNWOEEBj/+xUcuhGLGubG2D+xDaoaqt9bVZSM7FwM+PUcrj1UoJ6sKnZ95gkj/ZJ7a/xvPsb0ndeQkJYNIz0p5vesh/7NHIp9tZaRnYsRGy7ifPgzWJjo469PW6GmGgFSeVD3+f1G741FRESv3+3YZBz931iP8R1rlUmeEokEI1s74fnHZ54AZuwKxrYLkcjMKbwWzcvIzRP481IUOn5/Ar6HbiEpIwduNqbYMKI5FvdpAOn/HuAFPTOaBiwyMyO0qmVRJr0YEokEi/s2hH11I0Q+S8Msv+ASF/orjRACX+8NwbWHClQz1sOvHzctNdABgC71bHBoUjt41rJAenYuZuwKxoQ/rkCRll3o2pzcPHz+x1WcD3+GKga62DTqnQoLdDTxZr5cIyKiCvPL/8bqdKtvi9rWZbeMx/2naSjqUT5rdzAWH76F7g1l+LCxHZrWqA4dHc0G7Aoh8O+tOCw5fAt3HqcAAORmhpji5YYPG9tB+r/82rtZVfhqvs8zM9LDz4Mao9+aczhwPQata1licIuX6+n642IkdlyKgo4E+GlgYziYq//q0dbMEFtHt8DaU+H4/shtHAyORVBkIlYMbIx3nM0B5K+kPWNXMI6FPoaBrg7+b3gz1Lcze6m6vm58jQW+xiIiKhARn4pOy04gTwAHJraBu7zsHmYxinS0XvyvymwnCQCLKvqIT8lSHrOvboTejezQu7EdaluX3mtwJTIBiw/ewsX7zwDkBxATOtbCsFZOb+TMoKKsOxmORQdDYaCrg72ft0YdW82eRZcfJGDg2nPIzhWY/p4bxneo/dJ1uRaViEnbr+L+0zToSIDP33VBv6Z28Dl4C4duxEKqI8GvQ5uic73it2V6XThmRwMMdoiI8k3feQ1/XnqITnWssX5E8zLPv6hBvh81dcD58KfYfTUah4JjVLZXaGhvht6N7NDDQ66c9VSwVo6ORIKNZ+7jcEgsAMBAVwcjWzvjs/a1YGb8amNfXre8PIHRmwJx/PYT1LIywd9ftIGxvnovX+KSM9Dj59N4nJSJ9xvY4pfBTV55KntKZg7m7wvBzssPC53r38weSz8qfTuO14HBjgYY7BARAQ8T0tDhuxPIyRPwG++JJjWql0s5JQ3yTc/KxbHQx9h9NRoBd54g93/dQFIdCdrUtoTMzBB/XopS6R3SkQAfNbWHd2dXyKtV/Kupl/UsNQvdfjyJx0mZ+KipPb7vV3pAkZWThyH/dx6B9xPgYl0Fuye0LtPp35vO3cfXe0NUjr3MwO7ywgHK9NYq2N03RpFe0VUhKnNOTk6QSCSFPhMmTEB2djZmzJiBBg0awMTEBHK5HMOGDcOjR49KzNPPzw/NmjVDbXtbhH/fB4rfJyMkYL/KNfPnzy9Upq2t7UvdQ0mDfI30pejhIcdvI5rj4uxO+KanOxo5VENunkDAnSfYHhhVaNG/LaNbYOlHHpU60AHy1/b5aWBj6EiAnZcfwu9K4V6VFy06cBOB9xNgaqCLXz9uWubr3LgU8RqxYBPTyoQDlEmr/HHhAebsvgGB8t/dl6giBAYGIjf3v9c8N27cQJcuXdCvXz+kpaXhypUrmDdvHjw8PJCQkABvb2/07NkTly5dKjZPc3NzfD55GuafSkS2kKKfdRxGjhwJa2trdO3aVXmdu7s7jh07pvy5qK0cypJFFQMM93TCcE8nRMSn4ud/wuB3NbrQdTpv0B5Mr6pFTQt4d3bFcv87mLvnBjwcqhW77s3Oyw+x6Vz+GjkrBjYql1lRzpYm0JFAJcCUSiSvZRPTssSeHdIaMYp0ZaAD5P/lnO13gz08pFWsrKxga2sLYWSG8FRd7Ni1B7Vq1UL79u1hZmYGf39/9O/fH25ubmjZsiV+/vlnXL58GZGRxe/r1KFDB0RXawBUs0fLRvXww4JZaNiwIU6fPq1yna6uLmxtbZUfK6uX22LgZThbmmDae254cZJWZXzwlmZCx9rwrGWBtKxcTPj9CjKyC0/LD36owOzd+StCT+rkgk51y2ewsMzMCL5lMGW/ojHYIa1xIfxZoWmtlbG7lag0OwIj0Xrxvxi05jR+27QFzbz6FDsgVaFQQCKRoFq1asXm9yw1S7nJ5YSOtfDvv//i9u3baNeuncp1YWFhkMvlcHZ2xsCBAxEeHl5m96QObXnwlkaqI8GKAY1gYaKPW7HJWHQgVOX805RMfLr1MrJy8tCpjjUmdXIp1/oMaF4Dp2d2xLaxLXF6ZsdK2VvO11ikFYQQ2B5Y9L9cZWaGr7k2ROUnRpGu3Mwy7c555GWk4JxOfcQo0gs99DMyMjBz5kwMHjy4xMGbG85EICU5CY9WjUDXZdmQSqVYtWoVunTporymRYsW2Lx5M1xdXfH48WMsXLgQnp6eCAkJgYWFRbnd74sGNK+Bdq5v1lo55cG6qiGWD2iE4b9dxJbzD+BZywLdGsiQk5uHL7ZdRXRiOpwtTbB8QCON1yR6GQWbmFZW7NkhrXD4RizOhz+DVCIp1M29zP/OK61KSm+mkgbqAvkB8Pz58yGXy2FkZIQOHTogJCSklFyBFStWwM3NDUZGRnBwcMDkyZORkZGhPL969Wo0bNgQVatWRdWqVdGqVSscOnSo3O7zRRHxqcrxEynXj8KoZlNIqljgt9MRKq87srOzMXDgQOTl5WHVqlXF5peUkY2NZ+9Dom+EtbuPITAwEIsWLcKUKVNw4sQJ5XXdunVD37590aBBA3Tu3BkHDhwAAGzatKlc7rMkZbmK8ZusvasVPuuQv4L19F3XcfnBM3jvCMLZe09hrC/Frx83hZlR5ZpiX1HYs0OVXkpmDub/nf8Qm9CxFga1qIH78WmIT8nA5B3X8Pe1R3C2MMYUL7cKrimVpZIG6gLA0qVLsXz5cmzcuBGurq5YuHAhunTpgtu3b8PUtOhVgX///XfMnDkTv/32Gzw9PXHnzh2MGDECAPDDDz8AAOzt7bF48WLUrp2/aNumTZvQq1cvXL16Fe7u7uV4x/luxSQBAHIUcch4cA1WH84GAKw7FYHdV6PxcUsnDGwmx6cjhyIiIgL//vtvib06W849QHJGDlxtqmLEe62goyNBo0aNEBoaCl9fX3To0KHIdCYmJmjQoAHCwsLK/B7pP1O6uOJC+FNciUxE39XnlMc/bGwHV5uyW91a27Fnhyq95Ufv4HFSJhwtjDG+Y23lv/p6eNjB58MGAICf/r2LXUUsjkWVV8FA3YLP/v37lQN1hRBYsWIF5syZgz59+qB+/frYtGkT0tLS8McffxSb57lz59C6dWsMHjwYTk5O8PLywqBBg1RmMvXo0QPvv/8+XF1d4erqikWLFqFKlSo4f/58ud/zzssP8e3/xm+kBPtDamwGk9rN0b2BDHbVjBCfkoXlR26iVosuOH05GP+3fU+Jr5jSsnKUO5FP6Fhb5XWIEAKZmZnFps3MzERoaChkMlkZ3R0VRU+qg7nd6xY6vv1iFCdfaIDBDlVqN6IV2Hg2Ag9Xj8LJ6e/CSF9X5ZVGwMbF+KxDLQghMNZ7BqxsbDV6pbFr1y7Uq1cPBgYGqFevHnbv3q1yPicnB3PnzoWzszOMjIxQs2ZNLFiwAHl5eeV1y8V6m9cXysrKwtatWzFq1ChIJBJEREQgNjYWXl5eymsMDAzQvn17nD17tth82rRpg8uXL+PixYsAgPDwcBw8eBDdu3dXue7FV2gJCQkYM2bMK79CK6m9/XkpClP/vIJnAVuQ8NtYKM5sg5FOLj6SBuLnQY1wYloHLP+oPjIPf4+MmDDodZ6EPqvOYPCPh3Hwwk2VwGXYsGGYNWsW/rgQiWepWZBc2wPDxzcQHh6OW7duYfny5di8eTOGDh2qTDN16lQEBAQgIiICFy5cwEcffYSkpCQMHz681PuiV5ORU/j7hJMvNCRIKBQKAUAoFIqKrgppICc3T/T8+ZRwnLFfjFp9TMTExCg//v7+AoA4fvy4yM3NEy0HfC4k+kbCsf88cTDgghgwYICQyWQiKSmp2PzPnj0rpFKp8PHxEaGhocLHx0fo6uqK8+fPK69ZuHChsLCwEPv37xcRERHir7/+ElWqVBErVqx4Hb8Cpe0XHwjnmfuF44z9wnnmfrH94oPXWn5F27Fjh5BKpSI6OloIIcSZM2cEAOXPBcaOHSu8vLxKzOunn34Senp6QldXVwAQn332WaFrTpw4IYyMjISOjo4wNTUVCxcuVLY3IYRYvHixMDU1Fbt27RLBwcGv3N62X3wgnGbuF9XafiyMTKuJb775RgAQP/74o0p7i4iIEACK/HhO/EnsC4oW2Tm5on379qLvgCHCY/4R4Thjv/hw5Oeidu3awtDQUFSvXl20atVKbN++XaV+Bfegp6cn5HK56NOnjwgJCSn1z4Ze3aPENOXf74JPzZkHxKPEtIquWoVT9/nN7SLA7SIqqy3nH2DenhswNdDFsS/bw6bqf7OuvL29sX//fuV4ArlcjuoteiOtzgdwsjDG9tHNUKemA5YsWYJx48YVmf+AAQOQlJSkMvj0vffeQ/Xq1bFt2zYAwAcffAAbGxusX79eeU3fvn1hbGyMLVu2lMdtF1LU5opv0nLur0PXrl2hr6+Pv//+GwBw9uxZtG7dGo8ePVJ5zTJ27FhERUXh8OHDReZz4sQJDBw4EAsXLkSLFi1w9+5dTJo0CWPHjsW8efOU12VlZSEyMhKJiYnYtWsXVqxYASsrKzx4kL/Am1wuh7e3N2bMmAEg/5WPjY3NS7W3pDwDPGryCQBA/5+laNOgFn777TflNSW1t7txKVh/OgJ+Vx4i83+9A3bVjNDIoRoOBscol2pY1Ls+hrR0LPF3TBWrqD3FKuMU8LLG7SJIq8UlZ2Dp4VsAgKld3VQCneJeaaycOgJ21Yxw/2kaJv55A23btSvxlca5c+dUXoMA+Q/V59O0adMG//zzD+7cuQMAuHbtGk6fPo3333+/LG+3RLdikgotn/82dXE/ePAAx44dw5gxY5THCrYxiI2NVbk2Li4ONjbFL742b948fPzxxxgzZgwaNGiADz/8ED4+PvD19VV5Namvr4/atWujWbNm+Oabb5CbmwtbW9tXeoVWVHuzcGuOixfyB6WObO2EkX3ew7///qt2e6ttXQW+fRrg7Mx34d3ZBeYm+ohOTMeB5wIdAPhqb8hb+fqzMtGGtW4qEmdjUaXkcyAUyRk5aGBnhqEv/It0z549SExMVM6iKXjg1anpgA0upui76iwu3n8G01Q9ZGXGvpi1UmxsbKEHo42NjcoDdMaMGVAoFKhTpw6kUilyc3OxaNEiDBo0qIzutGRCCPx+IarQcR0JtG5V2eJs2LAB1tbWKuNqnJ2dYWtrC39/fzRu3BhAfhAcEBCAJUuWFJtXWloadHRU/w0olUohhCh2+YI9e/YgJycHTk5OAP5rb0W1nYKen6K82N62nLuPoxEZyE1NwOg2zvmDVD+oh6SkJI3bm0UVA3h3dsWn7WvhuyO3lYOSCxQEx29LT2BlVdnXuqlI7NmhSufM3XjsCXoEHQng82EDSF9YWGf9+vXo1q0b5HK5ynGJRAJXG1P8MqQJpDoS3I9PQeSzkv81++KqtEIIlWM7duzA1q1b8ccff+DKlSvYtGkTvv/++9e29sj60xE4FvoYOhKorC9krC+FvlT7/3rn5eVhw4YNGD58OHR1//u3m0Qigbe3N3x8fLB7927cuHEDI0aMgLGxMQYPHqy8rmCgboEePXpg9erV2L59OyIiIuDv74958+ahZ8+eyn2gZs+ejVOnTuH+/fsIDg7GzJkz8wfAjx2rUrfS2k5RCs5vOnsf8/aGQAgBXZ382TgSieSV25uhnhRj2jq/FVsuED2PPTtUqWRk52LunhsAgGGtnNDA3kzlfMErDT8/P+Wx519pyGQytHO1woJe7hj7lwJReSbYGxSNXo3sCpVla2tb6muQadOmYebMmRg4cCAAoEGDBnjw4AF8fX3LfZbK2Xvx8D2U/yrvqw/qoWt9W9x5nIxv9t1EeHwqZvkF49ePm5b6gK3Mjh07hsjISIwaNarQuenTpyM9PR3jx49HQkICWrRogaNHj6qssRMZGanSkzN37lxIJBLMnTsX0dHRsLKyQo8ePbBo0SLlNY8fP8bHH3+MmJgYGJtUQWLCM3w5c45yteEX21uB0l6hFbS3305HYMH+mwCAFjJd3JDZKv8My6K9FWy58OL4D/YYkDbT/n/60WsVHR2NoUOHwsLCAsbGxmjUqBEuX76sPJ+SkoLPP/8c9vb2MDIyQt26dbF69eoS8wwJCUHfvn3h5OQEI31dXDv0B6xNDTDFy1V5TcEUcA8PD+Tl5cHb21s5Bfz5VxoF+jWWQcTchIFdXUz76zou3X9WqNxWrVqppAGAo0ePwtPTU/lzca89ynvqeXRiOj7/4ypy8wT6NLbDcE8nyMyM0N7VGisHN4GeVIKjNx/jr9e0tlBFTXv38vKCEAKurq6FzkkkEsyfPx8xMTHIyMhAQEAA6tevr3LNiRMn4PvjamXddXV18fXXX+Pu3btIT09HZGQkfvnlF1SrVg3ZuXl4nJSByQuWY+ORi5j4+0WIel0hNamOnXnvYNvF/O1KimpvBa/Qnm87L2rVqhV+27FXGeiM71ALeVHXyqW9cfwHvW3Ys0NlJiEhAa1bt0bHjh1x6NAhWFtb4969eyobEE6ePBnHjx/H1q1b4eTkhKNHj2L8+PGQy+Xo1atXkfmmpaWhZs2aaP9eD0yZPAUA8FWPeqhq+N8y6UuWLMHq1auhr6+PTz/9FJ06dcLIkSNhZmaGSZMmKV9puLi4wMXFBT4+PqhetQq8PuyHExEp+GTLZTjf2ADXmo7w9fUFAEyaNAnt2rXDkiVL0KtXL+zduxfHjh1T2Qm64F/9NWrUgLu7O65evYrly5cX2dNQVjKyc/HZ1st4lpoFd3lV+PRpoNJ7U09eFVO6uGHJ4VtY8PdNtKppAQfz8ntFsSMwUrlXk44E8O3ToNI8PJ+vu0QC9G1sD2crE8SnZCI+JQvxyZn/+/9MJKRlq6QVIg8pwcdgUr8TIJFill8wjtyIRed6Nhj+yfhC7a2oV2h2dnbK9ubc/iP8+flAVDN0xtih/ZEXtKdc2xvHf9DbhFPPwannZWXmzJk4c+YMTp06Vew19evXx4ABA1Sm8TZt2hTvv/8+vv3222LTCSEw7LeL2DalJxq/PxgX/1iu8oD/4IMPkJOTgyNHjuD27dtwdXVVmZIrhMA333yDX3/9VflK45dffkFN1zoY8Ot5BEcroPhrDrq1aog/tm5W5rtz507MnTsX4eHhqFWrFhYtWoQ+ffoozycnJ2PevHnYvXs34uLiIJfLMWjQIHz11VfQ19d/2V9lib+HaTuvY+flh6hurId9n7cpMpDJzRMYuPYcAu8n4B0nc2z7pGWhsU1loTJPe3+UmIbWi49Dky9AHUn+YF9DXR3cuXIGcX9+BfnYX6FnrvoaVAgBceUvPLt0EFlpyWj+zjv4dfUqlZ6lDh06wMnJCRs3bsSagHtYfOgWUm+dhuTyDiQ+fvhGtDeiN526z28GO2CwU1bq1auHrl274uHDhwgICICdnR3Gjx+vMnDz008/xeXLl7Fnzx7I5XKcOHECPXv2xKFDh9CmTZti89537REmbruK6DWjMGval1gwZ7rK+cWLF2PNmjU4evQoXF1dce3aNXh5eWHFihWlzlR5nJSB3r+cQYwiA01qVIN3Z1e42FTR6GEdHR2NGTNm4NChQ0hPT4erqyvWr1+Ppk2bAig8WLXA0qVLMW3atFLz3759OwYNGoQmbbvgqeck6EiAzaNa4NTOdfDz88OtW7dgZGQET09PLFmyBG5uboh6lob3VpxEalYuZnarg0/b11L7ftTld+Uhpvx5rdDxbWNbolWt17cTtqbSsnIwamMgzocXfn3ZztUS9WRmsKyiDytTA1hWKfjoo7qxPnR0JEUGeToSYHQbZ1yLUuBKZAJynjupIwEa2FdD29qWaONiiSY1qkNfVwcxinSsOBaGHYH5M+q8O7vAu3PhV3JEVDR1n998jUVlJjw8HKtXr8aUKVMwe/ZsXLx4ERMnToSBgQGGDRsGAPjpp58wduxY2NvbQ1dXFzo6Ovi///u/EgMdRXo2vv3fOIaqhnowNyn8L9hXmQJuU9UQv41ojl4rT+NKZCKG/XZRo9cx6ry+i4mJUUlz6NAhjB49Gn379i01/wcPHmDq1Klo3LwVbsUmwwrA9PfqoI2LJRYGBGDChAlo3rw5cnJyMGfOHHh5eeHmzZtwMDfB1z3cMX3XdSw7ehvtXKxQT152wfy9JylY9L99mp73pk97f5iQhk82X8bN/22o+TypRIIlfRuWGugWN8i3oL2kZObgQvhTnAqLx+m78bgbl4JrUYm4FpWIlcfvwlhfCofqRrj9OEWZZ5d6Ngx0iMoJgx0qM3l5eWjWrBl8fHwAAI0bN0ZISAhWr16tEuycP38e+/btg6OjI06ePInx48dDJpOhc+fORea77OhtPEnORE0rE9wzLLrJPj8l193dHUFBQfD29oZcLldrlko1Yz1kP/cv8TwBzNwVjGpGevByty1xRtOSJUvg4OCADRs2KI8VrLlSoGCGToG9e/eiY8eOqFmzZon1ys3NxZAhQ/DlzLlY9JsfBJLRvYEM49rlp3txJeCCNWcuX76Mdu3aoV8ze/iHPob/zceY8mcQ9kxoDUM9aYllquNuXAoGrTuPp6lZsKlqgCfJmcpeDicLE9g+t8jjm+R8+FOM//0KnqVmwcJEH/2a2WPdyYiXmpU0oHkNtHO1wv34NDhZGqukq2Kgi051bdCpbv7sqxhFOk7/L/A5HRaPp6lZKoEOAPwbGocYRfob//qPqDJisENlRiaToV69eirH6tati127dgEA0tPTMXv2bOzevVu5AFzDhg0RFBSE77//vshg51pUIracz1+IbWHv+hj8c9Flv+qU3Ij4VLz4QlcAGLf1ChzMjfBhIzv0amyHWlZVCqXdt28funbtin79+hX7+u55jx8/xoEDB9RaG2XBggWwsLTEaWlDZGTvRBUDXSz9qGGh4KvgNdqBAwcAAJ988gl+//13NG3aFL59GuBqZAKCb9xE4zbz8ejWZeTl5cHd3R1//vknatQovvcqMTERc+bMgZ+fHxISEuDs7Iwv532LNeHVEJ+Sicdrx+BBgur0/AcAelwajv3bN5Z6f6+LEAJbzj/Agr9vIidPoL5dVfz6cTPYVTPCcE+nIgMWdag7yFdmZoR+zRzQr5kD8vIEtgdGYvbuGyrXcGE/ovLDYIfKTOvWrXH79m2VY3fu3IGjY/4Kx9nZ2cjOzlZ76mxObh5m7w6GEMCHje3gWcuy2LJfdUqus6UJdCRQGYMhAWCop4OoZ+n46d+7+Onfu/CwN0Pvxnbo4SGHZRUDAOq9vnvepk2bYGpqqjLwtChnzpzB+vXr0d/nD/jdTICeVIJG8mowMVD9a/v8a7T69esjIyMDixcvVr5Gs6xigInNqmLkoulI8eiCn7buQVt3R4SGhsLQsPgemKysLHTp0gXW1tbYuXMn7O3tcebabSw8Eo40UyPUlVXF0SuXUNXwv56i+ZsO49eZI3G/akOkZ+XCSP/Ve5FeVWZOLr7aE4Idl/LHxfRqJMfiPg2VdXvds5J0dCToWMe6UHvjwn5E5YfBDpWZyZMnw9PTEz4+Pujfvz8uXryItWvXYu3atQCAqlWron379pg2bRqMjIzg6OiIgIAAbN68GcuXL1fmUzAl1/WDTxDyKAlV9AR62GchKCgIWVlZiI6ORlBQEKpUqYLatWsDePUpucWNwejpYYejN2Ox52o0TobF49pDBa49VGDhgVC0c7FE78Z2Kq/vYhTpaFDVAYOHXVN5ffe83377DUOGDCkx0EhOTsbQoUPx8TQfbLuZDIkEeMfZHEYis9C1Ba/RjI2NERUVhdOnT8Pe3l7lmoMbf0Ddd9ohpdUorA0R+LCLA7qX8grtt99+w7Nnz3D27Fno6enhdmwyll2TIM3UAfVkVfH7mBao/sL4Kd2HV2FgLkdydVf8evJehY9BiUvKwKdbL+NKZCJ0JMDMbnUwtm3NCl9okQv7Eb1enI0FzsYqS/v378esWbMQFhYGZ2dnTJkyReV1TmxsLGbNmoWjR4/i2bNncHR0xCeffILJkycrH0AdOnSAjdwBIS5DkZKZA+8WZpjcp22hstq3b48TJ04AKLspuTGK9GJfacSnZGL/tUfYHfQI16ISlccfrRkFtyaeGDBlEX47E4E8AaRcPYi8q7vwLE71Fc+pU6fQrl07BAUFwcPDo9h6BAUF5e/pJMnvrdKRSCBEfi+Vjo4Obt++jVq18mdX1atXD/r6+rhz5w6MjY3h4OCg8hotLy8PZmZm8J4yFSu37UdSdBis5Q5Y/d236N27d7F1eP/992Fubg5jY2P47d6DVB1jGNZpD88+I/H7WE9UM1b9vWZlZUEul+P9wWNw0rgtDHR18M+X7WFfvWJ6K65FJWLclsuITcpAVUNd/Dy4Cdq7WlVIXYpTUnsjotJx6rkGGOy8WWIU6fDeHoQLEc/QuEY17PrUEzrlsEbMqwh/koI9V6OxOygaVzYuQG7yE9gOWao8/+yfdciKuY2IkCsqD7ERI0bgxo0buHTpUon5P4xX4INv/0JcSiZa1rTA/B7u+OqreUhOTsaPP/4IV1dX6OvrQwgBPT095ObmYty4cRg3bhwuXrwIb29v/Prrrxg2bJhy2wJjY2OMmzIbO6KrIi38MhQnN+P48eNo3759kXWoU6cO7t+/j+4f9sMNs5Z49ugBFP/8iqlTvOHz7TeFrv/zzz8xePBgPHjwAFP2R+JCxDN0byDDL0OavORv+eXtuvwQs3YHIysnD7Wtq2DdsGZwtjR57fUgovKl7vOb20XQG2VHYCQ8F/+LCxH565+0c7F64wIdAKhpVQVTvNxwclpHrF48F1kxt6E49yeyEx4h9eYJpFw7jCqNu2P4bxfxg/8dXLr/DE8TEvHXX39hzJgxReZZsCllTm4epvrdRKKRDHXqumPjl33RsGEDVKtWDaampqhfv76yt2rChAnIzc2Fu7s75s+fD5lMhl69emHkyJHKbTgKxi316tULy7+dg0n9u8CsZT+YurbAip9/KfYe8/LyUN3CCnfdBiOzmhM8vXri66/mYsP/rS3y+oINWO3s7DC/pzt0JMCB4BicvRf/Kr9qjeTk5uHb/Tfx5V/XkJWTh851rbF7vCcDHaK3HIMdemPEKNIxyy9YZVbUyn/vvvb9ljQhkUgwrGdnbPx9B1JDA/Bo/QQkntmO6u+ORRX3jrjzOAU//hOGj9acQ4OPv0ZmTi5ETU/ce5KCFztVIyMjERMTg8WHbuF8+DOY6Evx68dNVbbFeFFBQBMSEgKZTKb8pKSkIDIyf68mS0tL6OrqKmfKeXd2RT1ZVaCaHc5eu12oHgWqmlshxcASiow8NHKohi1jWqBJw/qIjY1FVlaWyrUFG7AWBHJ1ZVUxpEX+wPQFf99ETm757hUGAIlpWRixIRDrT0cAACa+WxtrP24G0xJ+f0T0duAAZXpjRMSnqsxOASrPdNxhA/rCoGZzlQGn07q6opqxPk7djceZu/FIrO8F+/peWPJvFJb8GwW5mSHaulihjYslWte2xLa9h/D7+QdYefweAOD7fh5wsflvh+6NGzcWKlcIgcGDByMqKkplm47JkycrZ8Hp6+ujefPmyply+ro6WDGwEZqseoQUver442KkMjApEPxQgUg9B6Q/PY5G9lWxefQ7qGqohzt37kAmkxUaB1Wwvk/BkgIAMKWLK/6+/gi3YpPxx8VIDGvl9Eq/4+LEKNJx8k48fvznDh4lZsBYX4pl/TzQrYGs9MRE9FZgsENvjAfxaYWOVabpuMUtMjfwnRrIzRMIeaTIX1E3LB6XHyTgkSIDOy5FKadEP6+Dm5XaD+vSZsEB+esQDRgwAO3atUPHjh1x9PBhpN+7CKuBPli4PxSetSzx9ZTPYGdnh4HjZ+Dj9Reg3+A9SAL3wSZkO2IjbXAqLAw+Pj6YOHGiSvl5eXnYsGEDhg8fDl3d/75Sqpvo40svN8zbcwPLjt5Bj4byQrO3XtWOwEjM3BWs3N+quoketo1tiTq2HHtHRP/hAGVwgPKbIC45A++tOIVnqVmQIH9BvxeX4NcmaVk5uBjxDKfD4nH8dhzuPUlVOa8jAc7MfFftHq3SZsEB+VPJfX198fDhQ7i5ueHrr+fjzye2OBf+FO7yqnj0+0xYyewR02gUkjNy0NypOj6tm4s5M6YhKCgIdnZ2GD16NGbMmAGp9L/1c44ePYquXbsqN2B9Xm6eQPefTuFWbDKGtqyBhb0bvORvrLAYRTo8ff9V2chT098bEVVunI2lAQY7FUsIgTGbLuGfW3GoK6uKNUOb4FFixlszHffsvXgMXneh0PHXsZlmdGI63v3+BDJzVMfUvONkjg0jmxdawPBlnA9/ioFrz0NHAvz9RRu4y81eOU8hBCbvCMKeoEeFzr3pm5ASUdnhbCyqNLYHRuGfW3HQl+pgxYBGcLQwQataFm9FoAP8t3rz817X6zsdCZCVU3jwsG+fBmoHOtHR0Rg6dCgsLCxgbGyMRo0a4fLly8rzhzf/DMXmCbi/rC8a13ZA586dceFC4eDuRYmJiZgwYQJkMhkMDQ1Rt25dHDx4EDm5eZix67pKoKM49yceLPkACf+sqzSvPYno9eGYHapQD56mKnc0n/6eG9xsTUtJoX0qcjXdiPhUFNW1G5eciVrWhfcBe5E6O767urpi9apfMPvYY2SkZ0An4TS8vLxw9+5dWFkVvchfUVtVREVFQc/QGOO2XMY/t+KgI8nfRmT7wRNIvnYE+lbOaF377QmSiUh9DHaowuTk5mHyjiCkZeWiZU1zjGrtXNFVqjAl7aBdnoraE0yTXiV1dnwfPHgwACDONAzL/e8gwd4eSbu34fr16+jUqVOR+b64VQUAVLWUYdSmQFyNTISBrg5WDm6CVjVMsGd2Pyz/aRW2r10BV5u3L1gmotLxNRZVmF9PhuNKZCJMDXTxfT+PN3LxwNdJZmb02l/fFfQqSf+3VYemvUr79u1Ds2bN0K9fP1hbW6Nx48ZYt25dkdd+0q4m5Ka6uHtyLwxNTEvcLmPfvn1o1aoVJkyYABsbG7jVrYem/cbjyv2nMDPSw+9jWqBLPRtMmDABPXt8gInD+kBfl19nRFQ09uxQhbgRrcAP/ncAAN/0cq+w/ZPo1XqV1N3xff/+/Rg4cGD+7vQm1SHv/y3SdYr/Mw8PD8e///6LIUOG4JfNf2LGb0fxYN/PkGflYOfvP8PFxhTbt2/HlStXEBgY+Er3T0Taj8EOvXYZ2bnw3hGEnDyBbvVt8WFju4qu0ltPZmb0Uj1Kz+/4DgCNGzdGSEhIoR3fO3bsiKCgIDx58gRDp/nggZ8v5jSti80TvIrN19raGqNm+uLT368i19kTtb0SkXhhF1xsTBEVFYVJkybh6NGjJe4eT0QE8DUWVYClh2/jblwKrEwNsOjDBsrdzqnykclkym0oCtStW1e5VUUBExMT1K5dG61atcKhXX9AoiPF33/+jtNhRe+bJZPJYC53xMiNl5Vr/iwa8R7iHj9GVlYWLl++jLi4ODRt2hS6urrQ1dVFQEAAfvrpJ+jq6iI3N7fc7pmIKh8GO/Ranbkbj9/O5O9dtPSjhjAv4xV16fVq3bq1chuKAnfu3FFuVVEUVxtTmBpIIXKz8c3fIcguYt8sM6f6uBF6B5k5OfCqZ4Mto1sgOjJcuVVFp06dEBwcjKCgIOWnWbNmGDJkCIKCglQWPSQi4mssem0UadmY+tc1AMCQFjXQ0c26gmtEr6q0rSpSU1OxaNEi9OzZEzKZDE+fPsWqVauQlhAH58YdERaXgi3nHuDE2q9hZ2cHHx8fLDt6B1dMmiMvYwOsgrdh8siv8c/RwypbVRTs/v48ExMTWFhYFDpORMRgh16br/bdQIwiA04WxpjTvW5FV4fKQPPmzbF7927MmjULCxYsgLOzM1asWIEhQ4YAAKRSKW7duoVNmzYhPj4eFhYWaN68OU6dOoW7wgaz/ILxw7E7qBpxH5BIMGPXdfx56SF0q1ph4ncbcf6P5WjcyAN2dnaYNGkSZsyYUbE3TESVEreLALeLeB3+vvYIX2y7CqmOBDs/bYXGNapXdJWoguXmCfRceRohj5LwnrstHidl4GpUInQkwMLeDTC4hfbtiUZEZYvbRdAbI1aRgbl7bgAAJnSoxUCHAABSHQm+6ekOADgcEourUYkAgKEtHBnoEFGZYrBD5UoIgWk7r0GRno0Gdmb4opNLRVeJ3iB21QtPd//9QiRiFOkVUBsi0lYMdqhcbTn/AKfC4mGgq4MfBjSCnpRNjv4TEZ9a6FiuELgfn1YBtSEibcUnD5Wbu3Ep8DkYCgCY1a0OaquxsSS9XSpyx3ciensw2NEy8+fPh0QiUfnY2toqzz9+/BgjRoyAXC6HsbEx3nvvPYSFhamd//bt2yGRSNC7d2+V405OToXKdbExRfSBX9DWxRLDWjmV0R2SNnnVvbmIiNTBqedayN3dHceOHVP+XLDAmhACvXv3hp6eHvbu3YuqVati+fLl6Ny5M27evAkTE5MS833w4AGmTp2Ktm3bFjoXGBioXLV279WH+HrTETzeMRcmdVqjrYvVW7/JJxWvonZ8J6K3h8Y9OydOnCiHalBZ0tXVha2trfJjZWUFAAgLC8P58+exevVqNG/eHG5ubli1ahVSUlKwbdu2EvPMzc3FkCFD8M0336BmzZqFzltZWcHW1ha5BlWxOOAx0u5ehG41GQwcGmDJoVsccEolqogd34no7aFxsPPee++hVq1aWLhwIaKiosqjTvSKwsLCIJfL4ezsjIEDByI8PBwAkJmZCQAqGydKpVLo6+vj9OnTJea5YMECWFlZYfTo0cVeczcuGaM3XkJebjZSb55AlYZdIJFIOOCUiIgqlMbBzqNHjzBp0iT4+fnB2dkZXbt2xZ9//omsrKzyqB9pqEWLFti8eTOOHDmCdevWITY2Fp6ennj69Cnq1KkDR0dHzJo1CwkJCcjKysLixYsRGxuLmJiYYvM8c+YM1q9fj3Xr1hV5PiM7F8v976Dbj6dw63Ey0u6cR15GCkzqdwLAAadERFSxNA52zM3NMXHiRFy5cgWXLl2Cm5sbJkyYAJlMhokTJ+LatWvlUU9SU7du3dC3b180aNAAnTt3xoEDBwAAmzZtgp6eHnbt2oU7d+7A3NwcxsbGOHHiBLp161bsxonJyckYOnQo1q1bB0tLy0Lnz4c/xfs/ncJP/4QhO1fg3TrWsHp0BsY1m0HX1IIDTomIqMK98nYRjx49wtq1a7F48WLo6uoiIyMDrVq1wpo1a+Du7l5W9SxX2r5dRJcuXVC7dm2sXr1aeUyhUCArKwtWVlZo0aIFmjVrhl9++aVQ2qCgIDRu3FglGMrL+98u1RIdyMasgV51GSyrGGB+z3qoXzULtWrVwv9t2YY6LTpxwCkREZWbct0uIjs7Gzt37sT7778PR0dHHDlyBCtXrsTjx48REREBBwcH9OvX76Ur/7zo6GgMHToUFhYWMDY2RqNGjXD58mXleSEE5s+fD7lcDiMjI3To0AEhISFlUrY2yMzMRGhoKGQymcpxMzMzWFlZISwsDJcuXUKvXr2KTF+nTh0EBwcjKCgIQUFBuHr1Kpq390IVZw/YjvgRulUtMbhFDfzzZXt80FCOjRs3wtraGh/378MBp0RE9EbQeOr5F198oZy5M3ToUCxduhT169dXnjcxMcHixYvh5OT0ypVLSEhA69at0bFjRxw6dAjW1ta4d+8eqlWrprxm6dKlWL58OTZu3AhXV1csXLgQXbp0we3bt2FqavrKdahspk6dih49eqBGjRqIi4vDwoULkZSUhOHDhwMA/vrrL1hZWaFGjRoIDg7GpEmT0Lt3b3h5eSnzGDZsGOzs7ODr6wtDQ0Pln2/UszTM2XMDIfE5yJMawt29Pnz6NEBzJ3MA+T0+GzZswPDhw6Gry1UNiIjozaDxE+nmzZv4+eef0bdvX+jr6xd5jVwux/Hjx1+5ckuWLIGDgwM2bNigPPZ8ECWEwIoVKzBnzhz06dMHQP7YFBsbG/zxxx8YN27cK9ehsnn48CEGDRqE+Ph4WFlZoWXLljh//jwcHR0BADExMZgyZQoeP34MmUyGYcOGYd68eSp5REZGQkfnv06/7Nw8rD8dgRXH7iAjOw86OhLUtDLBgYltoa/733XHjh1DZGQkRo0a9XpuloiISA2vPGanPNWrVw9du3bFw4cPERAQADs7O4wfPx5jx44FAISHh6NWrVq4cuUKGjdurEzXq1cvVKtWDZs2bSoy38zMTOU0bCD/nZ+Dg4PWjtl5GTGKdETEpyItKxffH7mNW7HJAICWNc3h82ED1LTi1g9ERFSx1B2zo3HPjq+vL2xsbAr96/23337DkydPMGPGDM1rW4zw8HCsXr0aU6ZMwezZs3Hx4kVMnDgRBgYGGDZsGGJjYwEANjY2KulsbGzw4MGDEu/hm2++KbN6apsdgZGY5ReMvOfC4GrGepjzfl181NQeEglXQyYiospD4wHKv/76K+rUqVPouLu7O9asWVMmlSqQl5eHJk2awMfHB40bN8a4ceMwduxYlVlFAAo9fIUQJT6QZ82aBYVCofxwcUQgL0/gRrQCSw/fwoxdqoGOBMAfY1qgXzMHBjpERFTpaNyzExsbW2hmD5C/XUBJC9O9DJlMhnr16qkcq1u3Lnbt2gUAyg0uX6xTXFxcod6e5xkYGMDAwKBM61oZxSjScSosHqfD4nHmbjyepha9MKQAoEjPeb2VIyIiKiMaBzsODg44c+YMnJ2dVY6fOXMGcrm8zCoGAK1bt8bt27dVjt25c0c52NbZ2Rm2trbw9/dXjtnJyspCQEAAlixZUqZ1qYwKxt04W5pAZmaElMwcnL/3FKfvxuNU2BPce5Kqcr2xvhSNHKrh3L2neH4gF1dAJiKiykzjYGfMmDHw9vZGdnY23n33XQDAP//8g+nTp+PLL78s08pNnjwZnp6e8PHxQf/+/XHx4kWsXbsWa9euBZD/+srb2xs+Pj5wcXGBi4sLfHx8YGxsjMGDB5dpXSqb58fdSAA4WZggKiENOc+9n9KRAA3sq6GdiyXa1LZE4xrVoa+rgx2BkZjtdwO5QnAFZCIiqvQ0no0lhMDMmTPx008/KffDMjQ0xIwZM/DVV1+VeQX379+PWbNmISwsDM7OzpgyZYpyNlZBfb755hv8+uuvSEhIQIsWLfDLL7+orP1TGm1bQTlGkQ7Pxf+iqD/ZGubGaONiiba1LeFZyxJmxnrF5nE/Po0rIBMR0RtL3ef3S089T0lJQWhoKIyMjODi4lKpx8BoW7Cz7uQ9LDp4q9DxHwc0Qq/GdhVQIyIiorJXblPPC1SpUgXNmzd/2eRUTq5FJWK5/51Cx6USCd6paV4BNSIiIqpYLxXsBAYG4q+//kJkZKTyVVYBPz+/MqkYae5uXDJGbLiI9Ow81LIyQUR8KvIEOO6GiIjeahoHO9u3b8ewYcPg5eUFf39/eHl5ISwsDLGxsfjwww/Lo46khujEdHy8/iIS0rLhYW+G38e2RHJGNsfdEBHRW0/jRQV9fHzwww8/YP/+/dDX18ePP/6I0NBQ9O/fHzVq1CiPOlY68+fPh0QiUfkUrAlUcL5OnTowMTFB9erV0blzZ1y4cKHEPDt06FAoT4lEgu7duyM+JRMf/98FRMc9Q97ZDbiydAisqpmib7dO0H0WzkCHiIjeahoHO/fu3UP37t0B5C/Ol5qaColEgsmTJyunhFP+itIxMTHKT3BwsPKcq6srVq5cieDgYJw+fRpOTk7w8vLCkydPis3Pz89PJb8bN25AKpWiR+8+GLHhIsLjU5H2zyoYPbmJ37duQXBwMLy8vNC5c2dER0e/jlsmIiJ6I2kc7JibmyM5OX9TSDs7O9y4cQMAkJiYiLS0tLKtXSWmq6sLW1tb5cfKykp5bvDgwejcuTNq1qwJd3d3LF++HElJSbh+/Xqx+Zmbm6vk5+/vD2NjY/inO+NGdBKq6wsk3jyF5d9/h3bt2qF27dqYP38+nJ2dC22vQURE9DbRONhp27Yt/P39AQD9+/fHpEmTMHbsWAwaNAidOnUq8wpWVmFhYZDL5XB2dsbAgQMRHh5e5HVZWVlYu3YtzMzM4OHhoXb+/7d+PeRNOuHyo3RUMdDFmiGNkJubC0NDQ5XrjIyMcPr06Ve6FyIiospM4wHKK1euREZGBoD8DTX19PRw+vRp9OnTB/PmzSvzClZGLVq0wObNm+Hq6orHjx9j4cKF8PT0REhICCwsLADkL5Y4cOBApKWlQSaTwd/fH5aWlmrlf/78BYTcuAHbj0eiqq4O/m94M7SoaYFWrVrh22+/Rd26dWFjY4Nt27bhwoULcHFxKc/bJSIieqNptKhgTk4Ofv/9d3Tt2lVlwG1lV96LCqampqJWrVqYPn06pkyZojwWExOD+Ph4rFu3Dv/++y8uXLgAa2vrEvMSQqB5twG4fvkiHMauwq9Dm6JzvfxNT+/du4dRo0bh5MmTkEqlaNKkCVxdXXHlyhXcvHmzzO+LiIioIqn7/NboNZauri4+++wzZGZmvnIF3yYmJiZo0KABwsLCVI7Vrl0bLVu2xPr166Grq4v169eXmtcPh4Jx5fgBVPHwwncfNVQGOgBQq1YtBAQEICUlBVFRUbh48SKys7MLbdpKRET0NtF4zE6LFi1w9erV8qiL1srMzERoaChkMlmx1wghSg0it5x/AJ9fNkDkZmP+5E/Rp4l9kdeZmJhAJpMhISEBR44cQa9evV6p/kRERJWZxmN2xo8fjy+//BIPHz5E06ZNYWJionK+YcOGZVa5ymrq1Kno0aMHatSogbi4OCxcuBBJSUkYPnw4UlNTsWjRIvTs2RMymQxPnz7FqlWr8PDhQ/Tr10+Zx7Bhw2BnZwdfX18AwL5rj/DV3htIuX4Ujdp0wcTuTQqVe+TIEQgh4Obmhrt372LatGlwc3PDyJEjX9u9ExERvWk0DnYGDBgAAJg4caLymEQigRACEokEubm5ZVe7Surhw4cYNGgQ4uPjYWVlhZYtW+L8+fNwdHRERkYGbt26hU2bNiE+Ph4WFhZo3rw5Tp06BXd3d2UekZGR0NHJ73g7cTsOU3YEIetpNDIf3sSS9T8UWa5CocCsWbPw8OFDmJubo2/fvli0aBH09Ire2ZyIiOhtoPGu5w8ePCjxvKOj4ytVqCK8qbuexyjScSQkFr4HQ5GZI9DDQ44fBzSCjo6koqtGRERU4cpt1/PKGMxURjsCIzHTLxgFoairTRUs6+fBQIeIiEhDGgc7mzdvLvH8sGHDXroylC9GkY5ZzwU6AHA3LgVPUzO5zxUREZGGNA52Jk2apPJzdnY20tLSoK+vD2NjYwY7ZSDscQryXni5mCeA+/FpDHaIiIg0pPHU84SEBJVPSkoKbt++jTZt2mDbtm3lUce3zu6rDwsdk0okcLI0roDaEBERVW4aBztFcXFxweLFiwv1+pDm/gyMwu6rjwAABcNzpBIJfPrUZ68OERHRS9D4NVZxpFIpHj16VFbZvZWuRSVi7p78XeSndHFFv2b2uB+fBidLYwY6REREL0njYGffvn0qPwshEBMTg5UrV6J169ZlVrG3TXxKJj7dehlZuXnoXNcGn3esDR0dCYMcIiKiV6RxsNO7d2+VnyUSCaysrPDuu+9i2bJlZVWvt0pObh4+/+MKYhQZqGlpguUDOMWciIiorGgc7OTl5ZVHPd5qvodu4Xz4M5joS7F2WFNUNeSKx0RERGWlTAYo08vbGxSN9acjAADL+nugtrVpBdeIiIhIu2gc7Hz00UdYvHhxoePfffedykaWVLqbj5IwY9d1AMD4DrXwXv3id0UnIiKil6NxsBMQEIDu3bsXOv7ee+/h5MmTZVKpt0FiWhbGbb2EjOw8tHO1wpdebhVdJSIiIq2kcbCTkpICfX39Qsf19PSQlJRUJpXSdrl5AhO3ByHqWToczI3w08BGkHJAMhERUbnQONipX78+duzYUej49u3bUa9evTKplLZb7n8bJ+88gaGeDn4d2gzVjAsHj0RERFQ2NJ6NNW/ePPTt2xf37t3Du+++CwD4559/sG3bNvz1119lXkFtc/hGDH45fg8AsKRvQ9STF78lPREREb06jYOdnj17Ys+ePfDx8cHOnTthZGSEhg0b4tixY2jfvn151FFrhD1Oxpd/XgMAjG7jjF6N7Cq4RkRERNpPIoQQpV+m3ZKSkmBmZgaFQoGqVcunpyUpIxu9V55BeHwqWtY0x9bRLaAr5cx/IiKil6Xu81vjp21gYCAuXLhQ6PiFCxdw6dIlTbN7K+TlCUzZcQ3h8amQmRli5eAmDHSIiIheE42fuBMmTEBUVFSh49HR0ZgwYUKZVErbrDx+F8dCH0NfVwdrhjaFZRWDiq4SERHRW0PjMTs3b95EkyZNCh1v3Lgxbt68WSaV0hYxinTsvhKN5f53AAALe9WHh0O1iq0UERHRW0bjYMfAwACPHz9GzZo1VY7HxMRAV1fj7LTWjsBIzPILRt7/RkS1cDZH/+YOFVspIiKit5DGr7G6dOmCWbNmQaFQKI8lJiZi9uzZ6NKlS5lWrrKKUaSrBDoAEHj/GWIU6RVXKSIioreUxl0xy5YtQ7t27eDo6IjGjRsDAIKCgmBjY4MtW7aUeQUro4j4VJVABwDyBHA/Pg0yM6OKqRQREdFbSuNgx87ODtevX8fvv/+Oa9euwcjICCNHjsSgQYOgp6dXHnWsdJwtTaAjgUrAI5VI4GRpXHGVIiIieku91CAbExMTfPLJJ2VdF60hMzOCb58GmO13A7lCQCqRwKdPffbqEBERVYCXHlF88+ZNREZGIisrS+V4z549X7lS2mBA8xpo52qF+/FpcLI0ZqBDRERUQTQOdsLDw/Hhhx8iODgYEokEBQswSyT5u3bn5uaWbQ0rMZmZEYMcIiKiCqbxbKxJkybB2dkZjx8/hrGxMUJCQnDy5Ek0a9YMJ06cKIcqEhEREb08jXt2zp07h3///RdWVlbQ0dGBjo4O2rRpA19fX0ycOBFXr14tj3oSERERvRSNe3Zyc3NRpUoVAIClpSUePXoEAHB0dMTt27fLtnZEREREr0jjnp369evj+vXrqFmzJlq0aIGlS5dCX18fa9euLbSqMhEREVFF0zjYmTt3LlJTUwEACxcuxAcffIC2bdvCwsICO3bsKPMKEhEREb0KiSiYTvUKnj17hurVqytnZFU2SUlJMDMzg0KhQNWqVSu6OkRERKQGdZ/fZbJzp7m5eVlkQ0RERFTmNB6gTERERFSZMNghIiIircZgh4iIiLSaxsHOyZMnkZOTU+h4Tk4OTp48WSaVIiIiIiorGgc7HTt2xLNnzwodVygU6NixY5lUioiIiKisaBzsCCGKnGL+9OlTmJiYlEmliIiIiMqK2lPP+/TpAyB/d/MRI0bAwMBAeS43NxfXr1+Hp6dn2deQiIiI6BWoHeyYmZkByO/ZMTU1hZGRkfKcvr4+WrZsibFjx5Z9DYmIiIhegdrBzoYNGwAATk5OmDp1Kl9ZERERUaWg8Zid6dOnq4zZefDgAVasWIGjR4+WacWIiIiIyoLGwU6vXr2wefNmAEBiYiLeeecdLFu2DL169cLq1avLvIJEREREr0LjYOfKlSto27YtAGDnzp2wtbXFgwcPsHnzZvz0009lXkEiIiKiV6FxsJOWlgZTU1MAwNGjR9GnTx/o6OigZcuWePDgQZlXkIiIiOhVaBzs1K5dG3v27EFUVBSOHDkCLy8vAEBcXFyJ26sTERERVQSNg52vvvoKU6dOhZOTE9555x20atUKQH4vT+PGjcu8gkRERESvQuNg56OPPkJkZCQuXbqEI0eOKI936tQJP/zwQ5lW7kW+vr6QSCTw9vZWHhNCYP78+ZDL5TAyMkKHDh0QEhJSrvUgIiKiyuOldj23tbWFqakp/P39kZ6eDgBo3rw56tSpU6aVe15gYCDWrl2Lhg0bqhxfunQpli9fjpUrVyIwMBC2trbo0qULkpOTy60uREREVHloHOw8ffoUnTp1gqurK95//33ExMQAAMaMGYMvv/yyzCsIACkpKRgyZAjWrVuH6tWrK48LIbBixQrMmTMHffr0Qf369bFp0yakpaXhjz/+KJe6EBERUeWicbAzefJk6OnpITIyEsbGxsrjAwYMwOHDh8u0cgUmTJiA7t27o3PnzirHIyIiEBsbqxwkDQAGBgZo3749zp49W2x+mZmZSEpKUvkQERGRdlJ7u4gCR48exZEjR2Bvb69y3MXFpVymnm/fvh1XrlxBYGBgoXOxsbEAABsbG5XjNjY2JdbF19cX33zzTdlWlIiIiN5IGvfspKamqvToFIiPj1fZCb0sREVFYdKkSdi6dSsMDQ2Lve757SuA/NdbLx573qxZs6BQKJSfqKioMqszERERvVk0DnbatWun3C4CyA808vLy8N1336Fjx45lWrnLly8jLi4OTZs2ha6uLnR1dREQEICffvoJurq6yh6dgh6eAnFxcYV6e55nYGCAqlWrqnyIiIhIO2n8Guu7775Dhw4dcOnSJWRlZWH69OkICQnBs2fPcObMmTKtXKdOnRAcHKxybOTIkahTpw5mzJiBmjVrwtbWFv7+/so1frKyshAQEIAlS5aUaV2IiIioctI42KlXrx6uX7+O1atXQyqVIjU1FX369MGECRMgk8nKtHKmpqaoX7++yjETExNYWFgoj3t7e8PHxwcuLi5wcXGBj48PjI2NMXjw4DKtCxEREVVOGgc7kZGRcHBwKHKAb2RkJGrUqFEmFVPX9OnTkZ6ejvHjxyMhIQEtWrTA0aNHlft3ERER0dtNIoQQmiSQSqWIiYmBtbW1yvGnT5/C2toaubm5ZVrB1yEpKQlmZmZQKBQcv0NERFRJqPv81niAcnEznVJSUkqcMUVERERUEdR+jTVlyhQA+bOv5s2bpzL9PDc3FxcuXECjRo3KvIJEREREr0LtYOfq1asA8nt2goODoa+vrzynr68PDw8PTJ06texrSERERPQK1A52jh8/DiB/6vePP/7IsS1ERERUKWg8G2vDhg3lUQ8iIiKicqHxAGUiIiKiyoTBDhEREWk1BjtERESk1RjsEBERkVZjsENERERajcEOERERaTUGO0RERKTVGOwQERGRVmOwQ0RERFqNwQ4RERFpNQY7REREpNUY7BAREZFWY7BDREREWo3BDhEREWk1BjtERESk1RjsEBERkVZjsENERERajcEOERERaTUGO0RERKTVGOwQERGRVmOwQ0RERFqNwQ4RERFpNQY7REREpNUY7BAREZFWY7BDREREWo3BDhEREWk1BjtERESk1RjsEBERkVZjsENERERajcEOERERaTUGO0RERKTVGOwQERGRVmOwQ0RERFqNwQ4RERFpNQY7REREpNUY7BAREZFWY7BDREREWo3BDhEREWk1BjtERESk1RjsEBERkVZjsENERERajcEOERERaTUGO0RERKTVGOwQERGRVmOwQ0RERFqNwQ4RERFpNQY7REREpNUY7BAREZFWY7BDREREWo3BDhEREWk1BjtERESk1RjsEBERkVZjsENERERajcEOERERaTUGO0RERKTVGOwQERGRVmOwQ0RERFqNwQ4RERFptTc62PH19UXz5s1hamoKa2tr9O7dG7dv31a5RgiB+fPnQy6Xw8jICB06dEBISEgF1ZiIiIjeNG90sBMQEIAJEybg/Pnz8Pf3R05ODry8vJCamqq8ZunSpVi+fDlWrlyJwMBA2NraokuXLkhOTq7AmhMREdGbQiKEEBVdCXU9efIE1tbWCAgIQLt27SCEgFwuh7e3N2bMmAEAyMzMhI2NDZYsWYJx48aplW9SUhLMzMygUChQtWrV8rwFIiIiKiPqPr/f6J6dFykUCgCAubk5ACAiIgKxsbHw8vJSXmNgYID27dvj7NmzxeaTmZmJpKQklQ8RERFpp0oT7AghMGXKFLRp0wb169cHAMTGxgIAbGxsVK61sbFRniuKr68vzMzMlB8HB4fyqzgRERFVqEoT7Hz++ee4fv06tm3bVuicRCJR+VkIUejY82bNmgWFQqH8REVFlXl9iYiI6M2gW9EV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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "plt.plot(np.arange(len(epochs_x)), epochs_acc, marker = '.')\n", - "plt.xlabel('epoch')\n", - "plt.ylabel('test accuracy')\n", - "plt.ylim(0, 100)\n", - "plt.xticks(np.arange(len(epochs_x)))\n", - "for i, txt in enumerate(epochs_acc):\n", - " if i%2 == 0:\n", - " pass\n", - " else:\n", - " plt.text(i, txt, f'{txt:.2f}', ha='center', va='bottom', color = 'k')\n", - "plt.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "with open('baseline_exp_set_B1_training_metrics.npy', 'wb') as f:\n", - " np.save(f, np.array(epochs_x))\n", - " np.save(f, np.array(epochs_y))\n", - " np.save(f, np.array(epochs_acc))" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "speck-rescnn", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.3" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/tests/test_nonsequential/exp_set_B1/non-sequential-SCNN-example_3.ipynb b/tests/test_nonsequential/exp_set_B1/non-sequential-SCNN-example_3.ipynb deleted file mode 100644 index fca63b7d..00000000 --- a/tests/test_nonsequential/exp_set_B1/non-sequential-SCNN-example_3.ipynb +++ /dev/null @@ -1,1509 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "import torch, random\n", - "import torch.nn as nn\n", - "import sinabs.layers as sl\n", - "from tqdm.notebook import tqdm\n", - "\n", - "from tonic.datasets.dvsgesture import DVSGesture\n", - "from tonic.transforms import ToFrame\n", - "from torch.utils.data import DataLoader\n", - "from torch.nn import CrossEntropyLoss\n", - "from torch.optim import Adam\n", - "\n", - "from sinabs.activation.surrogate_gradient_fn import PeriodicExponential\n", - "\n", - "import matplotlib.pyplot as plt\n", - "import numpy as np" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "torch.backends.cudnn.deterministic = True\n", - "random.seed(1)\n", - "torch.manual_seed(1)\n", - "torch.cuda.manual_seed(1)\n", - "np.random.seed(1)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Loading Data" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "batch_size = 3\n", - "num_workers = 1\n", - "epochs = 30\n", - "lr = 5e-4" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "root_dir = \"./DVSGESTURE\"\n", - "_ = DVSGesture(save_to=root_dir, train=True)\n", - "_ = DVSGesture(save_to=root_dir, train=False)" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "n_time_steps = 50\n", - "to_raster = ToFrame(sensor_size=DVSGesture.sensor_size, n_time_bins=n_time_steps)\n", - "\n", - "snn_train_dataset = DVSGesture(save_to=root_dir, train=True, transform=to_raster)\n", - "snn_test_dataset = DVSGesture(save_to=root_dir, train=False, transform=to_raster)" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The transformed array is in shape [Time-Step, Channel, Height, Width] --> (50, 2, 128, 128)\n" - ] - } - ], - "source": [ - "sample_data, label = snn_train_dataset[0]\n", - "print(f\"The transformed array is in shape [Time-Step, Channel, Height, Width] --> {sample_data.shape}\")" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [], - "source": [ - "snn_train_dataloader = DataLoader(snn_train_dataset, batch_size=batch_size, num_workers=num_workers, drop_last=True, shuffle=True)\n", - "snn_test_dataloader = DataLoader(snn_test_dataset, batch_size=batch_size, num_workers=num_workers, drop_last=True, shuffle=False)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Network Module\n", - "\n", - "We need to define a `nn.Module` implementing the network we want the chip to reproduce." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "device: NVIDIA RTX A4000\n" - ] - } - ], - "source": [ - "if torch.cuda.is_available():\n", - " device = torch.device('cuda:0')\n", - " print('device: ', torch.cuda.get_device_name(0))\n", - "else:\n", - " device = torch.device('cpu')" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [], - "source": [ - "class SNN(nn.Module):\n", - " def __init__(self) -> None:\n", - " super().__init__()\n", - "\n", - " self.conv1 = nn.Conv2d(2, 10, 2, 1, bias=False)\n", - " self.iaf1 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - " self.pool1 = nn.AvgPool2d(2,2)\n", - " self.pool1a = nn.AvgPool2d(6,6)\n", - "\n", - " self.conv2 = nn.Conv2d(10, 10, 2, 1, bias=False)\n", - " self.iaf2 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - " self.pool2 = nn.AvgPool2d(3,3)\n", - "\n", - " self.conv3 = nn.Conv2d(10, 10, 3, 1, bias=False)\n", - " self.iaf3 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - " self.pool3 = nn.AvgPool2d(2,2)\n", - "\n", - " self.flat = nn.Flatten()\n", - "\n", - " self.fc1 = nn.Linear(810, 100, bias=False)\n", - " self.iaf4 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - "\n", - " self.fc2 = nn.Linear(100, 100, bias=False)\n", - " self.iaf5 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - "\n", - " self.fc3 = nn.Linear(100, 100, bias=False)\n", - " self.iaf6 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - "\n", - " self.fc4 = nn.Linear(100, 11, bias=False)\n", - " self.iaf7 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - "\n", - " self.merge_fc = sl.Merge()\n", - " self.merge_conv = sl.Merge()\n", - "\n", - " def detach_neuron_states(self):\n", - " for name, layer in self.named_modules():\n", - " if name != '':\n", - " if isinstance(layer, sl.StatefulLayer):\n", - " for name, buffer in layer.named_buffers():\n", - " buffer.detach_()\n", - "\n", - " def init_weights(self):\n", - " for name, layer in self.named_modules():\n", - " if isinstance(layer, nn.Conv2d) or isinstance(layer, nn.Linear):\n", - " nn.init.xavier_normal_(layer.weight.data)\n", - "\n", - " def forward(self, x):\n", - " \n", - " con1_out = self.conv1(x)\n", - " iaf1_out = self.iaf1(con1_out)\n", - " pool1_out = self.pool1(iaf1_out)\n", - " pool1a_out = self.pool1a(iaf1_out)\n", - "\n", - " conv2_out = self.conv2(pool1_out)\n", - " iaf2_out = self.iaf2(conv2_out)\n", - " pool2_out = self.pool2(iaf2_out)\n", - "\n", - " merged_conv_out = self.merge_conv(pool1a_out, pool2_out)\n", - "\n", - " conv3_out = self.conv3(merged_conv_out)\n", - " iaf3_out = self.iaf3(conv3_out)\n", - " pool3_out = self.pool3(iaf3_out)\n", - "\n", - " flat_out = self.flat(pool3_out)\n", - " \n", - " fc1_out = self.fc1(flat_out)\n", - " iaf4_out = self.iaf4(fc1_out)\n", - "\n", - " fc2_out = self.fc2(iaf4_out)\n", - " iaf5_out = self.iaf5(fc2_out)\n", - "\n", - " fc3_out = self.fc3(iaf5_out)\n", - " iaf6_out = self.iaf6(fc3_out)\n", - "\n", - " merge_fc_out = self.merge_fc(iaf4_out, iaf6_out)\n", - "\n", - " fc4_out = self.fc4(merge_fc_out)\n", - " iaf7_out = self.iaf7(fc4_out)\n", - "\n", - " return iaf7_out" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [], - "source": [ - "snn = SNN().to(device)" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [], - "source": [ - "snn.init_weights()" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [], - "source": [ - "optimizer = Adam(snn.parameters(), lr=lr, betas=(0.9, 0.999), eps=1e-8)\n", - "loss_fn = CrossEntropyLoss()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Define train and test" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [], - "source": [ - "def train(dataloader, model, loss_fn, optimizer, epochs, test_func, dataloader_test):\n", - " epochs_y = []\n", - " epochs_x = []\n", - " epochs_acc = []\n", - " model.train()\n", - "\n", - " for e in range(epochs):\n", - " losses = []\n", - " batches = []\n", - " batch_count = 0\n", - " train_p_bar = tqdm(snn_train_dataloader)\n", - "\n", - " for X, y in train_p_bar:\n", - " # reshape the input from [Batch, Time, Channel, Height, Width] into [Batch*Time, Channel, Height, Width]\n", - " X = X.reshape(-1, 2, 128, 128).to(dtype=torch.float, device=device)\n", - " y = y.to(dtype=torch.long, device=device)\n", - "\n", - " # forward\n", - " pred = model(X)\n", - "\n", - " # reshape the output from [Batch*Time,num_classes] into [Batch, Time, num_classes]\n", - " pred = pred.reshape(batch_size, n_time_steps, -1)\n", - "\n", - " # accumulate all time-steps output for final prediction\n", - " pred = pred.sum(dim = 1)\n", - " loss = loss_fn(pred, y)\n", - "\n", - " # gradient update\n", - " optimizer.zero_grad()\n", - " loss.backward()\n", - " optimizer.step()\n", - "\n", - " # detach the neuron states and activations from current computation graph(necessary)\n", - " model.detach_neuron_states()\n", - "\n", - " train_p_bar.set_description(f\"Epoch {e} - BPTT Training Loss: {round(loss.item(), 4)}\")\n", - "\n", - " batch_count += 1\n", - " losses.append(loss.item())\n", - " batches.append(batch_count)\n", - "\n", - " epochs_y.append(losses)\n", - " epochs_x.append(batches)\n", - "\n", - " acc = test_func(dataloader_test, model)\n", - " print(f'Epoch {e} accuracy: {acc}')\n", - " epochs_acc.append(acc)\n", - "\n", - " return epochs_x, epochs_y, epochs_acc\n" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [], - "source": [ - "def test(dataloader, model):\n", - " correct_predictions = []\n", - " with torch.no_grad():\n", - " test_p_bar = tqdm(dataloader)\n", - " for X, y in test_p_bar:\n", - " # reshape the input from [Batch, Time, Channel, Height, Width] into [Batch*Time, Channel, Height, Width]\n", - " X = X.reshape(-1, 2, 128, 128).to(dtype=torch.float, device=device)\n", - " y = y.to(dtype=torch.long, device=device)\n", - "\n", - " # forward\n", - " output = model(X)\n", - "\n", - " # reshape the output from [Batch*Time,num_classes] into [Batch, Time, num_classes]\n", - " output = output.reshape(batch_size, n_time_steps, -1)\n", - "\n", - " # accumulate all time-steps output for final prediction\n", - " output = output.sum(dim=1)\n", - "\n", - " # calculate accuracy\n", - " pred = output.argmax(dim=1, keepdim=True)\n", - "\n", - " # compute the total correct predictions\n", - " correct_predictions.append(pred.eq(y.view_as(pred)))\n", - "\n", - " test_p_bar.set_description(f\"Testing Model...\")\n", - " \n", - " correct_predictions = torch.cat(correct_predictions)\n", - " return correct_predictions.sum().item()/(len(correct_predictions))*100" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Training loop (HPO)" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "12d134e3b89e41888c9c47892b8e6491", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - " 0%| | 0/359 [00:00" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "y_avg = []\n", - "for y in epochs_y:\n", - " y_avg.append(np.mean(y))\n", - "\n", - "plt.plot(np.arange(len(epochs_x)), y_avg, marker = '.')\n", - "plt.xlabel('epoch')\n", - "plt.ylabel('average loss')\n", - "plt.ylim(0,)\n", - "plt.xticks(np.arange(len(epochs_x)))\n", - "for i, txt in enumerate(y_avg):\n", - " if i%5 == 0:\n", - " plt.text(i, txt, f'{txt:.2f}', ha='center', va='bottom', color = 'k')\n", - " else:\n", - " pass\n", - "plt.show()" - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjsAAAG2CAYAAACZEEfAAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8fJSN1AAAACXBIWXMAAA9hAAAPYQGoP6dpAABq60lEQVR4nO3dd1hT1+MG8DfsHUW2TAfixK3gqqO46q6jtVWr1bZi62idraPVFrWt7dfROn5urauOOloXrqqooOBEBERBZYhI2DPn9weaGlmJBIH4fp4nT8vNPfecQMx9c+6550iEEAJEREREWkqnohtAREREVJ4YdoiIiEirMewQERGRVmPYISIiIq3GsENERERajWGHiIiItBrDDhEREWk1hh0iIiLSagw7REREpNUYdoiIiEirVWjYOXPmDPr06QMHBwdIJBLs27dP6XkhBObMmQN7e3sYGxujW7duCA8PV9onKSkJw4cPh4WFBapVq4YxY8YgLS3tNb4KIiIiqswqNOykp6fD09MTK1asKPL5xYsXY+nSpVi5ciUuXrwIU1NTdO/eHVlZWYp9hg8fjps3b+LYsWM4ePAgzpw5g3Hjxr2ul0BERESVnKSyLAQqkUiwd+9e9O/fH0BBr46DgwO+/PJLfPXVVwAAmUwGW1tbbNiwAcOGDUNoaCgaNGiAwMBAtGzZEgBw+PBh9OrVCw8ePICDg0NFvRwiIiKqJPQqugHFiYqKQlxcHLp166bYJpVK0aZNGwQEBGDYsGEICAhAtWrVFEEHALp16wYdHR1cvHgRAwYMKPLY2dnZyM7OVvwsl8uRlJSEGjVqQCKRlN+LIiIiIo0RQiA1NRUODg7Q0Sn+YlWlDTtxcXEAAFtbW6Xttra2iufi4uJgY2Oj9Lyenh4sLS0V+xTFz88P3377rYZbTERERBUhJiYGjo6OxT5facNOeZo5cyamTJmi+Fkmk8HZ2RkxMTGwsLCowJYRERGRqlJSUuDk5ARzc/MS96u0YcfOzg4AEB8fD3t7e8X2+Ph4NG3aVLFPQkKCUrm8vDwkJSUpyhfF0NAQhoaGhbZbWFgw7BAREVUxpQ1BqbTz7Li5ucHOzg7+/v6KbSkpKbh48SK8vLwAAF5eXkhOTsbly5cV+5w4cQJyuRxt2rR57W0mIiKiyqdCe3bS0tIQERGh+DkqKgohISGwtLSEs7MzJk2ahAULFqBu3bpwc3PD7Nmz4eDgoLhjq379+ujRowfGjh2LlStXIjc3FxMmTMCwYcN4JxYREREBqOCwExQUhM6dOyt+fj6OZuTIkdiwYQOmTZuG9PR0jBs3DsnJyWjfvj0OHz4MIyMjRZmtW7diwoQJ6Nq1K3R0dDBo0CAsXbr0tb8WIiIiqpwqzTw7FSklJQVSqRQymYxjdoiIiKoIVc/flXbMDhEREZEmMOwQERGRVmPYISIiIq3GsENERERajWGHiIiItBrDDhEREWk1hh0iIiLSagw7REREpNUYdoiIiEirMewQERGRVmPYISIiIq3GsENERERajWGHiIiItBrDDhEREWk1hh0iIiLSagw7REREpNUYdoiIiEirMewQERGRVmPYISIiIq3GsENERERajWGHiIiItBrDDhEREWk1hh0iIiLSagw7REREpNUYdoiIiEirMewQERGRVmPYISIiIq3GsENERERajWGHiIiItBrDDhEREWk1hh0iIiLSagw7REREpNUYdoiIiEqQn5+P2bNnw83NDcbGxqhduzbmz58PIYRin1GjRkEikSg9evToUeJxU1NTMWnSJLi4uMDY2Bje3t4IDAxU2ictLQ0TJkyAo6MjjI2N0aBBA6xcubJcXqc206voBhAREVVmixYtwu+//46NGzeiYcOGCAoKwkcffQSpVIovvvhCsV+PHj2wfv16xc+GhoYlHvfjjz/GjRs3sHnzZjg4OGDLli3o1q0bbt26hZo1awIApkyZghMnTmDLli1wdXXF0aNHMX78eDg4OKBv377l84K1EHt2iIiISnD+/Hn069cPvXv3hqurK9599134+Pjg0qVLSvsZGhrCzs5O8ahevXqxx8zMzMTu3buxePFidOzYEXXq1MG8efNQp04d/P7770p1jxw5Em+99RZcXV0xbtw4eHp6FqqbSsawQ0T0hiivyzF+fn5o1aoVzM3NYWNjg/79+yMsLExpn08++QS1a9eGsbExalhZo0O3njgTGFIeL1PjvL294e/vjzt37gAArl69irNnz6Jnz55K+506dQo2NjaoV68ePvvsMzx58qTYY+bl5SE/Px9GRkZK242NjXH27Fmluvfv34+HDx9CCIGTJ0/izp078PHx0eArfAMIEjKZTAAQMpmsoptCRFRuvv/+e1GjRg1x8OBBERUVJXbt2iXMzMzE//73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DBTPGRgYwNPTE1999ZXmW0hERERUBiqHnZMnTwIouPX7f//7H8e2EBERUZWg9t1Y69evL492EBEREZULtQcoExEREVUlDDtERESk1Rh2iIiISKsx7BAREZFWY9ghIiIircawQ0RERFqNYYeIiIi0GsMOERERaTWGHSIiItJqDDtERESk1Rh2iIiISKsx7BAREZFWY9ghIiIircawQ0RERFqNYYeIiIi0GsMOERERaTWGHSIiItJqDDtERESk1Rh2iIiISKsx7BAREZFWY9ghIiIircawQ0RERFqNYYeIiIi0GsMOERERaTWGHSIiItJqDDtERESk1Rh2iIiISKsx7BAREZFWY9ghIiIircawQ0RERFqNYYeIiIi0GsMOERERaTWGHSIiItJqDDtERESk1Rh2iIiISKsx7BAREZFWY9ghIiIircawQ0RERFqNYYeIiIi0GsMOERERaTWGHSIiItJqDDtERESk1Rh2iIiISKsx7BAREZFWY9ghIiIircawQ0RERFqNYYeIiIi0GsMOERERaTWGHSIiItJqDDtERESk1Rh2iIiISKsx7BAREZFWY9ghIiIircawQ0RERFqNYYeIiIi0GsMOERERaTWGHSIiItJqDDtERESk1Sp12PHz80OrVq1gbm4OGxsb9O/fH2FhYUr7ZGVlwdfXFzVq1ICZmRkGDRqE+Pj4CmoxERERVTaVOuycPn0avr6+uHDhAo4dO4bc3Fz4+PggPT1dsc/kyZNx4MAB7Nq1C6dPn8ajR48wcODACmw1ERERVSYSIYSo6Eao6vHjx7CxscHp06fRsWNHyGQyWFtb448//sC7774LALh9+zbq16+PgIAAtG3bVqXjpqSkQCqVQiaTwcLCojxfAhEREWmIqufvSt2z8zKZTAYAsLS0BABcvnwZubm56Natm2IfDw8PODs7IyAgoNjjZGdnIyUlRelBRERE2qnKhB25XI5JkyahXbt2aNSoEQAgLi4OBgYGqFatmtK+tra2iIuLK/ZYfn5+kEqlioeTk1N5Np2IiIgqUJUJO76+vrhx4wa2b99e5mPNnDkTMplM8YiJidFAC4mIiKgy0qvoBqhiwoQJOHjwIM6cOQNHR0fFdjs7O+Tk5CA5OVmpdyc+Ph52dnbFHs/Q0BCGhobl2WQiIiKqJCp1z44QAhMmTMDevXtx4sQJuLm5KT3fokUL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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "plt.plot(np.arange(len(epochs_x)), epochs_acc, marker = '.')\n", - "plt.xlabel('epoch')\n", - "plt.ylabel('test accuracy')\n", - "plt.ylim(0, 100)\n", - "plt.xticks(np.arange(len(epochs_x)))\n", - "for i, txt in enumerate(epochs_acc):\n", - " if i%5 == 0:\n", - " plt.text(i, txt, f'{txt:.2f}', ha='center', va='bottom', color = 'k')\n", - " else:\n", - " pass\n", - "plt.show()" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "speck-rescnn", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.3" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/tests/test_nonsequential/exp_set_TA1/main_loop.py b/tests/test_nonsequential/exp_set_TA1/main_loop.py deleted file mode 100644 index c328a576..00000000 --- a/tests/test_nonsequential/exp_set_TA1/main_loop.py +++ /dev/null @@ -1,5 +0,0 @@ -import os - -for w_load in range(3, 9): - print(w_load) - os.system(f'python train_script.py {w_load}') \ No newline at end of file diff --git a/tests/test_nonsequential/exp_set_TA1/nonseq_conv1_weights.pth b/tests/test_nonsequential/exp_set_TA1/nonseq_conv1_weights.pth deleted file mode 100644 index a4ff9cf6e910398edaef8f119a23cac63e8bb7a9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1693 zcmWIWW@cev;NW1u0J03M40-u^#i@ny$@zI@hVkX8nduoN#ri3UC5d_k**R`bj0{l? zOv%alIXS7xC7D3AT>eEVsYR(NE}6+CT!jppL4}MFY(SGCS__$yOY)17GxXw1OEPnc zx#EjblS(slQsPTe^NRC};>(P<3Yj%DBG`dCih(K<(^CssAX>QGa`F>Pf+2!jg{%>b zKs5%1Y+%!qOH&f93<}x314;@x0=*eDyt%xYK(M5cQ^T9Xn+3>bEGgvb%mBHFyQGjO zsF1g~wvaD^6KG0&ZfZ#)$WMj*V0nQEpddq`U~Qog*d=ADMa4kB6$*PZ78e&M=>>SR za|Cxi5BdaD1;PP1Lr{*v33~`8RhFdYgF?#9$&Mk4B9N0=Qj(Jja#O4AV@Xh0gD`G4 zNi!H?cM~WC^bOpcbV+lN%im`E^LqE~S=&tP5C1i=pZ@*p-d}22`+N>;*mr)yK|2jc zJKHsP|Lt40XRaOV6ApX1(~I~0YcRBX_Kk1fg6@WWw(ZC5a_Ya@P0zR4Z(4X{pMyEy z9wtpLJ1arey-WE%?-f%DvHz9WZC?>|%3d&Vy?x`f>wE9=zux<+b=AI!G7WaCvVQN2 zd%(VbnfJ_n<|@wnnPa5wKRG#^ zr}Dh*`eN(7uMCyMVo%ms46#d+zWOu%#l!nj?a&7g|i1$yAbQ=D3qnV6GV zl?W;d;xkj+oD>N=$iURx%)->d!qnW@!qn2z%*for$N&fo4UG)V%`8og%}fm}EsRY; zuH10dH&X-XLJ$t{W&}AFUUDJlNLi2s3cy>Ap&Nyqk>pT}0Ty`J0|1_((al1RT4@xs zuHiBZk`d7jLXIIB6oV!(<8Tx-U7(wU9E#c~CJ6y+0<0m0J$?hc+1PZT2FNk%!i{2u qvS4&G(5E1<186)50QG@Ncm``wNd*KT=>Tt5Fpm{j>44Nj)B*re#oZqO diff --git a/tests/test_nonsequential/exp_set_TA1/nonseq_conv2_weights.pth b/tests/test_nonsequential/exp_set_TA1/nonseq_conv2_weights.pth deleted file mode 100644 index 8b615944c77d94845ff8d0b501c4e634d51b9799..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2973 zcmbtW3sjBi8s6P@w=I?Fc2vqJxs<)P(#8JYKi%0P3@Yii+p?#ded&e{x=}-eQ*?+r zg+zxVUBv$1kHpM`aY8MpB}SN0t1xmIxt+Z+7EaDtv(Edk_y523fA9CK=X<|zt>+05 zYH71rdU~w?2pg6TD>)@uE|x}#Qj*j7QR!ky{BnhSN?eR0#$`o9Vt|hZD}1e{NR*P8 zC>ALss#=4&vN*9!9OowyDGa2n3G<~Ip==fM+oe)Xks?JVTJ92+s*ohg4WeY?*i=bk zT$DnbEKiX|rST1M!hNN$T#!Gp{k!OsY#a9^bM6Xu}rSooOF~>LoS!cx`YUI^_r`9iw0Fy>J0g8 z3vF35hHqhPrb3*eZdHH}#R~s_B2l7HB#PCP@~B%@>Rzk!^OQ!jc*9dtH(&}kz{mNI z@kzH#^{kq%!94Ui%al)k%dt96r74A4 z?4yK;h5Mksi$(nD0pz(yK4mNKg3n{jG^kMhm?+P6~>A;;811~NM8F=jk6}i zgM&TRbilM6@_L|WI@h!uzrNByWgY5ehR#J$7X8-riindCJeJL*|LsdA{#0i3mGYg? zxut~S-P!_i9=h~-ybYP>3W>su}=l>AkQSN@7^=y?4IlRCPZ8j7|@-${um3#!Gs8+OX7 zggn@i(*bQ=-O#*#Hhs!5pXms+LcyFIsy#9f+i7FEU-<>CU0e)pXLV@%L+#AaGIQ9J zaFIMRp4lXVUHg$qmu1O`u(-kYtDMqoe_xkrM*hmyZLBw zrT})R?zL%Q6g=-($84w#0pk{Hs{iIiaMl#i$=`P|yxn}LeafQ;>PORG{z8)ri;7^2 zMFHa-xr$cqD1g}8k#tL*IW6AN4c#3cgf&os-)UHo?HfDrl7j)&{B1nARz!gzuLQh0 zT*&FpKatk4{dgeb3?A!tB#p&8$WVG2+5D=B+zq*dezKRC`z@Q)tWl7^mcCN5esyJL zhK;8jgOT!0?t_sQY(bT`8Eg}B$r5WD;^sV_)SXyL)^K)_9;qJ_cB2kn=%)bP+JIW) zw!xkyfTirmkk@_$gZNF#j6Q9uV9y5TXznt&dgBCDd-j#G*}b3IrpF;iB!+Zx*58@T z;0OpvZpOwkL(q_4#-5eEjK2u|7cg0E39#bQRxE7vgryDns1s&{y}mJ|R#Qaj6`7L> z))J`PxfiL6YcarPG06xZcsw$nnf{1Fdc@PIAZCcE>}zGRj~{`uBNvcaMXq$Bd-C6>qx5P+XeEq-58%{3H#fvNy!`z zEDP?!g_a_GHoBg&TV2NFD4ik0CJkSmF(GS$7c&)R0@UlehP-+wQXZWGmFvt<>y8!u z%)^rI`>lZ1@!3oV3H$L`eJ(DM`_PZZ?*?f#SIIP8#md4Q_%&}M*!6@_jYUp)j}`-$ z>Y*aMbFe9}M6hd73+NY_)An^nO&=h#9WJ{f&S1xPTwBeQOojwQn@c)=} zy^-Ci25JWFyWm0(NA25GmRpCVu76wmZ<6Ow`Tzg` diff --git a/tests/test_nonsequential/exp_set_TA1/nonseq_conv3_weights.pth b/tests/test_nonsequential/exp_set_TA1/nonseq_conv3_weights.pth deleted file mode 100644 index 8e179172d529aec383c7cae44f5c5fd693b64cb3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4957 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

Kcjzn_Ob0%{Lbn-B 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 VzwGQN^1GP@M7Z1U_y6O){{=!6a^?U4 diff --git a/tests/test_nonsequential/exp_set_TA1/nonseq_fc3_weights.pth b/tests/test_nonsequential/exp_set_TA1/nonseq_fc3_weights.pth deleted file mode 100644 index 64ca4119f3b8831591efb8201563032e21aa1371..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41299 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 YKkxr~c$SOIuW6Q$5iY-;|Ig?CA4?LY@Bjb+ diff --git a/tests/test_nonsequential/exp_set_TA1/nonseq_model.py b/tests/test_nonsequential/exp_set_TA1/nonseq_model.py deleted file mode 100644 index 7e65c172..00000000 --- a/tests/test_nonsequential/exp_set_TA1/nonseq_model.py +++ /dev/null @@ -1,117 +0,0 @@ -import torch -import torch.nn as nn -import sinabs.layers as sl -from sinabs.activation.surrogate_gradient_fn import PeriodicExponential - -class SNN(nn.Module): - def __init__(self, nb_classes, pool2lin_size, batch_size) -> None: - super().__init__() - - self.conv1 = nn.Conv2d(2, 10, 2, 1, bias=False) - self.iaf1 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential()) - self.pool1 = nn.AvgPool2d(2,2) - self.pool1a = nn.AvgPool2d(6,6) - - self.conv2 = nn.Conv2d(10, 10, 2, 1, bias=False) - self.iaf2 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential()) - self.pool2 = nn.AvgPool2d(3,3) - - self.conv3 = nn.Conv2d(10, 10, 3, 1, bias=False) - self.iaf3 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential()) - self.pool3 = nn.AvgPool2d(2,2) - - self.flat = nn.Flatten() - - self.fc1 = nn.Linear(pool2lin_size, 100, bias=False) - self.iaf4 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential()) - - self.fc2 = nn.Linear(100, 100, bias=False) - self.iaf5 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential()) - - self.fc3 = nn.Linear(100, 100, bias=False) - self.iaf6 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential()) - - self.fc4 = nn.Linear(100, nb_classes, bias=False) - self.iaf7 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential()) - - self.merge_fc = sl.Merge() - self.merge_conv = sl.Merge() - - def export_conv_params(self): - torch.save(self.conv1.state_dict(), 'nonseq_conv1_weights.pth') - torch.save(self.conv2.state_dict(), 'nonseq_conv2_weights.pth') - torch.save(self.conv3.state_dict(), 'nonseq_conv3_weights.pth') - torch.save(self.fc2.state_dict(), 'nonseq_fc2_weights.pth') - torch.save(self.fc3.state_dict(), 'nonseq_fc3_weights.pth') - - def load_conv_params(self, w_load): - if w_load == 0: - self.conv1.load_state_dict(torch.load('nonseq_conv1_weights.pth')) - elif w_load == 1: - self.conv2.load_state_dict(torch.load('nonseq_conv2_weights.pth')) - elif w_load == 2: - self.conv3.load_state_dict(torch.load('nonseq_conv3_weights.pth')) - elif w_load == 4: - self.conv1.load_state_dict(torch.load('nonseq_conv1_weights.pth')) - self.conv2.load_state_dict(torch.load('nonseq_conv2_weights.pth')) - self.conv3.load_state_dict(torch.load('nonseq_conv3_weights.pth')) - elif w_load == 5: - self.fc2.load_state_dict(torch.load('nonseq_fc2_weights.pth')) - elif w_load == 6: - self.fc3.load_state_dict(torch.load('nonseq_fc3_weights.pth')) - elif w_load == 7: - self.fc2.load_state_dict(torch.load('nonseq_fc2_weights.pth')) - self.fc3.load_state_dict(torch.load('nonseq_fc3_weights.pth')) - elif w_load == 8: - self.conv1.load_state_dict(torch.load('nonseq_conv1_weights.pth')) - self.conv2.load_state_dict(torch.load('nonseq_conv2_weights.pth')) - self.conv3.load_state_dict(torch.load('nonseq_conv3_weights.pth')) - self.fc2.load_state_dict(torch.load('nonseq_fc2_weights.pth')) - self.fc3.load_state_dict(torch.load('nonseq_fc3_weights.pth')) - - def detach_neuron_states(self): - for name, layer in self.named_modules(): - if name != '': - if isinstance(layer, sl.StatefulLayer): - for name, buffer in layer.named_buffers(): - buffer.detach_() - - def init_weights(self): - for name, layer in self.named_modules(): - if isinstance(layer, nn.Conv2d) or isinstance(layer, nn.Linear): - nn.init.xavier_normal_(layer.weight.data) - - def forward(self, x): - - con1_out = self.conv1(x) - iaf1_out = self.iaf1(con1_out) - pool1_out = self.pool1(iaf1_out) - pool1a_out = self.pool1a(iaf1_out) - - conv2_out = self.conv2(pool1_out) - iaf2_out = self.iaf2(conv2_out) - pool2_out = self.pool2(iaf2_out) - - merged_conv_out = self.merge_conv(pool1a_out, pool2_out) - - conv3_out = self.conv3(merged_conv_out) - iaf3_out = self.iaf3(conv3_out) - pool3_out = self.pool3(iaf3_out) - - flat_out = self.flat(pool3_out) - - fc1_out = self.fc1(flat_out) - iaf4_out = self.iaf4(fc1_out) - - fc2_out = self.fc2(iaf4_out) - iaf5_out = self.iaf5(fc2_out) - - fc3_out = self.fc3(iaf5_out) - iaf6_out = self.iaf6(fc3_out) - - merge_fc_out = self.merge_fc(iaf4_out, iaf6_out) - - fc4_out = self.fc4(merge_fc_out) - iaf7_out = self.iaf7(fc4_out) - - return iaf7_out \ No newline at end of file diff --git a/tests/test_nonsequential/exp_set_TA1/train_script.py b/tests/test_nonsequential/exp_set_TA1/train_script.py deleted file mode 100644 index a752422b..00000000 --- a/tests/test_nonsequential/exp_set_TA1/train_script.py +++ /dev/null @@ -1,152 +0,0 @@ -import torch, random, sys -import torch.nn as nn -from tqdm.notebook import tqdm - -from tonic.transforms import ToFrame -from torch.utils.data import DataLoader -from torch.nn import CrossEntropyLoss -from torch.optim import Adam - -import numpy as np - -from nonseq_model import SNN - -torch.backends.cudnn.deterministic = True -random.seed(1) -torch.manual_seed(1) -torch.cuda.manual_seed(1) -np.random.seed(1) - -batch_size = 3 -num_workers = 1 -epochs = 30 -lr = 1e-3 -n_time_steps = 50 - -if torch.cuda.is_available(): - device = torch.device('cuda:0') - print('device: ', torch.cuda.get_device_name(0)) -else: - device = torch.device('cpu') - -def train(batch_size, feature_map_size, dataloader_train, model, loss_fn, optimizer, epochs, test_func, dataloader_test, phase): - epochs_y = [] - epochs_x = [] - epochs_acc = [] - model.train() - - for e in range(epochs): - losses = [] - batches = [] - batch_count = 0 - train_p_bar = tqdm(dataloader_train) - - for X, y in train_p_bar: - # reshape the input from [Batch, Time, Channel, Height, Width] into [Batch*Time, Channel, Height, Width] - X = X.reshape(-1, feature_map_size[2], feature_map_size[0], feature_map_size[1]).to(dtype=torch.float, device=device) - y = y.to(dtype=torch.long, device=device) - - # forward - pred = model(X) - - # reshape the output from [Batch*Time,num_classes] into [Batch, Time, num_classes] - pred = pred.reshape(batch_size, n_time_steps, -1) - - # accumulate all time-steps output for final prediction - pred = pred.sum(dim = 1) - loss = loss_fn(pred, y) - - # gradient update - optimizer.zero_grad() - loss.backward() - optimizer.step() - - # detach the neuron states and activations from current computation graph(necessary) - model.detach_neuron_states() - - train_p_bar.set_description(f"{phase} - Epoch {e} - BPTT Training Loss: {round(loss.item(), 4)}") - - batch_count += 1 - losses.append(loss.item()) - batches.append(batch_count) - - epochs_y.append(losses) - epochs_x.append(batches) - - acc = test_func(batch_size, feature_map_size, dataloader_test, model) - print(f'{phase} - Epoch {e} accuracy: {acc}') - epochs_acc.append(acc) - - return epochs_x, epochs_y, epochs_acc - -def test(batch_size, feature_map_size, dataloader, model): - correct_predictions = [] - with torch.no_grad(): - test_p_bar = tqdm(dataloader) - for X, y in test_p_bar: - # reshape the input from [Batch, Time, Channel, Height, Width] into [Batch*Time, Channel, Height, Width] - X = X.reshape(-1, feature_map_size[2], feature_map_size[0], feature_map_size[1]).to(dtype=torch.float, device=device) - y = y.to(dtype=torch.long, device=device) - - # forward - output = model(X) - - # reshape the output from [Batch*Time,num_classes] into [Batch, Time, num_classes] - output = output.reshape(batch_size, n_time_steps, -1) - - # accumulate all time-steps output for final prediction - output = output.sum(dim=1) - - # calculate accuracy - pred = output.argmax(dim=1, keepdim=True) - - # compute the total correct predictions - correct_predictions.append(pred.eq(y.view_as(pred))) - - test_p_bar.set_description(f"Testing Model...") - - correct_predictions = torch.cat(correct_predictions) - return correct_predictions.sum().item()/(len(correct_predictions))*100 - -from tonic.datasets.dvsgesture import DVSGesture - -root_dir = "../DVSGESTURE" -_ = DVSGesture(save_to=root_dir, train=True) -_ = DVSGesture(save_to=root_dir, train=False) - -to_raster = ToFrame(sensor_size=DVSGesture.sensor_size, n_time_bins=n_time_steps) - -snn_train_dataset = DVSGesture(save_to=root_dir, train=True, transform=to_raster) -snn_test_dataset = DVSGesture(save_to=root_dir, train=False, transform=to_raster) - -sample_data, label = snn_train_dataset[0] -print(f"The transformed array is in shape [Time-Step, Channel, Height, Width] --> {sample_data.shape}") - -snn_train_dataloader = DataLoader(snn_train_dataset, batch_size=batch_size, num_workers=num_workers, drop_last=True, shuffle=True) -snn_test_dataloader = DataLoader(snn_test_dataset, batch_size=batch_size, num_workers=num_workers, drop_last=True, shuffle=False) - -snn = SNN(11, 810, batch_size).to(device) -snn.init_weights() - -snn.load_conv_params(int(sys.argv[1])) - -optimizer = Adam(snn.parameters(), lr=lr, betas=(0.9, 0.999), eps=1e-8) -loss_fn = CrossEntropyLoss() - -epochs_x, epochs_y, epochs_acc = train( - batch_size, - DVSGesture.sensor_size, - snn_train_dataloader, - snn, - loss_fn, - optimizer, - epochs, - test, - snn_test_dataloader, - 'post-training' - ) - -with open(f'nonseq_TA1_w_load_{sys.argv[1]}_training_metrics.npy', 'wb') as f: - np.save(f, np.array(epochs_x)) - np.save(f, np.array(epochs_y)) - np.save(f, np.array(epochs_acc)) \ No newline at end of file diff --git a/tests/test_nonsequential/non-sequential-SCNN-example_1.ipynb b/tests/test_nonsequential/non-sequential-SCNN-example_1.ipynb deleted file mode 100644 index 16c36d57..00000000 --- a/tests/test_nonsequential/non-sequential-SCNN-example_1.ipynb +++ /dev/null @@ -1,649 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [], - "source": [ - "import torch\n", - "import torch.nn as nn\n", - "import sinabs.layers as sl\n", - "from tqdm.notebook import tqdm\n", - "\n", - "from tonic.datasets.nmnist import NMNIST\n", - "from tonic.transforms import ToFrame\n", - "from torch.utils.data import DataLoader\n", - "from torch.nn import CrossEntropyLoss\n", - "from torch.optim import Adam\n", - "\n", - "from sinabs.activation.surrogate_gradient_fn import PeriodicExponential\n", - "\n", - "import matplotlib.pyplot as plt\n", - "import numpy as np" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "torch.manual_seed(0)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Loading Data" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "batch_size = 64\n", - "num_workers = 4\n", - "epochs = 5\n", - "lr = 1e-3" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "root_dir = \"./NMNIST\"\n", - "_ = NMNIST(save_to=root_dir, train=True)\n", - "_ = NMNIST(save_to=root_dir, train=False)" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "n_time_steps = 50\n", - "to_raster = ToFrame(sensor_size=NMNIST.sensor_size, n_time_bins=n_time_steps)\n", - "\n", - "snn_train_dataset = NMNIST(save_to=root_dir, train=True, transform=to_raster)\n", - "snn_test_dataset = NMNIST(save_to=root_dir, train=False, transform=to_raster)" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], - "source": [ - "snn_train_dataloader = DataLoader(snn_train_dataset, batch_size=batch_size, num_workers=num_workers, drop_last=True, shuffle=True)\n", - "snn_test_dataloader = DataLoader(snn_test_dataset, batch_size=batch_size, num_workers=num_workers, drop_last=True, shuffle=False)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Network Module\n", - "\n", - "We need to define a `nn.Module` implementing the network we want the chip to reproduce." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "device: NVIDIA RTX A4000\n" - ] - } - ], - "source": [ - "if torch.cuda.is_available():\n", - " device = torch.device('cuda:0')\n", - " print('device: ', torch.cuda.get_device_name(0))\n", - "else:\n", - " device = torch.device('cpu')" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [], - "source": [ - "class SNN(nn.Module):\n", - " def __init__(self) -> None:\n", - " super().__init__()\n", - "\n", - " self.conv1 = nn.Conv2d(2, 10, 2, 1, bias=False)\n", - " self.iaf1 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - " self.pool1 = nn.AvgPool2d(2,2)\n", - " self.pool1a = nn.AvgPool2d(6,6)\n", - "\n", - " self.conv2 = nn.Conv2d(10, 10, 2, 1, bias=False)\n", - " self.iaf2 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - " self.pool2 = nn.AvgPool2d(3,3)\n", - "\n", - " self.conv3 = nn.Conv2d(10, 10, 3, 1, bias=False)\n", - " self.iaf3 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - " self.pool3 = nn.AvgPool2d(2,2)\n", - "\n", - " self.flat = nn.Flatten()\n", - "\n", - " self.fc1 = nn.Linear(10, 10, bias=False)\n", - " self.iaf4 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - "\n", - " self.merge = sl.Merge()\n", - "\n", - "\n", - " def detach_neuron_states(self):\n", - " for name, layer in self.named_modules():\n", - " if name != '':\n", - " if isinstance(layer, sl.StatefulLayer):\n", - " for name, buffer in layer.named_buffers():\n", - " buffer.detach_()\n", - "\n", - " def init_weights(self):\n", - " for name, layer in self.named_modules():\n", - " if isinstance(layer, nn.Conv2d) or isinstance(layer, nn.Linear):\n", - " nn.init.xavier_normal_(layer.weight.data)\n", - "\n", - " def forward(self, x):\n", - " \n", - " con1_out = self.conv1(x)\n", - " iaf1_out = self.iaf1(con1_out)\n", - " pool1_out = self.pool1(iaf1_out)\n", - " pool1a_out = self.pool1a(iaf1_out)\n", - "\n", - " conv2_out = self.conv2(pool1_out)\n", - " iaf2_out = self.iaf2(conv2_out)\n", - " pool2_out = self.pool2(iaf2_out)\n", - "\n", - " merged = self.merge(pool1a_out, pool2_out)\n", - "\n", - " conv3_out = self.conv3(merged)\n", - " iaf3_out = self.iaf3(conv3_out)\n", - " pool3_out = self.pool3(iaf3_out)\n", - "\n", - " flat_out = self.flat(pool3_out)\n", - " \n", - " fc1_out = self.fc1(flat_out)\n", - " iaf4_out = self.iaf4(fc1_out)\n", - "\n", - " return iaf4_out" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [], - "source": [ - "snn = SNN().to(device)" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [], - "source": [ - "# x = torch.randn((batch_size, 2, 34, 34)).to(device)\n", - "\n", - "# con1_out = snn.conv1(x)\n", - "# iaf1_out = snn.iaf1(con1_out)\n", - "# pool1_out = snn.pool1(iaf1_out)\n", - "# pool1a_out = snn.pool1a(iaf1_out)\n", - "# print(pool1a_out.shape)\n", - "\n", - "# conv2_out = snn.conv2(pool1_out)\n", - "# iaf2_out = snn.iaf2(conv2_out)\n", - "# pool2_out = snn.pool2(iaf2_out)\n", - "# print(pool2_out.shape)\n", - "\n", - "# conv3_out = snn.conv3(pool2_out)\n", - "# iaf3_out = snn.iaf3(conv3_out)\n", - "# pool3_out = snn.pool3(iaf3_out)\n", - "\n", - "# flat_out = snn.flat(pool3_out)\n", - "# print(flat_out.shape)\n", - "\n", - "# fc1_out = snn.fc1(flat_out)\n", - "# iaf4_out = snn.iaf4(fc1_out)" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [], - "source": [ - "snn.init_weights()" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [], - "source": [ - "optimizer = Adam(snn.parameters(), lr=lr, betas=(0.9, 0.999), eps=1e-8)\n", - "loss_fn = CrossEntropyLoss()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Define train and test" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [], - "source": [ - "def train(dataloader, model, loss_fn, optimizer, epochs, test_func, dataloader_test):\n", - " epochs_y = []\n", - " epochs_x = []\n", - " epochs_acc = []\n", - " model.train()\n", - "\n", - " for e in range(epochs):\n", - " losses = []\n", - " batches = []\n", - " batch_count = 0\n", - " train_p_bar = tqdm(snn_train_dataloader)\n", - "\n", - " for X, y in train_p_bar:\n", - " # reshape the input from [Batch, Time, Channel, Height, Width] into [Batch*Time, Channel, Height, Width]\n", - " X = X.reshape(-1, 2, 34, 34).to(dtype=torch.float, device=device)\n", - " y = y.to(dtype=torch.long, device=device)\n", - "\n", - " # forward\n", - " pred = model(X)\n", - "\n", - " # reshape the output from [Batch*Time,num_classes] into [Batch, Time, num_classes]\n", - " pred = pred.reshape(batch_size, n_time_steps, -1)\n", - "\n", - " # accumulate all time-steps output for final prediction\n", - " pred = pred.sum(dim = 1)\n", - " loss = loss_fn(pred, y)\n", - "\n", - " # gradient update\n", - " optimizer.zero_grad()\n", - " loss.backward()\n", - " optimizer.step()\n", - "\n", - " # detach the neuron states and activations from current computation graph(necessary)\n", - " model.detach_neuron_states()\n", - "\n", - " train_p_bar.set_description(f\"Epoch {e} - BPTT Training Loss: {round(loss.item(), 4)}\")\n", - "\n", - " batch_count += 1\n", - " losses.append(loss.item())\n", - " batches.append(batch_count)\n", - "\n", - " epochs_y.append(losses)\n", - " epochs_x.append(batches)\n", - "\n", - " acc = test_func(dataloader_test, model)\n", - " print(f'Epoch {e} accuracy: {acc}')\n", - " epochs_acc.append(acc)\n", - "\n", - " return epochs_x, epochs_y, epochs_acc\n" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [], - "source": [ - "def test(dataloader, model):\n", - " correct_predictions = []\n", - " with torch.no_grad():\n", - " test_p_bar = tqdm(dataloader)\n", - " for X, y in test_p_bar:\n", - " # reshape the input from [Batch, Time, Channel, Height, Width] into [Batch*Time, Channel, Height, Width]\n", - " X = X.reshape(-1, 2, 34, 34).to(dtype=torch.float, device=device)\n", - " y = y.to(dtype=torch.long, device=device)\n", - "\n", - " # forward\n", - " output = model(X)\n", - "\n", - " # reshape the output from [Batch*Time,num_classes] into [Batch, Time, num_classes]\n", - " output = output.reshape(batch_size, n_time_steps, -1)\n", - "\n", - " # accumulate all time-steps output for final prediction\n", - " output = output.sum(dim=1)\n", - "\n", - " # calculate accuracy\n", - " pred = output.argmax(dim=1, keepdim=True)\n", - "\n", - " # compute the total correct predictions\n", - " correct_predictions.append(pred.eq(y.view_as(pred)))\n", - "\n", - " test_p_bar.set_description(f\"Testing Model...\")\n", - " \n", - " correct_predictions = torch.cat(correct_predictions)\n", - " return correct_predictions.sum().item()/(len(correct_predictions))*100" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Training loop (HPO)" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "fbe5ba8d578d481b97c8e81bebb4d2c7", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - " 0%| | 0/937 [00:00" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "plt.plot(epochs_x[-1], epochs_y[-1])\n", - "plt.xlabel('batches')\n", - "plt.ylabel('loss')\n", - "plt.ylim(0,)\n", - "plt.show()" - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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", - "text/plain": [ - "

" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "y_avg = []\n", - "for y in epochs_y:\n", - " y_avg.append(np.mean(y))\n", - "\n", - "plt.plot(np.arange(len(epochs_x)), y_avg, marker = '.')\n", - "plt.xlabel('epoch')\n", - "plt.ylabel('average loss')\n", - "plt.ylim(0,)\n", - "for i, txt in enumerate(y_avg):\n", - " plt.text(i, txt, f'{txt:.2f}', ha='center', va='bottom')\n", - "plt.show()" - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjsAAAG2CAYAAACZEEfAAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8fJSN1AAAACXBIWXMAAA9hAAAPYQGoP6dpAABSpklEQVR4nO3deVxU5f4H8M8wwLAIo+yMgiAuCO4LBJmmoGhmbr9cMsUtraxcSsUKy8xI780y66rdXFBcslLb7lUBU69FigpuKCoiuLCoyAz7MnN+f5CTE4uMAjNz/Lxfr3m9mnOeOX4f53L5+JznPI9EEAQBRERERCJlZugCiIiIiBoTww4RERGJGsMOERERiRrDDhEREYkaww4RERGJGsMOERERiRrDDhEREYkaww4RERGJGsMOERERiRrDDhEREYmaQcPO4cOHMWzYMCgUCkgkEuzZs0fnvCAIWLx4Mdzd3WFtbY3Q0FBcunRJp01eXh4mTJgAe3t7NG/eHNOmTUNhYWET9oKIiIiMmUHDTlFREbp27Yovv/yyxvMrVqzA559/jrVr1+Lo0aOwtbVFWFgYSktLtW0mTJiAc+fOITY2Fj///DMOHz6MGTNmNFUXiIiIyMhJjGUjUIlEgt27d2PEiBEAqkZ1FAoF3nzzTbz11lsAAKVSCVdXV2zatAnjxo3D+fPn4efnh8TERPTq1QsAsHfvXjzzzDO4fv06FAqFobpDRERERsLc0AXUJj09HdnZ2QgNDdUek8vlCAwMREJCAsaNG4eEhAQ0b95cG3QAIDQ0FGZmZjh69ChGjhxZ47XLyspQVlamfa/RaJCXlwdHR0dIJJLG6xQRERE1GEEQUFBQAIVCATOz2m9WGW3Yyc7OBgC4urrqHHd1ddWey87OhouLi855c3NzODg4aNvUJCoqCkuWLGngiomIiMgQrl27hlatWtV63mjDTmNatGgR5s2bp32vVCrh6emJa9euwd7e3oCVERERUX2pVCp4eHjAzs6uznZGG3bc3NwAADk5OXB3d9cez8nJQbdu3bRtcnNzdT5XWVmJvLw87edrIpPJIJPJqh23t7dn2CEiIjIxD5qCYrTr7Hh7e8PNzQ3x8fHaYyqVCkePHkVQUBAAICgoCPn5+Thx4oS2zYEDB6DRaBAYGNjkNRMREZHxMejITmFhIS5fvqx9n56ejuTkZDg4OMDT0xNz5szBhx9+iHbt2sHb2xuRkZFQKBTaJ7Y6duyIwYMH46WXXsLatWtRUVGB1157DePGjeOTWERERATAwGHn+PHj6N+/v/b9vXk04eHh2LRpExYsWICioiLMmDED+fn56NOnD/bu3QsrKyvtZ7Zu3YrXXnsNISEhMDMzw+jRo/H55583eV+IiIjIOBnNOjuGpFKpIJfLoVQqOWeHiIjIRNT397fRztkhIiIiaggMO0RERCRqDDtEREQkagw7REREJGoMO0RERCRqDDtEREQkagw7REREJGoMO0RERCRqDDtEREQkagw7REREJGoMO0RERCRqDDtEREQkagw7REREJGoMO0RERCRqDDtEREQkagw7REREJGoMO0RERCRqDDtEREQkagw7REREJGoMO0RERCRqDDtEREQkagw7REREJGoMO0RERCRqDDtEREQkagw7REREJGoMO0RERCRqDDtEREQkagw7REREJGoMO0RERCRqDDtEREQkagw7REREJGoMO0RERCRqDDtEREQkagw7REREJGoMO0RERCRqDDtEREQkagw7REREJGoMO0RERCRqDDtEREQkagw7REREJGoMO0RERCRqDDtEREQkagw7REREJGoMO0RERCRqDDtEREQkagw7REREJGoMO0RERCRqDDtEREQkagw7REREJGoMO0RERCRqDDtEREQkakYfdgoKCjBnzhy0bt0a1tbWCA4ORmJiovb85MmTIZFIdF6DBw82YMVERERkTMwNXcCDTJ8+HWfPnsWWLVugUCgQExOD0NBQpKSkoGXLlgCAwYMHY+PGjdrPyGQyQ5VLRERERsaoR3ZKSkrw/fffY8WKFejbty/atm2L999/H23btsWaNWu07WQyGdzc3LSvFi1aGLBqIiIiMiZGHXYqKyuhVqthZWWlc9za2hpHjhzRvj948CBcXFzQoUMHvPLKK7hz506d1y0rK4NKpdJ5ERERkTgZddixs7NDUFAQli5dips3b0KtViMmJgYJCQnIysoCUHULa/PmzYiPj8fy5ctx6NAhDBkyBGq1utbrRkVFQS6Xa18eHh5N1SUiIiJqYhJBEARDF1GXtLQ0TJ06FYcPH4ZUKkWPHj3Qvn17nDhxAufPn6/W/sqVK/Dx8UFcXBxCQkJqvGZZWRnKysq071UqFTw8PKBUKmFvb99ofSEiIqKGo1KpIJfL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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "plt.plot(np.arange(len(epochs_x)), epochs_acc, marker = '.')\n", - "plt.xlabel('epoch')\n", - "plt.ylabel('test accuracy')\n", - "plt.ylim(70, 100)\n", - "for i, txt in enumerate(epochs_acc):\n", - " plt.text(i, txt, f'{txt:.2f}', ha='center', va='bottom')\n", - "plt.show()" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "speck-rescnn", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.3" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/tests/test_nonsequential/non-sequential-SCNN-example_2.ipynb b/tests/test_nonsequential/non-sequential-SCNN-example_2.ipynb deleted file mode 100644 index c6420691..00000000 --- a/tests/test_nonsequential/non-sequential-SCNN-example_2.ipynb +++ /dev/null @@ -1,639 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [], - "source": [ - "import torch\n", - "import torch.nn as nn\n", - "import sinabs.layers as sl\n", - "from tqdm.notebook import tqdm\n", - "\n", - "from tonic.datasets.nmnist import NMNIST\n", - "from tonic.transforms import ToFrame\n", - "from torch.utils.data import DataLoader\n", - "from torch.nn import CrossEntropyLoss\n", - "from torch.optim import Adam\n", - "\n", - "from sinabs.activation.surrogate_gradient_fn import PeriodicExponential\n", - "\n", - "import matplotlib.pyplot as plt\n", - "import numpy as np" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "torch.manual_seed(0)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Loading Data" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "batch_size = 64\n", - "num_workers = 4\n", - "epochs = 5\n", - "lr = 1e-3" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "root_dir = \"./NMNIST\"\n", - "_ = NMNIST(save_to=root_dir, train=True)\n", - "_ = NMNIST(save_to=root_dir, train=False)" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "n_time_steps = 50\n", - "to_raster = ToFrame(sensor_size=NMNIST.sensor_size, n_time_bins=n_time_steps)\n", - "\n", - "snn_train_dataset = NMNIST(save_to=root_dir, train=True, transform=to_raster)\n", - "snn_test_dataset = NMNIST(save_to=root_dir, train=False, transform=to_raster)" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], - "source": [ - "snn_train_dataloader = DataLoader(snn_train_dataset, batch_size=batch_size, num_workers=num_workers, drop_last=True, shuffle=True)\n", - "snn_test_dataloader = DataLoader(snn_test_dataset, batch_size=batch_size, num_workers=num_workers, drop_last=True, shuffle=False)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Network Module\n", - "\n", - "We need to define a `nn.Module` implementing the network we want the chip to reproduce." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "device: NVIDIA RTX A4000\n" - ] - } - ], - "source": [ - "if torch.cuda.is_available():\n", - " device = torch.device('cuda:0')\n", - " print('device: ', torch.cuda.get_device_name(0))\n", - "else:\n", - " device = torch.device('cpu')" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [], - "source": [ - "class SNN(nn.Module):\n", - " def __init__(self) -> None:\n", - " super().__init__()\n", - "\n", - " self.conv1 = nn.Conv2d(2, 10, 2, 1, bias=False)\n", - " self.iaf1 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - " self.pool1 = nn.AvgPool2d(2,2)\n", - " self.pool1a = nn.AvgPool2d(6,6)\n", - "\n", - " self.conv2 = nn.Conv2d(10, 10, 2, 1, bias=False)\n", - " self.iaf2 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - " self.pool2 = nn.AvgPool2d(3,3)\n", - "\n", - " self.conv3 = nn.Conv2d(10, 10, 3, 1, bias=False)\n", - " self.iaf3 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - " self.pool3 = nn.AvgPool2d(2,2)\n", - "\n", - " self.flat = nn.Flatten()\n", - "\n", - " self.fc1 = nn.Linear(10, 100, bias=False)\n", - " self.iaf4 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - "\n", - " self.fc2 = nn.Linear(100, 100, bias=False)\n", - " self.iaf5 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - "\n", - " self.fc3 = nn.Linear(100, 100, bias=False)\n", - " self.iaf6 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - "\n", - " self.fc4 = nn.Linear(100, 10, bias=False)\n", - " self.iaf7 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - "\n", - " self.merge_fc = sl.Merge()\n", - " self.merge_conv = sl.Merge()\n", - "\n", - " def detach_neuron_states(self):\n", - " for name, layer in self.named_modules():\n", - " if name != '':\n", - " if isinstance(layer, sl.StatefulLayer):\n", - " for name, buffer in layer.named_buffers():\n", - " buffer.detach_()\n", - "\n", - " def init_weights(self):\n", - " for name, layer in self.named_modules():\n", - " if isinstance(layer, nn.Conv2d) or isinstance(layer, nn.Linear):\n", - " nn.init.xavier_normal_(layer.weight.data)\n", - "\n", - " def forward(self, x):\n", - " \n", - " con1_out = self.conv1(x)\n", - " iaf1_out = self.iaf1(con1_out)\n", - " pool1_out = self.pool1(iaf1_out)\n", - " pool1a_out = self.pool1a(iaf1_out)\n", - "\n", - " conv2_out = self.conv2(pool1_out)\n", - " iaf2_out = self.iaf2(conv2_out)\n", - " pool2_out = self.pool2(iaf2_out)\n", - "\n", - " merged_conv_out = self.merge_conv(pool1a_out, pool2_out)\n", - "\n", - " conv3_out = self.conv3(merged_conv_out)\n", - " iaf3_out = self.iaf3(conv3_out)\n", - " pool3_out = self.pool3(iaf3_out)\n", - "\n", - " flat_out = self.flat(pool3_out)\n", - " \n", - " fc1_out = self.fc1(flat_out)\n", - " iaf4_out = self.iaf4(fc1_out)\n", - "\n", - " fc2_out = self.fc2(iaf4_out)\n", - " iaf5_out = self.iaf5(fc2_out)\n", - "\n", - " fc3_out = self.fc3(iaf5_out)\n", - " iaf6_out = self.iaf6(fc3_out)\n", - "\n", - " merge_fc_out = self.merge_fc(iaf4_out, iaf6_out)\n", - "\n", - " fc4_out = self.fc4(merge_fc_out)\n", - " iaf7_out = self.iaf7(fc4_out)\n", - "\n", - " return iaf7_out" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [], - "source": [ - "snn = SNN().to(device)" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [], - "source": [ - "snn.init_weights()" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [], - "source": [ - "optimizer = Adam(snn.parameters(), lr=lr, betas=(0.9, 0.999), eps=1e-8)\n", - "loss_fn = CrossEntropyLoss()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Define train and test" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [], - "source": [ - "def train(dataloader, model, loss_fn, optimizer, epochs, test_func, dataloader_test):\n", - " epochs_y = []\n", - " epochs_x = []\n", - " epochs_acc = []\n", - " model.train()\n", - "\n", - " for e in range(epochs):\n", - " losses = []\n", - " batches = []\n", - " batch_count = 0\n", - " train_p_bar = tqdm(snn_train_dataloader)\n", - "\n", - " for X, y in train_p_bar:\n", - " # reshape the input from [Batch, Time, Channel, Height, Width] into [Batch*Time, Channel, Height, Width]\n", - " X = X.reshape(-1, 2, 34, 34).to(dtype=torch.float, device=device)\n", - " y = y.to(dtype=torch.long, device=device)\n", - "\n", - " # forward\n", - " pred = model(X)\n", - "\n", - " # reshape the output from [Batch*Time,num_classes] into [Batch, Time, num_classes]\n", - " pred = pred.reshape(batch_size, n_time_steps, -1)\n", - "\n", - " # accumulate all time-steps output for final prediction\n", - " pred = pred.sum(dim = 1)\n", - " loss = loss_fn(pred, y)\n", - "\n", - " # gradient update\n", - " optimizer.zero_grad()\n", - " loss.backward()\n", - " optimizer.step()\n", - "\n", - " # detach the neuron states and activations from current computation graph(necessary)\n", - " model.detach_neuron_states()\n", - "\n", - " train_p_bar.set_description(f\"Epoch {e} - BPTT Training Loss: {round(loss.item(), 4)}\")\n", - "\n", - " batch_count += 1\n", - " losses.append(loss.item())\n", - " batches.append(batch_count)\n", - "\n", - " epochs_y.append(losses)\n", - " epochs_x.append(batches)\n", - "\n", - " acc = test_func(dataloader_test, model)\n", - " print(f'Epoch {e} accuracy: {acc}')\n", - " epochs_acc.append(acc)\n", - "\n", - " return epochs_x, epochs_y, epochs_acc\n" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [], - "source": [ - "def test(dataloader, model):\n", - " correct_predictions = []\n", - " with torch.no_grad():\n", - " test_p_bar = tqdm(dataloader)\n", - " for X, y in test_p_bar:\n", - " # reshape the input from [Batch, Time, Channel, Height, Width] into [Batch*Time, Channel, Height, Width]\n", - " X = X.reshape(-1, 2, 34, 34).to(dtype=torch.float, device=device)\n", - " y = y.to(dtype=torch.long, device=device)\n", - "\n", - " # forward\n", - " output = model(X)\n", - "\n", - " # reshape the output from [Batch*Time,num_classes] into [Batch, Time, num_classes]\n", - " output = output.reshape(batch_size, n_time_steps, -1)\n", - "\n", - " # accumulate all time-steps output for final prediction\n", - " output = output.sum(dim=1)\n", - "\n", - " # calculate accuracy\n", - " pred = output.argmax(dim=1, keepdim=True)\n", - "\n", - " # compute the total correct predictions\n", - " correct_predictions.append(pred.eq(y.view_as(pred)))\n", - "\n", - " test_p_bar.set_description(f\"Testing Model...\")\n", - " \n", - " correct_predictions = torch.cat(correct_predictions)\n", - " return correct_predictions.sum().item()/(len(correct_predictions))*100" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Training loop (HPO)" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "1b6ac71c89994fada6d3e4a0ef50b939", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - " 0%| | 0/937 [00:00" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "plt.plot(epochs_x[-1], epochs_y[-1])\n", - "plt.xlabel('batches')\n", - "plt.ylabel('loss')\n", - "plt.ylim(0,)\n", - "plt.show()" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjcAAAGxCAYAAACeKZf2AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8fJSN1AAAACXBIWXMAAA9hAAAPYQGoP6dpAABSe0lEQVR4nO3deVxU5f4H8M/MwMyAMAPIvigqijsgKqmZWiil10S7Vypv+LPtVloaLS6ZtoqWlpWm7WbdUiuXbhguKFqmmSyliLgLAsOiMuzbzPn9gU5NAjLIcGaGz/v1mteNw3POfB/PHefjOc95HokgCAKIiIiIbIRU7AKIiIiI2hLDDREREdkUhhsiIiKyKQw3REREZFMYboiIiMimMNwQERGRTWG4ISIiIpvCcENEREQ2xU7sAtqbXq9HXl4enJ2dIZFIxC6HiIiIWkAQBJSVlcHX1xdSafPXZjpcuMnLy0NAQIDYZRAREVEr5OTkwN/fv9k2HS7cODs7A2j4w1GpVE22O3DgAN59912kp6dDo9Hgv//9L/7xj3802f7777/HJ598gqNHj6K2tha9e/fGvHnzEBkZ2epjEhERUYPS0lIEBAQYvseb0+HCzbVbUSqVqtlwAwDh4eF49NFHMWXKFDg6Ojbb/siRI7jrrrvwxhtvwMXFBZ999hnuvfde/PrrrwgLC2vVMYmIiMhYS4aUSDrawpmlpaVQq9XQarUtDhYSiQRbtmxBdHS0Se/Vr18/xMTEYNGiRW12TCIioo7IlO9vPi1lJnq9HmVlZXBzcxO7FCIiog6F4cZMli9fjvLyckydOlXsUoiIiDqUDjfmpj189dVXePnll7Ft2zZ4enqKXQ4REVGHwnDTxjZs2ICHH34Y33zzjdGTUkRERNQ+eFuqDX399deYMWMGvv76a0yYMEHscoiIiDokXrlpQnl5OU6fPm34+dy5c0hPT4ebmxu6dOmC+fPnIzc3F+vXrwfQcCtq+vTpeOeddxAREQGNRgMAcHBwgFqtbtExiYiI6ObxUfAmJCcnY8yYMddtnz59OtatW4f/+7//w/nz55GcnAwAGD16NPbt29dk+5Yck4iIiBpnyqPgDDdtKF9bhXPFFejm3gk+aoc2PTYREVFHZsr3N29LtZGNv2Vj/uaj0AuAVALETxmAmCG81URERNTeRB1QvH//fkycOBG+vr6QSCTYunVrs+03b96MsWPHwsPDAyqVCsOGDcOOHTvap9hm5GurMO9qsAEAvQAs2HwM+doqcQsjIiLqgEQNNxUVFQgJCcHq1atb1H7//v0YO3Ystm/fjpSUFIwZMwYTJ05EWlqamStt3rniCvz95p5OEHC+uFKcgoiIiDowUW9L3XXXXbjrrrta3H7lypVGPy9ZsgTbtm3D//73P6PFKdtbN/dOkEpguHIDNNyaCnR3FK0mIiKijsqq57lpyfpNNTU1KC0tNXq1NR+1A+KnDID0LwuV3h3iy0HFREREIrDqcNOS9Zvi4+OhVqsNr4CAALPUEjOkCw7Mux0zRgQCAH46VYyy6jqzvBcRERE1zWrDzbX1mzZt2tTs+k3z58+HVqs1vHJycsxWk4/aAQvG90F3j064VFGLNclnzPZeRERE1DirDDfX1m/atGnTDddvUigUUKlURi9zspdJMf+uPgCAT34+h9wSPjFFRETUnqwu3FjD+k2RfTwR0c0NNfV6LN+RJXY5REREHYqo4aa8vBzp6elIT08H8OdaS9nZ2QAabinFxsYa2n/11VeIjY3FihUrDOs3aTQaaLVaMcpvkkQiwcIJfQEAW9Jy8cfFEnELIiIi6kBEDTdHjhxBWFiY4THuuLg4hIWFYdGiRQCA/Px8Q9ABgA8//BD19fWYOXMmfHx8DK/Zs2eLUn9zBvirMSXMDwDwekImOtgqF0RERKLh2lJmlFdShTHLk1FTr8eHD4RjXD9vs74fERGRrTLl+9vqxtxYE18XBzw8shsAYOmPJ1Cn04tcERERke1juDGzx0b1gLuTHGeLK/DVr9k33oGIiIhuCsONmTkr7TEnshcAYOXuk9BWcWI/IiIic2K4aQf3DglAkKcTrlTW4f3k02KXQ0REZNMYbtqBnUyKBeN7AwA++/k8ci5ztXAiIiJzYbhpJ2OCPTEiqDNqdXq8yYn9iIiIzIbhpp1IJBIsGN8HEgnw/e95SM8pEbskIiIim8Rw0476+apxzyB/AMDrCcc5sR8REZEZMNy0s2fHBUNpL8Vv569gR4ZG7HKIiIhsDsNNO/NWK/HoyO4AGib2q63nxH5ERERtieFGBI+O6gF3JwXOX6rEl4cuiF0OERGRTWG4EYGTwg7PjGuY2O/dPaegreTEfkRERG2F4UYkUwcHINjLGSWVdVi195TY5RAREdkMhhuRyKQSzL86sd/nv1xA9iVO7EdERNQWGG5ENDrYEyN7uqNWp8eyHSfELoeIiMgmMNyI7NrEfgl/5CPlwhWxyyEiIrJ6DDci6+OjwtTwAADAa5zYj4iI6KYx3FiAuHG94GAvQ1p2CbYf5cR+REREN4PhxgJ4qZT4z6irE/slZqKmXidyRURERNaL4cZCPHpbd3g6K5BzuQpfHOTEfkRERK3FcGMhHOV2eHZcMADg3aRTuFJRK3JFRERE1onhxoLcE+6P3t7OKK2ux3t7TotdDhERkVViuLEgMqkEL0zoAwD44tB5nC+uELkiIiIi68NwY2FG9vTA6GAP1OkELP2RE/sRERGZiuHGAi0Y3wdSCZCYocFv5y+LXQ4REZFVYbixQL28nBEzpAsA4LWETOj1nNiPiIiopRhuLNTTY3uik1yG33NK8MPRfLHLISIishoMNxbK01mJx0b1AAAs+/EEqus4sR8REVFLMNxYsIdHdoe3Sonckip8/st5scshIiKyCgw3FsxBLsOzUQ0T+63aexqXObEfERHRDTHcWLgpYX7o66NCWXU93tl9UuxyiIiILB7DjYWTSiVYeHViv//+mo0zReUiV0RERGTZGG6swPAgd9zR2xP1ek7sR0REdCMMN1Zi/vjekEkl2HW8AIfOXhK7HCIiIovFcGMlgjydcd/QAADA65zYj4iIqEkMN1ZkTmQvOCnscDRXi+9/zxO7HCIiIovEcGNF3J0UeHx0w8R+byRyYj8iIqLGMNxYmYdu7QZftRJ52mp88vM5scshIiKyOAw3VkZpL8NzdzZM7Lcm+QyKy2tEroiIiMiyMNxYoUkhfhjgp0Z5TT1WcmI/IiIiIww3VkgqleCFqxP7fX04B6cLy0SuiIiIyHIw3FipW7p3xti+XtDpBcRv58R+RERE1zDcWLH5d/WGnVSCpBOF+OV0sdjlEBERWQSGGyvW3cMJ0yK6AABe386J/YiIiACGG6s3O7IXnBV2yMgrxea0XLHLISIiEh3DjZVz6yTHzNuDAADLd2ShqpYT+xERUcfGcGMD/m94IPxcHKAprcbHP50VuxwiIiJRMdzYAKW9DM9fm9hv3xkUllWLXBEREZF4RA03+/fvx8SJE+Hr6wuJRIKtW7fecJ/k5GQMGjQICoUCQUFBWLdundnrtAZ3h/giJMAFlbU6vL3rlNjlEBERiUbUcFNRUYGQkBCsXr26Re3PnTuHCRMmYMyYMUhPT8ecOXPw8MMPY8eOHWau1PJJJBIsvDqx38bfsnGygBP7ERFRxyQRBMEinh+WSCTYsmULoqOjm2wzd+5cJCQk4NixY4Zt9957L0pKSpCYmNii9yktLYVarYZWq4VKpbrZsi3OY1+kIDFDg9HBHlg3Y6jY5RAREbUJU76/rWrMzcGDBxEZGWm0LSoqCgcPHmxyn5qaGpSWlhq9bNm8qxP7JWcV4adTRWKXQ0RE1O6sKtxoNBp4eXkZbfPy8kJpaSmqqqoa3Sc+Ph5qtdrwCggIaI9SRRPo3gkPDOsKAHg9IRM6TuxHREQdjFWFm9aYP38+tFqt4ZWTkyN2SWb31O09oVLa4YSmDN+lXBS7HCIionZlVeHG29sbBQUFRtsKCgqgUqng4ODQ6D4KhQIqlcroZetcO8nx5O09AQDLd2ahsrZe5IqIiIjaj1WFm2HDhiEpKclo265duzBs2DCRKrJcscO7ooubIwrLavDhfk7sR0REHYeo4aa8vBzp6elIT08H0PCod3p6OrKzswE03FKKjY01tH/sscdw9uxZPP/88zhx4gTef/99bNq0CU8//bQY5Vs0hZ0Mc+/sDQD4YN9ZFJZyYj8iIuoYRA03R44cQVhYGMLCwgAAcXFxCAsLw6JFiwAA+fn5hqADAN26dUNCQgJ27dqFkJAQrFixAh9//DGioqJEqd/SjR/gjUFdXFBVp8OKnSfFLoeIiKhdWMw8N+3F1ue5+buUC1dwz5pfIJEA258aiT4+tt9nIiKyPTY7zw2ZLryrKyYM8IEgAEu2Z4pdDhERkdkx3HQAc+/sDXuZBD+dKkZyVqHY5RAREZkVw00H0KWzI6YPCwTQcPWmXqcXtyAiIiIzYrjpIJ68vSdcHO1xsqAc33BiPyIismEMNx2E2tEeT12d2G/FzpOoqOHEfkREZJsYbjqQf9/SFYGdHVFcXoMP9p0RuxwiIiKzYLjpQOR2Usy7q2Fivw9/Oot8beOLjRIREVkzhpsOJqqfN4YEuqK6Ts+J/YiIyCYx3HQwEokEC8b3AQB8l3oRGXlakSsiIiJqWww3HVBYF1dMDPGFIACvJ2Sig01STURENo7hpoN6PioYcjspfjlzCXs5sR8REdkQhpsOKsDNETNGBAIAlmw/wYn9iIjIZjDcdGBPjA6Cq6M9TheWY8NvOWKXQ0RE1CYYbjowtYM95kT2AgC8veskyqrrRK6IiIjo5jHcdHD3R3RBd/dOuFRRi7Wc2I+IiGwAw00HZy/7c2K/j386h7wSTuxHRETWjeGGMLavF4Z2c0NNvR7Ld2SJXQ4REdFNYbghSCQSLJzQMLHf5rRcHL3Iif2IiMh6MdwQAGCgvwsmh/kBAF7ffpwT+xERkdViuCGDZ6OCobCT4tDZy9idyYn9iIjIOjHckIGfiwMeurUbACB+eybqOLEfERFZIYYbMvL46B7o3EmOs8UV+PpwttjlEBERmYzhhow4K+0xZ2zDxH4rd59CKSf2IyIiK8NwQ9e5b0gAenh0wuWKWry/lxP7ERGRdWG4oevYyaRYML7h0fBPD5xDzuVKkSsiIiJqOYYbatTtvT0xvEdn1NbrsXwnJ/YjIiLrwXBDjZJIJFgwvg8kEmBbeh7Sc0rELomIiKhFGG6oSf391JgS5g8AeD2BE/sREZF1YLihZj0b1QtKeyl+O38FOzIKxC6HiIjohhhuqFk+agc8MrI7AGDpj5morefEfkREZNkYbuiG/jOqB9ydFDh/qRL//fWC2OUQERE1i+GGbshJYYe4qxP7vZN0CtpKTuxHRESWi+GGWmTqYH/08nJCSWUdViefFrscIiKiJjHcUIvYyaSYf3Viv3UHznNiPyIislgMN9Rio3t5YGRPd9Tq9FiaeELscoiIiBrFcEMtJpFIMP+uhon9Ev7IR8qFK2KXREREdB2GGzJJX18V/hXOif2IiMhyMdyQyZ4ZFwwHexlSs0vw4zGN2OUQEREZYbghk3mplHj0tmsT+51ATb1O5IqIiIj+xHBDrfKfUd3h6axA9uVKfHGQE/sREZHlYLihVnGU2+GZcQ0T+7235zRKKmtFroiIiKgBww212j/DA9Db2xnaqjq8m8SJ/YiIyDIw3FCryaQSLLg6sd8Xh87jfHGFyBUREREx3NBNuq2XB0b18kCdTsAyTuxHREQWgOGGbtqC8X0glQA/HtPgyPnLYpdDREQdHMMN3bRgb2fEDAkAALyWkMmJ/YiISFQMN9Qmnh7bC45yGdJzSvDDH/lil0NERB2Y6OFm9erVCAwMhFKpREREBA4fPtxs+5UrVyI4OBgODg4ICAjA008/jerq6naqlpri6azEY6N6AACWJZ5AdR0n9iMiInGIGm42btyIuLg4LF68GKmpqQgJCUFUVBQKCwsbbf/VV19h3rx5WLx4MTIzM/HJJ59g48aNWLBgQTtXTo15ZGR3eKkUuHilCp//cl7scoiIqIMSNdy89dZbeOSRRzBjxgz07dsXa9euhaOjIz799NNG2//yyy8YMWIE7r//fgQGBmLcuHG47777bni1h9qHg1yGZ8cFAwBW7T2NyxWc2I+IiNqfaOGmtrYWKSkpiIyM/LMYqRSRkZE4ePBgo/sMHz4cKSkphjBz9uxZbN++HePHj2+XmunGpgzyR18fFcqq6/Fu0imxyyEiog5ItHBTXFwMnU4HLy8vo+1eXl7QaBpfafr+++/HK6+8gltvvRX29vbo0aMHRo8e3extqZqaGpSWlhq9yHxkUglemNAwsd+Xhy7gbFG5yBUREVFHI/qAYlMkJydjyZIleP/995GamorNmzcjISEBr776apP7xMfHQ61WG14BAQHtWHHHNCLIHbf39kS9XsDSHzmxHxERtS/Rwo27uztkMhkKCgqMthcUFMDb27vRfV588UU88MADePjhhzFgwABMnjwZS5YsQXx8PPR6faP7zJ8/H1qt1vDKyclp877Q9RaM7w2ZVIKdxwvw69lLYpdDREQdiGjhRi6XIzw8HElJSYZter0eSUlJGDZsWKP7VFZWQio1LlkmkwFAkxPHKRQKqFQqoxeZX5CnM+69OrHf69szoddzYj8iImofot6WiouLw0cffYTPP/8cmZmZePzxx1FRUYEZM2YAAGJjYzF//nxD+4kTJ2LNmjXYsGEDzp07h127duHFF1/ExIkTDSGHLMfTY3vBSWGHPy5q8f3veWKXQ0REHYSdmG8eExODoqIiLFq0CBqNBqGhoUhMTDQMMs7Ozja6UrNw4UJIJBIsXLgQubm58PDwwMSJE/H666+L1QVqhruTAo+P7oE3d2ThzR1ZuLO/N5T2DKFERGReEqGDLQRUWloKtVoNrVbLW1TtoLpOhzHLk5GvrcbzdwbjidFBYpdERERWyJTvb6t6Woqsj9JehueiGib2e3/vGVwqrxG5IiIisnUmh5uqqipUVlYafr5w4QJWrlyJnTt3tmlhZDuiQ/0wwE+N8pp6rNzNif2IiMi8TA43kyZNwvr16wEAJSUliIiIwIoVKzBp0iSsWbOmzQsk6yeVSrBgfMPEfl8dzsbpQk7sR0RE5mNyuElNTcXIkSMBAN9++y28vLxw4cIFrF+/Hu+++26bF0i2YViPzojs4wWdXsDSHzPFLoeIiGyYyeGmsrISzs7OAICdO3diypQpkEqluOWWW3DhwoU2L5Bsx/yrE/vtzizEL2eKxS6HiIhslMnhJigoCFu3bkVOTg527NiBcePGAQAKCwv59BE1q4eHE6ZFdAEAvJ7Aif2IiMg8TA43ixYtwrPPPovAwEBEREQYZhPeuXMnwsLC2rxAsi2z7+gJZ4UdMvJKsSUtV+xyiIjIBrVqnhuNRoP8/HyEhIQYJtk7fPgwVCoVevfu3eZFtiXOcyO+NclnsCzxBHzUSux5ZjQc5JzYj4iImmf2eW68vb0RFhYGqVSK0tJSbN26Fc7OzhYfbMgyzBgRCD8XB+Rrq/HJz2fFLoeIiGyMyeFm6tSpWLVqFYCGOW8GDx6MqVOnYuDAgfjuu+/avECyPUp7GZ6/s2FivzXJZ1BUxon9iIio7Zgcbvbv3294FHzLli0QBAElJSV499138dprr7V5gWSbJg70RYi/GhW1Ory9+6TY5RARkQ0xOdxotVq4ubkBABITE3HPPffA0dEREyZMwKlTnH2WWkYqleCFCX0BABsOZ+NUQZnIFRERka0wOdwEBATg4MGDqKioQGJiouFR8CtXrkCpVLZ5gWS7hnZzQ1Q/L+gFYMl2TuxHRERtw+RwM2fOHEybNg3+/v7w9fXF6NGjATTcrhowYEBb10c2bt5dfWAnlWBvVhF+PsWJ/YiI6OaZHG6eeOIJHDx4EJ9++il+/vlnw6Pg3bt355gbMlk390749y1dAQCvJRyHjhP7ERHRTWrVPDfXXNtVIpG0WUHmxnluLM+VilqMenMvSqvr8cY/B2Lq4ACxSyIiIgtj9nlu1q9fjwEDBsDBwQEODg4YOHAgvvjii1YVS+TaSY4nb+8JAFixMwuVtfUiV0RERNbM5HDz1ltv4fHHH8f48eOxadMmbNq0CXfeeScee+wxvP322+aokTqA2OFdEeDmgILSGny0/5zY5RARkRUz+bZUt27d8PLLLyM2NtZo++eff46XXnoJ585Z9hcTb0tZrh/+yMOsr9LgKJch+dnR8FTx6TsiImpg1ttS+fn5GD58+HXbhw8fjvz8fFMPR2QwYYAPwrq4oLJWh7d2cWI/IiJqHZPDTVBQEDZt2nTd9o0bN6Jnz55tUhR1TBKJBAsn9AEAbDqSgxOaUpErIiIia2Rn6g4vv/wyYmJisH//fowYMQIAcODAASQlJTUaeohMEd7VDeMHeGP7UQ2WbD+B9Q8OFbskIiKyMiZfubnnnnvw66+/wt3dHVu3bsXWrVvh7u6Ow4cPY/LkyeaokTqYuXf2hr1Mgv0ni7DvZJHY5RARkZW5qXlurBEHFFuH1344jo9/PodgL2dsnz0SMqn1zKVERERtz5Tv7xbdliotbfnYBwYGaguzbg/CNykXkVVQhm+O5ODeoV3ELomIiKxEi8KNi4vLDWchFgQBEokEOp2uTQqjjs3FUY6n7uiJV384jhW7TmJiiC86KUweIkZERB1Qi74t9u7da+46iK7zwC1dsf7geVy4VIkP9p9F3NheYpdERERWgGNuyKL9eDQfj/83FUp7KZKfHQNvNSf2IyLqiMy+thRRe7mzvzcGd3VFdZ0eK3ZmiV0OERFZAYYbsmgSiQQvXJ3Y79vUi8jI04pcERERWTqGG7J4YV1cMTHEF4IALNmeiQ52J5WIiEzEcENW4fmoYMhlUhw4fQnJWZzYj4iImtaqcFNfX4/du3fjgw8+QFlZGQAgLy8P5eXlbVoc0TUBbo6YMSIQQMPVm3qdXtyCiIjIYpkcbi5cuIABAwZg0qRJmDlzJoqKGv4VvWzZMjz77LNtXiDRNU+MCYKroz1OFZZj45EcscshIiILZXK4mT17NgYPHowrV67AwcHBsH3y5MlISkpq0+KI/krtYI/ZdzSsPP/2rpMoq64TuSIiIrJEJoebn376CQsXLoRcLjfaHhgYiNzc3DYrjKgx90d0RTf3Tigur8UH+86KXQ4REVkgk8ONXq9vdImFixcvwtnZuU2KImqK3E6KeXf1BgB89NNZ5JVUiVwRERFZGpPDzbhx47By5UrDzxKJBOXl5Vi8eDHGjx/flrURNWpcXy8M7eaGmno9lnNiPyIi+huTw82KFStw4MAB9O3bF9XV1bj//vsNt6SWLVtmjhqJjEgkEiy8OrHf5tRcHMvlxH5ERPSnVq0tVV9fjw0bNuCPP/5AeXk5Bg0ahGnTphkNMLZUXFvKdszZkIat6Xm4pbsbvn7klhuuXE9ERNbLlO/vFq0Kft1Odnb497//3ariiNrKs1HB2H5Mg0NnLyMpsxCRfb3ELomIiCyAyeHm+++/b3S7RCKBUqlEUFAQunXrdtOFEd2Iv6sjHrq1G9Ykn8GSHzMxKtgD9jJOuk1E1NGZHG6io6MhkUiuW9/n2jaJRIJbb70VW7duhaura5sVStSYx0f3wMbfcnC2qAIbDmfjgWGBYpdEREQiM/mfubt27cKQIUOwa9cuaLVaaLVa7Nq1CxEREfjhhx+wf/9+XLp0ibMVU7tQKe3xdOTVif12n0IpJ/YjIurwTB5Q3L9/f3z44YcYPny40fYDBw7g0UcfRUZGBnbv3o0HH3wQ2dnZbVpsW+CAYttTp9PjzpX7caaoAo+P7oG5d/YWuyQiImpjpnx/m3zl5syZM40eVKVS4ezZhhlje/bsieLiYlMPTdQq9jIp5t/V8Gj4Jz+fw8UrlSJXREREYjI53ISHh+O5554zLJgJAEVFRXj++ecxZMgQAMCpU6cQEBDQdlUS3cAdfTwxrHtn1NbrsXwHJ/YjIurITA43n3zyCc6dOwd/f38EBQUhKCgI/v7+OH/+PD7++GMAQHl5ORYuXNjmxRI1RSKR4IUJfSCRAFvT8/B7TonYJRERkUhMDjfBwcE4fvw4tm3bhqeeegpPPfUUvv/+e2RkZKBXr14AGp6oeuCBB1p0vNWrVyMwMBBKpRIRERE4fPhws+1LSkowc+ZM+Pj4QKFQoFevXti+fbup3SAb1N9PjclhfgCA1xMyr3uij4iIOoZWTeInlUpx55134s4777ypN9+4cSPi4uKwdu1aREREYOXKlYiKikJWVhY8PT2va19bW4uxY8fC09MT3377Lfz8/HDhwgW4uLjcVB1kO54dF4yEP/Jx+Pxl7DxegKh+3mKXRERE7axVyy9UVFRg3759yM7ORm1trdHvnnrqqRYfJyIiAkOGDMGqVasANKw4HhAQgCeffBLz5s27rv3atWvx5ptv4sSJE7C3tze1bAB8WqojWL4jC6v2nkY3907YMec2yO04sR8RkbUz5fvb5HCTlpaG8ePHo7KyEhUVFXBzc0NxcTEcHR3h6elpeGLqRmpra+Ho6Ihvv/0W0dHRhu3Tp09HSUkJtm3bdt0+48ePh5ubGxwdHbFt2zZ4eHjg/vvvx9y5cyGTyVr0vgw3tq+8ph6j39yL4vJavDSxL/5vBGfMJiKydmZ9FPzpp5/GxIkTceXKFTg4OODQoUO4cOECwsPDsXz58hYfp7i4GDqdDl5exusBeXl5QaPRNLrP2bNn8e2330Kn02H79u148cUXsWLFCrz22mtNvk9NTQ1KS0uNXmTbnBR2eHpsw/ivd5JOQVvFif2IiDoSk8NNeno6nnnmGUilUshkMtTU1CAgIABvvPEGFixYYI4aDfR6PTw9PfHhhx8iPDwcMTExeOGFF7B27dom94mPj4darTa8+Ih6xxAzOAA9PZ1wpbIO7+89LXY5RETUjkwON/b29pBKG3bz9PQ0zEKsVquRk5PT4uO4u7tDJpOhoKDAaHtBQQG8vRsfBOrj44NevXoZ3YLq06cPNBrNdWN/rpk/f75hmQitVmtSjWS97GRSLBjfMLHfZwfOI+cyJ/YjIuooTA43YWFh+O233wAAo0aNwqJFi/Df//4Xc+bMQf/+/Vt8HLlcjvDwcCQlJRm26fV6JCUlYdiwYY3uM2LECJw+fRp6vd6w7eTJk/Dx8YFcLm90H4VCAZVKZfSijmF0sAduDXJHrU6PZYknxC6HiIjaicnhZsmSJfDx8QEAvP7663B1dcXjjz+OoqIifPjhhyYdKy4uDh999BE+//xzZGZm4vHHH0dFRQVmzJgBAIiNjcX8+fMN7R9//HFcvnwZs2fPxsmTJ5GQkIAlS5Zg5syZpnaDOgCJRIIF4xsm9vvhj3ykZl8RuyQiImoHJs1zIwgCPD09DVdoPD09kZiY2Oo3j4mJQVFRERYtWgSNRoPQ0FAkJiYaBhlnZ2cbboEBQEBAAHbs2IGnn34aAwcOhJ+fH2bPno25c+e2ugaybX19VfjnIH98k3IRrydk4tvHhkEikYhdFhERmZFJj4Lr9XoolUpkZGSgZ8+e5qzLbPgoeMej0VZjzPJkVNXpsGbaINw1wEfskoiIyERmexRcKpWiZ8+euHTp0k0VSNSevNVKPHJbdwDA0sQTqK3X32APIiKyZiaPuVm6dCmee+45HDt2zBz1EJnFf27rDg9nBS5cqsQXhy6IXQ4REZmRyTMUu7q6orKyEvX19ZDL5XBwcDD6/eXLl9u0wLbG21Id14bD2Zi3+SjUDvbY99xouDg2/oQdERFZHlO+v01eOHPlypWtrYuo3a1evRpvvvkmNBoNBoaEwHvYg9DAH+/tOY0X/9HXqO26desMT+pdo1AoUF1dDQCoq6vDwoULsX37dpw9exZqtRqRkZFYunQpfH19261PRETUPJPDzfTp081RB1Gba2zV+a8/mwuX2NVYf/A8Yod1RdfOnYz2UalUyMrKMvz81yerKisrkZqaihdffBEhISG4cuUKZs+ejbvvvhtHjhxpt34REVHzWrUq+JkzZ/DZZ5/hzJkzeOedd+Dp6Ykff/wRXbp0Qb9+/cxRZ5vhbamOo6lV572GReNy0HiMH+CN96eFG9qvW7cOc+bMQUlJSYvf47fffsPQoUNx4cIFdOnSpa27QEREV5l14cx9+/ZhwIAB+PXXX7F582aUl5cDAH7//XcsXry4dRUTtbHa2lqkpKQgMjLSsE0qlSIyMhKu5echlQDbj2qQcsF4jFh5eTm6du2KgIAATJo0CRkZGc2+j1arhUQigYuLizm6QURErWByuJk3bx5ee+017Nq1y2jJg9tvvx2HDh1q0+KIWqu5VefLrxRj6uCGBVRfS8jEtYuXwcHB+PTTT7Ft2zZ8+eWX0Ov1GD58OC5evNjoe1RXV2Pu3Lm47777eBWQiMiCmBxujh49ismTJ1+33dPTE8XFxW1SFJG5xY3tBUe5DGnZJUg4mg8AGDZsGGJjYxEaGopRo0Zh8+bN8PDwwAcffHDd/nV1dZg6dSoEQcCaNWvau3wiImqGyeHGxcUF+fn5121PS0uDn59fmxRFdLNutOq8p0qJ/9zWAwCwLPEEaup11x3D3t4eYWFhOH36tNH2a8HmwoUL2LVrF6/aEBFZGJPDzb333ou5c+dCo9FAIpFAr9fjwIEDePbZZxEbG2uOGolM1pJV5x+5rRu8VArkXK7C57+cv+4YOp0OR48eNSwUC/wZbE6dOoXdu3ejc+fOZu8LERGZxuRHwa+twh0QEACdToe+fftCp9Ph/vvvx8KFC81RI1GrxMXFYfr06Rg8eDCGDh2KlStXGq06/9jDD8JH6owC7/F4b89pnNu5HmNuG4GgoCCUlJTgzTffxIULF/Dwww8DaAg2//znP5GamooffvgBOp0OGo0GAODm5mY0Bo2IiMTTqkfBgYYVu48dO4by8nKEhYVZzUKafBS8Y1m1apVhEr/Q0FC8++67iIiIAACMHj0aXbsGonDQQ8jML4X38Y3I/30fNBoNXF1dER4ejtdeew1hYWEAgPPnz6Nbt26Nvs/evXsxevTo9uoWEVGHY8r3t8nh5ueff8att956UwWKieGG/u7nU8X49ye/wk4qwVePRKBeL6Cbeyf4qB1uvDMREbULs4YbuVwOPz8/3Hffffj3v/+Nvn373ngnC8JwQ42Z8dlh7M0qMvwslQDxUwYgZggn5iMisgRmncQvLy8PzzzzDPbt24f+/fsjNDQUb775ZpNzgRBZg0dGdjf6WS8ACzYfQ762SqSKiIiotUwON+7u7pg1axYOHDiAM2fO4F//+hc+//xzBAYG4vbbbzdHjUTmJ7l+k04Q8H16HnT6Vg1LIyIikbR6QPE1Op0OP/74I1588UX88ccf0Omuny/EkvC2FDUmX1uFEUv3oLEc4+mswN0hvpg8yA99fVRGi2kSEVH7MOttqWsOHDiAJ554Aj4+Prj//vvRv39/JCQktPZwRKLyUTsgfsoAyK4GF6kEuKW7G1wc7VFYVoOPfz6HCe/+jDtX/oS1+87wdhURkQUz+crN/PnzsWHDBuTl5WHs2LGYNm0aJk2aBEdHR3PV2KZ45Yaak6+twvniSgS6O8JH7YDaej2SswqxJS0XSZmFqNXpAQASCTCse2dMDvPDXQN84KQwecooIiIygVmflhoxYgSmTZuGqVOnwt3d/aYKFQPDDbWWtrIO24/lY0tqLg6f/3M1caW9FGP7emNKmB9G9nSHnazVF0SJiKgJZg031o7hhtpCzuVKbEvPxea0XJwtqjBsd3eS4x8DfTFlkB8G+Kk5PoeIqI20S7g5fvw4srOzUVtba7T97rvvbs3h2g3DDbUlQRDwx0UttqTl4n+/5+FSxZ+fhx4enTBlkD8mhfrC39U6btsSEVkqs4abs2fPYvLkyTh69CgkEgmu7X7tX6h8Woo6qjqdHj+dKsLm1FzsOl6Amnq94XdDu7lhytXxOWoHexGrJCKyTmYNNxMnToRMJsPHH3+Mbt264fDhw7h06RKeeeYZLF++HCNHjryp4s2N4YbaQ2l1HRKPabAlNReHzl3CtU+Z3E6KyD6emBzmj1G9PCC34/gcIqKWMGu4cXd3x549ezBw4ECo1WocPnwYwcHB2LNnD5555hmkpaXdVPHmxnBD7S2vpArb0vOwJe0iThaUG7a7OtpjYogvosP8EBbgwvE5RETNMOX72+TnV3U6HZydnQE0BJ28vDwEBweja9euyMrKal3FRDbM18UBj4/ugcdGdUdGXim2puVi2+95KCqrwfqDF7D+4AV0c++E6FA/TA7zQ5fOHJ9DRHQzTA43/fv3x++//45u3bohIiICb7zxBuRyOT788EN07979xgcg6qAkEgn6+6nR30+NeXf1xoEzl7Al9SJ2ZBTgXHEF3t59Em/vPonwrq6YHOaHfwz0gYujXOyyiYisjsm3pXbs2IGKigpMmTIFp0+fxj/+8Q+cPHkSnTt3xsaNGy1+fSneliJLU1FTjx0ZGmxJy8WB08WGJSDsZRKMCfbElEF+GNPbEwo7mbiFEhGJqN3nubl8+TJcXV2tYswAww1ZsoLSanyfnofNabnIzC81bFc72GPCQB9MDvPD4K7W8VkjImpLnMSvGQw3ZC1OaEqxJS0X29LyoCmtNmwPcHPA5FA/RIf5obuHk4gVEhG1H4abZjDckLXR6QUcOnsJm1NzkXgsHxW1f84lFRLggilhfpgY4gu3ThyfQ0S2i+GmGQw3ZM2qanXYebxhfM5Pp4qhuzpAx04qwehgD0SH+SGyjxeU9hyfQ0S2heGmGQw3ZCuKymrwv9/zsCUtF0dztYbtzgo7jB/gg8mD/DA00A1SKcfnEJH1Y7hpBsMN2aLThWXYkpaLrWl5yC2pMmz3c3HApNCGhTyDPJ1FrJCI6OYw3DSD4YZsmV4v4PD5y9iSmovtR/NRVlNv+N0APzWiw/xwd4gvPJwVIlZJRGQ6hptmMNxQR1Fdp0NSZiG2pF1EclYR6q+Oz5FJJRjZ0x2Tw/wwrq83HOQcn0NElo/hphkMN9QRXSqvQcLRfGxOzUV6Tolheye5DHf298GUQX64pXtnyDg+h4gsFMNNMxhuqKM7W1SOrVcX8sy5/Of4HG+VEpNCfTF5kB96e/OzQUSWheGmGQw3RA0EQUDKhSvYnJaLhD/yoa2qM/yuj48Kk8N8MSnUD14qpYhVEhE1YLhpBsMN0fVq6nXYe6IIW9IuYs+JQtTpGv5akEqAEUHuiA71w539vdFJYfJau0REbYLhphkMN0TNK6msRcLRfGxJzcWRC1cM2x3sZYjq54XJg/wxokdn2MmkIlZJRB0Nw00zGG6IWi77UiW2pudiS1ouzhVXGLZ7OCtwd4gvJof5oZ+vigt5EpHZMdw0g+GGyHSCICA9pwRb0nLxv9/zcKXyz/E5vbycEB3mh+hQP/i6OIhYJRHZMlO+v3ldmYhuSCKRIKyLK16Z1B+/LojEx7GDMWGAD+R2UpwsKMcbiVkYsWwP7vvwEDYdyUFZdd2ND9pCq1evRmBgIJRKJSIiInD48OEm227evBmDBw+Gi4sLOnXqhNDQUHzxxRdGbcrLyzFr1iz4+/vDwcEBffv2xdq1a9usXiISH6/cEFGraavqkHisYf6cX89dNmxX2Ekxtq8Xpgzyw8ieHrBv5ficjRs3IjY2FmvXrkVERARWrlyJb775BllZWfD09LyufXJyMq5cuYLevXtDLpfjhx9+wDPPPIOEhARERUUBAB599FHs2bMHH3/8MQIDA7Fz50488cQT2Lx5M+6+++7W/UEQkdnxtlQzGG6IzOPilUpsS8/D5tSLOFP05/iczp3kmHh1fM5Af7VJ43MiIiIwZMgQrFq1CgCg1+sREBCAJ598EvPmzWvRMQYNGoQJEybg1VdfBQD0798fMTExePHFFw1twsPDcdddd+G1115rcW1E1L54W4qI2p2/qyNmjgnC7rhR+N+sWzFjRCDcneS4VFGLdb+cx6TVB3DHW/uwas8p5FyuvOHxamtrkZKSgsjISMM2qVSKyMhIHDx48Ib7C4KApKQkZGVl4bbbbjNsHz58OL7//nvk5uZCEATs3bsXJ0+exLhx41rXcSKyOBYRbky5p/5XGzZsgEQiQXR0tHkLJKIWk0gkGOCvxuKJ/XBo/h34bMYQ3B3iC6W9FGeLKrB850mMfGMvpq49iK8PZxtNHvhXxcXF0Ol08PLyMtru5eUFjUbT5PtrtVo4OTlBLpdjwoQJeO+99zB27FjD79977z307dsX/v7+kMvluPPOO7F69WqjAERE1k30Gbk2btyIuLg4o3vqUVFRTd5Tv+b8+fN49tlnMXLkyHaslohMYSeTYkywJ8YEe6Ksug47MgqwJe0ifjlzCYfPX8bh85exeFsG7ujjiclhfhgd7Am53c39m8vZ2Rnp6ekoLy9HUlIS4uLi0L17d4wePRpAQ7g5dOgQvv/+e3Tt2hX79+/HzJkz4evra3SViIisl+hjblpzT12n0+G2227Dgw8+iJ9++gklJSXYunVri96PY26IxJevrcK29DxsSc1FVkGZYbuLoz3+MdAHk8P80d/bEZ06dcK3335rdHV2+vTpKCkpwbZt21r0Xg8//DBycnKwY8cOVFVVQa1WY8uWLZgwYYJRm4sXLyIxMbHN+khEbctqxty09p76K6+8Ak9PTzz00EM3fI+amhqUlpYavYhIXD5qBzw2qgd2PH0btj81Eo+M7AZPZwVKKuvw5aFs3LPmF0S9+wv8evbD1oQ/A4der0dSUhKGDRvW4vfS6/WoqakBANTV1aGurg5SqfFffTKZDHq9vm06R0SiE/W2VHP31E+cONHoPj///DM++eQTpKent+g94uPj8fLLL99sqURkJn19Vejr2xfz7uqDX84UY0tqLhIzNDh/qRKVve7E55+9jaM17vjX+DE4sfNrVFRUYMaMGQCA2NhY+Pn5IT4+HkDD533w4MHo0aMHampqsH37dnzxxRdYs2YNAEClUmHUqFF47rnn4ODggK5du2Lfvn1Yv3493nrrLdH+DIiobYk+5sYUZWVleOCBB/DRRx/B3d29RfvMnz8fcXFxhp9LS0sREBBgrhKJqJVkUglG9vTAyJ4eeK22HjszCrA5zQPbq7T4fduHSP1qGRRe3RH11NtILdTj9s46ZGdnG12FqaiowBNPPIGLFy/CwcEBvXv3xpdffomYmBhDmw0bNmD+/PmYNm0aLl++jK5du+L111/HY489Jka3icgMRB1zU1tbC0dHxxbfU09PT0dYWBhkMplh27VLyVKpFFlZWejRo0ez78kxN0TWpbC0Gt//noctabnIyPvztrJKaYcJAxvmzxnc1RVSqQT52iqcK65AN/dO8FFzKQgiW2JVk/hFRERg6NCheO+99wA0hJUuXbpg1qxZ1w0orq6uxunTp422LVy4EGVlZXjnnXfQq1cvyOXyZt+P4YbIep0sKMPm1FxsS89FvrbasN3f1QG9vJyRnFUIvQBIJUD8lAGIGdJFxGqJqC2Z8v0t+m2puLg4TJ8+HYMHD8bQoUOxcuXKJu+pK5VK9O/f32h/FxcXALhuOxHZnl5ezph3V288HxWMQ+cuYUtqLn48psHFK1W4eKXK0E4vAPM2H4WnsxLDgzpDYSdr5qhEZGtEDzcxMTEoKirCokWLoNFoEBoaisTERMMg47/fUycikkolGN7DHcN7uOOVSf3xfvJpvLfH+KquIAAz1v0GO6kEPb2c0c9Xhf6+KvTzU6OPjwpOCtH/+iMiMxH9tlR7420pItuTr63CiKV7oP/b32ZqpR201fXXtZdIgG6dO6Gvrwr9/dTo56tCP1813Do1f1ubiMRjVWNu2hvDDZFt2vhbNhZsPgadIEAmkWDJlP6YOjgA+dpqHMvVIiOvFBl5Df/71/E6f+WrVqLfX8JOfz8VvFVKkxb7JCLzYLhpBsMNke3K11bhfHElAt0dm31a6lJ5zdWwU4pjeVoczyvFueKKRtu6dZIbwk6/q1d6uro5Qipl4CFqTww3zWC4IaLGlFXXITO/DBl5WhzLbbjKc6qwHLq/3+sC4KSwQ18fldFtrSBPJ9jLOD6QyFwYbprBcENELVVdp8PJgjJD2MnIK0Vmfilq6q9fqkFuJ0Vvb2ejqzx9fFRQ2vNJLaK2wHDTDIYbIroZ9To9zhZXXDeOp6yRgcsyqQQ9PDoZwk4/XzX6+qqgdrAXoXIi68Zw0wyGGyJqa4IgIOdyFY7laY1uaxWX1zbavoubI/r7qYxCj4ezop2rJrIuDDfNYLghovYgCAIKy2qMwk5GXqnRZIN/5emsMHosvZ+vCv6uDnxSi+gqhptmMNwQkZhKKmtx/OpTWtee2DpTVI7G/iZWO9hfDTt/Dlzu5u4EmZU9qbV69Wq8+eab0Gg0CAkJwXvvvYehQ4c22nbz5s1YsmQJTp8+jbq6OvTs2RPPPPMMHnjgAaM2a9euRUpKCi5fvoy0tDSEhoa2U29ILFa1/AIRUUfi4ijH8CB3DA9yN2yrrK03PKmVkdsQfE4WlEFbVYdfzlzCL2cuGdo62MvQx8fZ6CpPTy8ni11iYuPGjYiLi8PatWsRERGBlStXIioqCllZWfD09LyuvZubG1544QX07t0bcrkcP/zwA2bMmAFPT09ERUUBaFj9/dZbb8XUqVPxyCOPtHeXyArwyg0RkQWqrdfjVGEZMq7e0jp29UmtylrddW3tZRL09HQ2GsfTx0eFThawxERERASGDBmCVatWAWhYHDkgIABPPvnkdYsjN2XQoEGYMGECXn31VaPt58+fR7du3XjlpoPglRsiIisnt5NeDSpqAAEAAJ1ewLniCmRcnXjw2q2tkso6HM8vxfH8UgAXAVxdYsK9E/r/ZfLBfr4quDi23xITtbW1SElJwfz58w3bpFIpIiMjcfDgwRvuLwgC9uzZg6ysLCxbtsycpZKNYbghIrISMqkEQZ5OCPJ0wqRQPwANASC3pKph/M7Vx9OP5WlRUFqDs0UVOFtUge9/zzMcw8/FwWh5iX6+anipFGYZuFxcXAydTmdYCPkaLy8vnDhxosn9tFot/Pz8UFNTA5lMhvfffx9jx45t8/rIdjHcEBFZMYlEAn9XR/i7OiKqn7dhe/HVJSaO5f55lefCpUrkllQht6QKO48XGNq6O8nR11fdsGr61Ss9XURcYsLZ2Rnp6ekoLy9HUlIS4uLi0L17d4wePVqUesj6MNwQEdkgdycFRvXywKheHoZtpdV1OH71Ca1rg5dPF5WjuLwW+08WYf/JIkNbZ4Ud+viqjG5r9fDoBDsTlphwd3eHTCZDQUGB0faCggJ4e3s3sVfDraugoCAAQGhoKDIzMxEfH89wQy3GcENE1EGolPa4pXtn3NK9s2FbdZ0OJzR/rql1PE+LTE0ZymrqcfjcZRw+d9nQVnFtiYmr43f6+6oR7O3c5BITcrkc4eHhSEpKQnR0NICGAcVJSUmYNWtWi+vW6/WoqalpXaepQ2K4ISLqwJT2MoQGuCA0wMWwrU6nx5micsNj6Rl5pcjMK0VZTT1+v6jF7xe1hrYyqQQ9PZ3Q99o4Ht+GBUWdlQ1LTMTFxWH69OkYPHgwhg4dipUrV6KiogIzZswAAMTGxsLPzw/x8fEAgPj4eAwePBg9evRATU0Ntm/fji+++AJr1qwxvOfly5eRnZ2NvLyGsURZWVkAAG9v72avCFHHwXBDRERG7GVS9PZWobe3CveE+wMA9HoB2ZcrDQOWrw1gvlRRixOaMpzQlGFzaq7hGIGdHRvG7/iF4z/Pv4SFL76IwoIChIaGIjEx0TDIODs7G1Lpn7e6Kioq8MQTT+DixYtwcHBA79698eWXXyImJsbQ5vvvvzeEIwC49957AQCLFy/GSy+9ZM4/GrISnOeGiIhaRRAEFJRev8REbknjS0x4q5QNT2oZJiBUwc/FeImJfG0VzhVXoJt7J/ioHdqrK2QFuPxCMxhuiIjM60pFrWHQ8rGr/3uuuKLRJSZcHO0N43e0VXXYdCQHegGQSoD4KQMQM6RL+3eALBLDTTMYboiI2l9FTT0y80sNj6dn5JXiZEEZ6vXNfwXd0dsT3T06wVvtAB+1Et5qJXzVDvBwVljdGlvWypS1wT766COsX78ex44dAwCEh4djyZIlRu2bmlPpjTfewHPPPddkHQw3zWC4ISKyDDX1OpwqKEdGnha7jxdiV2bBjXe6SiaVwNNZAW+1Ej5qJXz+En4a/tcBXs4Kkx5dp+tt3LgRsbGxRmuDffPNN02uDTZt2jSMGDECw4cPh1KpxLJly7BlyxZkZGTAz69h4kmNRmO0z48//oiHHnoIp0+fRvfu3ZusheGmGQw3RESWJ19bhRFL9+CvF3KkEuDJ23uisrYe+dpqaLTVyNdWo6C0+oZXfK7t7+GsaLjqo/oz+Pi4XA1CKiW8VErI7RiAmnKza4PpdDq4urpi1apViI2NbbRNdHQ0ysrKkJSU1OyxuLYUERFZFR+1A+KnDMCCzcegEwTIJBIsmdK/0TE3Or2AS+U1yL8adjTaqr/8dzXyS6ug0VajTtcw4LmgtAa/N/Pe7k4K+Lo0hJ1rV318/nJFyEutsNhV183pZtcGA4DKykrU1dXBzc2t0d8XFBQgISEBn3/+eZvUfA3DDRERWYSYIV1wWy8PnC+uRKC7Y5NPS8mkEniqlPBUKRES0Pix9HoBlypqr17tqYKmtCH85Jc0BKFrP9fW61FcXoPi8hr8AW3jBwPQuZPc6BbYn7e//rwl1tRkhtaqtWuD/dXcuXPh6+uLyMjIRn//+eefw9nZGVOmTLnpev+K4YaIiCxGQ1C4+UfApVIJPJwV8HBWYIC/utE2giDgSmUd8kqqrl7x+ctVoJJrAagK1XV6XKqoxaWrT4E1xdXR/m8Dn5VGP/uolXCUd5yv3aVLl2LDhg1ITk6GUqlstM2nn36KadOmNfn71uo4f8pERER/IZFI4NZJDrdOcvT3azoAaavqrt72qjIa+6PRViNPW4X8kmpU1elwpbIOVyrrkJnfdABSO9gbD3xWOcDHRWm4DeatdoCTwjK+mlu7NhgALF++HEuXLsXu3bsxcODARtv89NNPyMrKwsaNG9us5mss40+QiIjIAkkkErg4yuHiKEcfn8YHsQqCgNLqesMtsL+PBboWhspr6qGtqoO2qg4nNGVNvqezwq4h/LgYD4T2Vivh69JwS8xZYdfkI9VtpbVrg73xxht4/fXXsWPHDgwePLjJdp988gnCw8MREhLS1qUz3BAREd0MiUQCtYM91A72CPZ2brJdWXWd0VWf668GVaG0uh5lNfUoKyzHqcLyJo/VSS4zGu/j87dbYL5qB6gcbj4Ambo22LJly7Bo0SJ89dVXCAwMNDz27eTkBCcnJ8NxS0tL8c0332DFihU3VV9TGG6IiIjagbPSHs5Ke/T0ajoAVdTUG4Wda2OB/joQuqSyDhW1OpwpqsCZooomj+VgLzOEncbnA3KAq6N9swEoJiYGRUVFWLRoETQazQ3XBluzZg1qa2vxz3/+0+g4f1/3a8OGDRAEAffdd9+N/thahfPcEBERWZGqWl3DYGejJ78aglDe1YHQlytqW3QshZ3UKOw0FoLcHOWQmjAbtLnWB+M8N0RERDbKQS5DN/dO6Obeqck21XU6FJQ2duvrz6tCxeW1qKnX4/ylSpy/VNnkseQyKbzUCuOrPqqG22C+Lg0/u3dSQCqVYONv2Zi/+ajo64Pxyg0REVEHVFOvQ2FpTaNjf64FoaLymkYXPP07O6kE7k4KaEqrjbbLJBL8PG9Mm1zB4ZUbIiIiapbCToYAN0cEuDk22aa2Xo/Csusff//rz4VlDcth/D3YAIBOEHC+uLJNb0+1BMMNERERNUpuJ4W/qyP8XZsOQPU6PQrLanAsV4v/fJGCv17okUkkCHRvel9z4WphRERE1Gp2Mil8XRwwrp83lt4zALKrT19dWx+sva/aALxyQ0RERG2kpeuDmRvDDREREbWZtlof7GbwthQRERHZFIYbIiIisikMN0RERGRTGG6IiIjIpjDcEBERkU1huCEiIiKbwnBDRERENoXhhoiIiGwKww0RERHZFIYbIiIisikWEW5Wr16NwMBAKJVKRERE4PDhw022/eijjzBy5Ei4urrC1dUVkZGRzbYnIiKijkX0cLNx40bExcVh8eLFSE1NRUhICKKiolBYWNho++TkZNx3333Yu3cvDh48iICAAIwbNw65ubntXDkRERFZIokgCIKYBURERGDIkCFYtWoVAECv1yMgIABPPvkk5s2bd8P9dTodXF1dsWrVKsTGxt6wfWlpKdRqNbRaLVQq1U3XT0REROZnyve3qFduamtrkZKSgsjISMM2qVSKyMhIHDx4sEXHqKysRF1dHdzc3MxVJhEREVkROzHfvLi4GDqdDl5eXkbbvby8cOLEiRYdY+7cufD19TUKSH9VU1ODmpoaw8+lpaWtL5iIiIgsnuhjbm7G0qVLsWHDBmzZsgVKpbLRNvHx8VCr1YZXQEBAO1dJRERE7UnUcOPu7g6ZTIaCggKj7QUFBfD29m523+XLl2Pp0qXYuXMnBg4c2GS7+fPnQ6vVGl45OTltUjsRERFZJlHDjVwuR3h4OJKSkgzb9Ho9kpKSMGzYsCb3e+ONN/Dqq68iMTERgwcPbvY9FAoFVCqV0YuIiIhsl6hjbgAgLi4O06dPx+DBgzF06FCsXLkSFRUVmDFjBgAgNjYWfn5+iI+PBwAsW7YMixYtwldffYXAwEBoNBoAgJOTE5ycnETrBxEREVkG0cNNTEwMioqKsGjRImg0GoSGhiIxMdEwyDg7OxtS6Z8XmNasWYPa2lr885//NDrO4sWL8dJLL7Vn6URERGSBRJ/npr1xnhsiIiLrYzXz3BARERG1NYYbIiIisikMN0RERGRTGG6IiIjIpjDcEBERkU1huCEiIiKbwnBDRERENoXhhoiIiGwKww0RERHZFIYbIiIisikMN0RERGRTGG6IiIjIpjDcEBERkU1huCEiIiKbwnBDRERENoXhhoiIiGwKww0RERHZFIYbIiIisikMN0RERGRTGG6IiIjIpjDcEBERkU1huCEiIiKbwnBDRERENoXhhoiIiGwKww0RERHZFIYbIiIisikMN0RERGRTGG6IiIjIpjDcEBERkU1huCEiIiKbwnBDRERENoXhhoiIiGwKww0RERHZFIYbIiIisikMN0RERGRTGG6IiIjIpjDcEBERkU1huCEiIiKbwnBDRERENoXhhoiIiGwKww0RERHZFIYbIiIisikMN0RERGRTGG6IiIjIpjDcEBERkU1huCEiIiKbwnBDRERENoXhhoiIiGyKRYSb1atXIzAwEEqlEhERETh8+HCz7b/55hv07t0bSqUSAwYMwPbt29upUiIiIrJ0ooebjRs3Ii4uDosXL0ZqaipCQkIQFRWFwsLCRtv/8ssvuO+++/DQQw8hLS0N0dHRiI6OxrFjx9q5ciIiIrJEEkEQBDELiIiIwJAhQ7Bq1SoAgF6vR0BAAJ588knMmzfvuvYxMTGoqKjADz/8YNh2yy23IDQ0FGvXrr3h+5WWlkKtVkOr1UKlUrVdR4iIiMhsTPn+FvXKTW1tLVJSUhAZGWnYJpVKERkZiYMHDza6z8GDB43aA0BUVFST7YmIiKhjsRPzzYuLi6HT6eDl5WW03cvLCydOnGh0H41G02h7jUbTaPuamhrU1NQYftZqtQAaEiARERFZh2vf2y254SRquGkP8fHxePnll6/bHhAQIEI1REREdDPKysqgVqubbSNquHF3d4dMJkNBQYHR9oKCAnh7eze6j7e3t0nt58+fj7i4OMPPer0ely9fRufOnSGRSG6yB8ZKS0sREBCAnJwcmxzPY+v9A2y/j+yf9bP1PrJ/1s9cfRQEAWVlZfD19b1hW1HDjVwuR3h4OJKSkhAdHQ2gIXwkJSVh1qxZje4zbNgwJCUlYc6cOYZtu3btwrBhwxptr1AooFAojLa5uLi0RflNUqlUNvt/WsD2+wfYfh/ZP+tn631k/6yfOfp4oys214h+WyouLg7Tp0/H4MGDMXToUKxcuRIVFRWYMWMGACA2NhZ+fn6Ij48HAMyePRujRo3CihUrMGHCBGzYsAFHjhzBhx9+KGY3iIiIyEKIHm5iYmJQVFSERYsWQaPRIDQ0FImJiYZBw9nZ2ZBK/3yoa/jw4fjqq6+wcOFCLFiwAD179sTWrVvRv39/sbpAREREFkT0cAMAs2bNavI2VHJy8nXb/vWvf+Ff//qXmasynUKhwOLFi6+7DWYrbL1/gO33kf2zfrbeR/bP+llCH0WfxI+IiIioLYm+/AIRERFRW2K4ISIiIpvCcENEREQ2heHGRKtXr0ZgYCCUSiUiIiJw+PDhZtt/88036N27N5RKJQYMGIDt27e3U6WtY0r/1q1bB4lEYvRSKpXtWK1p9u/fj4kTJ8LX1xcSiQRbt2694T7JyckYNGgQFAoFgoKCsG7dOrPX2Vqm9i85Ofm68yeRSJpcykRs8fHxGDJkCJydneHp6Yno6GhkZWXdcD9r+gy2po/W9Dlcs2YNBg4caJj/ZNiwYfjxxx+b3ceazp+p/bOmc9eYpUuXQiKRGM071xgxziHDjQk2btyIuLg4LF68GKmpqQgJCUFUVBQKCwsbbf/LL7/gvvvuw0MPPYS0tDRER0cjOjoax44da+fKW8bU/gENkzTl5+cbXhcuXGjHik1TUVGBkJAQrF69ukXtz507hwkTJmDMmDFIT0/HnDlz8PDDD2PHjh1mrrR1TO3fNVlZWUbn0NPT00wV3px9+/Zh5syZOHToEHbt2oW6ujqMGzcOFRUVTe5jbZ/B1vQRsJ7Pob+/P5YuXYqUlBQcOXIEt99+OyZNmoSMjIxG21vb+TO1f4D1nLu/++233/DBBx9g4MCBzbYT7RwK1GJDhw4VZs6cafhZp9MJvr6+Qnx8fKPtp06dKkyYMMFoW0REhPCf//zHrHW2lqn9++yzzwS1Wt1O1bUtAMKWLVuabfP8888L/fr1M9oWExMjREVFmbGyttGS/u3du1cAIFy5cqVdamprhYWFAgBh3759Tbaxts/g37Wkj9b8ORQEQXB1dRU+/vjjRn9n7edPEJrvn7Weu7KyMqFnz57Crl27hFGjRgmzZ89usq1Y55BXblqotrYWKSkpiIyMNGyTSqWIjIzEwYMHG93n4MGDRu0BICoqqsn2YmpN/wCgvLwcXbt2RUBAwA3/hWJtrOn83YzQ0FD4+Phg7NixOHDggNjltJhWqwUAuLm5NdnG2s9hS/oIWOfnUKfTYcOGDaioqGhy+RxrPn8t6R9gnedu5syZmDBhwnXnpjFinUOGmxYqLi6GTqczzJx8jZeXV5NjFDQajUntxdSa/gUHB+PTTz/Ftm3b8OWXX0Kv12P48OG4ePFie5Rsdk2dv9LSUlRVVYlUVdvx8fHB2rVr8d133+G7775DQEAARo8ejdTUVLFLuyG9Xo85c+ZgxIgRzc5Obk2fwb9raR+t7XN49OhRODk5QaFQ4LHHHsOWLVvQt2/fRtta4/kzpX/Wdu4AYMOGDUhNTTUsiXQjYp1Di5ihmKzTsGHDjP5FMnz4cPTp0wcffPABXn31VREro5YIDg5GcHCw4efhw4fjzJkzePvtt/HFF1+IWNmNzZw5E8eOHcPPP/8sdilm09I+WtvnMDg4GOnp6dBqtfj2228xffp07Nu3r8kAYG1M6Z+1nbucnBzMnj0bu3btsviBzww3LeTu7g6ZTIaCggKj7QUFBfD29m50H29vb5Pai6k1/fs7e3t7hIWF4fTp0+Yosd01df5UKhUcHBxEqsq8hg4davGBYdasWfjhhx+wf/9++Pv7N9vWmj6Df2VKH//O0j+HcrkcQUFBAIDw8HD89ttveOedd/DBBx9c19Yaz58p/fs7Sz93KSkpKCwsxKBBgwzbdDod9u/fj1WrVqGmpgYymcxoH7HOIW9LtZBcLkd4eDiSkpIM2/R6PZKSkpq8nzps2DCj9gCwa9euZu+/iqU1/fs7nU6Ho0ePwsfHx1xltitrOn9tJT093WLPnyAImDVrFrZs2YI9e/agW7duN9zH2s5ha/r4d9b2OdTr9aipqWn0d9Z2/hrTXP/+ztLP3R133IGjR48iPT3d8Bo8eDCmTZuG9PT064INIOI5NOtwZRuzYcMGQaFQCOvWrROOHz8uPProo4KLi4ug0WgEQRCEBx54QJg3b56h/YEDBwQ7Ozth+fLlQmZmprB48WLB3t5eOHr0qFhdaJap/Xv55ZeFHTt2CGfOnBFSUlKEe++9V1AqlUJGRoZYXWhWWVmZkJaWJqSlpQkAhLfeektIS0sTLly4IAiCIMybN0944IEHDO3Pnj0rODo6Cs8995yQmZkprF69WpDJZEJiYqJYXWiWqf17++23ha1btwqnTp0Sjh49KsyePVuQSqXC7t27xepCsx5//HFBrVYLycnJQn5+vuFVWVlpaGPtn8HW9NGaPofz5s0T9u3bJ5w7d074448/hHnz5gkSiUTYuXOnIAjWf/5M7Z81nbum/P1pKUs5hww3JnrvvfeELl26CHK5XBg6dKhw6NAhw+9GjRolTJ8+3aj9pk2bhF69eglyuVzo16+fkJCQ0M4Vm8aU/s2ZM8fQ1svLSxg/fryQmpoqQtUtc+3R57+/rvVp+vTpwqhRo67bJzQ0VJDL5UL37t2Fzz77rN3rbilT+7ds2TKhR48eglKpFNzc3ITRo0cLe/bsEaf4FmisbwCMzom1fwZb00dr+hw++OCDQteuXQW5XC54eHgId9xxh+GLXxCs//yZ2j9rOndN+Xu4sZRzyFXBiYiIyKZwzA0RERHZFIYbIiIisikMN0RERGRTGG6IiIjIpjDcEBERkU1huCEiIiKbwnBDRERENoXhhoiIiGwKww0RdXjJycmQSCQoKSkRuxQiagMMN0RERGRTGG6IiIjIpjDcEJHo9Ho94uPj0a1bNzg4OCAkJATffvstgD9vGSUkJGDgwIFQKpW45ZZbcOzYMaNjfPfdd+jXrx8UCgUCAwOxYsUKo9/X1NRg7ty5CAgIgEKhQFBQED755BOjNikpKRg8eDAcHR0xfPhwZGVlmbfjRGQWDDdEJLr4+HisX78ea9euRUZGBp5++mn8+9//xr59+wxtnnvuOaxYsQK//fYbPDw8MHHiRNTV1QFoCCVTp07Fvffei6NHj+Kll17Ciy++iHXr1hn2j42Nxddff413330XmZmZ+OCDD+Dk5GRUxwsvvIAVK1bgyJEjsLOzw4MPPtgu/SeitsVVwYlIVDU1NXBzc8Pu3bsxbNgww/aHH34YlZWVePTRRzFmzBhs2LABMTExAIDLly/D398f69atw9SpUzFt2jQUFRVh586dhv2ff/55JCQkICMjAydPnkRwcDB27dqFyMjI62pITk7GmDFjsHv3btxxxx0AgO3bt2PChAmoqqqCUqk0858CEbUlXrkhIlGdPn0alZWVGDt2LJycnAyv9evX48yZM4Z2fw0+bm5uCA4ORmZmJgAgMzMTI0aMMDruiBEjcOrUKeh0OqSnp0Mmk2HUqFHN1jJw4EDDf/v4+AAACgsLb7qPRNS+7MQugIg6tvLycgBAQkIC/Pz8jH6nUCiMAk5rOTg4tKidvb294b8lEgmAhvFARGRdeOWGiETVt29fKBQKZGdnIygoyOgVEBBgaHfo0CHDf1+5cgUnT55Enz59AAB9+vTBgQMHjI574MAB9OrVCzKZDAMGDIBerzcaw0NEtotXbohIVM7Oznj22Wfx9NNPQ6/X49Zbb4VWq8WBAwegUqnQtWtXAMArr7yCzp07w8vLCy+88ALc3d0RHR0NAHjmmWcwZMgQvPrqq4iJicHBgwexatUqvP/++wCAwMBATJ8+HQ8++CDeffddhISE4MKFCygsLMTUqVPF6joRmQnDDRGJ7tVXX4WHhwfi4+Nx9uxZuLi4YNCgQViwYIHhttDSpUsxe/ZsnDp1CqGhofjf//4HuVwOABg0aBA2bdqERYsW4dVXX4WPjw9eeeUV/N///Z/hPdasWYMFCxbgiSeewKVLl9ClSxcsWLBAjO4SkZnxaSkismjXnmS6cuUKXFxcxC6HiKwAx9wQERGRTWG4ISIiIpvC21JERERkU3jlhoiIiGwKww0RERHZFIYbIiIisikMN0RERGRTGG6IiIjIpjDcEBERkU1huCEiIiKbwnBDRERENoXhhoiIiGzK/wOA1bRvpRx+WAAAAABJRU5ErkJggg==", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "y_avg = []\n", - "for y in epochs_y:\n", - " y_avg.append(np.mean(y))\n", - "\n", - "plt.plot(np.arange(len(epochs_x)), y_avg, marker = '.')\n", - "plt.xlabel('epoch')\n", - "plt.ylabel('average loss')\n", - "plt.ylim(0,)\n", - "for i, txt in enumerate(y_avg):\n", - " plt.text(i, txt, f'{txt:.2f}', ha='center', va='bottom')\n", - "plt.show()" - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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b7O+sgMA/v7+OHz4MAoKCpCeno6TJ0+irKwMzZo1q7R9s2bN4ObmhuTk5CqPKZVK4ezsrPMiIiIicTL7sHOfo6MjvLy8cPfuXcTGxmLAgAGVtrt58yZycnLg5eVVxxUSERGROTL7R89jY2MhCAJatmyJ5ORkzJw5E4GBgRg3bhwKCgowf/58DB48GJ6enkhJScGsWbMQEBCA8PBwU5dOREREZsDsr+woFApMmTIFgYGBGD16NHr27InY2FjY2trC2toaf/zxB1555RW0aNEC48ePR+fOnfHbb79xrh0iIiICYAEDlOtCTQc4ERERkfkQzQBlIiIioifBsENERESixrBDREREosawQ0RERKLGsENERESixrBDREREosawQ0RERKLGsENERESixrBDREREosawQ0RERKLGsENERESVys/PR2RkJJo2bQqZTIbu3bvj1KlTAICysjK88847aNeuHRwdHSGXyzF69Gjcvn37sce9desW/vWvf8HV1RUymQzt2rVDQkKC9vPdu3fj5ZdfhqurKyQSCZKSkp6oHww7REREVKkJEyYgLi4OmzZtwrlz5/Dyyy8jLCwMt27dQlFREU6fPo2oqCicPn0au3fvxuXLl/HKK69Ue8y7d++iR48esLW1xU8//YSLFy9i2bJlaNCggbZNYWEhevbsiSVLlhikH1wIFFwIlIiI6GHFxcVwcnLCd999h379+mm3d+7cGX369MHChQsf2efUqVPo1q0bUlNT0aRJk0qPO3v2bBw7dgy//fbbY2u4ceMG/Pz8cObMGXTs2PGRz7kQKBEREdVaeXk51Go17O3tdbbLZDIcPXq00n0UCgUkEgnq169f5XG///57dOnSBUOGDIG7uzs6deqEr776ypClP4Jhh4iIiB7h5OSEkJAQLFiwALdv34ZarcbmzZsRHx+PjIyMR9qXlJTgnXfewYgRI6q9ynLt2jWsXLkSzZs3R2xsLF5//XW89dZb2LBhg9H6wrBDREREldq0aRMEQYC3tzekUimWL1+OESNGwMpKNz6UlZVh6NChEAQBK1eurPaYGo0GQUFB+Oijj9CpUydMmjQJEydOxKpVq4zWD4YdIiIiqpS/vz8OHz6MgoICpKen4+TJkygrK0OzZs20be4HndTUVMTFxT127KuXlxdat26ts61Vq1ZIS0szSh8Ahh0iIiJ6DEdHR3h5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UVERAFS7bldl8kvKMHrtSfyekgNHO2tsGNcNzvY2UKlUACoed5fL5bh8+bLOfleuXEHTpk0N1SUiIqKnCsNONTQaDWJiYjBmzBjY2Px9ESwwMBABAQGYPHkyTp48iZSUFCxbtgxxcXE6a3KFhoZixYoVAIC8olIEvTIOR4/+BvuSO5jX0wl7v/ovDh06hJEjRwKoWOtr5syZWL58Ob799lskJycjKioKf/75J8aPH1+nfSciIhIL3saqxoEDB5CWlqZdePQ+W1tb/O9//8Ps2bPRv39/FBQUICAgABs2bEDfvn217VJSUnDnzh3cKVDhX1+fQEZmNkpPfYLcort4c6sL2rdvj9jYWLz00kvafSIjI1FSUoJp06YhNzcXHTp0QFxcHPz9/eus30RERGLCeXZgvLWxMhTFOJ16F/+JvYwbOUVwqyfF1onBaOHhZLCfQURE9LTi2lgmtuNUGubsPgfNvSjpIrPBzsnPoFmjeqYtjIiI6CnDMTtGkKEo1gk6AJBfUg6ZnbXpiiIiInpKMewYwfU7hTpBBwA0AnDjTpFpCiIiInqKMewYgZ+bI6wkutusJRL4ujmYpiAiIqKnGMOOEXi5yBA9qB2s762jZS2R4KNBbeHlIjNxZURERE8fDlA2kmFdm+C5Fo1w404RfN0cGHSIiIhMhGHHiLxcZAw5REREJsbbWERERCRqDDtEREQkagw7REREJGoMO0RERCRqDDtEREQkagw7REREJGoMO0RERCRqDDtEREQkagw7REREJGoMO0RERCRqDDtEREQkagw7REREJGoMO0RERCRqDDtEREQkagw7REREJGoMO0RERCRqDDtEREQkagw7REREJGoMO0RERCRqDDtEREQkagw7REREJGoMO0RERCRqDDtEREQkagw7REREJGoMO0RERCRqDDtEREQkagw7REREJGoMO0RERCRqDDtEREQkagw7REREJGoMO0RERCRqDDtEREQkamYfdnx9fSGRSB55TZkyBQDwwgsvPPLZv//9bxNXTURERObCxtQFPM6pU6egVqu178+fP4+XXnoJQ4YM0W6bOHEiPvzwQ+17BweHOq2RiIiIzJfZh51GjRrpvF+8eDH8/f3x/PPPa7c5ODjA09OzrksjIiIiC2D2t7EeVFpais2bNyMiIgISiUS7fcuWLXBzc0Pbtm0xZ84cFBUVVXsclUoFpVKp8yIiIiJxMvsrOw/au3cv8vLyMHbsWO221157DU2bNoVcLscff/yBd955B5cvX8bu3burPE50dDTmz59fBxUTERGRqUkEQRBMXURNhYeHw87ODj/88EOVbX755ReEhoYiOTkZ/v7+lbZRqVRQqVTa90qlEj4+PlAoFHB2djZ43URERGR4SqUSLi4uj/3+tpgrO6mpqThw4EC1V2wAIDg4GACqDTtSqRRSqdTgNRIREZH5sZgxOzExMXB3d0e/fv2qbZeUlAQA8PLyqoOqiIiIyNxZxJUdjUaDmJgYjBkzBjY2f5eckpKCrVu3om/fvnB1dcUff/yBadOm4bnnnkP79u1NWDERERGZC4sIOwcOHEBaWhoiIiJ0ttvZ2eHAgQP49NNPUVhYCB8fHwwePBjvvfeeiSolIiIic2NRA5SNpaYDnIiIiMh81PT722LG7BARERHVBsMOERERiRrDDhEREYkaww4RERGJGsMOERERiRrDDhEREYkaww4RERGJGsMOERERiRrDDhEREYkaww4RERGJGsMOERERiRrDDhEREYkaww4RERGJGsMOERERiRrDDhEREYkaww4RERGJGsMOERERiRrDDhEREYkaww4RERGJGsMOERERiRrDDhEREYkaww4RERGJGsMOERERiRrDDhEREYkaww4RERGJGsMOERERiRrDDhEREYkaww4RERGJGsMOERERiRrDDhEREYkaww4RERGJGsMOERERiRrDDhEREYkaww4RERGJGsMOERERiRrDDhEREYkaww4RERGJGsMOERERiRrDDhEREYkaww4RERGJGsMOERERiRrDDhEREYkaww4RERGJGsMOERERiRrDDhEREYkaww4RERGJGsMOERERiRrDDhEREYkaww4RERGJGsMOERERiRrDDhEREYma2YcdX19fSCSSR15TpkwBAJSUlGDKlClwdXVFvXr1MHjwYGRlZZm4aiIiIjIXZh92Tp06hYyMDO0rLi4OADBkyBAAwLRp0/DDDz/gm2++weHDh3H79m0MGjTIlCUTERGRGZEIgiCYugh9REZG4scff8TVq1ehVCrRqFEjbN26Ff/85z8BAH/++SdatWqF+Ph4PPPMMzU6plKphIuLCxQKBZydnY1ZPhERERlITb+/beqwpidWWlqKzZs3Y/r06ZBIJEhMTERZWRnCwsK0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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "plt.plot(np.arange(len(epochs_x)), epochs_acc, marker = '.')\n", - "plt.xlabel('epoch')\n", - "plt.ylabel('test accuracy')\n", - "plt.ylim(70, 100)\n", - "for i, txt in enumerate(epochs_acc):\n", - " plt.text(i, txt, f'{txt:.2f}', ha='center', va='bottom')\n", - "plt.show()" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "speck-rescnn", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.3" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/tests/test_nonsequential/non-sequential-SCNN-example_3.ipynb b/tests/test_nonsequential/non-sequential-SCNN-example_3.ipynb deleted file mode 100644 index 956dfb88..00000000 --- a/tests/test_nonsequential/non-sequential-SCNN-example_3.ipynb +++ /dev/null @@ -1,1509 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "import torch, random\n", - "import torch.nn as nn\n", - "import sinabs.layers as sl\n", - "from tqdm.notebook import tqdm\n", - "\n", - "from tonic.datasets.dvsgesture import DVSGesture\n", - "from tonic.transforms import ToFrame\n", - "from torch.utils.data import DataLoader\n", - "from torch.nn import CrossEntropyLoss\n", - "from torch.optim import Adam\n", - "\n", - "from sinabs.activation.surrogate_gradient_fn import PeriodicExponential\n", - "\n", - "import matplotlib.pyplot as plt\n", - "import numpy as np" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "torch.backends.cudnn.deterministic = True\n", - "random.seed(1)\n", - "torch.manual_seed(1)\n", - "torch.cuda.manual_seed(1)\n", - "np.random.seed(1)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Loading Data" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "batch_size = 3\n", - "num_workers = 1\n", - "epochs = 30\n", - "lr = 1e-3" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "root_dir = \"./DVSGESTURE\"\n", - "_ = DVSGesture(save_to=root_dir, train=True)\n", - "_ = DVSGesture(save_to=root_dir, train=False)" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "n_time_steps = 50\n", - "to_raster = ToFrame(sensor_size=DVSGesture.sensor_size, n_time_bins=n_time_steps)\n", - "\n", - "snn_train_dataset = DVSGesture(save_to=root_dir, train=True, transform=to_raster)\n", - "snn_test_dataset = DVSGesture(save_to=root_dir, train=False, transform=to_raster)" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The transformed array is in shape [Time-Step, Channel, Height, Width] --> (50, 2, 128, 128)\n" - ] - } - ], - "source": [ - "sample_data, label = snn_train_dataset[0]\n", - "print(f\"The transformed array is in shape [Time-Step, Channel, Height, Width] --> {sample_data.shape}\")" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [], - "source": [ - "snn_train_dataloader = DataLoader(snn_train_dataset, batch_size=batch_size, num_workers=num_workers, drop_last=True, shuffle=True)\n", - "snn_test_dataloader = DataLoader(snn_test_dataset, batch_size=batch_size, num_workers=num_workers, drop_last=True, shuffle=False)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Network Module\n", - "\n", - "We need to define a `nn.Module` implementing the network we want the chip to reproduce." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "device: NVIDIA RTX A4000\n" - ] - } - ], - "source": [ - "if torch.cuda.is_available():\n", - " device = torch.device('cuda:0')\n", - " print('device: ', torch.cuda.get_device_name(0))\n", - "else:\n", - " device = torch.device('cpu')" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [], - "source": [ - "class SNN(nn.Module):\n", - " def __init__(self) -> None:\n", - " super().__init__()\n", - "\n", - " self.conv1 = nn.Conv2d(2, 10, 2, 1, bias=False)\n", - " self.iaf1 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - " self.pool1 = nn.AvgPool2d(2,2)\n", - " self.pool1a = nn.AvgPool2d(6,6)\n", - "\n", - " self.conv2 = nn.Conv2d(10, 10, 2, 1, bias=False)\n", - " self.iaf2 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - " self.pool2 = nn.AvgPool2d(3,3)\n", - "\n", - " self.conv3 = nn.Conv2d(10, 10, 3, 1, bias=False)\n", - " self.iaf3 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - " self.pool3 = nn.AvgPool2d(2,2)\n", - "\n", - " self.flat = nn.Flatten()\n", - "\n", - " self.fc1 = nn.Linear(810, 100, bias=False)\n", - " self.iaf4 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - "\n", - " self.fc2 = nn.Linear(100, 100, bias=False)\n", - " self.iaf5 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - "\n", - " self.fc3 = nn.Linear(100, 100, bias=False)\n", - " self.iaf6 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - "\n", - " self.fc4 = nn.Linear(100, 11, bias=False)\n", - " self.iaf7 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - "\n", - " self.merge_fc = sl.Merge()\n", - " self.merge_conv = sl.Merge()\n", - "\n", - " def detach_neuron_states(self):\n", - " for name, layer in self.named_modules():\n", - " if name != '':\n", - " if isinstance(layer, sl.StatefulLayer):\n", - " for name, buffer in layer.named_buffers():\n", - " buffer.detach_()\n", - "\n", - " def init_weights(self):\n", - " for name, layer in self.named_modules():\n", - " if isinstance(layer, nn.Conv2d) or isinstance(layer, nn.Linear):\n", - " nn.init.xavier_normal_(layer.weight.data)\n", - "\n", - " def forward(self, x):\n", - " \n", - " con1_out = self.conv1(x)\n", - " iaf1_out = self.iaf1(con1_out)\n", - " pool1_out = self.pool1(iaf1_out)\n", - " pool1a_out = self.pool1a(iaf1_out)\n", - "\n", - " conv2_out = self.conv2(pool1_out)\n", - " iaf2_out = self.iaf2(conv2_out)\n", - " pool2_out = self.pool2(iaf2_out)\n", - "\n", - " merged_conv_out = self.merge_conv(pool1a_out, pool2_out)\n", - "\n", - " conv3_out = self.conv3(merged_conv_out)\n", - " iaf3_out = self.iaf3(conv3_out)\n", - " pool3_out = self.pool3(iaf3_out)\n", - "\n", - " flat_out = self.flat(pool3_out)\n", - " \n", - " fc1_out = self.fc1(flat_out)\n", - " iaf4_out = self.iaf4(fc1_out)\n", - "\n", - " fc2_out = self.fc2(iaf4_out)\n", - " iaf5_out = self.iaf5(fc2_out)\n", - "\n", - " fc3_out = self.fc3(iaf5_out)\n", - " iaf6_out = self.iaf6(fc3_out)\n", - "\n", - " merge_fc_out = self.merge_fc(iaf4_out, iaf6_out)\n", - "\n", - " fc4_out = self.fc4(merge_fc_out)\n", - " iaf7_out = self.iaf7(fc4_out)\n", - "\n", - " return iaf7_out" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [], - "source": [ - "snn = SNN().to(device)" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [], - "source": [ - "snn.init_weights()" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [], - "source": [ - "optimizer = Adam(snn.parameters(), lr=lr, betas=(0.9, 0.999), eps=1e-8)\n", - "loss_fn = CrossEntropyLoss()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Define train and test" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [], - "source": [ - "def train(dataloader, model, loss_fn, optimizer, epochs, test_func, dataloader_test):\n", - " epochs_y = []\n", - " epochs_x = []\n", - " epochs_acc = []\n", - " model.train()\n", - "\n", - " for e in range(epochs):\n", - " losses = []\n", - " batches = []\n", - " batch_count = 0\n", - " train_p_bar = tqdm(snn_train_dataloader)\n", - "\n", - " for X, y in train_p_bar:\n", - " # reshape the input from [Batch, Time, Channel, Height, Width] into [Batch*Time, Channel, Height, Width]\n", - " X = X.reshape(-1, 2, 128, 128).to(dtype=torch.float, device=device)\n", - " y = y.to(dtype=torch.long, device=device)\n", - "\n", - " # forward\n", - " pred = model(X)\n", - "\n", - " # reshape the output from [Batch*Time,num_classes] into [Batch, Time, num_classes]\n", - " pred = pred.reshape(batch_size, n_time_steps, -1)\n", - "\n", - " # accumulate all time-steps output for final prediction\n", - " pred = pred.sum(dim = 1)\n", - " loss = loss_fn(pred, y)\n", - "\n", - " # gradient update\n", - " optimizer.zero_grad()\n", - " loss.backward()\n", - " optimizer.step()\n", - "\n", - " # detach the neuron states and activations from current computation graph(necessary)\n", - " model.detach_neuron_states()\n", - "\n", - " train_p_bar.set_description(f\"Epoch {e} - BPTT Training Loss: {round(loss.item(), 4)}\")\n", - "\n", - " batch_count += 1\n", - " losses.append(loss.item())\n", - " batches.append(batch_count)\n", - "\n", - " epochs_y.append(losses)\n", - " epochs_x.append(batches)\n", - "\n", - " acc = test_func(dataloader_test, model)\n", - " print(f'Epoch {e} accuracy: {acc}')\n", - " epochs_acc.append(acc)\n", - "\n", - " return epochs_x, epochs_y, epochs_acc\n" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [], - "source": [ - "def test(dataloader, model):\n", - " correct_predictions = []\n", - " with torch.no_grad():\n", - " test_p_bar = tqdm(dataloader)\n", - " for X, y in test_p_bar:\n", - " # reshape the input from [Batch, Time, Channel, Height, Width] into [Batch*Time, Channel, Height, Width]\n", - " X = X.reshape(-1, 2, 128, 128).to(dtype=torch.float, device=device)\n", - " y = y.to(dtype=torch.long, device=device)\n", - "\n", - " # forward\n", - " output = model(X)\n", - "\n", - " # reshape the output from [Batch*Time,num_classes] into [Batch, Time, num_classes]\n", - " output = output.reshape(batch_size, n_time_steps, -1)\n", - "\n", - " # accumulate all time-steps output for final prediction\n", - " output = output.sum(dim=1)\n", - "\n", - " # calculate accuracy\n", - " pred = output.argmax(dim=1, keepdim=True)\n", - "\n", - " # compute the total correct predictions\n", - " correct_predictions.append(pred.eq(y.view_as(pred)))\n", - "\n", - " test_p_bar.set_description(f\"Testing Model...\")\n", - " \n", - " correct_predictions = torch.cat(correct_predictions)\n", - " return correct_predictions.sum().item()/(len(correct_predictions))*100" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Training loop (HPO)" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "12d134e3b89e41888c9c47892b8e6491", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - " 0%| | 0/359 [00:00" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "y_avg = []\n", - "for y in epochs_y:\n", - " y_avg.append(np.mean(y))\n", - "\n", - "plt.plot(np.arange(len(epochs_x)), y_avg, marker = '.')\n", - "plt.xlabel('epoch')\n", - "plt.ylabel('average loss')\n", - "plt.ylim(0,)\n", - "plt.xticks(np.arange(len(epochs_x)))\n", - "for i, txt in enumerate(y_avg):\n", - " if i%5 == 0:\n", - " plt.text(i, txt, f'{txt:.2f}', ha='center', va='bottom', color = 'k')\n", - " else:\n", - " pass\n", - "plt.show()" - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjsAAAG2CAYAAACZEEfAAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8fJSN1AAAACXBIWXMAAA9hAAAPYQGoP6dpAABq60lEQVR4nO3dd1hT1+MG8DfsHUW2TAfixK3gqqO46q6jtVWr1bZi62idraPVFrWt7dfROn5urauOOloXrqqooOBEBERBZYhI2DPn9weaGlmJBIH4fp4nT8vNPfecQMx9c+6550iEEAJEREREWkqnohtAREREVJ4YdoiIiEirMewQERGRVmPYISIiIq3GsENERERajWGHiIiItBrDDhEREWk1hh0iIiLSagw7REREpNUYdoiIiEirVWjYOXPmDPr06QMHBwdIJBLs27dP6XkhBObMmQN7e3sYGxujW7duCA8PV9onKSkJw4cPh4WFBapVq4YxY8YgLS3tNb4KIiIiqswqNOykp6fD09MTK1asKPL5xYsXY+nSpVi5ciUuXrwIU1NTdO/eHVlZWYp9hg8fjps3b+LYsWM4ePAgzpw5g3Hjxr2ul0BERESVnKSyLAQqkUiwd+9e9O/fH0BBr46DgwO+/PJLfPXVVwAAmUwGW1tbbNiwAcOGDUNoaCgaNGiAwMBAtGzZEgBw+PBh9OrVCw8ePICDg0NFvRwiIiKqJPQqugHFiYqKQlxcHLp166bYJpVK0aZNGwQEBGDYsGEICAhAtWrVFEEHALp16wYdHR1cvHgRAwYMKPLY2dnZyM7OVvwsl8uRlJSEGjVqQCKRlN+LIiIiIo0RQiA1NRUODg7Q0Sn+YlWlDTtxcXEAAFtbW6Xttra2iufi4uJgY2Oj9Lyenh4sLS0V+xTFz88P3377rYZbTERERBUhJiYGjo6OxT5facNOeZo5cyamTJmi+Fkmk8HZ2RkxMTGwsLCowJYRERGRqlJSUuDk5ARzc/MS96u0YcfOzg4AEB8fD3t7e8X2+Ph4NG3aVLFPQkKCUrm8vDwkJSUpyhfF0NAQhoaGhbZbWFgw7BAREVUxpQ1BqbTz7Li5ucHOzg7+/v6KbSkpKbh48SK8vLwAAF5eXkhOTsbly5cV+5w4cQJyuRxt2rR57W0mIiKiyqdCe3bS0tIQERGh+DkqKgohISGwtLSEs7MzJk2ahAULFqBu3bpwc3PD7Nmz4eDgoLhjq379+ujRowfGjh2LlStXIjc3FxMmTMCwYcN4JxYREREBqOCwExQUhM6dOyt+fj6OZuTIkdiwYQOmTZuG9PR0jBs3DsnJyWjfvj0OHz4MIyMjRZmtW7diwoQJ6Nq1K3R0dDBo0CAsXbr0tb8WIiIiqpwqzTw7FSklJQVSqRQymYxjdoiIiKoIVc/flXbMDhEREZEmMOwQERGRVmPYISIiIq3GsENERERajWGHiIiItBrDDhEREWk1hh0iIiLSagw7REREpNUYdoiIiEirMewQERGRVmPYISIiIq3GsENERERajWGHiIiItBrDDhEREWk1hh0iIiLSagw7REREpNUYdoiIiEirMewQERGRVmPYISIiIq3GsENERERajWGHiIiItBrDDhEREWk1hh0iIiLSagw7REREpNUYdoiIiEirMewQERGRVmPYISIiIq3GsENERERajWGHiIiItBrDDhEREWk1hh0iIiLSagw7REREpNUYdoiIiEqQn5+P2bNnw83NDcbGxqhduzbmz58PIYRin1GjRkEikSg9evToUeJxU1NTMWnSJLi4uMDY2Bje3t4IDAxU2ictLQ0TJkyAo6MjjI2N0aBBA6xcubJcXqc206voBhAREVVmixYtwu+//46NGzeiYcOGCAoKwkcffQSpVIovvvhCsV+PHj2wfv16xc+GhoYlHvfjjz/GjRs3sHnzZjg4OGDLli3o1q0bbt26hZo1awIApkyZghMnTmDLli1wdXXF0aNHMX78eDg4OKBv377l84K1EHt2iIiISnD+/Hn069cPvXv3hqurK9599134+Pjg0qVLSvsZGhrCzs5O8ahevXqxx8zMzMTu3buxePFidOzYEXXq1MG8efNQp04d/P7770p1jxw5Em+99RZcXV0xbtw4eHp6FqqbSsawQ0T0hiivyzF+fn5o1aoVzM3NYWNjg/79+yMsLExpn08++QS1a9eGsbExalhZo0O3njgTGFIeL1PjvL294e/vjzt37gAArl69irNnz6Jnz55K+506dQo2NjaoV68ePvvsMzx58qTYY+bl5SE/Px9GRkZK242NjXH27Fmluvfv34+HDx9CCIGTJ0/izp078PHx0eArfAMIEjKZTAAQMpmsoptCRFRuvv/+e1GjRg1x8OBBERUVJXbt2iXMzMzE//73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DBTPGRgYwNPTE1999ZXmW0hERERUBiqHnZMnTwIouPX7f//7H8e2EBERUZWg9t1Y69evL492EBEREZULtQcoExEREVUlDDtERESk1Rh2iIiISKsx7BAREZFWY9ghIiIircawQ0RERFqNYYeIiIi0GsMOERERaTWGHSIiItJqDDtERESk1Rh2iIiISKsx7BAREZFWY9ghIiIircawQ0RERFqNYYeIiIi0GsMOERERaTWGHSIiItJqDDtERESk1Rh2iIiISKsx7BAREZFWY9ghIiIircawQ0RERFqNYYeIiIi0GsMOERERaTWGHSIiItJqDDtERESk1Rh2iIiISKsx7BAREZFWY9ghIiIircawQ0RERFqNYYeIiIi0GsMOERERaTWGHSIiItJqDDtERESk1Rh2iIiISKsx7BAREZFWY9ghIiIircawQ0RERFqNYYeIiIi0GsMOERERaTWGHSIiItJqDDtERESk1Rh2iIiISKsx7BAREZFWY9ghIiIircawQ0RERFqNYYeIiIi0GsMOERERaTWGHSIiItJqDDtERESk1Rh2iIiISKsx7BAREZFWY9ghIiIircawQ0RERFqNYYeIiIi0GsMOERERaTWGHSIiItJqDDtERESk1Sp12PHz80OrVq1gbm4OGxsb9O/fH2FhYUr7ZGVlwdfXFzVq1ICZmRkGDRqE+Pj4CmoxERERVTaVOuycPn0avr6+uHDhAo4dO4bc3Fz4+PggPT1dsc/kyZNx4MAB7Nq1C6dPn8ajR48wcODACmw1ERERVSYSIYSo6Eao6vHjx7CxscHp06fRsWNHyGQyWFtb448//sC7774LALh9+zbq16+PgIAAtG3bVqXjpqSkQCqVQiaTwcLCojxfAhEREWmIqufvSt2z8zKZTAYAsLS0BABcvnwZubm56Natm2IfDw8PODs7IyAgoNjjZGdnIyUlRelBRERE2qnKhB25XI5JkyahXbt2aNSoEQAgLi4OBgYGqFatmtK+tra2iIuLK/ZYfn5+kEqlioeTk1N5Np2IiIgqUJUJO76+vrhx4wa2b99e5mPNnDkTMplM8YiJidFAC4mIiKgy0qvoBqhiwoQJOHjwIM6cOQNHR0fFdjs7O+Tk5CA5OVmpdyc+Ph52dnbFHs/Q0BCGhobl2WQiIiKqJCp1z44QAhMmTMDevXtx4sQJuLm5KT3fokUL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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "plt.plot(np.arange(len(epochs_x)), epochs_acc, marker = '.')\n", - "plt.xlabel('epoch')\n", - "plt.ylabel('test accuracy')\n", - "plt.ylim(0, 100)\n", - "plt.xticks(np.arange(len(epochs_x)))\n", - "for i, txt in enumerate(epochs_acc):\n", - " if i%5 == 0:\n", - " plt.text(i, txt, f'{txt:.2f}', ha='center', va='bottom', color = 'k')\n", - " else:\n", - " pass\n", - "plt.show()" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "speck-rescnn", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.3" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/tests/test_nonsequential/transfer-learning/baseline-SCNN-3.ipynb b/tests/test_nonsequential/transfer-learning/baseline-SCNN-3.ipynb deleted file mode 100644 index 5e27fd6f..00000000 --- a/tests/test_nonsequential/transfer-learning/baseline-SCNN-3.ipynb +++ /dev/null @@ -1,525 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "import torch, random\n", - "import torch.nn as nn\n", - "from tqdm.notebook import tqdm\n", - "\n", - "from tonic.transforms import ToFrame\n", - "from torch.utils.data import DataLoader\n", - "from torch.nn import CrossEntropyLoss\n", - "from torch.optim import Adam\n", - "\n", - "import matplotlib.pyplot as plt\n", - "import numpy as np\n", - "\n", - "from seq_model import SNN" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "torch.backends.cudnn.deterministic = True\n", - "random.seed(1)\n", - "torch.manual_seed(1)\n", - "torch.cuda.manual_seed(1)\n", - "np.random.seed(1)" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "batch_size = 3\n", - "batch_size_pre = 32\n", - "num_workers = 1\n", - "epochs_pretrain = 1\n", - "epochs = 30\n", - "lr = 1e-3\n", - "n_time_steps = 50" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "device: NVIDIA GeForce RTX 3070 Ti\n" - ] - } - ], - "source": [ - "if torch.cuda.is_available():\n", - " device = torch.device('cuda:0')\n", - " print('device: ', torch.cuda.get_device_name(0))\n", - "else:\n", - " device = torch.device('cpu')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Training/Testing helper functions" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "def train(batch_size, feature_map_size, dataloader_train, model, loss_fn, optimizer, epochs, test_func, dataloader_test, phase):\n", - " epochs_y = []\n", - " epochs_x = []\n", - " epochs_acc = []\n", - " model.train()\n", - "\n", - " for e in range(epochs):\n", - " losses = []\n", - " batches = []\n", - " batch_count = 0\n", - " train_p_bar = tqdm(dataloader_train)\n", - "\n", - " for X, y in train_p_bar:\n", - " # reshape the input from [Batch, Time, Channel, Height, Width] into [Batch*Time, Channel, Height, Width]\n", - " X = X.reshape(-1, feature_map_size[2], feature_map_size[0], feature_map_size[1]).to(dtype=torch.float, device=device)\n", - " y = y.to(dtype=torch.long, device=device)\n", - "\n", - " # forward\n", - " pred = model(X)\n", - "\n", - " # reshape the output from [Batch*Time,num_classes] into [Batch, Time, num_classes]\n", - " pred = pred.reshape(batch_size, n_time_steps, -1)\n", - "\n", - " # accumulate all time-steps output for final prediction\n", - " pred = pred.sum(dim = 1)\n", - " loss = loss_fn(pred, y)\n", - "\n", - " # gradient update\n", - " optimizer.zero_grad()\n", - " loss.backward()\n", - " optimizer.step()\n", - "\n", - " # detach the neuron states and activations from current computation graph(necessary)\n", - " model.detach_neuron_states()\n", - "\n", - " train_p_bar.set_description(f\"{phase} - Epoch {e} - BPTT Training Loss: {round(loss.item(), 4)}\")\n", - "\n", - " batch_count += 1\n", - " losses.append(loss.item())\n", - " batches.append(batch_count)\n", - "\n", - " epochs_y.append(losses)\n", - " epochs_x.append(batches)\n", - "\n", - " acc = test_func(feature_map_size, dataloader_test, model)\n", - " print(f'{phase} - Epoch {e} accuracy: {acc}')\n", - " epochs_acc.append(acc)\n", - "\n", - " return epochs_x, epochs_y, epochs_acc\n" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], - "source": [ - "def test(feature_map_size, dataloader, model):\n", - " correct_predictions = []\n", - " with torch.no_grad():\n", - " test_p_bar = tqdm(dataloader)\n", - " for X, y in test_p_bar:\n", - " # reshape the input from [Batch, Time, Channel, Height, Width] into [Batch*Time, Channel, Height, Width]\n", - " X = X.reshape(-1, feature_map_size[2], feature_map_size[0], feature_map_size[1]).to(dtype=torch.float, device=device)\n", - " y = y.to(dtype=torch.long, device=device)\n", - "\n", - " # forward\n", - " output = model(X)\n", - "\n", - " # reshape the output from [Batch*Time,num_classes] into [Batch, Time, num_classes]\n", - " output = output.reshape(batch_size, n_time_steps, -1)\n", - "\n", - " # accumulate all time-steps output for final prediction\n", - " output = output.sum(dim=1)\n", - "\n", - " # calculate accuracy\n", - " pred = output.argmax(dim=1, keepdim=True)\n", - "\n", - " # compute the total correct predictions\n", - " correct_predictions.append(pred.eq(y.view_as(pred)))\n", - "\n", - " test_p_bar.set_description(f\"Testing Model...\")\n", - " \n", - " correct_predictions = torch.cat(correct_predictions)\n", - " return correct_predictions.sum().item()/(len(correct_predictions))*100" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Pre-training loop" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Loading the pre-training data. Dataset used to pre-train the network such that its parameters are set within a \"good\" region of the parameters space (i.e., hopefully training on a \"simpler\" dataset sets the wheights to values that improve the training on a harder dataset)." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The transformed array is in shape [Time-Step, Channel, Height, Width] --> (50, 2, 34, 34)\n" - ] - } - ], - "source": [ - "from tonic.datasets.nmnist import NMNIST\n", - "\n", - "root_dir = \"../NMNIST\"\n", - "_ = NMNIST(save_to=root_dir, train=True)\n", - "_ = NMNIST(save_to=root_dir, train=False)\n", - "\n", - "to_raster = ToFrame(sensor_size=NMNIST.sensor_size, n_time_bins=n_time_steps)\n", - "\n", - "snn_train_dataset_pre = NMNIST(save_to=root_dir, train=True, transform=to_raster)\n", - "snn_test_dataset_pre = NMNIST(save_to=root_dir, train=False, transform=to_raster)\n", - "\n", - "sample_data, label = snn_train_dataset_pre[0]\n", - "print(f\"The transformed array is in shape [Time-Step, Channel, Height, Width] --> {sample_data.shape}\")\n", - "\n", - "snn_train_dataloader_pre = DataLoader(snn_train_dataset_pre, batch_size=batch_size_pre, num_workers=num_workers, drop_last=True, shuffle=True)\n", - "snn_test_dataloader_pre = DataLoader(snn_test_dataset_pre, batch_size=batch_size_pre, num_workers=num_workers, drop_last=True, shuffle=False)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "instantiating model..." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [], - "source": [ - "snn = SNN(10, 10, batch_size_pre).to(device)\n", - "snn.init_weights()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "loss and optimizer..." - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [], - "source": [ - "optimizer = Adam(snn.parameters(), lr=lr, betas=(0.9, 0.999), eps=1e-8)\n", - "loss_fn = CrossEntropyLoss()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "pre-training the model..." - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "a5bfe44485924a4a85b3357e62c24e75", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - " 0%| | 0/1875 [00:00 {sample_data.shape}\")\n", - "\n", - "snn_train_dataloader = DataLoader(snn_train_dataset, batch_size=batch_size, num_workers=num_workers, drop_last=True, shuffle=True)\n", - "snn_test_dataloader = DataLoader(snn_test_dataset, batch_size=batch_size, num_workers=num_workers, drop_last=True, shuffle=False)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "instantiating model..." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "snn = SNN(11, 810, batch_size).to(device)\n", - "snn.init_weights()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "loading weights from pre-training..." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "snn.load_conv_params()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "loss and optimizer..." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "optimizer = Adam(snn.parameters(), lr=lr, betas=(0.9, 0.999), eps=1e-8)\n", - "loss_fn = CrossEntropyLoss()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "training the model..." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "epochs_x_dvs128, epochs_y_dvs128, epochs_acc_dvs128 = train(\n", - " batch_size,\n", - " DVSGesture.sensor_size, \n", - " snn_train_dataloader, \n", - " snn, \n", - " loss_fn, \n", - " optimizer, \n", - " epochs, \n", - " test, \n", - " snn_test_dataloader,\n", - " 'post-training'\n", - " )" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "y_avg = []\n", - "for y in epochs_y_dvs128:\n", - " y_avg.append(np.mean(y))\n", - "\n", - "plt.plot(np.arange(len(epochs_x_dvs128)), y_avg, marker = '.')\n", - "plt.xlabel('epoch')\n", - "plt.ylabel('average loss')\n", - "plt.ylim(0,)\n", - "plt.xticks(np.arange(len(epochs_x_dvs128)))\n", - "for i, txt in enumerate(y_avg):\n", - " if i%2 == 0:\n", - " pass\n", - " else:\n", - " plt.text(i, txt, f'{txt:.2f}', ha='center', va='bottom', color = 'k')\n", - "plt.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "plt.plot(np.arange(len(epochs_x_dvs128)), epochs_acc_dvs128, marker = '.')\n", - "plt.xlabel('epoch')\n", - "plt.ylabel('test accuracy')\n", - "plt.ylim(0, 100)\n", - "plt.xticks(np.arange(len(epochs_x_dvs128)))\n", - "for i, txt in enumerate(epochs_acc_dvs128):\n", - " if i%2 == 0:\n", - " pass\n", - " else:\n", - " plt.text(i, txt, f'{txt:.2f}', ha='center', va='bottom', color = 'k')\n", - "plt.show()" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "speck-rescnn", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.3" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/tests/test_nonsequential/transfer-learning/seq_model.py b/tests/test_nonsequential/transfer-learning/seq_model.py deleted file mode 100644 index a109c47e..00000000 --- a/tests/test_nonsequential/transfer-learning/seq_model.py +++ /dev/null @@ -1,86 +0,0 @@ -import torch -import torch.nn as nn -import sinabs.layers as sl -from sinabs.activation.surrogate_gradient_fn import PeriodicExponential - -class SNN(nn.Module): - def __init__(self, nb_classes, pool2lin_size, batch_size) -> None: - super().__init__() - - self.conv1 = nn.Conv2d(2, 10, 2, 1, bias=False) - self.iaf1 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential()) - self.pool1 = nn.AvgPool2d(2,2) - - self.conv2 = nn.Conv2d(10, 10, 2, 1, bias=False) - self.iaf2 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential()) - self.pool2 = nn.AvgPool2d(3,3) - - self.conv3 = nn.Conv2d(10, 10, 3, 1, bias=False) - self.iaf3 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential()) - self.pool3 = nn.AvgPool2d(2,2) - - self.flat = nn.Flatten() - - self.fc1 = nn.Linear(pool2lin_size, 100, bias=False) - self.iaf4 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential()) - - self.fc2 = nn.Linear(100, 100, bias=False) - self.iaf5 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential()) - - self.fc3 = nn.Linear(100, 100, bias=False) - self.iaf6 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential()) - - self.fc4 = nn.Linear(100, nb_classes, bias=False) - self.iaf7 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential()) - - def export_conv_params(self): - torch.save(self.conv1.state_dict(), 'seq_conv1_weights.pth') - torch.save(self.conv2.state_dict(), 'seq_conv2_weights.pth') - torch.save(self.conv3.state_dict(), 'seq_conv3_weights.pth') - - def load_conv_params(self): - self.conv1.load_state_dict(torch.load('seq_conv1_weights.pth')) - self.conv2.load_state_dict(torch.load('seq_conv2_weights.pth')) - self.conv3.load_state_dict(torch.load('seq_conv3_weights.pth')) - - def detach_neuron_states(self): - for name, layer in self.named_modules(): - if name != '': - if isinstance(layer, sl.StatefulLayer): - for name, buffer in layer.named_buffers(): - buffer.detach_() - - def init_weights(self): - for name, layer in self.named_modules(): - if isinstance(layer, nn.Conv2d) or isinstance(layer, nn.Linear): - nn.init.xavier_normal_(layer.weight.data) - - def forward(self, x): - - con1_out = self.conv1(x) - iaf1_out = self.iaf1(con1_out) - pool1_out = self.pool1(iaf1_out) - - conv2_out = self.conv2(pool1_out) - iaf2_out = self.iaf2(conv2_out) - pool2_out = self.pool2(iaf2_out) - - conv3_out = self.conv3(pool2_out) - iaf3_out = self.iaf3(conv3_out) - pool3_out = self.pool3(iaf3_out) - - flat_out = self.flat(pool3_out) - - fc1_out = self.fc1(flat_out) - iaf4_out = self.iaf4(fc1_out) - - fc2_out = self.fc2(iaf4_out) - iaf5_out = self.iaf5(fc2_out) - - fc3_out = self.fc3(iaf5_out) - iaf6_out = self.iaf6(fc3_out) - - fc4_out = self.fc4(iaf6_out) - iaf7_out = self.iaf7(fc4_out) - - return iaf7_out \ No newline at end of file diff --git a/tests/test_nonsequential/using_AvgPool2d/exp_set_A/baseline-SCNN-example_3-SumPool.ipynb b/tests/test_nonsequential/using_AvgPool2d/exp_set_A/baseline-SCNN-example_3-SumPool.ipynb deleted file mode 100644 index a25e3392..00000000 --- a/tests/test_nonsequential/using_AvgPool2d/exp_set_A/baseline-SCNN-example_3-SumPool.ipynb +++ /dev/null @@ -1,1539 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "import torch, random, sys\n", - "import torch.nn as nn\n", - "import sinabs.layers as sl\n", - "from tqdm.notebook import tqdm\n", - "\n", - "from tonic.datasets.dvsgesture import DVSGesture\n", - "from tonic.transforms import ToFrame\n", - "from torch.utils.data import DataLoader\n", - "from torch.nn import CrossEntropyLoss\n", - "from torch.optim import Adam\n", - "\n", - "from sinabs.activation.surrogate_gradient_fn import PeriodicExponential\n", - "from sinabs.exodus.layers import IAFSqueeze\n", - "\n", - "import matplotlib.pyplot as plt\n", - "import numpy as np\n", - "\n", - "sys.path.append('../../utils')\n", - "\n", - "from weight_initialization import rescale_method_1\n", - "import tonic" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "torch.backends.cudnn.enabled = False\n", - "torch.backends.cudnn.deterministic = True\n", - "random.seed(1)\n", - "torch.manual_seed(1)\n", - "torch.cuda.manual_seed(1)\n", - "np.random.seed(1)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Loading Data" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "batch_size = 3\n", - "num_workers = 1\n", - "epochs = 30\n", - "lr = 1e-3" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "root_dir = \"../../DVSGESTURE\"\n", - "_ = DVSGesture(save_to=root_dir, train=True)\n", - "_ = DVSGesture(save_to=root_dir, train=False)" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "n_time_steps = 50\n", - "to_raster = ToFrame(sensor_size=DVSGesture.sensor_size, n_time_bins=n_time_steps)\n", - "\n", - "snn_train_dataset = DVSGesture(save_to=root_dir, train=True, transform=to_raster)\n", - "snn_test_dataset = DVSGesture(save_to=root_dir, train=False, transform=to_raster)" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The transformed array is in shape [Time-Step, Channel, Height, Width] --> (50, 2, 128, 128)\n" - ] - } - ], - "source": [ - "sample_data, label = snn_train_dataset[0]\n", - "print(f\"The transformed array is in shape [Time-Step, Channel, Height, Width] --> {sample_data.shape}\")" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [], - "source": [ - "disk_cache_train = tonic.DiskCachedDataset(\n", - " dataset=snn_train_dataset,\n", - " cache_path='./cached_train'\n", - ")\n", - "snn_train_dataloader = DataLoader(disk_cache_train, batch_size=batch_size, num_workers=num_workers, drop_last=True, shuffle=True)\n", - "\n", - "disk_cache_test = tonic.DiskCachedDataset(\n", - " dataset=snn_test_dataset,\n", - " cache_path='./cached_test'\n", - ")\n", - "snn_test_dataloader = DataLoader(disk_cache_test, batch_size=batch_size, num_workers=num_workers, drop_last=True, shuffle=False)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Network Module\n", - "\n", - "We need to define a `nn.Module` implementing the network we want the chip to reproduce." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "device: NVIDIA GeForce RTX 3070 Ti\n" - ] - } - ], - "source": [ - "if torch.cuda.is_available():\n", - " device = torch.device('cuda:0')\n", - " print('device: ', torch.cuda.get_device_name(0))\n", - "else:\n", - " device = torch.device('cpu')" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [], - "source": [ - "class SNN(nn.Module):\n", - " def __init__(self) -> None:\n", - " super().__init__()\n", - "\n", - " self.conv1 = nn.Conv2d(2, 10, 2, 1, bias=False)\n", - " self.iaf1 = IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - " self.pool1 = sl.SumPool2d(2,2)\n", - "\n", - " self.conv2 = nn.Conv2d(10, 10, 2, 1, bias=False)\n", - " self.iaf2 = IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - " self.pool2 = sl.SumPool2d(3,3)\n", - "\n", - " self.conv3 = nn.Conv2d(10, 10, 3, 1, bias=False)\n", - " self.iaf3 = IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - " self.pool3 = sl.SumPool2d(2,2)\n", - "\n", - " self.flat = nn.Flatten()\n", - "\n", - " self.fc1 = nn.Linear(810, 100, bias=False)\n", - " self.iaf4 = IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - "\n", - " self.fc2 = nn.Linear(100, 100, bias=False)\n", - " self.iaf5 = IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - "\n", - " self.fc3 = nn.Linear(100, 100, bias=False)\n", - " self.iaf6 = IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - "\n", - " self.fc4 = nn.Linear(100, 11, bias=False)\n", - " self.iaf7 = IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - "\n", - " def detach_neuron_states(self):\n", - " for name, layer in self.named_modules():\n", - " if name != '':\n", - " if isinstance(layer, sl.StatefulLayer):\n", - " for name, buffer in layer.named_buffers():\n", - " buffer.detach_()\n", - "\n", - " def init_weights(self):\n", - " for name, layer in self.named_modules():\n", - " if isinstance(layer, nn.Conv2d) or isinstance(layer, nn.Linear):\n", - " nn.init.xavier_normal_(layer.weight.data)\n", - "\n", - " def rescale_conv_weights(self, rescale_fn, lambda_):\n", - " rescale_fn(self.conv2, [(2, 2)], lambda_)\n", - " rescale_fn(self.conv3, [(3, 3)], lambda_)\n", - "\n", - " def forward(self, x):\n", - " \n", - " con1_out = self.conv1(x)\n", - " iaf1_out = self.iaf1(con1_out)\n", - " pool1_out = self.pool1(iaf1_out)\n", - "\n", - " conv2_out = self.conv2(pool1_out)\n", - " iaf2_out = self.iaf2(conv2_out)\n", - " pool2_out = self.pool2(iaf2_out)\n", - "\n", - " conv3_out = self.conv3(pool2_out)\n", - " iaf3_out = self.iaf3(conv3_out)\n", - " pool3_out = self.pool3(iaf3_out)\n", - "\n", - " flat_out = self.flat(pool3_out)\n", - " \n", - " fc1_out = self.fc1(flat_out)\n", - " iaf4_out = self.iaf4(fc1_out)\n", - "\n", - " fc2_out = self.fc2(iaf4_out)\n", - " iaf5_out = self.iaf5(fc2_out)\n", - "\n", - " fc3_out = self.fc3(iaf5_out)\n", - " iaf6_out = self.iaf6(fc3_out)\n", - "\n", - " fc4_out = self.fc4(iaf6_out)\n", - " iaf7_out = self.iaf7(fc4_out)\n", - "\n", - " return iaf7_out" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [], - "source": [ - "snn = SNN().to(device)" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [], - "source": [ - "snn.init_weights()" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "recaling factor: 2.0 (computed using 1 kernels and lambda 0.5)\n", - "recaling factor: 4.5 (computed using 1 kernels and lambda 0.5)\n" - ] - } - ], - "source": [ - "lambda_ = 0.5\n", - "snn.rescale_conv_weights(rescale_method_1, lambda_)" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [], - "source": [ - "optimizer = Adam(snn.parameters(), lr=lr, betas=(0.9, 0.999), eps=1e-8)\n", - "loss_fn = CrossEntropyLoss()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Define train and test" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [], - "source": [ - "def train(dataloader, model, loss_fn, optimizer, epochs, test_func, dataloader_test):\n", - " epochs_y = []\n", - " epochs_x = []\n", - " epochs_acc = []\n", - " model.train()\n", - "\n", - " for e in range(epochs):\n", - " losses = []\n", - " batches = []\n", - " batch_count = 0\n", - " train_p_bar = tqdm(snn_train_dataloader)\n", - "\n", - " for X, y in train_p_bar:\n", - " # reshape the input from [Batch, Time, Channel, Height, Width] into [Batch*Time, Channel, Height, Width]\n", - " X = X.reshape(-1, 2, 128, 128).to(dtype=torch.float, device=device)\n", - " y = y.to(dtype=torch.long, device=device)\n", - "\n", - " # forward\n", - " pred = model(X)\n", - "\n", - " # reshape the output from [Batch*Time,num_classes] into [Batch, Time, num_classes]\n", - " pred = pred.reshape(batch_size, n_time_steps, -1)\n", - "\n", - " # accumulate all time-steps output for final prediction\n", - " pred = pred.sum(dim = 1)\n", - " loss = loss_fn(pred, y)\n", - "\n", - " # gradient update\n", - " optimizer.zero_grad()\n", - " loss.backward()\n", - " optimizer.step()\n", - "\n", - " # detach the neuron states and activations from current computation graph(necessary)\n", - " model.detach_neuron_states()\n", - "\n", - " train_p_bar.set_description(f\"Epoch {e} - BPTT Training Loss: {round(loss.item(), 4)}\")\n", - "\n", - " batch_count += 1\n", - " losses.append(loss.item())\n", - " batches.append(batch_count)\n", - "\n", - " epochs_y.append(losses)\n", - " epochs_x.append(batches)\n", - "\n", - " acc = test_func(dataloader_test, model)\n", - " print(f'Epoch {e} accuracy: {acc}')\n", - " epochs_acc.append(acc)\n", - "\n", - " return epochs_x, epochs_y, epochs_acc\n" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [], - "source": [ - "def test(dataloader, model):\n", - " correct_predictions = []\n", - " with torch.no_grad():\n", - " test_p_bar = tqdm(dataloader)\n", - " for X, y in test_p_bar:\n", - " # reshape the input from [Batch, Time, Channel, Height, Width] into [Batch*Time, Channel, Height, Width]\n", - " X = X.reshape(-1, 2, 128, 128).to(dtype=torch.float, device=device)\n", - " y = y.to(dtype=torch.long, device=device)\n", - "\n", - " # forward\n", - " output = model(X)\n", - "\n", - " # reshape the output from [Batch*Time,num_classes] into [Batch, Time, num_classes]\n", - " output = output.reshape(batch_size, n_time_steps, -1)\n", - "\n", - " # accumulate all time-steps output for final prediction\n", - " output = output.sum(dim=1)\n", - "\n", - " # calculate accuracy\n", - " pred = output.argmax(dim=1, keepdim=True)\n", - "\n", - " # compute the total correct predictions\n", - " correct_predictions.append(pred.eq(y.view_as(pred)))\n", - "\n", - " test_p_bar.set_description(f\"Testing Model...\")\n", - " \n", - " correct_predictions = torch.cat(correct_predictions)\n", - " return correct_predictions.sum().item()/(len(correct_predictions))*100" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Training loop" - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "d7307153ad334c27a70afe651a5daaf4", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - " 0%| | 0/359 [00:00" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "y_avg = []\n", - "for y in epochs_y:\n", - " y_avg.append(np.mean(y))\n", - "\n", - "plt.plot(np.arange(len(epochs_x)), y_avg, marker = '.')\n", - "plt.xlabel('epoch')\n", - "plt.ylabel('average loss')\n", - "plt.ylim(0,)\n", - "plt.xticks(np.arange(len(epochs_x)))\n", - "for i, txt in enumerate(y_avg):\n", - " if i%2 == 0:\n", - " pass\n", - " else:\n", - " plt.text(i, txt, f'{txt:.2f}', ha='center', va='bottom', color = 'k')\n", - "plt.show()" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "plt.plot(np.arange(len(epochs_x)), epochs_acc, marker = '.')\n", - "plt.xlabel('epoch')\n", - "plt.ylabel('test accuracy')\n", - "plt.ylim(0, 100)\n", - "plt.xticks(np.arange(len(epochs_x)))\n", - "for i, txt in enumerate(epochs_acc):\n", - " if i%2 == 0:\n", - " pass\n", - " else:\n", - " plt.text(i, txt, f'{txt:.2f}', ha='center', va='bottom', color = 'k')\n", - "plt.show()" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "speck-rescnn", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.10.0" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/tests/test_nonsequential/using_AvgPool2d/exp_set_A/baseline-SCNN-example_3.ipynb b/tests/test_nonsequential/using_AvgPool2d/exp_set_A/baseline-SCNN-example_3.ipynb deleted file mode 100644 index dc53313a..00000000 --- a/tests/test_nonsequential/using_AvgPool2d/exp_set_A/baseline-SCNN-example_3.ipynb +++ /dev/null @@ -1,1500 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "import torch, random\n", - "import torch.nn as nn\n", - "import sinabs.layers as sl\n", - "from tqdm.notebook import tqdm\n", - "\n", - "from tonic.datasets.dvsgesture import DVSGesture\n", - "from tonic.transforms import ToFrame\n", - "from torch.utils.data import DataLoader\n", - "from torch.nn import CrossEntropyLoss\n", - "from torch.optim import Adam\n", - "\n", - "from sinabs.activation.surrogate_gradient_fn import PeriodicExponential\n", - "\n", - "import matplotlib.pyplot as plt\n", - "import numpy as np" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "torch.backends.cudnn.deterministic = True\n", - "random.seed(1)\n", - "torch.manual_seed(1)\n", - "torch.cuda.manual_seed(1)\n", - "np.random.seed(1)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Loading Data" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "batch_size = 3\n", - "num_workers = 1\n", - "epochs = 30\n", - "lr = 1e-3" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "root_dir = \"./DVSGESTURE\"\n", - "_ = DVSGesture(save_to=root_dir, train=True)\n", - "_ = DVSGesture(save_to=root_dir, train=False)" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "n_time_steps = 50\n", - "to_raster = ToFrame(sensor_size=DVSGesture.sensor_size, n_time_bins=n_time_steps)\n", - "\n", - "snn_train_dataset = DVSGesture(save_to=root_dir, train=True, transform=to_raster)\n", - "snn_test_dataset = DVSGesture(save_to=root_dir, train=False, transform=to_raster)" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The transformed array is in shape [Time-Step, Channel, Height, Width] --> (50, 2, 128, 128)\n" - ] - } - ], - "source": [ - "sample_data, label = snn_train_dataset[0]\n", - "print(f\"The transformed array is in shape [Time-Step, Channel, Height, Width] --> {sample_data.shape}\")" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [], - "source": [ - "snn_train_dataloader = DataLoader(snn_train_dataset, batch_size=batch_size, num_workers=num_workers, drop_last=True, shuffle=True)\n", - "snn_test_dataloader = DataLoader(snn_test_dataset, batch_size=batch_size, num_workers=num_workers, drop_last=True, shuffle=False)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Network Module\n", - "\n", - "We need to define a `nn.Module` implementing the network we want the chip to reproduce." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "device: NVIDIA RTX A4000\n" - ] - } - ], - "source": [ - "if torch.cuda.is_available():\n", - " device = torch.device('cuda:0')\n", - " print('device: ', torch.cuda.get_device_name(0))\n", - "else:\n", - " device = torch.device('cpu')" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [], - "source": [ - "class SNN(nn.Module):\n", - " def __init__(self) -> None:\n", - " super().__init__()\n", - "\n", - " self.conv1 = nn.Conv2d(2, 10, 2, 1, bias=False)\n", - " self.iaf1 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - " self.pool1 = nn.AvgPool2d(2,2)\n", - "\n", - " self.conv2 = nn.Conv2d(10, 10, 2, 1, bias=False)\n", - " self.iaf2 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - " self.pool2 = nn.AvgPool2d(3,3)\n", - "\n", - " self.conv3 = nn.Conv2d(10, 10, 3, 1, bias=False)\n", - " self.iaf3 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - " self.pool3 = nn.AvgPool2d(2,2)\n", - "\n", - " self.flat = nn.Flatten()\n", - "\n", - " self.fc1 = nn.Linear(810, 100, bias=False)\n", - " self.iaf4 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - "\n", - " self.fc2 = nn.Linear(100, 100, bias=False)\n", - " self.iaf5 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - "\n", - " self.fc3 = nn.Linear(100, 100, bias=False)\n", - " self.iaf6 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - "\n", - " self.fc4 = nn.Linear(100, 11, bias=False)\n", - " self.iaf7 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - "\n", - " def detach_neuron_states(self):\n", - " for name, layer in self.named_modules():\n", - " if name != '':\n", - " if isinstance(layer, sl.StatefulLayer):\n", - " for name, buffer in layer.named_buffers():\n", - " buffer.detach_()\n", - "\n", - " def init_weights(self):\n", - " for name, layer in self.named_modules():\n", - " if isinstance(layer, nn.Conv2d) or isinstance(layer, nn.Linear):\n", - " nn.init.xavier_normal_(layer.weight.data)\n", - "\n", - " def forward(self, x):\n", - " \n", - " con1_out = self.conv1(x)\n", - " iaf1_out = self.iaf1(con1_out)\n", - " pool1_out = self.pool1(iaf1_out)\n", - "\n", - " conv2_out = self.conv2(pool1_out)\n", - " iaf2_out = self.iaf2(conv2_out)\n", - " pool2_out = self.pool2(iaf2_out)\n", - "\n", - " conv3_out = self.conv3(pool2_out)\n", - " iaf3_out = self.iaf3(conv3_out)\n", - " pool3_out = self.pool3(iaf3_out)\n", - "\n", - " flat_out = self.flat(pool3_out)\n", - " \n", - " fc1_out = self.fc1(flat_out)\n", - " iaf4_out = self.iaf4(fc1_out)\n", - "\n", - " fc2_out = self.fc2(iaf4_out)\n", - " iaf5_out = self.iaf5(fc2_out)\n", - "\n", - " fc3_out = self.fc3(iaf5_out)\n", - " iaf6_out = self.iaf6(fc3_out)\n", - "\n", - " fc4_out = self.fc4(iaf6_out)\n", - " iaf7_out = self.iaf7(fc4_out)\n", - "\n", - " return iaf7_out" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [], - "source": [ - "snn = SNN().to(device)" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [], - "source": [ - "snn.init_weights()" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [], - "source": [ - "optimizer = Adam(snn.parameters(), lr=lr, betas=(0.9, 0.999), eps=1e-8)\n", - "loss_fn = CrossEntropyLoss()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Define train and test" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [], - "source": [ - "def train(dataloader, model, loss_fn, optimizer, epochs, test_func, dataloader_test):\n", - " epochs_y = []\n", - " epochs_x = []\n", - " epochs_acc = []\n", - " model.train()\n", - "\n", - " for e in range(epochs):\n", - " losses = []\n", - " batches = []\n", - " batch_count = 0\n", - " train_p_bar = tqdm(snn_train_dataloader)\n", - "\n", - " for X, y in train_p_bar:\n", - " # reshape the input from [Batch, Time, Channel, Height, Width] into [Batch*Time, Channel, Height, Width]\n", - " X = X.reshape(-1, 2, 128, 128).to(dtype=torch.float, device=device)\n", - " y = y.to(dtype=torch.long, device=device)\n", - "\n", - " # forward\n", - " pred = model(X)\n", - "\n", - " # reshape the output from [Batch*Time,num_classes] into [Batch, Time, num_classes]\n", - " pred = pred.reshape(batch_size, n_time_steps, -1)\n", - "\n", - " # accumulate all time-steps output for final prediction\n", - " pred = pred.sum(dim = 1)\n", - " loss = loss_fn(pred, y)\n", - "\n", - " # gradient update\n", - " optimizer.zero_grad()\n", - " loss.backward()\n", - " optimizer.step()\n", - "\n", - " # detach the neuron states and activations from current computation graph(necessary)\n", - " model.detach_neuron_states()\n", - "\n", - " train_p_bar.set_description(f\"Epoch {e} - BPTT Training Loss: {round(loss.item(), 4)}\")\n", - "\n", - " batch_count += 1\n", - " losses.append(loss.item())\n", - " batches.append(batch_count)\n", - "\n", - " epochs_y.append(losses)\n", - " epochs_x.append(batches)\n", - "\n", - " acc = test_func(dataloader_test, model)\n", - " print(f'Epoch {e} accuracy: {acc}')\n", - " epochs_acc.append(acc)\n", - "\n", - " return epochs_x, epochs_y, epochs_acc\n" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [], - "source": [ - "def test(dataloader, model):\n", - " correct_predictions = []\n", - " with torch.no_grad():\n", - " test_p_bar = tqdm(dataloader)\n", - " for X, y in test_p_bar:\n", - " # reshape the input from [Batch, Time, Channel, Height, Width] into [Batch*Time, Channel, Height, Width]\n", - " X = X.reshape(-1, 2, 128, 128).to(dtype=torch.float, device=device)\n", - " y = y.to(dtype=torch.long, device=device)\n", - "\n", - " # forward\n", - " output = model(X)\n", - "\n", - " # reshape the output from [Batch*Time,num_classes] into [Batch, Time, num_classes]\n", - " output = output.reshape(batch_size, n_time_steps, -1)\n", - "\n", - " # accumulate all time-steps output for final prediction\n", - " output = output.sum(dim=1)\n", - "\n", - " # calculate accuracy\n", - " pred = output.argmax(dim=1, keepdim=True)\n", - "\n", - " # compute the total correct predictions\n", - " correct_predictions.append(pred.eq(y.view_as(pred)))\n", - "\n", - " test_p_bar.set_description(f\"Testing Model...\")\n", - " \n", - " correct_predictions = torch.cat(correct_predictions)\n", - " return correct_predictions.sum().item()/(len(correct_predictions))*100" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Training loop" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "ebf2bea3d0124365abf1f2aa248ceab6", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - " 0%| | 0/359 [00:00" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "y_avg = []\n", - "for y in epochs_y:\n", - " y_avg.append(np.mean(y))\n", - "\n", - "plt.plot(np.arange(len(epochs_x)), y_avg, marker = '.')\n", - "plt.xlabel('epoch')\n", - "plt.ylabel('average loss')\n", - "plt.ylim(0,)\n", - "plt.xticks(np.arange(len(epochs_x)))\n", - "for i, txt in enumerate(y_avg):\n", - " if i%2 == 0:\n", - " pass\n", - " else:\n", - " plt.text(i, txt, f'{txt:.2f}', ha='center', va='bottom', color = 'k')\n", - "plt.show()" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjsAAAG2CAYAAACZEEfAAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8fJSN1AAAACXBIWXMAAA9hAAAPYQGoP6dpAAB9HElEQVR4nO3dd1RUx98G8GfpRUB6kaqg2HvB3oIt9qiJJjHGWH5irLFgYkw0ETWJJsbE9ipqrDGxG3vBhgiKXSmKglQLLL3uvH8QNq60XYrg+nzO2XNk7p07c3evu987d4pECCFAREREpKY0qroCRERERJWJwQ4RERGpNQY7REREpNYY7BAREZFaY7BDREREao3BDhEREak1BjtERESk1hjsEBERkVpjsENERERqjcEOERERqbUqDXbOnTuH/v37w87ODhKJBPv27VPYLoTA119/DVtbW+jr66Nnz54ICwtT2OfFixcYNWoUjI2NUbNmTYwdOxapqamv8SyIiIioOqvSYCctLQ1NmzbFb7/9VuT2ZcuWYeXKlVizZg0CAgJgaGiIXr16ITMzU77PqFGjcOfOHZw4cQKHDh3CuXPnMH78+Nd1CkRERFTNSarLQqASiQR79+7FoEGDAOS36tjZ2WHmzJn44osvAABSqRTW1tbYtGkT3n//fdy7dw8NGjRAYGAgWrVqBQA4evQo+vbtiydPnsDOzq6qToeIiIiqCa2qrkBxIiIiEBcXh549e8rTTExM0LZtW/j7++P999+Hv78/atasKQ90AKBnz57Q0NBAQEAABg8eXOSxs7KykJWVJf9bJpPhxYsXMDc3h0QiqbyTIiIiogojhEBKSgrs7OygoVH8w6pqG+zExcUBAKytrRXSra2t5dvi4uJgZWWlsF1LSwtmZmbyfYri4+ODb7/9toJrTERERFUhKioK9vb2xW6vtsFOZfL29saMGTPkf0ulUjg6OiIqKgrGxsZVWDMiIiJSVnJyMhwcHGBkZFTiftU22LGxsQEAxMfHw9bWVp4eHx+PZs2ayfdJSEhQyJebm4sXL17I8xdFV1cXurq6hdKNjY0Z7BAREb1hSuuCUm3n2XFxcYGNjQ1OnTolT0tOTkZAQAA8PDwAAB4eHkhKSsLVq1fl+5w+fRoymQxt27Z97XUmIiKi6qdKW3ZSU1MRHh4u/zsiIgLXr1+HmZkZHB0dMW3aNHz33Xdwc3ODi4sL5s+fDzs7O/mIrfr166N3794YN24c1qxZg5ycHEyePBnvv/8+R2IRERERgCoOdoKCgtCtWzf53wX9aEaPHo1NmzZh9uzZSEtLw/jx45GUlISOHTvi6NGj0NPTk+fZtm0bJk+ejB49ekBDQwNDhw7FypUrX/u5EBERUfVUbebZqUrJyckwMTGBVCplnx0iIqI3hLK/39W2zw4RERFRRWCwQ0RERGqNwQ4RERGpNQY7REREpNYY7BAREZFaY7BDREREao3BDhEREak1BjtERESk1hjsEBERkVpjsENERERqjcEOERERqTUGO0RERKTWGOwQERGRWmOwQ0RERGqNwQ4RERGpNQY7REREpNYY7BAREZFaY7BDREREao3BDhEREak1BjtERESk1hjsEBERkVpjsENERERqjcEOERERqTUGO0RERKTWGOwQERGRWmOwQ0RERGqNwQ4RERGpNQY7REREpNYY7BAREZFaY7BDREREao3BDhEREak1BjtERESk1hjsEBERkVpjsENERERqjcEOERERqTUGO0RERKTWGOwQERGRWmOwQ0RERGqNwQ4RERGpNQY7REREpNYY7BAREZFaY7BDREREao3BDhEREak1BjtERESk1hjsEBERkVpjsENERERqjcEOERERqTUGO0RERKTWGOwQERGRWmOwQ0RERGqNwQ4RERGpNQY7REREpNYY7BAREZFaY7BDREREao3BDhEREak1BjtERESk1hjsEBERkVpjsENERERqjcEOERERqTUGO0RERKTWGOwQERGRWmOwQ0RERGqNwQ4RERGptWod7OTl5WH+/PlwcXGBvr4+6tSpg0WLFkEIId9HCIGvv/4atra20NfXR8+ePREWFlaFtSYiIqLqpFoHO0uXLsXq1auxatUq3Lt3D0uXLsWyZcvw66+/yvdZtmwZVq5ciTVr1iAgIACGhobo1asXMjMzq7DmREREVF1IxMvNJNXMu+++C2tra2zYsEGeNnToUOjr62Pr1q0QQsDOzg4zZ87EF198AQCQSqWwtrbGpk2b8P777ytVTnJyMkxMTCCVSmFsbFwp50JEREQVS9nf72rdstO+fXucOnUKoaGhAIAbN27gwoUL6NOnDwAgIiICcXFx6NmzpzyPiYkJ2rZtC39//2KPm5WVheTkZIUXERERqSetqq5ASebO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Li4OOjo6qFmzpsK+1tbWiIuLK/ZYPj4+MDExkb8cHBwqs+pERERUhd6YYMfLywu3b9/Gzp07y30sb29vSKVS+SsqKqoCakhERETVkVZVV0AZkydPxqFDh3Du3DnY29vL021sbJCdnY2kpCSF1p34+HjY2NgUezxdXV3o6upWZpWJiIiomqjWLTtCCEyePBl79+7F6dOn4eLiorC9ZcuW0NbWxqlTp+RpISEhiIyMhIeHx+uuLhEREVVD1bplx8vLC9u3b8f+/fthZGQk74djYmICfX19mJiYYOzYsZgxYwbMzMxgbGyMzz//HB4eHkqPxCIiIiL1Vq2HnkskkiLTfX198cknnwDIn1Rw5syZ2LFjB7KystCrVy/8/vvvJT7GehWHnhMREb15lP39rtbBzuvCYIeIiOjNo5bz7BARERGpisEOERERqTUGO0RERKTWGOwQERGRWmOwQ0RERGqNwQ4RERGpNQY7REREpNYY7BAREZFaY7BDREREao3BDhEREak1BjtERESk1hjsEBERkVpjsENERERqjcEOERERqTUGO0RERKTWGOwQERGRWmOwQ0RERGqNwQ4RERGpNQY7REREpNYY7BAREZFaY7BDREREao3BDhEREak1BjtERESk1hjsEBERkVpjsENERERqjcEOERERqTUGO0RERKTWGOwQERGRWmOwQ0RERGqNwQ4RERGpNQY7REREpNYY7BAREZFaY7BDREREao3BDhEREak1BjtERESk1hjsEBERkVpjsENERERqjcEOERERqTUGO0RERKTWGOwQERGRWmOwQ0RERGqNwQ4RERGpNQY7REREpNYY7BAREZFaY7BDREREao3BDhEREak1BjtERESk1hjsEBERkVpjsENERERqjcEOERERqTUGO0RERKTWGOwQERGRWmOwQ0RERGqNwQ4RERGpNQY7REREpNYY7BAREZFaY7BDREREao3BDhEREak1BjtERESk1hjsEBERkVpjsENERERqjcEOERERqTUGO0RERKTW1CbY+e233+Ds7Aw9PT20bdsWV65cqeoqERERUTWgFsHOrl27MGPGDCxYsADXrl1D06ZN0atXLyQkJFR11YiIiKiKqUWws3z5cowbNw5jxoxBgwYNsGbNGhgYGGDjxo1VXTUiIiKqYlpVXYHyys7OxtWrV+Ht7S1P09DQQM+ePeHv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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "plt.plot(np.arange(len(epochs_x)), epochs_acc, marker = '.')\n", - "plt.xlabel('epoch')\n", - "plt.ylabel('test accuracy')\n", - "plt.ylim(0, 100)\n", - "plt.xticks(np.arange(len(epochs_x)))\n", - "for i, txt in enumerate(epochs_acc):\n", - " if i%2 == 0:\n", - " pass\n", - " else:\n", - " plt.text(i, txt, f'{txt:.2f}', ha='center', va='bottom', color = 'k')\n", - "plt.show()" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "speck-rescnn", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.3" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/tests/test_nonsequential/using_SumPool2d/ARCHITECTURES_SEARCH/Res-SCNN3.ipynb b/tests/test_nonsequential/using_SumPool2d/ARCHITECTURES_SEARCH/Res-SCNN3.ipynb deleted file mode 100644 index 64926de1..00000000 --- a/tests/test_nonsequential/using_SumPool2d/ARCHITECTURES_SEARCH/Res-SCNN3.ipynb +++ /dev/null @@ -1,1380 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "import torch, random, sys\n", - "\n", - "import tonic\n", - "from torch.utils.data import DataLoader\n", - "from torch.nn import CrossEntropyLoss\n", - "from torch.optim import Adam\n", - "\n", - "from sinabs.activation.surrogate_gradient_fn import PeriodicExponential\n", - "\n", - "import matplotlib.pyplot as plt\n", - "import numpy as np\n", - "\n", - "sys.path.append('../../utils')\n", - "sys.path.append('../models')\n", - "\n", - "from train_test_fn import training_loop, load_dataset, split_train_validation, load_architecture" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "device: NVIDIA GeForce RTX 3070 Ti\n" - ] - } - ], - "source": [ - "if torch.cuda.is_available():\n", - " device = torch.device('cuda:0')\n", - " print('device: ', torch.cuda.get_device_name(0))\n", - "else:\n", - " device = torch.device('cpu')" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "rand_seed = 1" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "achitecture = 'ResSCNN3'" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "torch.backends.cudnn.enabled = False\n", - "torch.backends.cudnn.deterministic = True\n", - "random.seed(rand_seed)\n", - "torch.manual_seed(rand_seed)\n", - "torch.cuda.manual_seed(rand_seed)\n", - "np.random.seed(rand_seed)" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], - "source": [ - "batch_size = 8\n", - "num_workers = 4\n", - "epochs = 30\n", - "lr = 5e-5\n", - "\n", - "spk_thr = 2.0\n", - "v_min = -0.313\n", - "\n", - "grad_scale = 1.534\n", - "grad_width = 0.759\n", - "\n", - "validation_ratio = 0.2\n", - "n_time_steps = 50" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Loading Data" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [], - "source": [ - "snn_train_dataset, snn_test_dataset, sensor_size = load_dataset('DVSGESTURE', n_time_steps)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "getting validation dataset...." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [], - "source": [ - "train_dataset, validation_dataset = split_train_validation(validation_ratio, snn_train_dataset, rand_seed)" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The transformed array is in shape [Time-Step, Channel, Height, Width] --> (50, 2, 128, 128)\n" - ] - } - ], - "source": [ - "sample_data, label = train_dataset[0]\n", - "print(f\"The transformed array is in shape [Time-Step, Channel, Height, Width] --> {sample_data.shape}\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "disk caching samples..." - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [], - "source": [ - "disk_cache_train = tonic.DiskCachedDataset(\n", - " dataset=train_dataset,\n", - " cache_path='./cached_train'\n", - ")\n", - "snn_train_dataloader = DataLoader(disk_cache_train, batch_size=batch_size, num_workers=num_workers, drop_last=True, shuffle=True)\n", - "\n", - "disk_cache_validation = tonic.DiskCachedDataset(\n", - " dataset=validation_dataset,\n", - " cache_path='./cached_validation'\n", - ")\n", - "snn_validation_dataloader = DataLoader(disk_cache_validation, batch_size=batch_size, num_workers=num_workers, drop_last=True, shuffle=True)\n", - "\n", - "disk_cache_test = tonic.DiskCachedDataset(\n", - " dataset=snn_test_dataset,\n", - " cache_path='./cached_test'\n", - ")\n", - "snn_test_dataloader = DataLoader(disk_cache_test, batch_size=batch_size, num_workers=num_workers, drop_last=True, shuffle=False)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Network Module" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [], - "source": [ - "snn = load_architecture(achitecture, sensor_size, 11, batch_size, PeriodicExponential(grad_scale=grad_scale, grad_width=grad_width), v_min, spk_thr).to(device)\n", - "snn.init_weights()" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [], - "source": [ - "optimizer = Adam(snn.parameters(), lr=lr, betas=(0.9, 0.999), eps=1e-8)\n", - "loss_fn = CrossEntropyLoss()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Training loop" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "5bf192a7696645b9a33b40575b296ed8", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - " 0%| | 0/107 [00:00" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "y_avg = []\n", - "for y in epochs_y:\n", - " y_avg.append(np.mean(y))\n", - "\n", - "plt.plot(np.arange(len(epochs_x)), y_avg, marker = '.')\n", - "plt.xlabel('epoch')\n", - "plt.ylabel('average loss')\n", - "plt.ylim(0,)\n", - "plt.xticks(np.arange(len(epochs_x)))\n", - "for i, txt in enumerate(y_avg):\n", - " plt.text(i, txt, f'{txt:.2f}', ha='center', va='bottom', color = 'k')\n", - "plt.show()" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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KpX43//+h8GDBwMA4uPjAQD29vYa5ezt7dX7ihIYGIjPP/+84hpOREREVUaVvrKzbds2bNy4EZs2bcL58+exfv16LFq0COvXr3+m8wYEBEChUKgf9+7dK6cWExERUVVTpa/sTJs2DTNnzlT3vfHw8MDdu3cRGBiIYcOGwcHBAQCQkJAAR0dHdbmEhAS0aNGi2POamJjAxMSkQttOREREVUOVvrKTmZkJmUyziQYGBlCpVAAANzc3ODg4ICgoSL0/LS0NZ8+ehY+Pz3NtKxEREVVNVfrKTs+ePfG///0PLi4uaNq0KS5cuIBvvvkGI0aMAABIkoSJEyfiyy+/RIMGDeDm5obZs2fDyckJffr0qdzGExERUZVQpcPOd999h9mzZ+Ojjz5CYmIinJyc8MEHH2DOnDnqY6ZPn46MjAyMHj0aqamp6NChAw4cOABTU9NKbDkRERFVFVV6np3nhfPsEBERvXj0Yp4dIiIiomfFsENERER6jWGHiIiI9BrDDhEREek1hh0iIiLSaww7REREpNcYdoiIiEivMewQERGRXmPYISIiIr3GsENERER6jWGHiIiI9BrDDhEREek1hh0iIiLSaww7REREpNcYdoiIiEivMewQERGRXmPYISIiIr3GsENERER6jWGHiIiI9BrDDhEREek1hh0iIiLSaww7REREpNcYdoiIiEivMewQERGRXmPYISIiIr3GsENERER6jWGHiIiI9BrDDhEREek1hh0iIiLSaww7REREpNcYdoiIiEivMewQERGRXmPYISIiIr3GsENERER6jWGHiIiI9BrDDhEREek1hh0iIiLSaww7REREpNcYdoiIiEivMewQERGRXmPYISIiIr3GsENERER6jWGHiIiI9BrDDhEREek1hh0iIiLSaww7REREpNcYdoiIiEivMewQERGRXmPYISIiIr3GsENERER6jWGHiIiI9BrDDhEREek1hh0iIiLSaww7REREpNcYdoiIiEivMewQERGRXmPYISIiIr3GsENERER6Teewc+zYsYpoBxEREVGF0DnsdOvWDfXq1cOXX36Je/fuVUSbiIiIiMqNzmHn/v37GDduHH777TfUrVsXXbt2xbZt25Cbm1sR7SMiIiJ6JjqHHRsbG0yaNAnh4eE4e/YsGjZsiI8++ghOTk74+OOPcfHixYpoJxEREVGZPFMHZS8v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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "plt.plot(np.arange(len(epochs_x)), epochs_acc, marker = '.')\n", - "plt.xlabel('epoch')\n", - "plt.ylabel('test accuracy')\n", - "plt.ylim(0, 100)\n", - "plt.xticks(np.arange(len(epochs_x)))\n", - "for i, txt in enumerate(epochs_acc):\n", - " if i%5 ==0 or i == epochs-1:\n", - " plt.text(i, txt, f'{txt:.2f}', ha='center', va='bottom', color = 'k')\n", - "plt.show()" - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [], - "source": [ - "with open(f'./architectures_results/{achitecture}-Training_Validation-TM.npy', 'wb') as f:\n", - " np.save(f, np.array(epochs_x))\n", - " np.save(f, np.array(epochs_y))\n", - " np.save(f, np.array(epochs_acc))" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "speck-rescnn", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.10.0" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/tests/test_nonsequential/using_SumPool2d/ARCHITECTURES_SEARCH/architectures_results.ipynb b/tests/test_nonsequential/using_SumPool2d/ARCHITECTURES_SEARCH/architectures_results.ipynb deleted file mode 100644 index f6df49bf..00000000 --- a/tests/test_nonsequential/using_SumPool2d/ARCHITECTURES_SEARCH/architectures_results.ipynb +++ /dev/null @@ -1,306 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "import numpy as np\n", - "import matplotlib.pyplot as plt" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "top_n = 3" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "nb_skip_conns = {\n", - " 'ResSCNN1': {'nb_skip_conns': 1, 'nb_jumped_layer': 1},\n", - " 'ResSCNN2': {'nb_skip_conns': 2, 'nb_jumped_layer': 1},\n", - " 'ResSCNN3': {'nb_skip_conns': 3, 'nb_jumped_layer': 1},\n", - " 'ResSCNN4': {'nb_skip_conns': 4, 'nb_jumped_layer': 1},\n", - " 'ResSCNN5': {'nb_skip_conns': 1, 'nb_jumped_layer': 2},\n", - " 'ResSCNN6': {'nb_skip_conns': 2, 'nb_jumped_layer': 2},\n", - " 'ResSCNN7': {'nb_skip_conns': 2, 'nb_jumped_layer': (1, 2)},\n", - " 'ResSCNN8': {'nb_skip_conns': 4, 'nb_jumped_layer': (1, 2)},\n", - "}" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "architectures_TM = {}\n", - "acc = []\n", - "architecture = []\n", - "\n", - "for i in range(1, 9):\n", - " with open(f'architectures_results_set_1/ResSCNN{i}-Training_Validation-TM.npy', 'rb') as f:\n", - " epochs_x = np.load(f)\n", - " epochs_y = np.load(f)\n", - " epochs_acc = np.load(f)\n", - "\n", - " architectures_TM[f'ResSCNN{i}'] = {\n", - " 'epochs_x': epochs_x,\n", - " 'epochs_y': epochs_y,\n", - " 'epochs_acc': epochs_acc,\n", - " }\n", - "\n", - " acc.append(epochs_acc[-1])\n", - " architecture.append(f'ResSCNN{i}')" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "combined = list(zip(acc, architecture))\n", - "sorted_combined = sorted(combined, key=lambda x: x[0], reverse=True)\n", - "sorted_values, sorted_labels = zip(*sorted_combined)" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], - "source": [ - "top_indices = np.argsort(acc)[-top_n:]" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAA2gAAAG2CAYAAAAKvaVLAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8fJSN1AAAACXBIWXMAAA9hAAAPYQGoP6dpAAEAAElEQVR4nOzddXyV5fvA8c+pdXfBigWjGR2SAhISooAdiAoGdmL7xRbBAkWRFpEG6YbRDAYb6+7u7dTz++PZzhjbCEWdP+/363VebE8/57DtXOe67utWSJIkIQiCIAiCIAiCIPzjlP/0BQiCIAiCIAiCIAgyEaAJgiAIgiAIgiC0EiJAEwRBEARBEARBaCVEgCYIgiAIgiAIgtBKiABNEARBEARBEAShlRABmiAIgiAIgiAIQishAjRBEARBEARBEIRWQgRogiAIgiAIgiAIrYQI0ARBEARBEARBEFoJEaAJgiAIgiAIgiC0Ev9ogHbw4EHGjRuHl5cXCoWCDRs2NFovSRJvvvkmnp6eWFpaMnz4cOLj4xttU1RUxD333IOdnR0ODg488sgjVFRU/I13IQiCIAiCIAiCcHP8owFaZWUlXbp04euvv252/ccff8z8+fP57rvvOH78ONbW1owcOZKamhrTNvfccw8XL15k165dbNmyhYMHDzJjxoy/6xYEQRAEQRAEQRBuGoUkSdI/fREACoWC9evXM2HCBEDOnnl5efH888/zwgsvAFBaWoq7uztLlixh6tSpxMTEEBYWxsmTJ+nRowcA27dvZ/To0WRkZODl5fVP3Y4gCIIgCIIgCMINU//TF9CS5ORkcnJyGD58uGmZvb09vXv3JiIigqlTpxIREYGDg4MpOAMYPnw4SqWS48ePM3HixGaPXVtbS21trel7o9FIUVERzs7OKBSKv+6mBEEQBKEVkCSJ8vJyvLy8UCrFcHRBEITWpNUGaDk5OQC4u7s3Wu7u7m5al5OTg5ubW6P1arUaJycn0zbNmTt3Lu+8885NvmJBEARB+HdJT0/Hx8fnn74MQRAE4TKtNkD7K7366qs899xzpu9LS0tp27YtycnJ2Nra/oNXJgiCIAh/vfLycvz9/cXfPEEQhFao1QZoHh4eAOTm5uLp6WlanpubS9euXU3b5OXlNdpPr9dTVFRk2r855ubmmJubN1nu5OSEnZ3dTbh6QRAEQWi9NBoNgCjrFwRBaIVabeG5v78/Hh4e7Nmzx7SsrKyM48eP07dvXwD69u1LSUkJp0+fNm2zd+9ejEYjvXv3/tuvWRAEQRAEQRAE4c/4RzNoFRUVJCQkmL5PTk4mMjISJycn2rZty+zZs3n//fcJCgrC39+fOXPm4OXlZer02L59e0aNGsWjjz7Kd999h06n48knn2Tq1Kmig6MgCIIgCIIgCP86/2iAdurUKYYMGWL6vn5c2AMPPMCSJUt46aWXqKysZMaMGZSUlDBgwAC2b9+OhYWFaZ8VK1bw5JNPMmzYMJRKJXfccQfz58//2+9FEARBEARBEAThz2o186D9k8rKyrC3t6e0tFSMQRMEQRD+3xN/9wRBEFqvVjsGTRAEQRAEQRAE4b9GBGiCIAiCIAiCIAithAjQBEEQBEEQBEEQWgkRoAmCIAiCIAiCILQSIkATBEEQBEEQBEFoJUSAJgiCIAiCIAiC0EqIAE0QBEEQBEEQBKGVEAGaIAiCIAiCIAhCKyECNEEQBEEQBEEQhFZCBGiCIAiCIAiCIAithAjQBEEQBEEQBEEQWgkRoAmCIAiCIAiCILQSIkATBEEQBEEQBEFoJUSAJgiCIAiCIAiC0EqIAE0QBEEQBEEQBKGVEAGaIAiCIAiCIAhCKyECNEEQBEEQBEEQhFZCBGiCIAiCIAiCIAithAjQBEEQBEEQBEEQWgkRoAmCIAiCIAiCILQSIkATBEEQBEEQBEFoJUSAJgiCIAiCIAiC0EqIAE0QBEEQBEEQBKGVEAGaIAiCIAiCIAhCKyECNEEQBEEQBEEQhFZCBGiCIAiCIAiCIAitRKsP0MrLy5k9eza+vr5YWlrSr18/Tp48aVovSRJvvvkmnp6eWFpaMnz4cOLj4//BKxYEQRAEQRAEQfhjWn2ANn36dHbt2sWyZcuIiopixIgRDB8+nMzMTAA+/vhj5s+fz3fffcfx48extrZm5MiR1NTU/MNXLgiCIAiCIAiCcGMUkiRJ//RFtKS6uhpbW1s2btzImDFjTMvDw8O57bbbeO+99/Dy8uL555/nhRdeAKC0tBR3d3eWLFnC1KlTr+s8ZWVl2NvbU1paip2d3V9yL4IgCILQWoi/e4IgCK2X+p++gKvR6/UYDAYsLCwaLbe0tOTw4cMkJyeTk5PD8OHDTevs7e3p3bs3ERERLQZotbW11NbWmr4vKysDQKfTodPp/oI7EQRBEITWQ/ytEwRBaL1adYBma2tL3759ee+992jfvj3u7u6sWrWKiIgI2rVrR05ODgDu7u6N9nN3dzeta87cuXN55513mizfuXMnVlZWN/cmBEEQBKGVqaqq+qcvQRAEQWhBqw7QAJYtW8bDDz+Mt7c3KpWK7t27M23aNE6fPv2Hj/nqq6/y3HPPmb4vKyujTZs2jBgxQpR6CIIgCP/v1VeOCIIgCK1Pqw/QAgMDOXDgAJWVlZSVleHp6cmUKVMICAjAw8MDgNzcXDw9PU375Obm0rVr1xaPaW5ujrm5eZPlGo0GjUZz0+9BEARBEFoT8bdOEASh9Wr1XRzrWVtb4+npSXFxMTt27GD8+PH4+/vj4eHBnj17TNuVlZVx/Phx+vbt+w9erSAIgtDa7YvNI3TO76w5mf5PX4ogCIIgmLT6AG3Hjh1s376d5ORkdu3axZAhQwgNDeWhhx5CoVAwe/Zs3n//fTZt2kRUVBT3338/Xl5eTJgw4Z++dEEQBKEVm7crjhqdkS92x6E3GP/py6G8RkdURilGY8vNlfPLa4nPLb/qcYortaQWVt7syxMEQRD+Jq2+xLG0tJRXX32VjIwMnJycuOOOO/jggw9M5RkvvfQSlZWVzJgxg5KSEgYMGMD27dubdH4UBEEQhHrn0ks4l1EKQHZpDbtjchnV0fMae/11LmSW8tiy02SWVOPrbMXUnm2ZHO6Dq605BqPEofh8Vp1IY3dMHgajxBODA3lhRAgqpaLRcfbF5vHMqrOU1+p5cWQITwwKRKFQtHBWQRAEoTVq1fOg/V3EfDCCIAj/v2j1RtacSmdYezc87S2brH9+zTl+O5OBhUZJjc5Iv0BnVj7a5x+4Ulh3JoNX10VRq2+cxVMrFQwKduVSTjmZJdVN9rsl2JX5U7viYGWGJEl8sz+RT3fGcvlf9dGdPPhkcheszRt/Hiv+7gmCILRerb7EURAEQRBu1Pw98byx4QIP/XQS3RXli0WVWjafzwLg0zu7oFTA0cRCEvKuXjp4s+kMRt7edJHn1pyjVm9kSIgrx14dxseTO9OtrQN6o8SeS3lkllRjb6nhof5+7Hz2Fr6c2hULjZKDcfmM++owp1KKeGL5GT7ZIQdn03q15b3xHdCoFGyLymHiN0dILhAlj4IgCP8WIoOG+CRREITrk1pYyVd7E3h6WBBtnP74nImH4wvYEJnJG2Pa42BldhOv8N/nSEIBm89l8cbYMGzMW6i6j94IZ5aBdFmgpVRBz0cheESTzYsrtQz4aC+VWgMAr94WymODAk3rv92fyEfbL9HR247NTw5gxrLT7IrO5YG+vrwzvuM1r3lx1GJszWy5K+SuG7vZOvUliwv2JnA6tRiAp4cFMXtYEMrLShYv5ZSx82IubZwsua2jJxYalWlddFYZjy0/RXpRQ2bNTKXk3fEdmNqrLQCnU4t5Yvlp8sprsbVQ8+XUrgwNlecNFX/3BEEQWq9WPwZNEAShtVh4MIlfT2dQpTPw9d3d/9AxzmeUMH3pSWp0RkI9bJk+MOAmX+W/R5VWzzOrz1JQocXfxbpREGVi0MGWZ6GqsOm63IvwzHlQNf5T9v2hJCq1Bmwt1JTX6PlidxyjO3nSxskKg1Fi+bFUAO7v64dCoeD+vr7sis7ltzOZvDgqtOVAEUguTWbemXkADG4zGDcrt+u+35zSGn49lc7qk+mmkkUbczWf39WFER08mmwf6mFHqEfzwVOYlxxcPrXqLIfiC3C3M+e7e8Pp1tbRtE24ryNbnhrAEyvOcDq1mIUHkhgS4ibGpAmCILRyIkATBEG4TjHZ8uS+u6NzKavRYWdxY3NJ5ZTW8OjSU9To5ExQZHrJzb7Ef0xhRS1PrDiDnYWGD+/ohItN07kmr7T8WCoFFVoAdkXnNh+gJe6VgzNrVxjxfsPyHa9DWSbEboOw202Liyq1/Hw0BZDLF386ksyxpCLe2HCBJQ/1ZF9dyaCDlYbbu3gB0D/QhQAXa5IKKll/NpP7+vi2eM0XCi6Yvt6fvr/ZLFpplY57Fx8n5YqywkqtnvoGjfaWGiZ19+ahfv60da7Lxu7/EC6uh8k/gnuHFq+hnoOVGUse6sXRxAI6eds3m411s7Ng1aN9mLc7jof6+4vgTBAE4V9AjEETBEG4DkajRGyOPEapVm9k+4WcG9q/Wmtg+tKT5JbVYmchfzZ2LqPkT12TzmCkolb/p45xM9TqDTy+/DQnkovYHZPLuAWHOZdeApIE5bnN7lOl1bPwQBJq9NhTwem0YvLLa5tueP4X+Ryhk6DL1IZH+APy+hOLGm1enz3r4GXHiDB3PpjYCTOVkgNx+Ww7m8LKiHgA7urRxlQyqFQquLcuKFsWkcLllf+SJJFXXmP6PqogyvT1nrSGOTgvN/f3GKIySymv1Td6GCXo5e/EF1O6cPy1Ybw1rkNDcJZ+Qg7Q8i/ByilQkdfCs92YSqlgYJBr4+BMVwM1paZvzdRKXhoViqvttYNmQRAE4Z8nAjRBEITrkF5cRVXdmCaADWczr3tfo1Hi+V8juZBZhpO1GatmyN0C04uqKaxoJii5Tk+vOkvvD3aTlF/xh4/xZ0mSxBvrL3AypRhbczUBLtZkl9Zw18IjpH5/D3wWDAtvgVM/Qk2Zab+New/zSO1Sjls8zWmLJ+ijuMjumCuCuZoyuLQVgGnHfTmVUtSwLvwhUCgh5RDkXQLkLF599mz28GAUCgWBrjbMGtIONXoCNk1kQdokxqoiuLd34yzZHeE+WGpUxOVWcDy5iIKKWhYeSGToZwfo9cEePt0RCzTOoJ3IPkGZtqzRcU4kF7G6buLr7+/vwf4XBpseJ14fxprH+jKxm0+j8WQYdLD5GUCS76k0HX65Vw60bpTRCEvGwEd+cqAX+zsY/vkgXhAEQbh+IkATBEG4DjHZcvbMw06eYzEiqZDs0qatz5vzxe44tkXloFEpWHhfOB287AlwtQbgfGbpNfZuXo3OwO6YXCq1Btacymhxu5SCSk5eHtj8QRcySzmWVNhkEuVFdePylAr46p7ubHyyP8PbuzOTtfhmycEV2efkcWSfhcKGWRiW3M60Y+OZqd6EMyWoMfCyejU7LmQ3PumlLaCvIdHoyRm9L6+si6JWXxckO7SBkNHy1yd/AOD7Q8lUaQ109LZjePuGsWGPDw7gCfvjtCcZa0UtX2kW0Pb03EaBi72lhondvQF49pdI+s7dw9zfL5m6H361L4FfTiZzqUgOBh3MHdBLeg5lHDIdo1Zv4NV15wF4sWMFt1Zvxy91renhlrGr+WDp6HzIiwYrZ3hoO1jYQ/px2Pw0XNnHK/s8pBxp+YVK3k967lmiNSqI2w6rpsK8TrDvf1CS3vJ+giAIQqshAjRBEITrcClHzpQMDHKhl58TkgSbIrOuuV9MdhkL9iYAMHdSZ3r6OQHQ1ccBkCdM/iPOZ5SiM8hv3jdGZjYJnEAOGKYsiuDO7yJYd6blIO5aDscXMP7rI0xddIxBn+7j630J5JXXsCs6lw+3ywHLm2PDGBTsiq2FhkXdknlGvQ6At3X3s8RmBnqnINBVQuRyVCkHMEoKjqu6Yxj/LUa1JV2ViWiS9lBeo7vsJuXyxvWGAYCChLwKFh5Ialjfc7r877nVFBYVsjQiBYDZw4IbjbUyx8CT6g0AnDYGyQuPzoflk6CyofnI/X3lrFp2aQ06g0SXNg58dEcnHhskN3KZ8/sudEYddmZ2TA6eDMDetL2m/b/bn0RifiX3WR1jVsIMOcC6/PHLvbB8IlQWNNxDURIc+Fj+euT/oG1vuPNnUKjk+z/8OdSWw6mfYOEgWDgQloyG+N3NvlbrIj5mvI8Xd3t7cqnn/XLQV54FBz6C36Zf5VUWBEEQWgsRoAmCICC3Zv9sZyzpRVXNrr9Ul0EL8bBlQjc507L+Osoc64OG0Z08mBzuY1re2ccekAOtP+JUakNWLLu0huPJTbNkv0flkFsml1C+8ltU4xLB65SYX8HMFacxGCVUSgXpRdV8seMib334ESmrn2eg4hz39fbhgX5+8g4Zp1BunAVAauh0flOP5e2CwfQrm0vsbWvQdX+YRYo7uUU7j/TRy1B1uxtlr0cBeFL5K/sv1Y29KstGSjoAwG/mfoR3OQXKGr7al9BQ0hkwGJyDQFvO8fXfUKU10NnHnmHtr+iseG4l5pWZVJs5E9H/R4yTl4DGGpIPwKLBcoYPuWvi2+PCmD7An61PD2DjrP5M6dmWl0eGcltHDyQzOQMVZB/G8LbDATiceZhaQy2J+RV8vS+B7oo43uZb+bxtekPwbXWPUWBmA8kHYdFgdBknWXLhJ05sfgL0NeA/CDpPkfcLHAKjP5G/3vMufBoCW2ZDdiRHLSxY4GBP3P53GmXXtAYt7x54ibcMmegUCgzAKkcneC5GbjrifwuEP3jDr78gCILw9xMBmiAIAvDO5oss2JvAJ3Vjja5Un0Fr72nHmE6emKmUXMopNy1vTmm1jg1n5SzbA339Gq3r0sYBkDNof2Q6yjN182dZm8ljmZobE1cfHDpZm6E1GHls2ekWA9DmlFRpmf7zKcpq9IT7OnL2ySB+77iPk1bP8K3mcx5Vbmap2Ue8m3ovikOfQsZpWDUNDLUQMhrfuz5m45P9CXKzIa9Cy9hNBh4pmMb/qieidvJlQle5iyL9n0GrtKCLMonMkxvlZRfWokBipyKIyjYbidOuxSX4O/TKHF5ff0F+zhQK9D3krFBQ6ipAYvbwoMadCvVaOPgpAJZDXuDJkZ1RdpwI03eDoz+UpsHiEXBOztY92N+fN8aG0cHL3nQIpVLBZ3d1wdlZbgwTm+ZAG+sg3KzcqNJXcSzrGK+vj8LVkMsSy3mojDoIHSuXK969uu7xi3xOp0Ck0nTe3TiNz05/zmNSJietbGDsF3D5dfd8BHo9Jn+tqwTnIDKHvMJsnzYscrTnDrMS7lk3jvXx60krS+PhHQ/za8rvKCSJ25HLZ7clbaPUUAMd74AHNsvNVQRBEIRWTwRogiD85yXkVbDpnBxIHU0sbBIwVdbqSa0LbEI9bLG30jA4xBXAFIA1Z+3pDKp1BkI9bOnl79RoXXtPO9RKBYWVWjKKm45lW382g0eWnKS4UttknSRJpgmOnxoml+xti8qmRtfQxORCZiln0krQqBRsmNmfDl52FFbKAVejMsIW6AxGZq44Q3pBKffYRrLK8iPsFvWgfcL3OBqL0Vu6kOJ5G5KFPYqSNNj7PvwwFCrzwL0jTFoEShUBrjasn9Wf2zp6oDNIHIzLl697aBBqVd2fIGsXijrIXRkHZPxArU6PVFfe+KmzPZJSbpZRq8jByv9rTuYd5LczmeSV1/DwmUAqJXOClJl83rOcISFXZM8iV0BpOpKNO5+rynl+//NU6arAPQxm7IN2t8oZrPUz4PdX5IYdzbAyU+PiLDcxyStwY/jnBykvCgXg+a0riErK5CfzT7EzllDu0ZHn3Vz46NQn1Ojla684cID0OV+iv2MtPwf2YIONJQB6hYJnPT1I1zQzYfnI/8HEhfDgNqRZJ/hAl061oRZXpQVqSeJ8RSpvHn2TMevHcC7/HLZGia9z83m/x6sEOwZTY6hhQ8KGhuOJFvuCIAj/CiJAEwThP2/B3njT/FQFFbUk5jeevyoutxxJAldbc5zr5veaWFfm2NL4L6NRYlldBuv+Pj4orgj6LDQq2nvKkxCfzyiVy9XqttEZjLy7OZo9l/JYc6ppY4ekgkqKq3SYq5U81N8PL3sLymv17L2UJ3fxoyF7NqqjJ22drfjhgR642ZoTm1vOM6sjKa3SUVZT96jWUlZS2OixYM3vDEj9mmPmT/GB7mPMUvbLJw8cCnf+jPr5GPweW43i+Vg5iGjbV15v7QbTVoG5rel6bczVfHNPd14cGYJCIRHqacv4+uxZHbcRL1KFBR0ViWRsmYsiJ4rdltZk2+ahUqhYeOtCerj3QKGsxbLNMt49/Bljv9rFwcwy1ir6U65QcLtua9Ps2aHPANjd5XZ+ilnOztSdvHLoFYySESwd5czWwBfk7Y9/C0snQEma3Ka+/qGtolJXSVq5/JyaG3zJK6+lMDcYgBrNeb7QLCBYkY7exp0XfYPYmb6X5THLuf/3+8mqyKLgu4VUHDjAmVU/8LlRDlKfLSqmo1FFqVHLrL2zKNeWN36hVWo56+XXnx1pOzmUeQiNUsPi4d+xK7uIZ4pK8DF3BqCdhSurM7MZqHFGETqGqaFytuyX2F/kexUEQRD+NUSAJghCq/HR9ksEv/E7M1ec5lB8frOBz82WkFduyp75OMpZjYikwkbbXKqb/yzUoyHoGBLqhq2FusXxX4cSCrAuiuYj85+YtncgLBokN4S4TJc2chldddRGucPhpicBOBiXT3GVnMnZcbHpfGv12bMuPg6Yq1WMrwsW44+sg4/90K66j92RcmOS+sYXnvaWfH9/D8zVSvZeyqPLuzvp/PZO+r+9gfi5/bCbF9Do8Vzs3cxUb8JFUQo27jDgOXg6Eu5bDx0mgLou46OxlIOIh7fDM+dg1nFwaNvkmhUKBZN72dK2y6d4hSzFQONMldLWlZOudwAQeO5TqhQK3nWWs5T3h91PP69+LBqxiGmh9wAgOeym2us1bEPe5lP/BPr5teG2ytPErX8IMk/Lwe7ZZVCaTrmtB3OLT5vOtS99H1+e+bLuxCoYNgemLJfHiKUelrsefti24fE/T6JXTkBCwsPKnUPPj2fVo31YOvl2rBXmKNSVuFjFIKkt+LTbWI7kncZCZYGDuQMxRTFM3XQXVbExAFyM2IyExF3Bd/HQQxHMn7QJNys3kkuTefHAi+iNTbs8lmnL+OjERwA82ulR/D3DcekxnemlZWwtk1g79ldWl0FbvR56PAQqNWP8x2CrsSW9PJ0jmVfp+igIgiC0OiJAEwThhhVU1LI/Nq/R42RKEYarBFS1egPxueUtrk8rrGLRwSS0eiPbonK4b/EJU8fA0qprl+RdlSRBViTompYSzt+TgCTBrWHu3NWjDQDHrgzQshvGn9Wz0KgY08kTuGL8l0EHp5fQdu1otpq/xhTFLhTaCsg5D4uGQEJD973O3nY8p17D5PiXoSIHzi6H/NhGzUfOppeQV9Z4PqzTKXKA1t3XEZCzeaGKNB7JfhdqSjGL3cQa5RsMdyujR902II97mzelq2mibBUGvtZ8SbgyvsnzYpAUZLr0lwOXZy/C8LfAyb+FJ7iOox9YObW4+vuo7ymqLeRk7nHePvp2k1JS9cBnqJDkaQy+crSnWGPE1dKTx7s8DoBGqeG13q8wM2wOGC2bHD9HrebpwmMULh4udzs8IAc1X7YLJ7+6AF87X97t9y4AP174sXH5X/tx8OhecO/U7LVHFckBVqeiTJyPvkffS/+j/8ZbGFIuB+d7bGz4tf8jrMjYBcDcgXP5ZewvtHdqjzq/BEWV/Bq2ydbT26M3r/R+BYVDG1zt2/LV0K+wVFtyJOsIH5/8uEnGa97peRRUF+Bn58cjnR6RF/Z7GjTWKLMiCYnagHnmaVBqoLtcKmqlsWJ8u/EArI5d3eJrIgiCILQ+6n/6AgRB+He5kFnKlIURVF42aXO9/u2cWTCtO07WjcfTpBRU8tiy08TmljNnbBiPDGj6Rv+rffEYjBI9/RwJ87Rj3dlM0ouq+WRHLJvPZbHpyQGYqf/gZ0rRG+DXB8ElBKauABd53FZ8bjmbz8vZs9nDg6isle/peJI8Dq2+XC6mmQwawIRu3qw+mc76yEz6tXNmfFdv2DgLzv+CP6CVVNQGj8U2fAoc+hwyT8HyyTDsTejxEKOjZmOjltu0SzbuKCpy0UYsZFf0rQC42JhRUKFlV0wu91w2sfLpNDlAqw++gq2rWWr5GTbGGvIcukBpBu2UWXxb9TyKWHsIHW3a97ZOntwa5o5BklDteAX1ySgkjRW6+zYhuXUwbadSqvA2M/9jz3czcipzWBcvt95XKpRsSdpCoEMg0zs1tH7vGRbEz7+Nop/ZVlbYyc/1u/3fxEpj1ehYT/S8i0e7T8JIQyBTVlvGA1umkEYez7q78UN2FGZApKMXa0rkyaXn9JlDb8/eZFZksvD8Qt6JeIe2tm3p7t5dPohrCDx+CAxXjPsrz+bCrplQnU6HqnI4usC0apjCjy0Y2ejiQUX6NgCe7vY0w33lLo9Lb1vKT98+ARwDwLMYPun1HhqlxnSM9s7t+d+A//Hs/mdZdWkVBzMOMjl4MhPaTSCjPINf434F4M2+b2KmqvvZsnaBXo/CkXmwf668rMMEsGkYgzc1dCrLY5ZzKOMQGeUZ+Ng2dBEVBEEQWi+RQRME4brlldXw6NJTVGoNeNlb0NHbzvSw1Kg4klDIuAWHuXDZ5Mv7YvO4/avDxNZlzz7d0bSVfWphJb+dkbNGr45uzzvjO3LiteF8emcXnKzNuJRTzveHGpcH1tPqjaw6kdbQer055+U3uBTEwvdDIfZ3AL7cE48kwcgO7nTwsqdLG3ssNEoKKrQk5MnHkyTJlEEL9bBrdNhefk4Mb++OVm/kmdWRrFq5GM7/ghElc3XTeMZrFbb3LIXQMfDQtrrshgR73oEvOmKTtpcaScNs7UwyBs8DQHF+NWp9JYGu1jzUXw5kd17MNZ2zpKrh2pwci9kctw7d6rtxM+aTZPRgcukzjK5+n1O0R6OvhNXTYPfbUNVQhqlWKTE/+xPqk4vkc05ciFnbnphbWJke6psYnAF8f/57dEYdvTx68Vqv1+Tn/8yX7E5tyCiaqZVcaDeZ55zbYlQo6OwwmAHeA5o9nlqlxkxlZnq4WLmwYOT32GpsOWthxjtdbkUXMJR3vNogIXF74O309uwNwMyuM7nV91b0Rj2z983mq7Nf8XXk1/Lj3DfszToCavOGh6MfF5Ry6WGnfi9D2ATodBfcv5F+jxzBXGVOqbYcg2RgbMDYRkGnhdqCycqepu+VEpgnXzEhNzDcdzhz+szBVmNLZkUmX575klt/vZWn9j4FwMR2E+np0bPxTnVZNJNeMxqt9rXzpZ9XPyQk1sSuucYrJAiCILQWIoMmCMJ1qdEZeHTZabJLawh0tWbdzP7YWzZkAWJzypmx7BSphVXc8e1R5k7qRHZpDZ/ujEWSoHtbBxQKBadTi3lz4wV+fLCnKUO1YG8CBqPEoGBXureVs0KWZiomh/ugUsKzv5zjyz3xjOnkiZ9LwxtSSZJ4bX0Ua09nEOBqza5nB6FSXtGpTlsJiXvkr906QN5FWDWVgh7PsS2qO6DkmWFyswdztYpwX0eOJBRyLKmQIHdbcspqKKvRo1YqCHSzbnRopVLBwvvC+WxnLD/uj6b/pbmghJXcxkLDOBYO6NKwsdocbp8PXt1g24ugrQD7tryleYkNGU70kzrSxjkITWE8E1WH8eg2i5EdPPhkRyxHEwsoq9FhZ6HhTF32zM/NyNP7p1OqLWWdvoaPLR14tPQF0rQWgAXbuy+ih2YFHP8ODn8BEV9D2Hh5LiyDFra9JF/XsDch7PY/95/jGrIrslmXIGfPnujyBD08epBYmsiqS6t47fBreFp7UlRTxNq4tew37sdoYQSjJZ8Om3ND5wmwD+DTwZ8yc/dMNpXFkuLSmYSCBBzMHXihxwum7ZQKJR8M+IDMikyiC6NZeH5hk2P9POpnU2atoLqA7MpsFCgI6/YQ9H7KtJ0V0NerL/vT99PFtQtv93u7caMSoDYurtH3NRejserevck57wq5i3GB49iZspO1cWuJzI+kpLYEJwsnnu/xfNMbtnaG3jPk19ejM/j0bLLJtNBpHM06yrqEdczsOhMLtcXVnkJBEAShFRAZNEEQrkmSJF749Rzn0ktwsNKw+IGejYIzkCdw3jRrAENCXKnVG3luzTk+2SEHZ3f3bsuqGX34eHJnzFRK9sXmszVKziKkFFSaxlzNHh7U+MS1FUzI/JzZXtFo9UZe3xDVaNzSooNJrD2dAUBSfiWbzjUzcXTiXrmNuoMvzNhvyjK4nPqcb9RfcluYK2FeDZmxPv5yV7xjSXLGqX6C6kBXG8zVqiaHVykVvDQqlK2dj9JWmU+m5Mz/au7Ay96CYaFuTbanx0PwyE4Y8gbM2I9DQA8AzmWUUtZJHj90v2on47t40c7NhkBXa3QGif2xcue/U3Xjz8zdtlKqlTOVpywtmNa2LXaBDSWY9/QLhNs+gjuXyG/eDVqI+hWWjIFlE0EyyBMjD3iu6TVeh4isCF4++DLpZU27TF7p+6jv0RvlsVc9POT7fannS/Tz6ke1vpqpW6cyc89M9qbvxYgRb4sw3ujxKZ42zTx/19DPqx+v9HoFgPMF5wF4occLOFo4NtrOUm3Jt8O/5bHOjzE1ZKrp0d1NDpzejXgXXV3L/YsFFwHwt/fHxsymyTlf6vkST3Z9kq+GfoW5qmnmsTZWnlvPsoscsNfExLR4/ZZqS8a3G8+y0ctYf/t6ZnWdxdfDvsbe3L75HQa9DMPegjt+aLaN/kDvgXhZe1FaW8rvyb+3eF5BEASh9RABmiAI1/Tlnni2nM9GrVTw3b3hjbJYl7OvC96eHtoOADOVkg8ndeJ/EzthrlYR6GrDzCGBALyzOZrSap0pezY4xJVubRu/iWbPuyhOLeapqm+wUkscSShkQ6QchO2KzuXD7ZcA6NbWAYAFexLQG65oKR6zRf43dCyozSga9AELHZ+nVtIwSnWS14JSG23eN7A+QJPHocXUTUQd6tl4/FkjORcIjP8RgK8tH6cKCx4e4N8wz9eVvLvDoBfB2pnOPvK1n8soYZ3xFiolc4KVmbQpOwPAiA4eAOys6+Z4OrUYK6uLZBmOoJAkPsgvxM/MkVxtCSmaj1Hbn2JYqBv+9a9Rh4nyuKoZ++XsWX2A4dMLxs2/4bmxJElicdRiHt/9ONuSt7H4wuKrbp9VkcX6hPUAPNH1CdNytVLNJ4M+IcA+AAA7MzvubX8vG8ZvYPuUX5jS6ZYbuq7LTQ2Vgy2A3p69uT2w+Qyhk4UTT3Z7ktf7vG56zB86HycLJxJLE/np4k8ARBVEAdDRpWOzx2lj24bHujyGg4VDk3XG6mq0qfL/MfuJEwGoiY6+rvto59iOx7s83uJ5AbmL5sDn5PFzzVApVdwVchcAa+PXXtd5BUEQhH+WCNAE4V/g56MpjJl/qEk3v7/D/tg85u2Wu/x9MLEjfQKcr7q9UqnguREhbHlqADuevYWpvRq3XH9icCABrtbkl9fy3C+RpoBr9vDgxgfKOA0n5DFSqpoi3g+Xx629tyWGowkFPLP6LJIE9/Zpy7JHeuNopSGpoNLUMh+QOyrGbZe/bj+WC5mljFtwmLnZ4SxnFABt4lc0Om1nHwcsNEoKK7XE51WYMmhXjj8zMRpg8zNyRqr97bz+7HOsfbxvs41QmlPfav9SdjkrIktYb6gbc1V37yPC3AHYH5tPZa2eoswovD2XAjC1vIrbB73Lyju2MrjNYPSSDkuvtfToEtn0RF7dYNyX8PwluPtXuH8DaG6s3K1KV8XzB55n3pl5pk6D+9L3YTA2bRhTz5Q98+xNuHt4o3V2ZnYsvW0p3w7/lr137eXlXi8T6BB4Q9fUkld7v8rCWxcyb/C8JiWHV2Nvbs9LPeXyz4XnFpJalsqFQrnJSCeX5js8Xk1tQgJIEipnZ2wGDjAtM2qbTkBeuHgxSRMmostsJhP8J0wKmsRT3Z7iyyFf3tTjCoIgCH8NEaAJwr/AooNJXMwqY0d07rU3vsl+PSWXEE7r1YYpPZvOb9WSjt72DVmcy5irVfxvovxGd8+lPAxGiSEhrnRt49CwkUEvBz1IoJSHyo63OEuwuw1FlVru/uE4VVoDA9q58Na4DtiYq3n0FjkTs2DvZVm01KNQUwJWzqwv9OaOb4+SWVKNr7MVQ+55FVBA0j4oSDCd2kytpIev3Cr+UEIW0TlyaeGVHRxNTv0od2c0s4XbPsLaXE0PP6dGQUG5tpxqfdMW/wDeDpY4W5uhN0rE51WwUhopr7i0FUoz6eLjgLudORW1enZvXMYIp4/IMVPgZpB4esxi6DkdWzNbvhzyJY91fgyAn6K/p6im6dxs8gtgC8EjwKz5LGhLUstSuWfbPexK3YVaqebVXq9iq7GlqKbIVEp4pcyKTDbEbwBgZpeZzW5jb27PAO8BzZYG/hlKhZJ+Xv2aLUm8ltH+o+nn1Q+tUct7Ee9xoUAO0K6ayWpBfXmjRUgwai8vVPb2oNdTG9d4agNJp6Pgu4XUXrpE4U9Lbvg8V+No4ciMzjNwsXS5qccVBEEQ/hoiQBOEVi67tJrMEvnN/dXmEfsr6A1GDicUADA5vM1NO26fAGfu6tHQ8rtJ9uzYN5AbBZaOMOYzAFSxW5g7seENcoCLNV/f3R1NXRnh/X39cLTSkFxQycbIuizaJbm88axlX55dc4FavZEhIa5smjWAgOAOEFwXDJ384YrrcwIMfBc/i2zbd0BZ1XyJY34s7H5H/nr4W2Dn1WSTrIosRv02ikG/DOKto29xPv98o3F0CoWCLpcFp94h4eDbX87InV6C0lDDix5nWWP2Dh3iX2Slgzz/12v93sImYIhpP6VCyayus+jg3IFqfTVLLixper03yCgZiciK4Pn9zzNh4wQSShJwtXTlp5E/cXf7u7mljVyGuDdtb7P7/xj1I3pJTx/PPg2t7P8FFAoFb/R+A3OVOcdzjlNaW4pGqSHYMfjaO1+hJlZuEGIeHIJCocA8rL28PKZxmWPliRMYy+Wf79INGzBWVv7JuxAEQRD+rUSAJgit3OnUYtPXcX9zgHYuo5TSah32lhq6+LTQpOAPem10e/oEODF9gH+jAIXi1IZ5nW59T25nrraEkjTCLbJ47tZgOvvY88MDPbC3amhUYmOuZsYtcnncgr3x6PUGDHXjzxZkhwLw1NB2coOT+v16Pir/G7kCahva9PcNdEZpkUWNIhelpgxb96N42F1RDlhVBCungLZcDqh6PNzsfS46v4gybRnV+mrWxa/jnm33MHnzZFZfWo3OKDeh6HzZczuxmzf0rGvTfvw7+CyEyWnv00MZy9suTugVCvwsejA0ZHKTcykUCmZ2lTNVq2NXU1hd2GSb61Glq+KHqB8Ys24MM3bNYGfqTlOTj1/G/kJXt64ADG0zFIA9aXuaTDpdpi1jc9JmAGZ0btz+/d+gjV0b0wTZACGOIQ1zkN2A+gyaeYg8RsyifZi8/IpGIRV79pi+NlZUULp58w2fSxAEQfj/QQRogtDKXR6gxedeZa6vv8DBOLm8b0A7l5YbXvxBDlZmrJ7RlzfGhjUslCTY+jzoqsB3AHS7F8ysoN0weX3MFp4eFsSmJwcQ4Nq0dO3+vr44WZuRUljF0nUbUJVnUSmZE6npysL7wnl+RAjKy9vwBw4FpwCoLYOohnmiOnk7YGGbYvpeaX+YMm1Zw356LfxyHxQny90h71oKyqYdHjPKM9iYsBGAN3q/we2Bt2OuMieuOI4Pjn/AozsfpbC60FTeaWuuZmioG7QfBzYe8nXVlCLZt+Ely5GcszBHMpjxROeXWhxXNdB7IJ1cOlGtr+anCz9d41Voqr6U8cszX5JRkYGNxoapIVNZO24tP4z8AVcrV9O2A7wHYKY0I708nYSShEbH2ZSwiWp9Ne0c2tHDvccNX0dr8ECHB2jnIDe8+SPljZIkNSpxBLAIk/+/11xsyKBJRiPle+QspPUAeZxa8YqVTYJeQRAE4b9BBGiC0MpdHqAVVmoprKhtdrujiQV8viuOilr9TTv3gboAbVCwa+MVp5fIY69uRN6lJhMmN3FxHSTsApUZjP2iocNg6Bj530tbr3oKa3M1M+rGolWe3wTAKU04a2YNZmRdN8RGlMqGbNWJH+QAEXkcmqNTGgCSpMCoqOHniz9TtwC2Pgeph5HMbPl1wKNsyz3R7PX8EPUDeklPX8++TAmdwgcDPmDPnXt4uefLWGusOZ17milbpuDkmMtTQ9vxxZSuWGhUoNLApIVyVu7e31A8c54LXnL5pL6sO0MCWy61UygUPNFF7pb4S+wvFFQXNFqfVZHFJyc/4ffk39EaGjeqOJhxkGlbpplKGd/t9y577tzD631eJ8SpaZdAK40Vfb36Ao3LHI2SkV9ifwFgasjUG2rS0ZpolBq+GPwFdwXfxUMdH7rh/fV5eRhKS0GlwixQzu5a1Jc4xsYiGeTmKjUXLqDPzUVpZYXXh3NRWFpSGx9P9alTN+9mBEEQhH8NEaAJQitWpdVzMUvO3NiYy80y4vOaz6K98lsU8/fEM+HrIyTm//lMW3GllvMZJQAMDL6suUDcTrmBx5Zn4fii6zuY0Qi/PSJPqLtldvPbVBfD7/L8VQx4DlwvC0KCR4FCJY9LK0656qnu7+uLi40ZI5UnAeh52320c7tKi/yud8sllHkXIS0CAL1RT7VKzghpC+QyvhUxKyipKZEnfD67DBRKFve9h3cvLuLlQy+zPn59o8Nenj2rLzsEuSnGvWH3snLMSvzt/cmtyuWhHQ8S4B/N8LqOjQAEDJaD1HbDQamkRiOXxPlZdcfSrGm27nIDvAfQ2aUzNYaaRlm049nHmbJlCkujl/LSwZcY/utwPjv1GUmlSXx37jue3PMk5bpyurp25ZexvzAxaCJWGqurnmto24Yyx3rHso6RUpaCtcaasYFjr7p/a+dn78ecvnPwsmk6vvBa6rNnZv5+KM3lJihmvr4orKyQamrQJicDUL5bfu6sB92C2sUF+3HjAChasfJm3IIgCILwL9OqAzSDwcCcOXPw9/fH0tKSwMBA3nvvvUZlH5Ik8eabb+Lp6YmlpSXDhw8nPj7+KkcVhH+Pc+mlGIwSHnYW9PaXOws21yikoKKWtCK5DX1CXgUTvjrC7j/Z8fFwQgFGCULcbfG0lxtToK2USxDrbX8ZEvY0f4DLXdoMuXInPKI3Quz2ptvsfgcq88A5SJ7X6XJWTuDbr+5YV8+iWZmpWT/FjWBlJpJSjVXYbSSXJvPQ9od4/9j7xBbFNt7B0hE63yl/feJ7AGIKY9BJ1UgGS7QFw/C1CaJKX8XSo+/Bzjfky+37CF+mbTMd5t1j73Iy56Tp+++jvkcv6enn1c80ZutyAfYBrBy9kqFthqI1annz6Jt8Hfl1s/eUVpZGYW0WKoWaLyc0HXt2JYVCYZpzbE3sGgqqC/j54s/M2DWDktoSAu0DcbNyo7i2mCUXlzB+w3i+jvwaCYkpIVP4ceSPjUoZr2Zwm8EoFUpiimLIrpAnH18VuwqA8YHjsdbcWLfI/09q4+QGIRbBDdlHhUqFRd14tPoJq8vrxp/ZDhsOgOM9d8vLd+9Gl5v3t12vIAiC0Dq06gDto48+4ttvv+Wrr74iJiaGjz76iI8//pgFCxaYtvn444+ZP38+3333HcePH8fa2pqRI0dSU/P3zxclCDfbmTS5vDHcz5EgdzkLFNfMOLT6TJePoyU9/Rwpr9Uzfekp5u2Ow2i8wXEsdR+A1I8/u+Xy7Nn+uVCaBvZt5OYdkhF+fUjuZtgSoxH2fyR/bVfXuXHbC42acpB2DE7XZXrGzQN1My3XQ+syMdcI0ADa5O4DQOE3EKOFPW8cfoNTuaf4JfYXJm+ezN1b72Zd/DqqdHJQa2oWErMJynM4mSsHWhpdO9ztLHmym5wBW5G+m2KlgpiO43gt/wAgl/CN9BuJ3qjnuf3PkV6WTnp5uil7Vl9u2BwbMxu+GPIFs7rOAuSuh+XapgH4kawjAHR370aI2/UFTv29+tPZVc6iTd0ylU9PfYpRMnJ74O2sHruaHXfsYMHQBQzyGYRSoUSj1PBOv3d4o88baFSaa5+gjpOFE11duwKwN30vWRVZHMw4CMCU0CnXfZz/j0wdHEMal4dePg6tNikZbWIiaDTYDJK7YlqEhGAZHg56PSVr1nAzVJ0+jaS/eeXPgiAIwl+nVQdoR48eZfz48YwZMwY/Pz8mT57MiBEjOHFCHu8hSRLz5s3jjTfeYPz48XTu3JmlS5eSlZXFhg0b/tmLF4Sb4FSKPF4rvK0jwe5yU4zmOjmeSy8FoJefEyum9+GBvr4AzNsdz4xlpyir0V3fCY1GWDoe6csulMXKAcigYDd5XfZ5iPhG/nrMZzD+K2jbF2pL5W6GLY0ti9kklw+a28EjO8G+LZSmN3Rq1Gvr5jxDbgriN6D549SPQ0uLgMqC5rcBKM2AMz+b9lkTu4bzBeex1lhzq++tqJVqogqieOvoW0zaNInS2lLw7AxteoNRD2eWciJH/h0zs88Itj9zCyP9h9HeMZQqjHzh5MCT+jSq9TX08+rHy71e5v3+79PRuSMltSU8ufdJ5p2eh0Ey0N+rf7PZs8spFUoe6/wY7RzaoTVq2Z26u8k2RzLlAK2/V/+rHutyCoWCWV3kwC+3Khe1Qp677P3+72OhtkCtVDO4zWC+GvYVuyfvZtukbUwKmnTdx79cfZnj3rS9rIldg1Ey0tuzNwH2AX/oeP9fNHRwbDxm0DQOLSaG8j3y623duzcq24ZSXMe7pwFQsmYNku46f36bIRmN5H/9Nan33EveF1/84eMIgiAIfx/1P30BV9OvXz8WLVpEXFwcwcHBnDt3jsOHD/P5558DkJycTE5ODsOHDzftY29vT+/evYmIiGDq1KnNHre2tpba2oZGC2Vl8hgfnU6H7k/8IRSEK9XqjcTmlNPByw6V8sYaJRiNkimD1tXHFgXy/nG55U3+n0bWbdfRyxaFZOCN0SGEedowZ1MMu2PyGL/gMN/c3ZV2bleftFeRuAd18gEUwFfS23xodh9dvYaiq61BtekplJIBY/vxGPyHggRM+gn1kpEoipMxrr4Hw91r5QYf9SQj6v0fogAMPWdgtHJDMepj1L9MRTr2Dfr2E1Em7kGVfwnJygX9kLegpZ9Baw/UHp1R5JxHH70Fqes9Ta8/9TCqddNRVBUgWbmQ3aYvX+6Ts2OzOs9iashUimqK2Jy0meWXlpNZkclvsb9xX/v7UHS9D3X6cbQX13HWXs4i9vPsiY2ZAr1ezwzPwTxbfIn1tjZQW4yfnR9z+81FMkioUPHZwM+4b8d9JJUmkVSaBMCMjjOu+3fKbb63saBkAZsSNzHWr2HcltagNQWMvd1739DvqB6uPRjlO4pLxZd4vdfrhLuFo28mi+KgcQD4w7//bvG6hU/5lNO5p00lpHe2u/M/8/tU0mrRJidjFhxsaogi6XTUJsn/D1SBgY2eC3WwHLDVREdjqJazuFZDhjTaxnLIEFQuLujz8ynevgPbUSNv+LoM5eXkvfY6lfv3y99XVaPValEoFP+Z10YQBOHfqFUHaK+88gplZWWEhoaiUqkwGAx88MEH3HOP/MYsJycHAHd390b7ubu7m9Y1Z+7cubzzzjtNlu/cuRMrq6sPiBeEG7E+Rcn+bCWh9kbuDzJiff2VY+RUQWm1GjOlRMrZIxgkUKCiuErHLxu3YVt3LEmCU8kqQEF56gW2FcljvSyAp9rD4lgVyYVVTPj6CPe0M9LFueWSx96Jn+MBlCodsDeWMEexhLTFCZRbeNMhOxKdyoo9qmHUbmsYe2Xr8RgDy95Fk3aUwq+Gc8pvJlqNHQBexSfomR+DTmXFztJA9HX7hTv0xqfkONUr78e6Vh5jc8Z1Mhn7Iq76nAQr2tGe8+QfWsKJLMeGFZJEQP4OOmSuRoGREsu2nPB7hh/3vU+FrgIflQ82CTZsS5TP74orAxQD2MhGfj73M45JjpgblIxCyaXSRKqsPbBUWBJ3NI4EhdwsJCQrgvYqLTHmZlgqLJkoTeTQ7kONrm+yajLf8z06dASrg0k/kU466Ve9p3rmRrms83TuaVZuWYmD0gGARF0i1fpqbBQ2xB+NJ1GReF3HqzeAAQxQDiD3VC7b2HbtHf4gD6UHOcYcSrWl2CvsqTxfybaov+58rYnz9u0479tP8YAB5I+Tg2uz7Gz89HoMFhbsOn26oSMpgF5PkEqFsbyc2vNRABwzGjBsa/x8OXfpgvOePWS89x5ZaanU+vhwvcxy8/Batgyz/HyMajV5EycQ17UL/P47AFVVVX/yrgVBEIS/SqsO0NasWcOKFStYuXIlHTp0IDIyktmzZ+Pl5cUDDzzwh4/76quv8txzDU0IysrKaNOmDSNGjMDOzu5mXLogoNUbeevjA4COS6VKvk205pu7uxLq0VDGJEkSx5OLSciv4M7u3phrGrrzrTmVAeei6ebrxLixPQGYH3+I9OJqfDv1oU+A3DQkvbiKymOH0agUPDJpZKNjANxZqeWZX85xPLmYH+NUTO7ujZttwxgvjUrBuC6e+CrzUZ89B8A7Lp/imLmP1zWraFt02LSt8tZ3GBZ+d5N7VSQFI619ANeKaEalfYh+8s/g0Qn19/+T9+s3ixG33NmwQ0U40nd9savJBMDoP5jO097DqTKTEzknuD3gdtTKZn495fnB9+vwqIxmrFUk1GUVFfkxKDPlN7fGjpOxHv05qrxTXDxwEZVCxacjPiXYsXGZ2RD9EPas30ORrgjHbo709xoL5as4USw/B328+zD2loZMlurHz3mroIj5IX15tO+bdHHt0vT6gPZZ7VkVu4oXwl/Az86v2W1asm/3Pk7nnUYboGV02GgAvjz7JcTAYL/BjO3bejsipp5P5fsLcpOVezrdw7iO4/7hK/r7ZG7YSDXgePgwwUOHYn/nZMo3byEXsA4LY/SYMU32SV++wjRZtXnnzoxspuLD0K8fGYmJkJKC38JFuM6Zg92E8Y220aWnU7FzF8bLAi5Jp6N0zRqkykrUHh54zPuC4A4dGu1XXzkiCIIgtD6tOkB78cUXeeWVV0ylip06dSI1NZW5c+fywAMP4OEhz2uUm5uLp6enab/c3Fy6du3a4nHNzc0xN2/ahECj0aDR3ECKQxCuYn98LiXVOlxszLA0U5FeVM1di07w8eTO9At0Zu3pDFafTCe5oBKA1KIa3r694U1UZIb8BqqHn5Pp/2WIhy3pxdUkF1UzMEReFp0j79/e0w4bK4sm1+HhoGHF9D7M/f0Siw8ns/ZMZpNtfjySyubQnfghYfAfwpY4G7SGMTxyxzi8ds2E6iLw6YWq13RUymaGrobcCo/ugdX3oChKRLN0DHScDPmXwNweVb8nUV3+s+XoA7e+I7fqV1ugHPcFCo2GV468QnRhNBX6Ch7p9EjT83h1BqcAFEVJqI583nidQgUjP0DZ+3Fq9NV8dEpuTHJ/2P10cOvQ5FAajYaJQRNZFr2MNfFrGOw7GNrfzqkzlwDo7dW74fdBZQFkn6MDEgtHLALbZuZUqzPYd7B8rD9gXOA4Tued5vfU33m0i1yaGZEjZxUH+Axo1b+fRvqP5PsL36NRargz9M5Wfa03myE72/R1/v/+h2VAALpEOfNqGRra7HNh0SHMFKDZj7i12W00rq74r/2VrJdepmLvXvLmzEEXE4PbC89TceAAxWvWUBVxrMXrsurZE+95X6B2dm567P/Q6yMIgvBv06oDtKqqKpRXvBlUqVQYjUYA/P398fDwYM+ePaaArKysjOPHj/PEEy13ThOEK608nkZ8Xjmv3BaKufrqc0xdrw1n5UBoYjdvZg5ux9Orz3IovoCnVp1FrVSgr+uuaGWmokpr4OeIFCZ286ZLGwegYYLqHr5OpmMGuduyOyaP5Kw82PgpBN3KufQgADr72Ld4LWqVkjljw+gX6Myh+MYNNiLTS4hJz8P+0mpQQJT3FLQxRnwcLfHsNgQCDsKFtdDlbnli55a4tYdH98K6GRC/AyKXy8v7zgRLh6bbd39Q7gLpFAhOAZzLiyS6MBqAJReXMDV0atMW7QoFTPoBon6V962nVEGHidCmF0bJyCenPiG7MhtvG28e7/J4i5c8JWQKy6KXcTjzMOnl6XgEj+BM9JcA9LALbNgwcR8ggXvHqwZnf9atfrfywfEPiC+OJ7YoFkcLR+KK41CgME0I3VqFOIXw4cAPcTR3xMXS5do7/D8hSRK6ugDNqlcvqk6cIOOZZ9DUld5f2cGxnkVYGKX8BoDNsGEtHl9lY4PPVwso+PZbChZ8RfHKlRT/+mvDWE2FAuv+/THz82u0n5mvL45Tp6AQgZggCMK/TqsO0MaNG8cHH3xA27Zt6dChA2fPnuXzzz/n4YcfBuQuZbNnz+b9998nKCgIf39/5syZg5eXFxMmTPhnL17416jRGXh700W0BiOl1To+u7OLaaD/H1VWo2NXjDwP2YRu3jham7HkoV58siOW7w4kojdKdGnjwLSebRjXxYvX10exITKLV9dFsenJ/pTV6Emqy6x1a+tgOm59J8e2qb9B2TKI+pUcx28AC7r4OHAtw9q7M6x94zGbOoORrUs/xTG1ggzJhQcOOwBGBgW7ys+DQxsY8Oz13bilA0xbDQc+hAMfgZUL9G4hQFIqoed007erY1ebvi6pLWHVpVVM7zS96X4+4fKjGeXacl47/Br70/cD8EafN6460bKvnS/9vfpzJOsIa2LXMKztMKqVShwMBoKyL4F3H3nDhLrOiu1afiN9M9iZ2THIZxC703azNWkrAQ5yF8Qw5zCcLJyusfc/b0xA01K+/+8MRUVItbWgUODzzdekPfIINefOU1sqd1a1uKKDYz3rnj1BqcSiQwfM/f2veg6FUonrrFlYhIWR9eJLGCsqULu54TD5DhzuuAONt/dNvy9BEAThn9OqA7QFCxYwZ84cZs6cSV5eHl5eXjz22GO8+eabpm1eeuklKisrmTFjBiUlJQwYMIDt27djYdG01EsQmhOVWYrWIGdj1p3JJMjNlicGB15jr6vbHpWDVm/kEadIwpbNAn0tKuAV4EUbiQq/kdhP/R7UcsfDN8aGsT8un+jsMn48koy/ixyIBbnZ4GDV0BUxyE0ev9azbJe8QF/DtLwv2MwrpszbjdIoFUzQynOLrTLeSqlOfi4GBV/ffFtNKJUw5DXoeAeYWTefPbtCYXUhO1N2AnBv+3tZHrOcJReXMC102nVPdJxUksQz+54hpSwFM6UZc/rOYYB3Cy37LzM1dCpHso6wPmE95iq59LlHTS3K2G3Q40F56oHEvfLGgX9tgAYwNmCsHKAlbzXNL9bf+/rb6wt/L11WFgBqV1dUNja0+eorku+agr4uq2YeFNTsfuZBQfj/tha16/X/nNkOGULAls1oU1Kw6tEDhbpV/wkXBEEQ/qBWPQ+ara0t8+bNIzU1lerqahITE3n//fcxM2t4w6pQKHj33XfJycmhpqaG3bt3Exzc/CeWgtCcUylyKaGLjfz/6uMdl9hxsWkX0LIa3XXPJ7a+rrzxfvPDKKqLQVdleqj01dgnbJAna66bFNrFxpzXbpPnRvpiVzwbI+X9w30dGx030NWGAGU2HUlEUqgwqszpp4jiLrMIAl2v3kK/RZmnITsSVOaMeeBlvB0scbczp3+7hjK1vKo8JOkGJ7x2DQH76+s6ty5+HTqjjs4unXmhh9xco7S2lJUxK5tsqzfqTSWA9Y8tSVuYtnUaKWUpuFu5s/S2pUxoN+G6zj3QeyDeNt6U1pby80V5/rQeNTWQtB9qyyH3AlTmgcYa2va53rv/wwb6DMTWzJa8qjx2p8mZuxuZ/0z4e+ky5QBN4+UFyIFam2+/QeXggFXfPiitW/6AwaJ9e9QuN1YOqvHwwLpPHxGcCYIg/D8mfsML/3n1Y70eHxRIamEVy46lMnt1JGuf6EuYpx0RSYWsOpHOjgs5WJmrWPt4X9q52bZ4vKySao4lFwISPjVx8sKpq8C9rlFF5ilY+4g8mbJrqDxGC7izhw9rz2RwIrmILeflT9+vDNAszVTcb30CdFDiOZAMm050ilvA6+plqGqeB6s/UAZ3Qu68R8dJhLXzZ/+LvhiMEhYaFVW6Kt6OeJvfk3/nufDneKjjQzd+/GvQG/WsiVsDyNkslVLFY10e49VDr5qyaDZmcvCZWpbK7H2zSShJaPZYPdx78OmgT3G2bNoUoSUqpYq7Qu7ii9NfUGOoAaCXmRuUJcmljUXJ8ob+A0HdtLnQzWamMmOk30jWxq3FKBmx0djQybXTX35e4Y+pH39WH6ABWISG0m7/PhSXfZgoCIIgCNerVWfQBOGvJkkNk0F393XkrXFhDAxyoVpn4OElJxn62QHu/v44m89loTUYKanS8cjPpyiu1LZ4zE3nspAkGNkWVNUFoFBCwGBw9JUfHe+AEe/LG+98HeLk0j6FQsH/JnbCTNXwY3llgIYkMVo6CMB5p5GsMZ9ErNEHe2Mp7JrTeNvqEojZDPmxLT8BpZlwcZ38dU+5a6BGpcRCoyK9PJ37fr+P35PleZN+if3lxrNo1+FA+gFyKnNwNHdkhN8IAG7zuw1/e3/KtGWsvLTStN20LdNIKEnAUm2Ji6WL6eFm5cZDHR9i0YhFNxSc1ZvYbiJmSvnNtKO5I4FBdWOpLm1tKG9sN/zP3+x1GhvQ0E6/j2cfNErR6KG1qi9x1Hh5NlqutLBAcbWmOoIgCILQApFBE/7TkgsqKarUYqZW0tHLHrVKyVd3d2fiN0dIyq8EarExVzO+qxdjOnny0m/nSS2s4vHlp1n2SG/M1E3fgNV3b7y7bQnkAS4hYHZFo4q+s6AgFs4shbUPwyM7wT2Mdm42PDE4kC/3xONsbYa/yxXlURkncdNnUyFZsFfRk7NZlUTrHuE383fg7HLoMg1UZnB6CVxYB/pqeb+2fSH8QQgbD2oLSDksbxOzCQxa8OrWqPHGkcwjvHTwJcq0ZThZOFGtryazIpNz+efo6tb15jz5dVbFrgJgUtAk0xgwlVLF450f5+VDL/PzxZ+p0dfwfZSc6evm1o3PB39+UzsFOlo4Msp/FJsSN9HDowfKgHEQsQDidsilqQCBQ2/a+a6lm1s3vKy9yKrMop93v7/tvMKN02XXjUG7LIMmCIIgCH+GCNCE/7T68sYuPvamYMveUsPPD/Xim/0JdG3jwNjOXlibyz8qPz7Yk0nfHOV4chFzNlzgwzs6Ner4GJNdxqWccsxUSnpbpMsLPTs3PbFCAaM/g8IkSD0MKyaD/y0APG2UuLVNOdr2k5p2kzz/CwA7jD2JzK7lUnY5eimEio73YXNhGSydAMbLxsk5tJWzZGkR8uP3l8DKGYqSGrbx7AK3f2X6dmXMSj46+RFGyUgnl058PvhzFpxdwKbETWxJ2vKHA7T44njWJ6xnoPdAenv2RqlQklSaxPHs4ygVSu4KuavR9iP9RrLw/EKSSpNMwdnUkKm81PMlNKqbn1F6NvxZrNRW3N3+brD1BWs3eewZgKM/OP+5xjE3QqlQ8v6A9zmYcZDxgeOvvYPwj2nIoIkATRAEQbg5RIAm/KfVB2jhvo3HbrVxsmLupKaBVbC7LQvu7sYjS07yy6l0gtxtmD4wwLS+Pns2NNQNi4IL8kLPLs2fXG0GU5bB90OhOBnOyZkkFdARoGA7+Do1ZG70WjkrBmww9OdchtzG28XGDOsx70HKTqjIBbUldJwkZ8x8ekJ5NpxdIWfrStOgphTMbKDTnRD+gJw9q1Opq+STU59glIzcEXQHr/V+DTOVGWMCxrApcRM7Unbwcs+XbzhAqtZX8/Tep8moyGBZ9DJ8bHy4I/gOkkvl8V2DfAbhZdP4Da5KqeKJLk/w4sEXMVOa8UafN5gYNPGGznsjXCxdeL3P6w0LQkfLWUb4y9vrN6enR096evT8288r3Bh9fZMQTxGgCYIgCDeHCNCE/7SGAM3xGls2GBLixutjwnhvSzQfbIthxfE007qsErmkcEI3b9h1Xl7o0UwGrZ6VEzyyCy78BobahuWpERD3O6x5EKbvBtdgSNwD1UVI1u4cq+1g2rSzjwMKS0d4cCtknoHgkY1b29t5waAXYeBzkHwAqoshaCSYN+36eDbvLHqjHm8bb97q+5Ypg9fbozculi4UVBdwJOsIg9sMvu7nC2DhuYVkVGRgb26PwWggoyKDL898aVo/NXRqs/uN8h+FlcYKH1sfAuwDmt3mLxM67rIA7e8bfyb8exgrKzHUzXem8RYBmiAIgnBziABN+M8qqdISn1cBQPfLJoO+Hg/39yO5oILlx9JIrptQup6HnQVDfNVytgrA4xod+Gxcoc8Vkzn3fhx+vh3Sj8HKu+DRvabyRkWnyfhcsDOd1zRBtUuQ/GiJUnXNcVQnc04Ccvbm8vJKlVLFbf63sSx6GVuSttxQgBZXHGdqX/9uv3fp49mHnak7WRu3lnP552jv1J4+ni23r7/F55brPtdN5T9QLhHVa8Fv4D9zDUKrVt/BUWlri8rmD05zIQiCIAhXEAGa8J91Nq0EgABnK5w33A2FCfDYQbCwv+a+CoWC9yd04t4+vpTX6ButC3S1wTz3qPyNo991TdTchNocpixvKH9cfQ9knZHXdb6Ldnn6hgCtzbWv93qdyjkF0Gxp3diAsSyLXsb+9P2Ua8uxNWt5qoF6RsnIuxHvopf0DGs7jKFt5QBxQrsJTGg3geyKbOzM7VAqWmG3O7W5/P9BkprNNgpCcy32BUEQBOHPEgGa8J91KrUIgLHuBfJ8VyD/2/GO6z5GqIdd8yuy68obWxp/dg1xxXFkV2TD8Bdh15uQfwYnpZFOLiHg2YVg91h2RecCconjzVCpq+Ri4UUAero3DdDaO7UnwD6ApNIkdqfuvq7xYL/G/sq5/HNYa6x5pdcrTdZ72ng2s1crYnn9pa/Cf8+Vk1QLgiAIws0gAjThP6t+/Fn9vGIAJOy9oQCtRdnn5H+vNv6sBUklSdy5+U6MklFe4GwLyNmqHzwG0luhINhd/r6NkyVO1jdnMtwzuWcwSAZ8bHyaDZwUCgVjA8Yy/+x8tiZtvWaAlleVx7wz8wB4qttTeFh73JTrFITWwtTB0bOVf9AgCIIg/KuIAE34f+9sWjHxuRVMDvdBqZTHVekMRiLTS1BipF3ujoaNE/fIJW1XtrcHSNoP2iq5u9+15PzxDNqhzEMYJSOO5o742PoAkFuaQp6unN3W1vQGRnbw4I7uPtwa5nbDx2/JydyG8WctGR0wmvln53Mi5wQ5lTlXDbo+PPEhFboKOjp3ZGpI801ABOHfzFTi+Dc2CMlPTaYwI43Q/oNa3CYrvpi0i0VNlru0saVd+M37nSEIgiD8NUSAJvy/lltWw/2LT1BeqyelsJKXRoUC8nxlNTojIyxiUVflyqVsuhq5JX1eNLh3aHyginxYPlmeY+yBzaY5y5pVWwEF8fLXfyBAq2/U8XDHh3mw44MA7Enbw+x9szmadxoAC42Kz+76Y+WTLZ43+9oBmreNN93dunMm7wy/J//OQx0fana7A+kH2JW6C5VCxVv93kKlVN3UaxWE1uDvzqBJksSGT96jLD8PGydnfNp3bLJNdbmWzV+dR19raLIupI+HCNAEQRD+BUSAJvy/9s7mi5TXyk08vtmfSDs3GyZ19zGVN95vfQwqgQ6ToCQNEnZBwp6mAdrFdQ0TQG+eDU8cBY1F8yfNvQhIYOMBNjf2ZshgNHA6Vw7Ceno2BEq9PXqjVqhJK08jvSydNnZtbui411KhrSC6KFo+7zXm3hobOJYzeWfYlLiJBzo80KTBR5Wuig+OfwDAfWH3EeoUelOv9b+qtlrP4TVx+HZ0EW+y/0IF3y2kMiKi0TKlpSVuL76AeWDjycr/7kmqc5MSKMuXJ09Pj45qNkA7uysNfa0BezdLfDs6N1rn5tvCmFlBEAShVWmFrdME4ebYE5PLtqgcVEoFt3eR30C98lsUp1OLOJVajAW19Ko5Im/ceUrDZMT1DUMud35Nw9dFiXDos5ZPXD/+7A9kzy4VX6JCV4GNxoZQx4bAxsbMhi5u8vGOZB254eNey5m8MxglI21s21xzrNgI3xFYqCxIKElgwdkFTdZ/Hfk12ZXZeFl78USXJ276tf5XndmewqWIHPYsiaY0v/qfvpz/l/QFBeTPm0fV8eONHhX791P400+NtpX0evS5cqMe9d8UoCWcbAgcs+IuNVlfVaYlan8GAAPuDGLgXcGNHiG9xThQQRCEfwMRoAn/L1XW6nlzo9yRcPoAf+ZN6cqIMHe0BiMzlp7mWGIhtypPY2aoAgdfaNOrYTLitAjQXja3WWEiZJ4ChQpGfyovO/wF5DV9gwRATn2AduMNQurLDMPdw5uUBQ7wHgBcf4C2M2Unt2+4nV8u/XLt89aVVfby6HXNbe3N7Xmz75sA/BD1A5sTN5vWRRdGszxmOQBv9HkDK43VdV2rcHXV5VrO788EQK8zcmBVLJIk/cNX9f9PdVQUABofH7w//wzvzz/DZeZMAKpOnGy0rT43F4xGFBoNaheXP31undbA3qUxLJsTQeqFwma3STh5zPR1dtwlJKOx0frIXWnotUbcfG2bZM8EQRCEfw8RoAn/KgUVtdTomo6tuNIXu+LILKnGx9GSZ4b4oqwt5YspXQnztKOwUkthpZaJ6vrs2V1yUxDndmDfFgxaSDnccLD67FngEOg5HYJHyeWOW2bDFW+QgD+VQbtao45+Xv0AOJF9Ap1B1+IxDEYD807P4/kDz5Ncmsy8M/Oo0lVd/bx1AVoPjx7XdZ3jAsfxaKdHAXjr6FtE5kWiN+p5J+IdjJKRUX6jGOjz35jcWVujR9fMeJ/L1VTorrnN1dSXrTm4W6FSK0mPLiL+ZO4fPp7QvJqoKPQqC1Td+2I3ejR2o0fj9PBDoFSiS0szNQWpqdRRmSqXN6o9PVEo/9yf0rKCan77+DQxR7Mpy69my9fnOLUtpVEQXpSVSWFGGkqVCrW5ObVVlRRmpJnWV5VpiTogZ896jvVvNNG8IAiC8O8iAjThX+N0ahH9PtzLfYuPYzC2nD24kFnKj0eSAXj/9hCsVtwOnwRiffYHfrg/HFdbc5woY5CyLpDqdJf8r0JxWZnjHvlfSYLzdRmozlPkbUZ/ChprOdN2dmnjk+u1DZm1G2yxrzfqOZMrT0bdXIAW6hSKk4UTVfoqIvMjmz1GaW0ps/bMYvGFxQBYqi2p0FWwJWlLi+ct15YTUxQjn7eZ+c9a8mS3Jxnedjg6o45n9j3Dl2e+JLowGluNLS/3evm6j/NvlngmjyUvH2HFW8coL6ppdpuc5FJ+fv0ov354Cr32xoO06vKGsrX+d7Sjx2hfAA7/Gk9NZcuBunDjUqMKONrnXX4vG8Tv30WRerEQhZU1Fh06IKEgbstptn5znh9fOMSq5WVcaP8Qpd5d/1Q2Mz26iDVzT1KYUYGlrYagnu4gwfFNSWxfeAFtjTyGtr68sU2HzngFhQCQGRtjOs7Znaly9szPTmTPBEEQ/uVEgCb8K2j1Rl75LQqt3sjJlGKWRaQ0u53eYOTVdVEYJRjb2ZPBhb9Cxkkw6mH7y3jte5Yf7+nIY87nUGEEr27gGtxwgPoALbEuQMs4BcXJckAWOkZe5tAGhryGFth38F0qipIa9s+PkbNrFg7g0PaG7jG2KJYKXQW2GltCHEOarFcqlKYs2pHMpmWOccVxTNkyhSNZR7BQWfDxLR/zZNcnAVgdu7rFN5FncuXxZ752vrhbu1/39SoVSj4Y8AHtndpTVFPEkotLAJgdPhsXyz9W8lVdriX5fME/Ur5n0BlJOJ2Htlp/zW2NRomIDYlsX3QBXa2BypJatn5z3vRmul55UQ3bvo1CX2ugOLuSU9tSbvi6zu68rGytkzPdRvji6GlNdbmOo+sSbvh4/xUGg5HEs3nUVFw7iJUkiVPbkjmuvAW9xhoJBUmR+WxZcI5lbxzlkv8dHO3zHvtPW5FyvgBJAqNRQZ57D46Zj2TFW8c4syOVqjLtdV+fTmvg1O8pbF4QSW2lHjc/O+56rScjHunAkHtDUarla1j74SlKcqtIOCWXN7br2RevkDAAsuLkAK2qTMuFA3IJbK9msme62hp2//A1lSXF1319giAIwj9HBGjCv8Kig4nE51WgrpvH7JMdsWSXNm2U8MnOWKIyS7GzUPP2Ldaw/0N5Rfvb5TFk51fTacddPGZdNzl15ymND+B/CyjVUJgAxSkN2bP2Y8HMumG73o/zRttAnnayZtqG8SQm7pKXZ182/uwGS4xO5JwAmh9/Vq+/d3+g6Ti0Sl0lM3fPJLMiE28bb5aPXs5t/rcxvt14LFQWxBfHcybvTLPHNJU3ul9feePlrDRWzB86H1dLVwC6uXVjcvDkGz4OyG+St317nm3fnCfuxN9bvicZJXb8cIEd319g3/IWxhbWqanUsfWrc5zZngpAx0HeWNqZUZhRwe6fopHqsrvaGj1bvzlPdZkWK3t5MvGzO9MozKy47utqrmxNpVYy+B45gI85kk1WvHjTfSVJkti//BLbF15g548Xr7qttkbP9kUXOL4pGRRKvHOOcNdLXek81AdzKzUVRbUklblSa+GIxlBF1+FtuPvt3gxxPI135iHUSgOledVErE/k51ePsH3RBdJjikz/D65UkFHOwVWxLHn5CMc3JiFJ0L6fJxOf74aNo9wZNmyAFxOf7461gznFOVWs//QQ2XVNQQJ79MIruD0AWXUZtDM7U9HrjLj729G2g1Pj58JoZPs38zi363fWf/SOGLsoCILwLyDa7AutXnJBJfP3JmCGjg2dTnA0U8+CgnDe3nSRhfc1BBW/nkpn4QE5m/X+hI647H8a9NXgNxDuWgoph+DXBxuCKIUKOt7R+GQW9uDTC9KOQtwOuPCbvLy+DLLO4Zxj/K6SP5lPUcHdB5/lg+x7GF5aN7j/T8x/drU29309+wJwqegSBdUFpkzVgrMLyK3KxcfGh9VjV2Nvbg/IDT3GBIzht/jfWH1pNeHu4U3Pex0TVF+Nh7UH3936HasurWJ6p+lN2u5fr9QLheQklQFwKSL7b+04d2xTEsnnCgBIOJ1Hj9EVOHvbNNmuJLeKzQsiKSuoQa1RMvT+9gT1dCektwcbPj9L8rkCjm1MpM/4QHb/FG0qW7vjpXAOr4kn+VwB+1fEMumF7iiU1w7gz9Y3fbiibM2rnQNhA72I2nuMzV+eZcLzj+Du73Bd91pZWsvZnWm4trUlsLsras3NmaNOkiQuHMhEY64ipI/HXzoGqqpMS+TuNNqEOtEmzKnJ+rM707gUkQPIJYTZCSV4tnNosl15UQ2b50dSnFOFUikRHLOSANcKXAOccA1wou+EQBLP5pMVU4Biyce45p4l+J0daDysKc+PIyT+MP3v7Ui+T18uHswkL7WcxDN5xJ+MRq1KwKWtPw6XNQsqya0mL6XM9L2diwXht/nRvp8n2uoqLuw7QHlhPr0n3ImHvz13vtqDjV+cJT9Vzp55BAajKVBhn2WHUqmmJDebnORsLtZlz5obe3Z07Srijh1GqVIz+L7pYmyaIAjCv4DIoAmtmiRJvL5eLm38yG0XYbFfM71iISfMZzEy7i1O7N8CksSJ5CJeWy93YHt6aDtuV0XI7fJVZjB2npzN8r8FZhwAz67ywdsNa36esvoyxwMfQ3URWLtCwGDT6mp9Ne8fex+ASX6j6SmZU6VU8GziSuYnb8QA4HFjAZreqDdluK4WKDlbOhPmLJc3Hc06CsCFggusjFkJwJy+c0zBWb2poVMB2J26m/yq/EbryrRlXCq6dM3zXkuwYzBv9X0LbxvvP7S/JEmc3JJs+j4jtpiK4to/fD034tKxbFM2zMFd7jp5cmtyk+2MRoldP16krKAGOxcL7ng5XB4vBHgE2DP0fnlahDM70tj4ZSTJ5wpQqZWMfqIzds6WDJwSjMZcRU5SKRcPZ13zuqrKtFyoG3vWXNlaj9t80FdtoSJ/H7+8t4Y1/zvJhYOZVy3R1NUa2PLVOc7tSWf3T9EsefkIh9fEU5RV2eI+1yslqpCDq+PY83MMO3+42KTc82bJTSnj17knObszjU0LIjm5NblRtiopMp+IDYlAw+t5YkvT11OSJPYujaE4pwprezMGuUXjlX0Uy44Nc4upzVSE9PZgyIMd8XWvRSnpqTwhZ7rr50CzautFWH8vJjzXie4jqlApfkNbtpSq4qOknVvJpSMXiDueS9zxXPJSylAqFQR2d+X2p7tyzzt9cHAtY8d3X/Ld4/ezZ/E3nNjwK1vnf4LRaMDa3pzRMzuDQb4fiQCKfoml6mAOA9pMAmDjZ9sasmdXBKsxRw5w7LdVAAx/dCY+YU3nTRMEQRBaH5FBE/4ROy/m8PGOWHSGxl0QQz1smdqzLbcEu6JSKlh/NpOjiYW0V2czoaKu3NApAPOiJCapDsP+w9RGtuNQaT9sDP0I7+jKRf3/eP3ICSabm9G1z/MoXNo1nMChDTy8HaI3QcCg5i+u3TDY+x5UyRkVOk4GVcOPyrfnviWzIhMPaw9e7vcWZv3e4fMNU1hWlcT3thakKF34zKMzN/I5dUxhDJW6SmzNbAl2DL7qtv29+hNdGM2RzCOM9h/NOxHvICExJmCMaYxao+fUKZSurl2JzI9kbdxanujaMDfZ7tTdGCUjfnZ+uFn9c5Mfp14oJC+1HLWZEntXKwozK4g/mUu3ETc2ju9GZSeUmEoaw0f5EtTTndXvnyDxTD4FGRW4+DRk0aL2Z5CXWo6ZpZpJL4Rj7WDe6FjBvTwozqni1LYUMmPlssMh94XiESAHzLZOFvQeH8DhNfFErE/Ev4sL1vaNjwFy4JCTWMrJrcktlq0BpEQeRTLKjUkkQyr5ae04sDKWI2vjCb/Nj/CRvo2ydJJRYveSaArSK7Cw1qA2V1JRVMu5vemc25uOZzt7wgZ40a67G2qzG8uqXRlgJ5zOoyi7ktse74SD282baiH6SBYHV8Vh0BuxtNVQXa7jxOZk8lLLGf5QGGUF1ez6KRok6HiLN91GtmXFnGNkXComK74EryAH07HijueQcakYlUbJhOe7U/Lsd1QDFp07NXtu6169qDl3nqoTJ7EfP97U0VHt6cnZHVs4snoZtVVyoKtUqTC3dqC6rBALi0OEj3sBhVKJxlxFQFdXrOzMqCguYtWc58lJjDedw8m7DWV5uSSdOcmhlT8z6N6HsbSRMOrlbo3K4jYYjXLm3lPpT6h9b+LL0nBv15ERj3RoFMRnx8ey49t5APQYN4lOQ0bcrJdBEARB+IuJAE3420mSxKc7Y0nJK0aPptG61MIqdlzMxdvBksnhPiw7looCI4udl6Mo1UHQCLh7DbVpp9i59COG6g9iXZLA8yTwtMVK3qEzG/MLwFLNJksPAksjmBy9nHGB4xoySxpL6DKlmSur49EFrFwaArTODeWNsUWxLL0od258vffrpnm+XrpzIx32v8kbKevYZW1FnNJA0zYfLasvM+zh3qPF8Wf1+nv35/uo74nIimBp9FIuFV3CzsyOF3u82OI+00KnEZkfya9xvzK983TUCjU/RP1gmmh6SJshN3C1N9flb+47DfLBztWSAytjiTuZ85cGaGUF1fy+MAqjXiKgmyu9bw9AoVTQrrsbCafzOLk1mdsek9+slxfVcHyjXD7bd2Jgk+CsXq+x/pTkVRF/MpueYwOblGl2GuxD3PEc8lLLOfRLHIOmNfwv0euMJJ3N5+KhTIpz5GkRFAroPT6gSfZMkiTO7mjozGlpk03PCYHEHMmmOKeK4xuTyEspY/iDYZhZyr/mj29OIulsPkq1gtse64BHO0fSo4u4eCiTlKhCshNKyU4o5fCaeIJ7exDa1wPbujFR9SysNc2WZqacLyA/rRy1uYoRD4exf0UsRVmVrP3wFMMfCsOv0401jdHV6tDVGk33LUlwcksyFw7KpXz+XVwY/mAYiWfzOLAyjpTzBfw69yR6rR59rQGfUEcGTAlCpVIS2t+T6ENZnNiSzIRnuwFQXaHl8Fq5wUrPMX7YO5mRc1Eeq2bZqWmAJhmNWPXqReH3P1B1/DiGkhKk6moMCgV7Nq0l5sh+AOzdPeg0ZAQdBg8HSeKn556gLD8FhRRFt1vHNdyftpaNn75PTmI8ao0ZwX0H0HnYKLxC2hN79CBb53/Cqc3rcPZug9rMDKPBgLWjB151v8NqlQrMjRJdnAZTW36IsS+FY2bR8Oe8rCCfDZ+8h0GnIyC8FwPuug9tejlmbWxv6HUQBEEQ/hkiQBP+djHZ5fjpP6YoJJU3XO+kTaenANDqJXZF5/LbmQwyS6r5co/8yfLTjsfxKj0LGiu5xb1CgblvTxymfkvvxfsZrzrKfWb7sFalsUWfDwoFt1ZWcdjWgcTSJD46+RELzi7gvf7vMcLvOj5FViohcChErQHnILnTI/L8Yu9GvItBMnCr760MbjO40W5jBr/Lnt1F7Mo8wJaU3wlxCbvu5+R6xp/V6+zaGWuNNcW1xcw/Mx+A53s8j7Nly621b/W9lY9Pfkx+dT5bErdwMOMgu9N2AzA5eDJPdnvyuq/1ZkuJqsuemavoNqItCqWCQ7/EUZBeQWFm82PB/qzinEq5gUe5Dte2tgx/MMwUePQY40fCmTySzuZTkFGOi48th36JQ1drwCPAjg4DvFo8rkKpwMUrkeiKn7C2mQUENFqvVCoYfE8ov354isQz+SSeyW/2OGozJUE93Ok4yBs3X7sm67PiLpGfkoRaY4YkGSkvyMO3g5quw3sTczSbA6tiST5XwK8fnmL0E53ISy3n9O+pSJKEd2A8v77/Fbfc/SDdRo3Dt6MzlaW1xBzJJvpIFuWFNUTu2MvJdVvRWI1EZd7w/9jZ25rbn+mGlZ2ZaZkkSaYSws6DffDv4oqbrx3bF0WRk1TG1m/OM/zBsOseU1hwNp6138RjUFk0XamQg+Aet/mhUCpo388LJy8bfv/2LPmJP2PUZ2NhF0anQVNR1r+et/lx6Wg2mbHFZMUX4xXkyNF1idRU6HDysqbrrW2pjY9DqqlBaW2Nmb8/IHc+jI04zPk928mOu4R3UCguTnZ4ZGVRdfIk1Ro1Z9r5UHpkPwqlklvueYjw0eMbzYk2cNoD7PnxWw6vXkq7Xn2xdXJBkiR2fDOPnIQ4LGxsufuDz3D0aPg/Fdp/EIWZGRz7bRW7vv8aZ582AHQYOACfWDPQGjhXrsNFpSXAworu1n0w5JaDryMARoOBTZ/9j6rSElza+jHmqReojS6maHUsFmHOuNx//b+XBEEQhH+GGIMm/O0ijuylyi6eWqWCI2nLCCeWcF8n+gY68+a4MI6/Nox5U7rSy9+JEJsanjbUzTU25DVw9DUdZ2CQK5P7hbHXZiy6Rw6wqPdUDAoF/WsNfB50L3um7OeN3m8Q5BhElb6K5w88z7zT8zAYr2Muqp7TwcYdBr1s6sa4Jm4N5wvOY6Ox4ZVerzS725jgiQBsS9rW4nlSy1JJL083fX+t+c+upFFq6OPZBwCDZCDcPZyJ7SZefR+VhjuC5YYobx59k91pu9EoNbzV9y3e6vsWZiqzq+7/V7k8e9Z5sDeWtmZYWGtMDTGup5uj0WAkK6GE2qrrmxMsKTKfXz88RWleNTaO5ox+ohMa84aspbOXDe3C5XLPk1tSSIrMJ/lcgSm4ulpzD8lo5My2jRj1enZ9/xVpF8432ca1rS09x/g12+TTpY0Ng6YF8+BHAxh6f/tmgzOAyLrsWXCP3ni2lQOKlHOnUSgUhPX3YtLz4dg4mlOSW8WvH55i77IYJGMNVlY7iT+2GX1tLUfXrkKvldvCW9ub02O0H/e915exT3VGKZ0AJPS1kY3OW5hZye/fnUd/2WTxyecKKEivQGOuwq+TivKiAqwdzJnwbHfa9/MECfYtu0ROUmmLz9vlzi4/2mxwZmVvxpgnOtNzjH+j18DN1xZHt2MY9RmAgZqyKNZ/+DpLnp/J6a0bsbBR0L6/HACd2JxMZmwxl47K5YlD7g1FpVJSHSWPX7Xo1ImC9FT2/PgtCx9/gB3fzjN1T8yMv8S5Nq7sDfNlz4ofORLsQ6mZCktbOya//j49xk5sMmF1l1tvw7NdCNrqavb+uBCAiLWriI04hFKl4vbnX2sUnNXrN3kawX0HYjToyU+Vfz4C2/VAozVgVECVrRl+j4STp0tHrdRQ+HM0hroW/2e2bSQ3KR4LaxsmvvQmZpZWVETI92vmZd3kXIJwPQoLC3FzcyMlJeWfvhThXyQlJQWFQkFkZORNPe727dvp2rUrRqPx2hv/S4kATfhbGfR6eke/Q5yZXNp4yNIc7S/3yC3t61hoVEzo5s2ax/qyo/3vqLWl8qTPvZ9ocry3b+9AxKvDsLcrZXO23DRj5sTVcOs72JrZMiV0CmvGruGBsAcAWHxhMbP2zKK09hpvFtv2hhfioPOdAGxI2MCnJz8F4Jnuz7Q4Xmug90DszOzIq84zlS1eLrEkkYkbJzJ63Wge3vEw25K2EZkXSZW+Cjszu2uOP6tXP9ZMrVTzZt83r6sz253Bd6JSyIGIm6UbP4366Q+3xL9ZLi+N63prQzljcC852xJ3IqfFduVlhdUc35TE0teOsv7TM6x+7wR5qWXNbgvyGKzjm5L4/bsodDUGvIIcuPPVnqbW5pfrOdofFHIwVz9GreuIttfM5mXGRlOWnwfImYzNn/+P4uzMpscf488T3wxh5reNH1Ne70XHQT6YW7Zc3FBZUkzcMXmaBed1m7E5LHf4SznXMI2Cu78dd77aE68gB3Q1BvS1BUjaXyjOuohaY4aFrR015WXERhxqdGyFUoFCyqK2Sr4HyZDDfR90Zua3Q7j77d6YW6nJSSpj3/JLSJIkB9h1DVXahZvxy9vPsvSFJynKykSlUTLk3lD8u7hg0BvZ9u15ygqbTo1xOX1ZOalF8nPc8eIPDL/wFo992J2Z3w7hwQ/749e5aank8XW/kHBCDnhuffRJOg65FbW5OUWZ6exf+j07vplH+ChflCoFmXEl7PjhAgAdbvE2jQ+siIwk3cmW/cpalr70FJE7tlJbVYm9mzsDpt7PfR/Np/9d92JtZo5OrSKppgKtWoWj2px7P5xH247NT0qvUCq5dcaTKFUqEk5GsGvRV0SslRv6DJ8+izZhzY93UyiVjHriGdwDggCwcXTCukx+XqzaO3Pv//rTtpMLWe6plGkLocpI8bp4yvLzOPLrCgBuufdh7Fzd0GZVoE0tA6UC616eV33+/wsefPBBFAoFCoUCjUaDv78/L730EjU1zU80/0ccOHCAoUOH4uTkhJWVFUFBQTzwwANotQ3z5EmSxKJFi+jduzc2NjY4ODjQo0cP5s2bR1WVXOL89ttvo1AoePzxxxsdPzIyEoVCYQqW6t8Eu7m5UV5e3mjbrl278vbbb5u+f/vttwkNDcXa2hpHR0eGDx/O8ePHr3lPH3zwAePHj8fPz8+07OTJkwwbNgwHBwccHR0ZOXIk586da3Su+uf68oe19dU/KGhun9WrV5vWnz17lm7dumFjY8O4ceMoKioyrdPr9YSHh3OirpnPzZSfn4+ZmRmVlZXodDqsra1JS0u76ee5EX/09byaMWPGsGjRIgBmzJjBu+++ezMu9YY8/fTThIeHY25uTteuXZusHzVqFBqNhhUrVvzt1/Z3afUBmp+fX7M/rLNmzQKgpqaGWbNm4ezsjI2NDXfccQe5uX/vHEr/dfti89gXm3dd26Zun4eVOo3quk+aK5VKjkuVsHIq1Fz25tpogMhVEPUrKJQw7stGjTqutOj8IgySgQHeA+js2vjNklqp5oWeL/DRwI+wUFlwJOsIU7ZMIbEk8ZrXqzPo+ODYB8w5MgetUcuwtsO4M/jOFrc3U5kx0m8kAFsStzRZ/+25b9HVDfI/mXOSlw+9zCM7HwHk8WfX26J+VJvR3Kl/lDkh7xFgH3DtHZDb4b/W+zXuCLqDX8b9QhfXG58K4Ga6sjTO0qYhi+fX2RkzCxUVxbVkJZQ02i87sZTNC86x7I0ITm1LobJUCwqoKK5l3SdniKnLjlyuOKeSrd+eN00U3XmoD7fP7tqoVO9yTl7WBPWQOzTWVOiwc7Gg52i/a95TzKH9AIT0uwXPdiHUVFaw/uP3qKloOvdZc7/XrkfU3h0YDXocqmqwzSvEpVx+M5cedc6UEQOwsjPj9tldCehSgb5yNdrqQmxdXJn67sf0GDMBaMjEXS5yZ+NlSaeOo1AocPSwZuSjHVEoFcQdz+XMjtSG7JmFisrCwxh0OmoqK9jw8bvUVFSgTUmmm+IETq5yQ49tzUzmfbmEZdupNXdEbazB07YCY0EB+Z9/0eLzE3fsMEfWLAdg2MNP0Hn4KEY+/gyPf7eUIQ8+BgoFsRGHqC7LIqwui1ZdrsPKzoy+EwKorapk9+JvWRd/jqg2bhRUlqFUqQju3Z87Xn+PR778nt4T78LNL4A+d0zl7unP0DMpC8/icvzySxjZqSd2LldvruPq60/4WDnDfX7PdgDCx06k09Crl1trzC2Y8OIbhPQdyOAHHqUmWn4TahnWUMrs3j6Ew3nrkJCouVTEsUXL0dfW4tO+Ix2H3ApAZV32zLKjM6oW/r//14waNYrs7GySkpL44osvWLhwIW+99dZNOXZ0dDSjRo2iR48eHDx4kKioKBYsWICZmRkGQ0Pm+b777mP27NmMHz+effv2ERkZyZw5c9i4cSM7d+40bWdhYcHixYuJj49v7nSNlJeX8+mnn151m+DgYL766iuioqI4fPgwfn5+jBgxgvz85sutAaqqqli8eDGPPPKIaVlFRQWjRo2ibdu2HD9+nMOHD2Nra8vIkSPR6eS/cS+88ALZ2dmNHmFhYdx5Z8t/Q+v99NNPjfabMGGCad306dMZOnQoZ86cobS0lP/973+mdZ999hn9+/enV69e1zzHjYqIiKBLly5YW1tz5swZnJycaNv2r21kdS1/5PW8GkmSOHbsGP37y3OuHjp0yPT13+3hhx9mypSW+wU8+OCDzJ8//2+8or9Xqw/QTp482eiHdNcueULg+h/wZ599ls2bN/Prr79y4MABsrKymDRp0j95yf8pcbnlPLzkJI8sOUlq4TVadZdm4HXmU2LMGr9J2GvvDPkx8NsjUJoBBz6BL7vChrpPDXvNAO/uLR42rSyNLUnym8qZXWa2uN3ogNEsH70cbxtvMisymb1vNlqDtsXtC6oLmL5zOqtj5U/uZnadyeeDP79mE4+xAWMB2J22mxp9w6ey8cXx7EyR//B+M+wbZnaZibuVO0ZJTtH39ux91ePWKy+qYceXMTif7EjJWgdqKq+vtA/grpC7eLvf26b50/5Jl5fGdb21TaN1ao2KwLoyw7jj8nxWkiRxbm866z87Q9rFQpDAJ9SREdM78PDHA/DrLGdq9i6N4eDqOLTVemKP57Du09OsfPs4qVGFqDRKhj8UxsC7glGprv7rr8doP+pbcQ6+O/SanQ31Oh2xx+SMVOdhIxn/4hvYOrtSnJXB5nkfYtD/+bbz+ooKzqyV/z/6FpRiP348XgMGYq7To9frSDl8sNH2tZXlxB9bhtFQS5sOnbl37jzcA9rRadhIVGo1OYnxZCfEmrYvLywg4aSckQu7ZSgACaeOmda3ae/ELVPkrM6xDUkcWCXv2y5cQ/xx+d6t7B0ozs5k/RsvkDj5TkrmfUboppcxN1ZRmFnJzu+jMDaTFZUkidgIOdvo62XE5505AJSsWUPV6dNNts9JjOf3r78AoPvo8XQePsq0ztzKmu63jSOkzwBALivsPsoXpVp+QQdOCcbcSsPO7+ZzbudW9AqwqtXRb+wkZnyzhHHPvYpf525NShZteoTjWq2jW1oeYVmFWHr7tPRSNdL3jqnYu8kBf0D3ntxyz4PXtZ+NkzNjZ79MYEhPdNmVoACL9g0dPb2C21OuKyK9Rn4dHHKdUKrUDH90FgqFAmOVjqpI+cMzm74tj538rzE3N8fDw4M2bdowYcIEhg8fbnpvAWA0Gpk7dy7+/v5YWlrSpUsX1q5da1pfXFzMPffcg6urK5aWlgQFBfHTTz8BsHPnTjw8PPj444/p2LEjgYGBjBo1iu+//x5LS0sA1qxZw4oVK1i1ahWvvfYaPXv2xM/Pj/Hjx7N3716GDGlo2hQSEsKQIUN4/fXXr3lfTz31FJ9//jl5eS1/YHr33XczfPhwAgIC6NChA59//jllZWWcP9+0HLvetm3bMDc3p0+fPqZlly5doqioiHfffZeQkBA6dOjAW2+9RW5uLqmp8rQlNjY2eHh4mB65ublER0c3CvRa4uDg0GhfC4uGSoeYmBgeffRRgoODmTZtGjEx8oTtSUlJLF68mA8++OCax/8jjh49agpWDh8+fF2By/79++nVqxfW1tY4ODjQv39/0/MDsHnzZnr27ImFhQUuLi5MnHj14QpX+iOv59XExsYiSRJhYWEUFBSQkJBA795Xf29ytZ+HP2r+/PnMmjWLgICWP4AeN24cp06dIjHx2h+2/xu1+iYhrq6ujb7/8MMPCQwMZNCgQZSWlrJ48WJWrlzJ0KHym4mffvqJ9u3bc+zYsUa/TIS/xpd74pEkkIDlx1J5fUzLA9ANW1/EwljNfjN/wIC/vT/Jpcnss3fijYJCVPE74YsODTtYOEC3e2HoG1e9hoXnF2KQDAz0Hkgn1+ZLhuqFOIWwcsxKJm2cREpZCosvLOaJLk1LJ+OL43l81+PkVedho7Hhw4EfMqhNC235r9DVraspCNyfsZ9RfvIbx+/OfYeExK2+tzLQZyADfQYyo/MMjmQdIaU05aqZuXqZscVs//4CNRVyUFZdpiViQyJD7gm9rms7tyedpMjGn6yp1Ao63uJDQDfXZvfJii/h/L4MwgZ40jas5UYkN+Ly0rhOQxpnz+qF9PIg5kg2CWfy6TupHYfWxBF3XM6OB/Vwo9ftAY1auI9+vBMnt6VwcksyUfszuHAw01QeqVAq8OvkTM+x/rheZyc7J09rRj/eCb3O2OxkyFdKPnuS2spKbJyc8QnriFKpYsJLc1j15oukRUVycPmPDHlwBgDl+/ZRum4dNkOGYnfbKJR1b9zqadPTKfl1LdWRkXILwzqphblU22ow0xvo/PhTuN5/H1J1Ne4PTCUNIxe/mod/rz6obORyuFNb1qOrqcbNL5DJr7+HUqVCm5FJ4fvv421UkgYcmfMqPdU2mAcFkRDgjWQ04tO+I30mTSH64F7SL56npqICi7pjdhzkQ1F2FVH7M6gq1crZs4LDSJKRgPBe9L/zHla99hxZ2RmoHa3o6uqCRUYmHc9+zdlus0m9WMz+9zYw9K3Gb0TKjkSQYyFPidFhYnesunhhP/kOsjZtYvf7b1HdpSOXz11RkJ6GXluLf9dwevceSO7cuRgqK3F/5VVUNnIJVd/J04g9dpiEkxH0nZzFmJmdqSrVEtjdlcTTJ4g7fgSFQkn3pEw8za0Ivvehq2YyldbWWHbsKL8ugMb7+oIejbkFE19+i8TTJ+g6cgzKa3zIc6Xq6EIAzP3tUVk3dL51D2iHSq3mfP4BfHyC8bIKZMCt9+DsLX/gUXk6F0lnRONhjZlf8+MZbxZJkqjWXcf43pvMUqP6U5NvX7hwgaNHj+Lr2zC+ee7cuSxfvpzvvvuOoKAgDh48yL333ourqyuDBg1izpw5REdH8/vvv+Pi4kJCQgLV1XL5roeHB9nZ2Rw8eJBbbrml2XOuWLGCkJAQxo8f32SdQqHA3r7xXJYffvghPXv25NSpU/To0aPFe5k2bRq7du3i3Xff5auvvrrmvWu1WhYtWoS9vT1durRcUXHo0CHCw8MbLQsJCcHZ2ZnFixfz2muvYTAYWLx4Me3bt29UBnm5H374geDgYAYOHHjNa5s1axbTp08nICCAxx9/nIceavjZ7NKlC7t27aJdu3bs2bOHzp3lqpnHH3+cjz/+GFvbm9etNC0tzXT8qqoqVCoVS5Ysobq6GoVCgYODA3fffTfffPNNk331ej0TJkzg0UcfZdWqVWi1Wk6cOGG6j61btzJx4kRef/11li5dilarZdu2bab93377bZYsWXLd4/6u9/VsztixYzl8+DB6vZ7q6mocHR0xGAwYDAZ8fOQPokpKSprd92o/D83x8/PjwQcfbFR6+0e0bdsWd3d3Dh06RGBg4J86VmvU6gO0y2m1WpYvX85zzz2HQqHg9OnT6HQ6hg8fbtomNDSUtm3bEhER0WKAVltbS21twyS4ZWVyaZ1OpzOl5oVri8stZ1tUQznZmlPpPDU4AMtmMg2KS1tRx21DJ6k4bOEFpDMteBrzI+dTqC3l7NBX6LHzbQCMbfti7HofUug4uSU+QAuvy+XZs0c7PHpdr5+typYXur/Aq0df5fvz3zPcZzh+dn6m9YXVhczcPZO86jz87fz5/JbP8bXzvaH/G6N8R7H44mI2J2xmmPcwEkoS2JkqZ8+md5je6Fh93fvS170vGDGVP15JkiQu7M/i2IYkJCM4+1jTeagP+5bGEn0oi3bhLngE2je7b72cpFIO/9p8mUx6TDFdhvvQc5yfqfudJElcPJhFxDp5IuDEs3n0HONL1xFt/tQbIoCUy7JnHQd7NvvcuvpZY+1gRmWJlpVvH6O6XIdCCX0mBNBxsBcKhaLJft1G+uDkZcnepbHoagzYOJkT2s+DkD7upjnHbuR19AlzuO59Lh7cC0Bw34EYDEYMBiOO3m0Y+cSzbJ33IWe3b6HLyLGoM7LIemY2klZL+a7d5M6di+2YMdhOnIA+PYPS336jOiKi2XMkBXgCGtr3GYjj3dPQ6/Wg0RBy34OkrfiRHH0tGc8+h+eC+VRXVhC5Xf7Z6DVpCgajEYPRSN6CBVTs34+PlTlpQT6k62sIOh+L+tRJIjsGgFJBx2Gj/o+98w6Povr+8Ls1vfcGaSSEEggdQm+hCoIgIAoWEAS/ClYsIIiIiF2qIIoCiiKC9N57CSWNJISEhPRedrNtfn8MWVhSSGiWX97n2edJZu7cuTM7MzvnnnM+B2tnVxy9fchLvU78mRM0Dr81QdF+qC/5maWkxuQT0ErOhW1HAGjTewBlH86jRWIqZ33dSXG2w/ep52jWuj1Fmzah2bmFSx6PE3PDBu/v/sBv/C3p+Zi1B9DJO2AhVeMcYEfUoX1ckpSTFnIzhCjmcqXzYW9rT7PIOJJ/vGXs6XJycf/yCyQyGbZuHgS1D78ZCrmGQdNEcZ+ykmL2rlwCQJOGAbhFxmPeva14Pu+CeZvWRgNN4uJS6+vJ1s2DsAHiC3ldf2fKLouTKsrG9pW2dfULJD0+lmsll/G3CaWBLgitVotgECg5LhbTNm/nWunYHvRvnUqrp8nMnQ+0z9oQPScCS2XdXmW2bNmCtbU1Op2O8vJypFKp0aApLy9n3rx57Nmzh44dOwLg7+/PkSNHWLZsGd26dSMlJYWwsDCjsXS7QTJixAh27txJt27dcHd3p0OHDvTq1YtnnnkGW1vRSI6Pjyc4uPaFWFq1asXIkSN566232Lt3b7XtJBIJ8+fPZ/DgwUybNq3al9YtW7YwatQoysrK8PDwYPfu3Tg7Vx9VkZycjKen6WSEjY0NBw4cYOjQoXz44YcANGrUiJ07dyKXV/4+1Go1a9as4e23qxbYup05c+bQs2dPLC0t2bVrFy+99BIlJSX873//A0RD76WXXmLhwoWEh4czY8YMfvrpJywtLWnbti0REREkJiYyatQo5s6de9f91YSnpyeRkZEUFRXRpk0bTp48iZWVFS1btmTr1q00aNAAa+uqc5OLioooLCxk0KBBxu8iJCTEuP6jjz5i1KhRzJ4927jsdsPK2dm5VoZHXb/PqlixYgVqtZpJkybRoUMHxo8fz8yZM7G3t2f69Ok1blvT/VAVAQEBdR5fdXh6epp4JP9L/KsMtD///JOCggLGjx8PQEZGBkqlEnt7e5N2bm5uZGRkVNvPxx9/bHJDVLBr1y4sLR9cUdX/OquuSBEEKaGOBlJLJeSpdHy8dhcdXE3Dl5TaIrrHvY8cWKofiMpMDMcpiCnAH38ucpGVKVcoDv4Qg1RJibkHXAeu7zfpJ0ufxS+lv5BryDUuExAwYCBYHkzKqRRSqF3CriAINJI3Il4Xz2s7XuM5q+fEF35By/cl35Ohz8BJ6sRoRhN1JIoooup0bqz04gz+kbQj/LblNzarNgPQTNGM+GPxxHP3fILbKYg1oyRJ9DJZemoxb5JBfHYGlt5mlKUq2bbiPG7hZVSXwiYYIPOoJSDDwk2LhcetlzVNvoySZCUX9qQSG3kNxxYqpDLIjzKnLE2crVfY6NEWyzi9JZnLpxNwCFUjlYvOnfIcGaXXFZQXyLAPKcfSo+aXXEGArJtjMfcuY9/B3dW2lToqocAMVbEWqdKAY0s111UXuL79QrXbADh1kKBXSVE6FJOhzyHjaOWX+8zjB9AWF+HZoz9ShaKKXu6ORKvFe/l3SNPTudrYB6QSLL5cROxXS8nt25fC9u1AIsHCzQNVZjqbv/mc1rsOItdoUPn4ICstRZmXR+Evv1B4WxK8IJFQ1qgRxaGhGMzE772srITcq1GAhAKvBiYzrfpy8WW7xMKM3BPHuP7aa8S52KEtV2Pm6ExMehax27YhLS3Ff+tWpEB5z95YZF9HpS4luns4TtGxYn0trZ4bh46QkFeIYOcEqdc5vWoF+llzQQJFrVpT1LoVgo81zjYyEi5vQhAM2CstKXjxJeTFxbgoFHi6NeBG1nUOrV1FfNoNrLx8YLwHDjuvkS/x5djBUpKKv0Ud4I88v4CSLAtwBqltFstffg5d2a2QaZeiUjwKSk1i8qUGA87FV9EbBASplNLgYCzj4yk9cIDTr7xKzoD+AGicRMGZq2dPsvHn1Zg5OpNz7gTFudnIrayxvSYaMSlKJZG3ndPqsBSgIrBx/+XLGK5ereNVUzfkWgmh1+yRIOFYxgU0286brFfJxesjuuAYfjbN0SYWcfDXXch0Ehrl2aCTGTiUcRbDHYdWIUTx/5EePXqwZMkSSktL+eKLL5DL5QwfLqrcJiQkUFZWRp8+fUy20Wg0hIWJJVcmT57M8OHDOXfuHH379mXo0KF06iQKN8lkMlatWsXcuXPZt28fJ0+eZN68eXzyySecOnUKDw8PBKFq4aOamDt3LiEhIezatQtX1+rzHiMiIujcuTPvv/8+a9eurfb4IyMjycnJ4bvvvmPkyJGcPHmy2n5VKpVJiGHFsueff57w8HDWrVuHXq9n4cKFDBw4kNOnTxvDOSvYuHEjxcXFjBs37q7H+v777xv/DgsLo7S0lE8//dRooDVt2pSDBw8a2+Tm5jJr1iwOHTrEyy+/TKdOnfjjjz9o27Yt7du3Z/DgwZX2MWnSJH7++Wfj/yVV5AkDyOVyfH19Wb9+PW3btiU0NJSjR4/i5uZWrYe0AkdHR8aPH09ERAR9+vShd+/ejBw5Eg8PUawnMjKSCRMmVLv91KlTmTr17iVw6vp9VoW7uztarZYTJ07wzTff4Ovry/Hjx1m1atVdDa6a7oeqqGmSoa5YWFj8Z59l/yoDbeXKlfTv37/STE5dmTFjhsmMQFFRET4+PvTt29c4w1VPzVzJLCby5iz/vNHhHIzP4dNd8Vwos2d2/w63PCy6cmRrhiHV5nNV8OBbSQ+UkkjkUjnjBo6jYVpDLh65yDXFNcIHf1WtZyZfnc+4XePIMlSOrVdKlczqPYvGjrUL86ugZUlLRmwdQZIuCV1jHY/5P8b7x9/neuF1bBQ2rIhYQUPbhnfvqBp2bd9FbH4s8a7xRCVEIUHCzD4z8ZY3RKaQmki710TG1SI23zRIOg675T0CUHfTsn7uWdQl4KFoRquIqhOWz+1MIa0kGQsbBSOmdcDcytQgSTybzcG1VyjPkVNy3hkzKwVlaSVIpGKh5OY9PIk9lsHR3xNRZSowu2SLf5gL8acyKc675Y0uvGxJ116huPraoi4pRiKVYmZpqtiVdCGHtOIYFOYyHp/QrdJYbqewjYoNn5zDwcOKPs81xtqxitpY90Buagpr1n4HQAMrM5P8pbpQsGYtOSkpXHe0QZBKsFGVY1cm5h26bdxIIwk4v/MOV50d2Pb1AooTYpGUlqAMDsZ/9Y9IzM1RnThJ4e+/k3/oIGa2dtgPHYrtsMdReN/KbyrNz+PXWW8C0KhDOP1HVE6c/jXyBJmJ8eTYWOJ24gQlTcRrt++zE/ELE8s35H//Pbk6HWYhIXSaNw+HQ/vY8923FKPF0D4MkhLxyS3E+6c12I19iuwb2ewBikqLkGdlIRMEXLZtw2XXLqx79ULTvCl/Jovx/00vxyFXaZB7e+Px5Rc0Cgpi73ffEn1oH7knD9Hzg/k4eflQ1rWc9e8eptTaCw5cos/QoeT8voktjk0RBAGFPBZdWSlWDo407d6HJl17UjpnLqVJByods9zbG7vhw7EZOgS5szPFW7eS+fYMHA8epHHv3tgOFT1WO/OziDt2CHlWKm06d+bXdSsBGPDSq0hmfoIWCB0+HMsaXioqMPRQcX3vXmQODkQMH37f3uS7oTqbRdGZq8g9LOn9eOWokMzgRvw2ZwaNenXBwtoV9blsQtU+IJOgoQDbdp70G1D5uCoiRx4UFgoZ0XMiHmiftd1vXbGysiIwUAyn/f7772nRooVRBKPiRX3r1q14eXmZbGdmJnrh+/fvT3JyMtu2bWP37t306tWLKVOmmAh0eHl58fTTT/P000/z4YcfEhQUxNKlS5k9ezZBQUHExsbWacwBAQFMmDCBt99+m5UrV9bYdv78+XTs2JE33nijxuMPDAykQ4cONGrUiJUrVzJjxowq2zs7O5Ofn2+ybO3atVy7do3jx48jvZmruXbtWhwcHNi0aROjRo0yab9ixQoGDRqEm5tbbQ/ZSPv27fnwww8pLy83fge3M336dF599VW8vb05cOAAc+fOxcrKioEDB3LgwIEqDbQ5c+bw+uuv33XfTZs2JTk5Ga1Wi8FgMHpedTod1tbWNGzYkKio6idwV61axf/+9z927NjBr7/+ynvvvcfu3bvp0KFDJSP2Xqnr93kn8+bNY968eQiCQFlZmXEiorS0lIiICCQSCdu3b682NLU298PDIi8vr1Iq1H+Ff42BlpyczJ49e/jjjz+My9zd3dFoNBQUFJh40TIzM3F3r74oqpmZWZU3uUKhQHGPM+n/31h0UMwfGtjcg2Y+jng6WvPVvkSi04u5lF5K64YOoqtky8uQehKN3IYJpdPxalBKNtDIvhGW5pZ0a9ANpVRJakkqKaUpBDoEVtqXVq/lzaNvklqSipe1F4t7L8ZSfsvTaaO0wUpR9/o+vg6+ovDH2c/5MvJLkkuS2XZtGzKJjM97fE6gU+Wx1IXBAYOJPRPL7wm/IzVIGaJ4mvh15eyLOYGTpzUj321rDCesDr3OwJFfEwBo3MmDVn19TdYr7BV0HtGIPauiOb/jOsFtPbB3M/UCF2SVcX6HWHet84hG2NhX9hI37uCJi4+tKIWeo6Y4rxxzawURLzTFu7GYfxXavQGuDezYsewSBRkqzm0XvZVmlnKC2rtTmKUiJSqXnd/FEPGCDxvnv4muvJxG7cMJ7RWBd5PmIMC57eJYQnt4VzmW23H2UvD8wi7IFNIH+iIcf+KI8e9Le7bTqt+gOvdvUKspuPmilBXaBPJzCH1yDIG9+lP4119kf/ElRX9sRJOQiP9nC7GQylAZ9GR5e9BlyWIUN/NMlN26UublxoGCNKzs7Hls+FAsff2M+9Fqytn65XxK8nJx9PSm78SpVT6n/Fq2ITMxnjwfD0qzctBpNLgHNKJR245IJBIEvZ6i9b8B4Dj2KZRKJU269uDIuh8pzsmmOCcbqUxG8x59Kf/lVwp/XoMCMA9piFopxzB5Al7uXhSs/w315cuU7NzJ+Zjz4GCDW2EJHs1aYD9yJDZ9+yC9+Xzt++LLFGZlkhYbxZbP5zFm7mfYOdkRProJ+9clctWtJ56vvku24IrgFYq5LJqM+MvIFUpGffAJ9u7iTLPj4kXosrNN8vGQSJG7OJsIeTgOHYo+JYWcxUvImjMHC38/LFu3puMTo7ly/AhJ506Tl3YdQTAQ3LEL7qWuFIZOR+4ejWVQ09o9/xUKArZtrSQg8rAojCsAwLKZS5Xj827chJd//B2ZXI4+v5yMyBw0CbfKiNh08qpyuwf9WyeRSOocavhPQCqV8s477zB9+nTGjBlDkyZNMDMzIyUlhW7dqs87dnFxYdy4cYwbN44uXbrwxhtvVPtC6uDggIeHB6Wlold4zJgxjBo1ik2bNlXKQxMEgaKiokp5aAAzZ84kICDARHK+Ktq1a8ewYcNqFU4IoijK7WkfdxIWFmbibQLRAyuVmj6XK/6/szZVUlIS+/fvZ/PmzbUaz51ERkbi4OBQ5Xvb3r17iYmJMYpS6PV6Y/huTWG8rq6utfIwbdu2Da1WS69evViwYAGtW7dm1KhRjB8/3ij1fjfCwsIICwtjxowZdOzYkbVr19KhQwdCQ0PZu3cvzz777F37qAt3+z7vZNKkSYwcOZLFixeTmprKvHnz+O2339i1axfffSdOZN45WXEndbkfHhRqtZrExESjQflf4x+v4ljBqlWrcHV1ZeDAgcZlrVu3RqFQmLhL4+LiSElJMcaO1/PgiUkvYtulDCQS+F8vUdHN0UrJYy1Ez+ZPx6+JDY9+CRfWgUTGx9ZvkSh44edZAGD0dlkprOjgKc4K702p7PYWBIEPT3zI2cyzWCus+bbnt/jb+eNu5W783ItxVsHYJmMJdgimsLyQH6J+AOCd9u/Q1rUdCWezapQE12r0xJ/ORKupOjG+v19/zPSWtEsexNhzs3E70orr0XkgQG5aCSmXc6vc7nbO704h70Yp5tYKwofdMhgFQSDx7CmKcrIJaueGTxNH9DoDB9bGmoxZEAQOro1DrxOFLhq1rX720snLmhEz2uIdrMPRPZthb7QwGmcVuPvbMeKdtvg2d8IryJ5e40MYNz+crk8GETGhKU5e1pQVlrPxk88pLy1Fr9MRe/Qg6+e8w6ppL7Jt0UoyE4+A/gIyyWXO79xS6RNz9CDCbT/wcuX9iQDciWAwEHv0tvCY1BRSq8hvuhsF69ejy85G6+1FZn4OSCQ0iRiEwt0d5wkT8Fm+HKmdHeqLF0kaOAjvNDGP6EbzYBS3RQHodTp2L/sGnaacwuxM1r3/BjE3xycIAjsXf0lGYjzm1jYMfWsm5lZV5zv4thCVTrOVcpKdxJe7dn0HGs9dyaFDaNPSkNnZYXvzOapQmhnl2AEC23XC/4MP8PxkPmaNGuE4ZgyNOosvqelKGQ4jR+L3+2/4/bEBybAhpNuLyfjd35tDw59WYzd4kNE4A5DJFTz22jvYubpRmJnBX59/jF6nJaRrAzz9rDDIlFw278QN66YIBhVlxaLh3GH4KKNxBmJdMIWbGwp391sfN9cqjSTnqVOxiYgArZbUqS+T99PPSA4cws9TFM4ozMxAqVDQ0sqZwh3iRJPctQk5PyWhuVF1mNOdPCrjzFCuRx0vei4smlYv0CNXKJBIJMgdzbFqfeseN2tkj8KlPmz/bowYMQKZTMaiRYuwsbHh9ddfZ9q0afz4448kJiZy7tw5vvnmG3788UdANJQ2bdpEQkICUVFRbNmyxZhbtGzZMiZPnsyuXbtITEwkKiqKt956i6ioKKMnZ+TIkTz55JOMHj2aefPmcebMGZKTk9myZQu9e/dm//79VY7Tzc2N6dOn10pa/KOPPmLfvn3Exd1SaS0tLeWdd97hxIkTJCcnc/bsWZ577jnS0tJqlL6PiIggKirKxIvWp08f8vPzmTJlCjExMURFRfHss88il8tNVChB9FJ6eHjQv3//Sn1v3LiRxo1vRb/89ddfrFixgsuXL5OQkMCSJUuYN28eL7/8cqVt1Wo1U6dOZfny5UYvXnh4OIsWLeLChQts2LDhviXiGzZsiLW1NZmZmQwZMgQfHx+ioqIYPnw4gYGBJuIyd5KUlMSMGTM4fvw4ycnJ7Nq1i/j4eOO1MmvWLNatW8esWbOIiYnh0qVLfPLJJ8btv/32W3r16lVt//f6fd6Jo6MjgYGBREdH079/fwIDA4mPj6dv375Gz1xN3r6a7oeq6NWr111FbBISEoiMjCQjIwOVSkVkZCSRkZEmtQRPnDiBmZnZf/Z9/19hoBkMBlatWsW4ceNMkk/t7Ox4/vnnmT59Ovv37+fs2bM8++yzdOzYsV7B8SHy9V4xf2pAcw+C3W+pJT3TUXxQbbuUQdH5jbBHzPPb4vUqqzL8kUpAYibme4Q43bp5ezUQH0D7ru+rtK/V0avZmLARqUTKgq4LqvSw3Q8KqYJZHWchuSkP91TIU4wMHsmFPdfZ+d1ldiy/XG2+wL7VMexaGcW+1TFVrne2cOaJa6/Q6kYfLLW2WNoqad2vIY07it7dSwdTaxxbQVaZsW5X5xGNMLe+NVMXe/Qgfy6Yw/rZb6PTlNNtdBAyhZS0uAJ+ePsoB9bGkZ1SzJWTGaTG5iNTSOk2Ouiuhk5eWgJJZxZzI+Ynfnn/JQ6t/YH8jBsmbazszBg4pQVDp7eicQcPFDdFYZTmcga81By5LIHykkQkEjmPTX+HFn36o7SwID/9BrFH/kSn2oe6aC+H1nzHvu+XVvps+/pTTm36varhPRAqikkrLSyMUvIVYhq1xaBWk3NzZjGvm/jj4NOkObbOt0ItrDuH4/f7b5gFByNoNDTIK0IqlZKZdp3MqwnGdme3/kl2yjXMrW1oGBqGTlPOtq8/5cDqFRz7bQ1xx8UizI+99g4O7tWHd3sEBmFmZYVGU45eJsWuVI3NsVvFWvPXrgPAbvhwpLflk7TsOwBuXhdhfUXDzW7IEPz/2oz7zPdpHDEAgMSzJzEYxMmIQnMlhwozQQKBbTvi3bn6XAxLWzsef2sWSgtLUmMus2eFqHbWY3xzpFLIc2xCoV0AOtUhtOUlOHk3oM3guklN345EKsVz/seYN22KPj+fzI8+IvPDuXjvPWz0wAVdTUP9ZyQISgxleSCUos9Tk73kglGW/p9A8b4U0AnIHM2Ru9XO0LLpIeZCQr20fm2Ry+VMnTqVBQsWUFpayocffsj777/Pxx9/TEhICP369WPr1q34+YmebaVSyYwZMwgNDaVr167IZDKjV6tdu3aUlJQwadIkmjZtSrdu3Thx4gR//vmn0SMnkUhYu3Ytn3/+uXF5aGgoH3zwAUOGDCEiovpQ0ddff71aUYrbCQoK4rnnnjMpwC2TyYiNjWX48OEEBQUxePBgcnNzOXz4ME2bNq22r+bNm9OqVSvWr19vXNa4cWP++usvLl68SMeOHenSpQs3btxgx44dxhwrEN/ffvjhB8aPH49MVjkctbCw0MSIVCgULFq0iI4dO9KyZUuWLVvG559/XmWdutmzZzNw4ECTQsZff/01kZGRdO3alcGDBxtzC++HAwcOGKXwT506hbe3t8kxVoelpaXJ+Z44cSJTpkzhxRdfBKB79+789ttvbN68mZYtW9KzZ0+TAts5OTk1SsjX9vvs3r27UbuhOnQ6HUePHjXm1R08ePCuOXYV1HQ/VEViYiI5OTk19vnCCy8QFhbGsmXLuHLlitELeePGrfeRdevW8dRTT/1ntSMkwr1kqz5idu3aRUREBHFxcQQFBZmsU6vVvPbaa6xbt47y8nIiIiJYvHhxjSGOd1IRTlBYWFifg1YDOr2BbZcz+N+680gksPPVrgS5mcrZDv/2AF43dvGZ+fcoDCp2WA5mUt5oAN7u35jfMieSpcrip/4/0dK1JSCqJvZY3wMBgV3Dd+Fh7UGptpQ/4v/g09OfIiDwVtu3GNtk7EM7ts2Jm0ktTmVi6ETkUjnr550mO6UYgD7PNSGonen1dO1SDlsX3aozMmhqCxo2M53hjjuZwZ5V0QgyA+FjfQlt549MJqUwu4yfZ54AAZ6a08FEKr4CQRDY/FUkqbH5eDd24LFXWhqNK4Nezw+vTSY/XXxQtR3yBF3HjOdqZDbHNiRQmH1L3lYilSAYBDoM9ad1P18Sz54iJ+UarQY8hsLMNJ+rKDuLNe9Op6ywQAyXuk31rUGzUHo+Oxknb9N6ZXeiKinm+1deRF1ShNy8E75h/bG0VaLXlZOTcp7sa9FIZdCwmRMyeeX5IY2qjGsXziFXKBm3cJGJF8V47i+c43r0JToOH41cWVme/27sXv4tF/fuoGn33rQeOJTVb0xFIpUyYdH32DiaKkvlr1+PoawMx7Fjkdw2OZT3449kfjyfch8vzjbxoyAjnb6T/kfzHpWLDxvKyshdsRKlb0OOXIsj9uhBmvXoQ8SkVyjMyuCH16ag05QTMflVmnTtwbH1azi5cb1JH31f/N9dCxsD/PX5x1w5eRSANlfTcdPoCdi9C6GsjMR+/UEiIWDXTpQ+pt9j1MG9qEuKaTVgSCUjXq/TsXTiWNSlJTz5wXyKsrPYvfxbdFoN9u4ePPHuXGONr5pIijzLxvmzEQQDrQcOpe1jw4k+WsCpv5LQa6+jLRHDL0fN+RSv4OpnX2uLLjubnKXL0OXe8lRfKyuizKAjxMoZiXk/kJgjES7i+ExfSk6WU35F9BBYd/XGrr/vQ80vM6h1FB9MReFhhWVo5RyK0rOZ5P92BQDH0cFYtqh9wn/ZhWx0eWpsunkjqSaMuv53r566sHXrVt544w0uX75s9FbV8++gYcOGzJ49+65G2r+JnJwcgoODOXPmjHHi5L/GvyJgvG/fvtV6MczNzVm0aBGLFi16xKP6/8P1vDJ+PX2d9Weuk1UsxjUPCvU0Nc5yEuDcD6wt+hkzZT4Y4ISkJVPyRmJtJueLJ1sS5idj0fosJEgIcrhlaDtZOBHmGsa5rHP8EPUD5fpytiVtQ6UTDY0ngp7gqZCnHuoxPhbwmPHv4jy10TgDOPJbPA2aOhnFLLTleg6tE1+crOzNKC0o5+C6OEbPbG8U/lCXajn6u+hp7DAwkLCOvsb+7FwsadDEiZSoXC4fTKPziEaVxnPlVOYtz9eYYJMXxdijB8lPv4FcoUSn1XDmrz8ICe+Gf0s//EKdSYsvIPpwGonnszHoBRw9rWjZpwHFuTn89fk89DodcccPM+T1d7FzFQ1PjaqMjQvmUFZYgIuvPyNnzuN69CUu7dlB0oVzpFy+yIZ5M3lq3udY2TtUex4Pr1mFuqQIa0cPtIa2pMbenljuh9LajzYDfWk/uOrik4Ig8Pvc90i5fIE9Kxcz/J05JseeFhvNnwvmoNfpMLO0ot2QJ6odS1XcXky6SZceuDTwxatxU9Jio7i4ZyfhI29dZ3lr1pD5oSjRXLJvP15ffoHc0RFNYSEXfv6RawGe5FmbQ0Y6CnMLgtpXHUojtbTE5X9ieE7L2Ghijx4k9shBuo59jj0rl6DTiEWkm3brhUQiofOoZ3D1C2DHoi/QlqtpPejxWhlnAAFt2nPl5FE8GgXTQGKDOjKS3BUrkNyU97Tq2qWScQbQtFv1YTQyuRz/1u2IPrSPHYu/oDBLrEXnF9aGAS+/Xm3I5Z34tWxN93EvsP+H5Zzd+ifnd/xFQOv2WFg3oCBtDwAt+vR/IMYZgNzFBff3TWsoVsiuFB9KpXBbEjJHc9xfm4xEJsU8RKBodzLF+69TcigVqaUc2+41T0jcK9qsMnJ/ikZ3czKl/Goh9oP8kdyctCi/Vkj+H+Lzw6aHT52MMwDLFv/NpPl6/j4GDhxIfHw8aWlp+FTxDKnnn0lUVBR2dnY888wzf/dQHijXrl1j8eLF/1njDP4lBlo9fw+CIPD4LzOIy72G6sZIMJjhZKXkiTbevNzzplFRmgObpsCVHQCYAZk48ouuO8t0g/B1sWX5M20IcLHmSJqYX+Jr54ulwtRr1LNBT85lnWNt7C1ZYF9bX0YGj2RU41EPXSntdpIuiLlCbn62aNR68tNLOfZHAj2fFl8cT21JojhPjbWjGSPebstvH5+mOFfN6S1JdBouhmAe25CAqliLo6cVYX0rKys27+5FSlQuscfTaT/E3xgmCFBaWG6sV9ZmgK+Jh82g13N8gxiq1uGJ0WQmxhN/6hi7l3/L6A8/RSKV4h3sgHewA6piDSnReXg3dkAmk3Lyz9+MXrHs5CR+njGNga+8SYNmoWz9+lNyUq5hZe/A0Dfex9zKmkZtO9KobUcKszLZ8PEs8m+ksunTuYyYNQ+FsnKydmrMZS7tE2u9DXzlVaQyL7KSTZXilBZygttX792WSCT0fuElfnxjKskXzxN75AAhXcR8hsKsTDZ99pHxGM789QctIwaiNK+9EtadxaQBWkYMJC02ikt7d9Bh2EhkcgUlR46SOe9jcSOFgrJTp7g4cgR5A/sSe/Yk5Y6WN8crxS+sNR2GjaqkVlkVnsEhuDT0Izs5ib8+E41gmVxO7xemmFzjQe3DcfMLICs5iYDW7Wp9fCGduyNTKPFp0gzD5SiuP/8CBb/8iuRmXpjjmDG17ut2Att2IPrQPqNx1mH4KDo9MabOuVhh/QZjYWvH+W2bSU+II/7UMeAYAFb2DnQefXcJ7vvFoNFTfDO82LaHDxKZeAwSqQS7CF9k1goK/rpK0c5rKFwssGj6YOr1VKCKyiFv/RWEcj1SKzmGMh2lJ9LRppfiNDYEQWsg96do0AtYNHPCts+9K8nWU8+D5NVXX/27h1BPHWnatCkXL168e8N/GW3atKmxaPt/gXoDrZ5q2R4dR6JmK3Ib8Gq0gRmtP6FvE0+UFaFpN87DL2OhKBUkUmjUF1qP588b/nyxM4G+Tdz4bGQLbMxFz1NMrpirVZUcfoRvBEsuLEGr19K7YW+eCHqCNm5tHqlhVsHVSNFAC2ztiquvLRsXniPmaDqNO7ijMJdzYa+oQthtVDCWtkq6jg5m2+KLRO69TqN2bmhUOmKOiQW8u48JBvTcme7ZoKkTts7mFOWoiT+VSZPOYq6ITqNn+9JLqEtuGnd9TI27mCMHKMhIx9zGlrCIgZSryki+dJ70hDgu7N5Oy4hbIjoWNkqjMVSUk83lfWIR2QFTX+Pcjr/ISLjCH/Nm4RXShNRoUTlvyBvvmeRRAdi5uvH4m++z9t3XSE+IY9fSrxnw8usm341Oq2X3cjHpt3mvCLwbi/Hvno3s63z+HTy86DBsFEd//Yn9q1fgG9YGqVTGnwvmoCoqxNU3AI26jIKMdCJ3bq2TFy3m8AEAGod3QyoVjeJG7Tpi5eBIaX4e8aeO4+fuTdq0aaDXYzV4MAXtW3Fu3U/kyiVw0/tmrtER0rINbaa8Uul81YREIqFlxEB2L/+W69GXAGj/+JM4elZWyLJzdTd6OGvdv1RKcMfOAAidOmHRqhWqc+cQNBoUPj5YVSOTfDd8Q1thaWePTlNOvynTadT23pKyJRIJIeHdCAnvRta1q1zat5PoQ/vRqFX0fG5Srb1x90PpiXQMpVpkjuZYtqrsmbIO90KbraL0RDp5v8bhMskcpef9j0swCBTtSaZ4n/j8UPrZ4fRUYzSpJeT9EosmuYjMr88jNZdhKNWh8LLGYWRwtSGK9dRTTz31/HepN9DqqRJBEPjy2Ba4meJTJL1InOZXBslfExecXwNbpoG+HBwDYNQacBU9TC8Gw9DWDXG1MTN5iY/JEw20Jo5NKu3P3cqdbcO2IZfKsVX+ffkQ6hItN+JFiWq/Fi7YuVjQpIsn0YdvsP/nOJTmMgSDQEArF3xDxZl1v1BnAsJcSDyfzYGfY9GoRSGFpl08Sbm8m7Xv/ohP01Ca94qgUbtOyBUKpFIJzbp6c+yPBC4dTCUkXMy12vdTLJlJRZhZyun/YnOTPC2DXs+JDWLibdvBw1BaWKK0sKTzqGfYt2oZh9f9SGDbDlg7VlZ7O3XTe+bTpDkhXXrQqH04e79fwuX9u0mNFhUMIya/gkdgcJXnxcHDi8HT32HDvPeJPXoQRy9vOg4fjUatIvboIS7s3kbejVQs7ezpOub+JYPbPjaM2KMHyU1N4eDqlaiKC8m5noyVgyND33yflMsX2LH4C07/9Qct+w5AaXH3JGF1SQlXz4kJ2E263FIZk8kVhPaK4Pjv6zi/dRPy05cp1KhJbxnC9dwUyn+LBrkoI+NSWIpPbhFedo4EvjMLyT1IlYeEd+fQz6soLyvF0dObtnUM06wtEokEl5enkvLscwA4jBp1z+qDCnNzxn+2WCy6bW1z9w1qgauvP72em0zXp55FVVyErXPdwvjuBRPvWc9b3rM7sR/sjy5HRXlCAbk/RuM6tSUym7rnO1YgCAL5v1+h7JwoQGId7ondAD8kMikWjR1xnRpG7upodFllGIpBaqPE6ZkmSJV1r/FVTz311FPPv5/6TM96quRYYi4pqvMAhDg0B+CHqB/YGPcbbHsDNr0kGmdB/Uh4ciWpFqYvbW625pW8X0YPmlPVBaUdzR3/VuMM4NrlHASDgJOXNXYuYuhcx6EBWNgqKcgsIyu5GKW5jC4jTcVqujwZhNJcRlZyMQWZZVjYKmnURs6x9WLtmOtRF9n29acsmzyOA6tXEH/qGGYWKQiGRDITIzm/8yintyQQfzoTqVRCvxebV6pnFn14PwWZ6VjY2Jp4ylr0HYBHYDAaVRn7f1he6ZiKcrKMoYcdR4ghbnKlkr4v/o/eL7yEtYMjXZ96lsbh1df8AVEopNfzkwE4tn4Nmz+fx9IXn2H38m/ISkpEJpfTZ+LLmNdCYexuyOQKek+YAkDUwT1cPXcauULJ0Nffw8bJmZDO3XHw8ERdXMT5WiowXjl5BL1Oh3MDX1wamsath/bqh1Qm40ZCHAfM9Bxu3IAEQUN5aQk2zi50GvkULyxaRb/BT+BlY4f7e+/ek3EGorHT8YnRWDs6ETH5VeQPsfaiZYcO2A4ejFnjxtg/cX9qZhY2tg/MOLsdhZn5IzHOAEqP3xC9Z07mWIZVL2wikUlxGtMYuYsF+sJycldHI2irLqdRG4oPXBeNMyk4jAzCfnCAiXGocLbAdUoLLMNckTma4/xME+R2lcOI66mnnnrq+f/Bv0LF8WFTr2ZliiAIjFh2lFjFa0jkZazuv5pjN46x9MJS5Ej4Lj2DkHIN21sN5zdKiM6LxkJuwYbHNuBjU3XycJGmiPB1oojCkVFHsDOrXITzn8C2JRdJupBTScgi/kwmu1ZEAdBtdBDNunlX2vbSgVQO/SKKh/R5PoSzmz/nxpUY/Fq2xj0wiEv7dlGSV0PtM4kFMmVTOj3xGO0ea2WySq/TsWr6JAozM+j61LO0fcz0ZTs7OYmf3n4FwWCgZcRAuj/zAjK5+OK/+7tvubhnBz5NQxk5c949nZfbObD6O85u3WT8397dg9Be/WjarReWdvb33f/tVCguAgx69S2CO94K0Ys+vJ/t336GubUNE75deVcv2q+z3yY1+jJdxoyvMizy98nPkZwnejgkUikBrdsT2rsfDUNbGsMh6/n3YijXk7HgFIZSHQ5PBGHV5u7Kk9ocFVmLIhFUOmz7+d6TaEjZpRzy1oiTU/aPB2Ld/u7y3I+C+t+9euqpp55/LvUhjvVU4mhCLucyLmHlV4aVwprmzs1p4dKCpISd7CxN4n9uLujl5pTl3arXodKp+OjERyzpvaTKvLG4PLHOiaeV5z/WONNq9GIhacC/pWleUWBrV3LTStCW62napXK+EECzrl4UZqmQm0kpyz/PjSsxKMwt6D1hKrbOLnQYNoqkyLNEHdxDSb64H125npzUEgRDkViLqfwMh9ec4VpkKG7+gcZzWZSTTWFmBha2drTsO7DSvl0a+tFt7PMcWP0dkTu3kp2cxOBpM9BrtVzeLyrkdXri3gQi7qTrWDFkTlVcTNNuvfFp2vyh5Qp2eWo8GrUK75BmJsYZQONOXTmx4Rfy09M4v2ML7R8fWW0/RTlZYiinRFKlp1AddwXfE+dRu9nh07MPrSdMxtrBsYqe6qlAX6Sh7HwWVm3dkFo+PC/gg6Lk+A0MpTrkTuZYhtXOY6dwtsC2ZwMKt15Fc4fgTW3QpJWQv1589ll38vzHGGf11FNPPfX8s6mVgbZ58+Y6d9ynT58aK4/X889EEAS+2HMFubXoCerk2RG5VA4xW/gw6jCpHi5EmZmBQYOvrS9PBD1BC5cWPL/zeY7eOMr2pO0M8B9Qqd+aBEL+KVyPzkOnNWDjaI6zt2mYnkQiocOQgBq3l0gldB7ZiJL8PH6Y/iMAnUc9bRSRkMpkBLRuV0mV7/dPzpBxtQAnj2zMzOJIunCW61EXuR5VWXmp7WPDUZibV1oO0HrgEOzd3dn2zWekxUbz89uv4NzAF4NeR4NmoUbVwvtFKpXR/ZkJD6Svu2FuZc3A/71R9ThkMjoOH8W2bz+7qeg4CLNqClZW1BXzCWlWSdRDMBjImDULK5WaboHh+Lz57oM9iP8o+RuuoI7LRxWVg8uEUCSKf27EvKFcR8khMffMpmcDJLLaTygobz4LtDdK6rRPfVE5OT9GIWgNmAU5YDew6tIS9dRTTz311HMntTLQhg4dWqdOJRIJ8fHx+PvX/yD92ziSkMPZ5HysfEWZ93DPcEi/AH9MwEIwsNgjgg0NQ2np2tJEZXFC6AQWRS7ik9OfEO4VXslLViEQEuL0YGocPQySbqo3+rV0rpVHKCPhCic2rsenSTOadO2JhY0YJrT/x+8oLyvFzb+RSa5YdfQe34Skizk07dIdpbmcopwsYo8eoqyo0KSdpa0drfo/Vk0vIgGt2/PUvC/YtHAueWnXjZ66jg/Ie/ZPIzi8K8f/+JX8G6mc3fonnUZUPs602Ggu7hHDJEN9Kj+TCtavRxUZidTKCvf33qu0vp7KlKcUoY4Ta9xpUorJ23AFxyeD/xbV1dpQcjwdQ5kOubMFli3rlu+m8BDLJ+gLNehLNMis7y4WIugM5KyOxlCkQe5qgdOYxnUyCuupp5566vn/Ta2nPDMyMjAYDLX6WFYzi13PPxtBEPhi9xWQliG1SAEg3K4RrBsN2jLw747jgC+YEDqBtu5tTV7Gnm/2PP52/uSp8/ji7BeV+o7NiwUgxPGfaaAZ9AaSLuUAlcMbq6IwK4M/5n9A4pkTHFi9gmWTnmHr159y+q8/uHL8MBKplD4Tp9Yqd8nezZKwPg1QmovzJbbOrrQb8gTdn37e5NNuyBPI5HefU3H09OKpjz6jUbtOgFgg2DvkwXjP/mlIpTI6PjEagBN//ELyxUiT9Xqdlt3fifL/3nlFCAs+J+OjeQhaLQDarCyyPvscAJdXX0XhXjdZ+/+vFO0Rnw/KBjYglaCKzDbKx//TMPWe+dTZUJKay5E7i9Eg2hultdqm+MB1tKklSC3lOI9ritS8Ppugnn83ubm5uLq6cu3atb97KPX8x7h27RoSiYTIyMg6b/v+++8zceLEBz+ou7Bjxw5atmyJwWAwLtNoNPj6+nLmzJkHso9aGWjjxo2rU7ji2LFj65OO/4X8dCKZcykFmNteBQT87fxx/+s1KEoDp0Yw4keQVf2ioZApmNlxJgAb4jdwNvMsABmlGSy5sISrhVeBR+9BEwSBPSsW8cNrLxnl5KviRkIh5aU6zK0UeATUnCNXXlbGxk/moCouwsm7Aa6+Aeh1OmKPHuTQz98D0GrAENz8ag6JfJgoLSwZPH0GT837gsGvvfPQ95f/63qudAon7bXXKT15itpoD2lS07g69HFimjU3+ST07EXZuXO13nfjTl1p0qUHgsHAX19+TN6NVOO6M39tJDc1BaVOT+MbokBL/k8/kfLsc+hycsic9zGG4mLMmzfHYczoOh+3oBfIXnFJDGUz/P/QWypPLqL8Sj5IJTg+GYz9zdDfot3JlN2c5LgfdLkqMj47Q8H2pDptl78xnoyFZyi/Zup5Ljl2m/esxb2pRSo8RS+aphZhjtrsMor2i8aq/ZAA5E71of7/JMaPH49EIkEikaBQKPDz8+PNN99ErVY/sH0cPHiQnj174ujoiKWlJY0aNWLcuHFoNBpjG0EQWL58Oe3bt8fa2hp7e3vatGnDl19+SVlZGQAffPABEomESZMmmfQfGRmJRCIxGksVL7iurq4UFxebtG3ZsiUffPCB8f+KY7/z8+mnn9Z4TB999BFDhgzB19fXuOz06dP06tULe3t7HBwciIiI4MKFCybbCYLAwoULCQoKwszMDC8vLz766KMa95WXl8dTTz2Fra0t9vb2PP/885SUmN57d+v3/PnzhIWFYW1tzeDBg8nLyzOu0+l0tG7dmlOnTvGgyc7ORqlUUlpailarxcrKipSUlAe+n9qi1Wp56623aN68OVZWVnh6evLMM89w48aN++p34MCBLF8uqkZPnDiROXPmPIjh1omMjAy++uor3n33VlrCoUOHGDx4MJ6enkgkEv78888693vt2jWef/55/Pz8sLCwICAggFmzZpncv/369UOhULBmzRrjMqVSyeuvv85bb711X8dVQa0MtFWrVmFjU3t55SVLluDs7HzPg6rn/tEatOSr82tso9FryFPnUa7T887GS8zcJKoUhviLN2641AZST4GZHYz5FSzsa+yvtVtrhjcS1QU/OPYBL+99mYgNESyOXIxBMBDiGIKLRe2L+j4I4k8e5cLu7eSmpvDb3Hc5v+OvKo2HivBG3xbOSKupjQRgMOjZ+vUCclNTsHJwZPg7c3j6k68Y+/GXhPbqh8LcAifvBoSPeOqBHoeg1aLNzKzTNhKJBPeARiiUD1euu+TwYTJmz0afl0fR1q2kjBvH1f4DyF35Pbr8qq9BfUkJqZMnUx4bCzqdyUd74wapU6aiSU2tcts7kUgk9Hnxf3gGhVBeWsrGT2ajKikmP+MGxzesAyAkLQfH7j3w/vYbpFZWlJ05w9XBj1G8YwfIZHjMmY1EVnelRm1mKeUJBahj8lDVwTgRdAZ0BQ/uhfBu+9KkFpt+bpQg6O/NoCzakwyAZStX5E4WWLf3wDpcLLSevz4OTWpxTZujL9Ui6A1VrhMEgfyNCeiyVZQcTkVfWF6rMelLNJSeykCXoyJ7+SVKjt9AEAQMah0lh296z3rVLffsdhSetctDEwSBgo0JoBcwC3LAIvTRPu/qqR39+vUjPT2dq1ev8sUXX7Bs2TJmzZr1QPqOjo6mX79+tGnThkOHDnHp0iW++eYblEolev2tUg1PP/00r776KkOGDGH//v1ERkby/vvvs2nTJnbt2mVsZ25uzsqVK4mPj7/rvouLi1m4cGGNbdLT000+33//PRKJhOHDqy/DUVZWxsqVK3n++eeNy0pKSujXrx8NGjTg5MmTHDlyBBsbGyIiItDejFAAeOWVV1ixYgULFy4kNjaWzZs3065du6p2Y+Spp54iKiqK3bt3s2XLFg4dOlTJS3K3fl944QV69uzJuXPnKCwsZN68WwrGn332GeHh4Xcdx71w/PhxWrRogZWVFefOncPR0ZEGDRo88P3UlrKyMs6dO8f777/PuXPn+OOPP4iLi+Oxx2pOl6gJQRA4ceIE4eGiMvfhw4eNfz9KVqxYQadOnWjYsKFxWWlpKS1atGDRokX33G9sbCwGg4Fly5YRFRXFF198wdKlS3nnHdPJ7vHjx/P111+bLHvqqac4cuQIUVFR97x/I8J9oNFohMuXLwsXLlwQ1Gr1/XT1t1JYWCgAQmFh4d89lAeCTq8Txm0fJzT/obmw/MJywWAwVGpzIeuC0HN9T6HV6tZCxJKVQsO3tgi+b28Rvtl7Rei5vqfQ7IdmwpGFDQVhlq0gnF5Z630XqAuErr90FZr90Mz4Gb99vLAlcYug1j3aa0RdWiIsefFpYeHIgcLKVyYIC0cOFBaOHChs+/YzQVN+aywlBWph5euHhG9f3Ctcjcyqsc/9Py4XFo4cKHz51ONCenxcpfV6nU7Q63QP/FhSX39DiA5uLGQu/EwwPIT+7xV1fLwQ27qNEB3cWEidNk24MXOWEBvWSogObixEBzcW4jp0FEqOnzDZxqDTCSkTXxSigxsLVzp3EVRxcYImI1P8pKYKV4cNF6KDGwuJgwYJuuLiWo+ltCBfWD7lWWHhyIHCr7NnCOvnvCMsHDlQ+KF/DyEquLGgiooSx5yYKCT0628cY8YnC+75+EvOZgjX3zokXH/rkJD+2WnBoK98r92OJqtUyN+SKKTNPiZcf+uQUHw07Z73XRt0xeVC+qenjWO8/ZO34Uqd+1NfKxS3n3FY0OaqjMsNOoOQtfKScP2tQ0LaRycEXWHV97oqIV9Ife+IkP7ZaUFfqqm0/vbzef2tQ0LBrmu1GlfJqXRxm3cOG7fNXR8nFOxMEr+bhXf/bmpCFZcn9vPp6ZrHcVocf+p7R0zOzz+R/9rvXm0ZN26cMGTIEJNlw4YNE8LCwoz/6/V6Yd68eYKvr69gbm4uhIaGCr/99ptxfV5enjBmzBjB2dlZMDc3FwIDA4Xvv/9eEARB+OKLLwRfX98ax/Drr78KgPDnn39WWmcwGISCggJBEARh1qxZQosWLYQ+ffoII0aMMLY5f/68AAhJSUmCIAhCUlKSAAhvvPGGYG1tLWRmZhrbtmjRQpg1a1a1YxkyZIjQs2fPGsf722+/CS4uLibLTp8+LQBCSkqKcdnFixcFQIiPjxcEQRCio6MFuVwuxMbG1tj/7URHRwuAcPr0rXtt+/btgkQiEdLS0mrdr4WFhRATEyMIgiAsXrxYGDBggCAIgpCYmCg0atRIKCoqqvWY6sJbb70lvPLKK4IgCMLChQuFJ5988q7b7N+/X2jbtq1gaWkp2NnZCZ06dRKuXbv17Nu8ebPQpk0bwczMTHBychKGDh16X2M8deqUAAjJycn3tH1MTIzg4OAgGAwGITs7W5DL5ULxXX6ra7pnKq7f8+fP12kcTZs2Fb799ttq1wPCxo0b69RndSxYsEDw8/MzWZacnCwAQkJCgsnyHj16CO+999597/OeZbcOHz6Mr68vPXr0oHv37vj4+LBjx477tRfreQD8EvcLZzPPIiDw9fmvmX5gOqXaW7kTG65sYPyO8WSVZaExlJOqWIaNdQHfj2tLvzAJWWVZmCGhdUkB+LSHVuNrvW87MzvmdZ5HiGMI45qMY/PQzazqt4qB/gMxkz3awquH1/5IaX4eDh5ePLPgW7o9/TwSiZToQ/v4ZeabnNu+mTNbN/HrnBUUZ5/C3CIZj8Cqiywb9HrObt1krP/Vb8o03AODKrWTymRI78ETUxMGjYbiPaJUfu5333F94ovoCwoe6D7uBV1+PtcnTcZQUoJlmzZ4zp+Px+wPaHT4EO4fzkEZGIA+P5+U558nd9UPRs9l1qcLKTl4EImZGd6LF2EeFITCzVX8eHnhvXgRchcXyuMTSJs+HUFfuwLBlnb2DH1zJgpzC65HXSTl8gVkSGiamo1N716YN2kCgJm/P76/rcfuieHY9OmNy9Qp93wOtBm37itdlgrVxewq26micshadpHMz85ScjgNQ5kOgIK/ElHH5VW5TW3Q5ahQReVWGV4p6Azk/hyDLkeFRClDZm9m/ACUnsqg/GpBlf0aNHrKzmehyzP18lV4z6xauyF3vKUmKpFJxMLOrpYYijSiQIbG9HvT5qjI/TkGQWtAl3Xz79s8afpSLYVbxVBopa/tzTGmI+iq9rbdjipaDF+17eGDXX8/kEDZ2UxjXpxtrwZIpPcu0lER4qjLUWFQ66psoy/RULhNHL9t7wYm5+f/BYIAmtJH/7nPUq6XL1/m2LFjKJW3xF8+/vhjVq9ezdKlS4mKimLatGmMHTuWgwcPAmLeS3R0NNu3bycmJsYkasjd3Z309HQOHTpU7T7XrFlDcHAwQ4YMqbROIpFgZ2caZj9//nw2bNhw19yW0aNHExgYWOtws8zMTLZu3WriGauKw4cP07p1a5NlwcHBODk5sXLlSjQaDSqVipUrVxISEmIMg/zrr7/w9/dny5Yt+Pn54evrywsvvGASbngnx48fN4Z7VtC7d2+kUiknT56sdb8tWrRg9+7d6HQ69u7dS2hoKACTJk1iwYIFdYoKuxspKSnY29tjb2/P559/zrJly7C3t+edd97hzz//xN7enpdeeqnKbXU6HUOHDqVbt25cvHiR48ePM3HiRGOO/9atW3n88ccZMGAA58+fZ+/evSaevw8++MAk7LQ2FBYWIpFIsLe3r9N2gwYNMn43hYWFODg44Ofnh16vx9vbu8b+arpnqsLX19ckNPdO8vLyiI6ONrlOHiaFhYU4OpqW3mnQoAFubm4cPnzYZHm7du0qLbsXap25bDAYkEpv2XOvvvoqa9asoXv37gAsX76cyZMnk5RUt7yBeh4sGaUZfH1OdLn2adiHA9cPsCdlD1e3XuXTbp+yLnYdv1/5XWxc2gy9tBCZxXW8G6+jtf9gNsZvB6BNWRnmEhkM+hKkdbPjw73CCfd69O7u27lxJYYLe8Rj6f3CFORKJW0GPY6rrz9bvvyErKREspISTbYpUMHK/+2iabeeNO/ZDydvH4pysrm8fxeX9u+mJFcMYes04qlKNbkeJqqzZxFUKqTW1gg6HaVHj5L0xAi8v/0G88Z/T9kCg0ZD6ssvo01NReHjg9c3XyO5+YIjtbLCYcQI7AYPJmPWBxRu2kTWJ5+gvnwZi5YtyfvhBwA853+MRfPmlfpWuLnhvXgxyWPHUnroMFkLPsVtxtu1GpdLA18G/u8N/vz0QxAEAtJzsdLocJliaoTJrK3xnDv3/k4CoE0XDTS5swW6HBVFe1OwCHUxMQZKT2eQv+FmeJIEzBs7YtXOHdXlXMrOZpK7NhbXKS1RuNZNXEkQBHJWR6HLUmHexAnHkUFGMQrhZqig5loREjMZri+1QOFmZdw2f2M8pSczyN+YgNsrrZDIb93jgl4g96doyuMLQAJmgfZYtfNAaikXl0kl2PSoXLBZai7HeVwTshZHok0tIf+3KziOboxEKsFQpiX3hygElQ6FhxW6XDXlVwsp2JSI/eNivb/CbUlinTI3S5yfa0bGp6cxFGtRReVi2aL6UEFDuR51vBhKa9HMGYW7FQpPK/LWxYq5Zy4W9x1qKLNWIrNToi/UoE0vxcyvcp5q4dYkDGU6FO5WWHeuulbifxptGczzfPT7fecGKK3u3u42tmzZgrW1NTqdjvLycqRSKd9+K4oJlZeXM2/ePPbs2UPHjh0B8Pf358iRIyxbtoxu3bqRkpJCWFiY8eXw9hfkESNGsHPnTrp164a7uzsdOnSgV69ePPPMM8bc/Pj4eIKDg2s93latWjFy5Ejeeust9u7dW207iUTC/PnzGTx4MNOmTSMgoOY86B9//BEbGxuGDRtWY7vk5GQ8PU2/WxsbGw4cOMDQoUP58MMPAWjUqBE7d+5EflPM6urVqyQnJ/Pbb7+xevVq9Ho906ZN44knnmDfvn1V7isjIwNXV9NcUblcjqOjIxkZGbXud8WKFbz00kssXLiQ8PBwZsyYwU8//YSlpSVt27YlIiKCxMRERo0axdz7/C3w9PQkMjKSoqIi2rRpw8mTJ7GysqJly5Zs3bqVBg0aYG1d9eRvUVERhYWFDBo0yPh9hYTcytX/6KOPGDVqFLNnzzYua9GihfFvZ2fnu37Pt6NWq3nrrbcYPXp0nbUiVqxYgVqtZtKkSXTo0IHx48czc+ZM7O3tmT59eo3b1nTPVEVAQECNBlxKSgqCIFS6Lh8GCQkJfPPNN1WGD3t6epKcnHzXZfdCrd+827dvz7nbEvc1Go1JXG2DBg0eaJJtPbVHpzfwxe4rnLyay8cnP6ZMV0YLlxYs7LaQVf1W4WrhytXCqwzfPJzfr/yOBAn+sicoThmDt+YlXC3cSC1N5o2Db3AoRXy4havUEP4KuDX5247rxpVYDvy0Eo1aVaft9Dodu5d/C4JAcKce5N6w5+iGBDKvFeHTNJSxH39Jiz4DcPFthVQRjEwZjE/Tdtg4uaAuKebs1k388NpkVk2fzIqpz3P893WU5OZgbmNLpxFP0WH4qId0xFVTcvgIADa9e+P7yzoU3t5oU1O5Nmo0JTdndO8VXW4uGfPmUfDHRgyq2p1nQRDI+GA2qjNnkVpb47NkMXIHh0rtpObmeMz/GLd33wWZjKKtW8m8mcTt/PJUbPv3r3YfFs2b4fnJfADyfvyRrK++qjaf7U4CWrdj0Ctv0sTGEf+sfGz69MY85OGI01R40OwfC0BiIUeXbepFK79aQP6fCQBYtXfH/e12OI9rikWIEw6PB6L0tUUo15PzQxT6Um2V+6gOXVYZuizxO1NH55K1KBJttiguUHIojbKzmSABp6dCTIwzALt+fkhtFOiyVRQfMFVfLNiSKBpiMgkIUB5fQN6aGHK+uyQeRxu3ar1DcicLnMY2AZkE1aUcivamIOgN5K6NRZejQmZnhvNzzXAcFQwS0YtXcuwG6sQC43gdhjVCqpRh1U4s6lxyvOZkdvWVfNAJyJzMkbuJRq55Iwdcp4Zh3dULp6dC7st7VkFFHpomrXIemjohn7LzWeL4hzdCUkMeaz1/Pz169CAyMpKTJ08ybtw4nn32WWMOVkJCAmVlZfTp0wdra2vjZ/Xq1SQmipN6kydP5pdffqFly5a8+eabHDt2zNi3TCZj1apVpKamsmDBAry8vJg3bx5NmzYlPT0doFYiSncyd+5cDh8+bJKfVhURERF07tyZ999//659fv/99zz11FOYV1NbswKVSlWpjUql4vnnnyc8PJwTJ05w9OhRmjVrxsCBA1Hd/C0xGAyUl5ezevVqunTpQvfu3Vm5ciX79+8nLi7uruOrjtr027RpUw4ePEhycjJr165Fq9Uya9Ysvv32W15++WU6derEhQsX+OOPP/jrr7+q3M+kSZNMroHqkMvl+Pr6EhsbS9u2bQkNDSUjIwM3Nze6du2Kr69vtcaGo6Mj48ePJyIigsGDB/PVV18ZrxMQBWF69epV7b6nTp1ao9F+O1qtlpEjRyIIAkuWLKnVNrfj7u6Ol5cXJ06c4KmnnsLX15fjx48zcuRIfH19azS6arpnqmLv3r1MnTq12vUV19jdrt37JS0tjX79+jFixAgmTKhc/9XCwsIo6lPTsnuh1h60b7/9lhdeeIFu3boxd+5cZs2aRevWrQkODkar1RIbG8s333xz3wOqp+7sjMrkq73x/HxpKxqnfcglcmZ1nIVUIqWFSwt+Hfwrrx14jXNZ57BR2vC0/zt8slGCVAKfPh6O0jKAcTvGcezGrRsmXOkMXasuEPwoUJUUs2nhXMoKC1Cam9OpDqIbZ/76g5zrycgUVqTEhpAcI74gR+5OwdnHmqadPfFq8jhxZ2JQWkO3McE06+qFwaDn2oVzXNyzk6vnTpGXJr64+jQNJbRXBIHtOiFXKB7K8dZE6RHRQLPq0hnzxo3x+/03US3x6FEyP56Pdbdu99SvIAikv/seJQcOAJD58cfYDR6M/cgRNXrm8r5fReEff4BUitcXn2MWGFhtW4lEguPTYzELDiJt2nT0ubnYDhiAczXhHrdj268f5f+7Ss7X35C7ZCl5K1Zi07cv9iNHYtmubY01t3yd3TEcFcOBnKfcewhjTehLNBiKRaNK2dAWmy5eFO1KNnrR9Plqcn+OAb2ARagz9kMCTQwFiVyK09NNyFoUiT5PTe7P0bg839zEm1UTqigxrE/haYWhRIsuW0XWt5FYd/Sg+KAojGE/yB/zoCqMZws59oMDyFsbS9H+61iEuqBwtaTk+A1Kj6eLht2YxijcrSg9k0npmQzxWGVVe89ux8zPDofHG5H/+xWK96ZQfrUATVIREqUUp3FNkNkosWjihF1/Pwq3JVG45SrSm7XFrNp7YNZQnNW1bu9O8f7raK4VoUkvRelRtZdEfTO80aKJk8k1IXc0x37Ag6vFqfC0Rh2TV6VQSPEB8XxbdfBA6fPgQqf+VSgsRW/W37HfOmJlZUXgzefW999/T4sWLYwiGBVqgVu3bsXLy9QTamYmhgf379+f5ORktm3bxu7du+nVqxdTpkwxmWH38vLi6aef5umnn+bDDz8kKCiIpUuXMnv2bIKCgoiNja3TmAMCApgwYQJvv/02K1eurLHt/Pnz6dixI2+8Uf1v+OHDh4mLi+PXX3+9676dnZ3Jv2OCbO3atVy7do3jx48bo6vWrl2Lg4MDmzZtYtSoUXh4eCCXywkKupUOUOEdSklJqdKL6O7uTlZWlskynU5HXl4e7jfLoNxLv9OnT+fVV1/F29ubAwcOMHfuXKysrBg4cCAHDhxg8ODBlbaZM2cOr7/++l3PT9OmTUlOTkar1WIwGIzeWZ1Oh7W1NQ0bNqxRNGLVqlX873//Y8eOHfz666+899577N69mw4dOtRJQb0mKoyz5ORk9u3bV2fv2bx585g3bx6CIFBWVkZYWBgginJEREQgkUjYvn07XbpUHV1Um3umLlQYvPn5+bi4PBwxphs3btCjRw86depkVKy8k7y8vEr7r2rZvVBrA619+/acPn2aBQsW0Lp1axYsWEBcXBwnT55Er9fTtm3bSg+zeh4NsVfiWKGcywxb8WVxfLPxNHJoZFzvbOHMir4r2Ht9L8F2zRj3XTxQxqqGu2jxuxg69rECXr35XuGu0+HX7ytQ/H3y0IfXrKKssACAi3t30v7xJ6usAXZmy0Yid24RFdsMAtpyPeUl4nZSRRcEwRw3P1tsncy5GplDzvUSDq67Ytw+tKc3zbqK161UKsM/rC3+YW0pycvletRF3AKCcPT8+65rbWYm5VeugESCVSexrpnM3h6vLz7nSoeOaK5dQ5uZhcKtsny4vqic3HWxWLfzwDKs8vriXbtF40yhQOHmhjY1lfy1a8lfuxbLtm3xXPAJCg8P02327SPr5gPV7e23sa7mYXwnVu3a4f/nRsrOncemR/daFzR2njwZhbsH+WvWoI6KomjrVoq2bkUZEIDn/PlYNK9c382gVpM5/xMQBGz69KnW2CzcnoQuXy0WWL4Hj0eF90zmZI7UTIZ1J09KjqShy1ZRejKdkuM3xJA3b2scRwRV6cWRWSluhgVeQJNURN76OBxHBCNR3H08FQaadUdPzBs7krsmBs21IhNjwapT9eEfFs2dMQ92QB2XT/7GBGx7+FDwl+ghsI3wxaKp+ANoF+GLbe8GqOMLkFkrkDvcfcbSqo0b2qwySg6lokkqAgk4jmqM0vPWLLR1Fy+0WWWUncnEUKxBaqPArp/vrXNja4ZFUydUl3IoPX4D5bBGlfYj6A2oYsS8E4umTncd1/2g9KpayVFfWE55YgEANl28H+oY/tFIJHUONfwnIJVKeeedd5g+fTpjxoyhSZMmmJmZkZKSQrcaJr9cXFwYN24c48aNo0uXLrzxxhvVvmw6ODjg4eFBaan4zBgzZgyjRo1i06ZNlfLQBEGgqKioUh4awMyZMwkICOCXX36p8ZjatWvHsGHDePvt6kPDV65cSevWrU3C5aojLCyMn3/+2WRZWVkZUqnU5Fle8X9Fbajw8HB0Oh2JiYnGMLwrV8Tf39uV926nY8eOFBQUcPbsWWPe2759+zAYDLRv3/6e+t27dy8xMTGsWrUKAL1eb1SavF1x8k5cXV0rhVtWxbZt29BqtfTq1cv4jjxq1CjGjx9vlGO/G2FhYYSFhTFjxgw6duzI2rVr6dChA6Ghoezdu5dnn332rn1UR4VxFh8fz/79+3FyqvuzctKkSYwcOZLFixeTmprKvHnz+O2339i1axffffcdwF1tgLrcM3cjICAAW1tboqOjTQz1B0VaWho9evSgdevWrFq1yiTFqwK1Wk1iYqLRWK3g8uXLlZbdC3V6K5HJZMyYMYOtW7fyzTffMHnyZFq3bs3QoUPrjbNHTK4ql+yybLLLsmkS/xEnXNJRK8qxkLjwYuiLldorZAr6+fZj/ckSUvLKaGSjo2vmT1CYAoUp9MpJYVqeOEPW39IXSWDPR31IRlJjLnNpnxjGobSwpDQ/j4TTxyu1K8rJ5si6HynMyqQoO4uS3GzKS/IAAzIzX1r06c2T77Xlibfa0PeFZoz/JJzOIxrh4C7OuDZs5kT48Kq9P9aOToR06fG3GmcApUeOAmDevLlJGKHM1tYYtldWTS2X0rNZaJKKKNiSiKA1FVrQFxeTeTPu3umF5wnYtZMG36/Epl8/kCsoO3OOpOFPUHryVt/quDjSXn8DBAH7UU/i8PTYOh2L3MUF24i+xly12iCRSLAf9jh+G37H9/ffsX/ySaSWlmgSE0l+6ikKNv5p0l6blsa1MWMoPXoU5HKcqwmR0GaUUnwwFdXFHDTXa5aFrw5tuhjCoHAXX0ql5nKsu4jXS8GmRHRZKmS2SpyfaYJEUb1wjMLNCqcxjUEKqos5ZC27gK6gZnl5XUE52rQSMactxBGZjRKXCc2xvmmQmQU5YD/Yv0ZDWCKRiF49hRRNUiE5P0aBQZTPt+lmamhIZFIsGjui9K69d8iun6/RaLLr74dFE9OXAolEgsPQQMz87cTQwCGBlQo6W3cUJwjKzmdhUFUW5yi/Woig1iG1VqBs8HBrbxql9rPKTO6nsgvZIIjCJv/vhEH+I4wYMQKZTMaiRYuwsbHh9ddfZ9q0afz4448kJiZy7tw5vvnmG3788UdANJQ2bdpEQkICUVFRbNmyxejBWbZsGZMnT2bXrl0kJiYSFRXFW2+9RVRUlNFLM3LkSJ588klGjx7NvHnzOHPmDMnJyWzZsoXevXuzf//+Ksfp5ubG9OnTK0l7V8VHH33Evn37qgwlLCoq4rfffuOFF16o1fmJiIggKirKxIvWp08f8vPzmTJlCjExMURFRfHss88il8vp0aMHIIp7tGrViueee47z589z9uxZXnzxRfr06WN8qT516hSNGzcmLS0NED1h/fr1Y8KECZw6dYqjR48ydepURo0aZcw3qk2/FajVaqZOncry5cuNL9nh4eEsWrSICxcusGHDhvuWiG/YsCHW1tZkZmYyZMgQfHx8iIqKYvjw4QQGBlZrjAIkJSUxY8YMjh8/TnJyMrt27SI+Pt54Pc2aNYt169Yxa9YsYmJiuHTpEp988olx+2+//bbGEEitVssTTzzBmTNnWLNmDXq9noyMDDIyMkzqet0NR0dHAgMDiY6Opn///gQGBhIfH0/fvn0JDAwkMDCwRm9fTfdMVfTq1cuYF1oVUqmU3r17c+RmhFEFJSUlREZGGoteJyUlERkZWadadGlpaXTv3p0GDRqwcOFCsrOzjefsdk6cOIGZmZkxV7WCw4cP07dv31rvr1rqIvl4+fJl4ffffxfi4kR58R9++EHw9/cXFi1adN9ykn8n/ya54ZyyHOGFnS+YyNjf/nni41cFlaZqGfaY9EIhYMZWoeFbW4QLW5eIEvrftBWE62eMn/SrewWd5u8rmaDVaITvX31RWDhyoLBz2dfCkV9/FhaOHCj8MuutSm13f/etsHDkQOGzMROFr5//Wfj6+Z+FNTM3Csf+OCaUFVcvcW0wGIT8zFJBfx+y24+K66++KkQHNxayvvqq0rqM+Z8I0cGNhRvvvV/lttmrLhslx0vOZpisS589W4gObiwk9I0Q9LeVyDDoDUL65yeFlOlbhZiwzkJ0k6ZC7o8/CtqsLOFKjx5CdHBj4dr48YJBU1ki/VGhKywUUl6cZJTJT5/zoWDQaISS48eFuPYdqpX3v528P64Yz03Roev3NI7c9XGVpOD1aq1RQj/1vSNCeWrtywSoruQZt02bc1xQJ+ZX27b4SKpw/a1DQuaSyErrdAXqOknKFx28bjwXmYsjBYNWX+tt74bBYBB0ReU1t9Hpq5WkNxgMQvrnZ8Tv6XBqpfV5G+PFkgG/171kQF0xGAxC2hzx+ylPuSXRnfHlWbFkwokbD30MD5J/0+/eg6QqmX1BEISPP/5YcHFxEUpKSgSDwSB8+eWXQnBwsKBQKAQXFxchIiJCOHjwoCAIgvDhhx8KISEhgoWFheDo6CgMGTJEuHr1qiAIgnDu3Dlh7Nixgp+fn1EWvWvXrsLmzZtN9qfX64UlS5YY5dVtbW2F1q1bC1999ZVQVlYmCMItmf3bKSwsFJydnauU2b9TpnzixIkCUElmf9myZYKFhYVRzr82tGvXTli6dKnJsl27dgnh4eGCnZ2d4ODgIPTs2VM4fvy4SZu0tDRh2LBhgrW1teDm5iaMHz9eyM3NNa7fv3+/ybEIgiDk5uYKo0ePFqytrQVbW1vh2WefrSTjfrd+K3j77beF1157zWRZfHy80LZtW8HW1laYPHmyoNff/zNv3bp1QufOnQVBEIRDhw4JgYGBtdouIyNDGDp0qODh4SEolUqhYcOGwsyZM03GtGHDBqFly5aCUqkUnJ2dhWHDhhnXzZo1S2jYsGG1/VdcG1V99u/fb2zXrVs3Ydy4cTWOVavVCtbW1kZZeX9/f+HIkSO1Os6a7pmqrt+GDRvWWB5CEARh27ZtgpeXl8m5qrie7vzcfmx3O2erVq2q9pzdzsSJE4UXX3zRZNmxY8cEe3t74z18P0gEoXbZqp9//jnvvfceoaGhxMfHM3/+fCZMmEBOTg7Tp08nPj6e5cuX07wKVbZ/OhXhBIWFhXWOy32UROVE8eqBV8koFa14qUQKBlHKWgI8WVSCZ1YbnEZ+zaBQ09Amg0Fg+NJjnE8poG8TN5abfQkxf0HXN6Hnu/xTOL5hHcfWr8HSzp5nP1+KVqPmuynPIRgMPPPpt7g08AWgKCeLFS9PQDDoMbMbSWivDjTt7ImTV/WJvP82BL2eK53CMRQW0nDtWixbmbrMi/fvJ3XySygbNiRgp2mJC0EQSP/whFHOXeljg+uUlgCoIiO5NnoMCAINfliFVYcOxu3KkwrJXnbxZifFFG99D3QqZHZ26AsLUfr64vvrL8iqCL95lAgGAzmLFpNzsxileWhX1DGnQavCvEkTvL/9BkU16k4GtY70eScRNKIXxKKFC06j666GmfnNebRpJTiNDcGi2a0E8NLTGRTuuobD0EZ1DrvT5anJ/SlaVIeUgt0Af6zDPSt5wrK/u0h5YiF2A/3uO6xO0Avk/BiFoVSL87NNkVnX3sP5KCg5kU7BnwnInS1wm97aGCoqGAQy5p9CX6TBaXxTLBo73qWn+yd75SXK4wuwfzwQ6/YeaDNKyfzyHMgkeL7bHqnlo89RvVf+Lb979fwz2Lp1K2+88QaXL1+uMtyrnn83DRs2ZPbs2YwfP/7vHkqtEQSB9u3bM23aNEaPHl3r7caNG4dEIuGHm4rS90JOTg7BwcGcOXMGPz8/4/Inn3ySFi1aVCpqfS/U+i5bsGABW7du5cSJE5w7d47PP/8cEBP1Vq9ezZw5cxg5cuR9D6ieqvkz4U+e2f4MGaUZNLRtyJ9D/uSCcwQXrl1n01UNU8ufZ0ZePn1lZ9l07nql7decSuF8SgHWZnJmD/SHhJuqP40HPuIjqZ68G2mc3LgegO7jJmBubY2NozON2oru48idW4xtj/++HsGgRyr3oe2gznR9Mug/ZZwBqC9dwlBYiNTGBovQyhMflm3agFSKJjkZbWamyTpdtko0zuQSkEnQXC9Gk1qMoNWSPnMWCAJ2Q4aYGGcghpIZkdhg9+THIFegLyxEameH95LFf7txBiCRSnF5eapYM80nDIX/WCy7vIntkOE0XLumWuMMxPpYgsYAN8U47iXEUdALaDNNQxwrsGrrjue7He4pJ0ruaI7L5BZYtnQBAxRuuUrZOdOEeUOZlvKkQoBKYYP3gkQmweW5Zri9HPaPM84ALMNckZjJ0OWoKNiYYKyLpk0rQV+kQaKUYR5g/0jGUpFDV5GHVnG/mAc7/quMs3rqqSsDBw5k4sSJxlDEev47REVFYWdnxzPPPPN3D6VOSCQSli9fjk5XdW3KqhAEgQMHDhhLQ9wr165dY/HixSbGmUajoXnz5kybNu2++q6g1gaaIAjGWROZTFZJJrZPnz6cP3/+gQyqnlsIgsD8U/N5/+j7aAwaunt3Z93AdQSUFMApUVXmXd1zKEP6Y1BY4SHJIyf+FHmlt2KLM4vULNguKka93jcIj+wTYs0aOx/wuHuC8KNAEAT2rFiEXqvFt0UrGnfqalzXMkI0ImMOH6C8rJSi7CyiDuwGwN6zO637Vx/f/W+m5Gb+mVWnTkiqEEiR2dgYiy/fmYemSS4CRM+ZRXPRu1NyPJ3cH36g/MoVZPb2uL79lsk2gs5A2UWx1pvdAD8kCimGUkucX1mKTb9++CxdgtltD6N/AjY9e+IwVlTZktl6oWw8Comy+oLogiBQckKUMLbtKaoR6vPU1Urcq6/ko4rJrbRcl6sCnQGJQorsAecdSZUyHJ4Mxqa7OL7CrVdNxqeKyQODaBjKnf4+IZ9HhdRMht0Asfh06ekMspddRF9YbhRJMQ92qJWoyoPAKLV/oxTBIFAWKRpolmEPR0Wsnnr+Sbz66qv4+NSs4lrPv4+mTZty8eLFf6VntGXLljz99NO1bi+RSEhOTr7v67hNmzY8+eSTJsuUSiXvvffeA1PerPW38cYbbzBgwAA6depEy5YtqyxK97DrEfx/ZOe1nayJWQPASy1e4queX2Ejs4C/XgEE/qILRw3NaenvjrRRHwB6SU6z9eItuePZf0VRXK6jhY89T3f0hdit4orGA0XlrX8AyRfPcz3qInKlGb1feMkkpMu7SXOcvBugLVcTdXAv+1f/jCCI3rM+L/RFXoMAw7+Z0puV6K06V5/AbNmuHVDZQCu/aaCZNbTFuqPoTSo7n0n2ku8BcH3rrUq1y9RxeQhqHTJbJdadvXB8UpQqLk/UYz/qTSwfgCrRg0YQBLQZt2bPyuPyKdyWVG378oQCdNkqJEpRdVHuLD5ItamVvWiGMi05P0aRuzpaNMhuo0LBUeFu9UBqbN2JRCLBtk8DFO6WGMp0Jsekuikrb/6QVQv/SVi398D52WZILORorheT+c15ys6LXuOHrd54O4oKJcf0UsoTC9AXapCYybBo/P/nu6innnrqqefhU2sD7fXXX+fEiRNMmzaNI0eOMHHixIc5rnoAvUHP4gtiMcEuzmOY3HKymHd2cglkXkJvZs8H6jFYKGSEeNhC40EAREjPsPG8GIawNyaTbZcykEklzHu8GTJBD3HbxB38jeGNNxIK2LbkIpcPpaFR6YjcJRqNzXv2xc7VnaIcFSf+TGT7skvEHk+neU+xqPGZLRtJOH0AAP82g/AOrlzj6b+AvrAQ1SWxMLB1587VtrNqLxpot6stwm0etIa2KBvYIHdWil4Xz3bYDuiP3dAhlfqqCNeyaOmKRCrBopkzthGid7Jgc4LRY/Eo0Zdqyfs1jtJzmVWu1+Wo0OeXg0yCwwhRvavkSBolp9KrbF9yXFxu2doVqbkcpfdNj0gVYY7qhALQCyDcEfqJ+IIOoKimNteDQCKTYj+sEUjEsEx1YgEGjZ7yK6KS2oMIb/w3YR7kgNvUlijcxbpv+kINyCSYP4LcswrkjuZIzGSgM1C0OxkQyxU8Kg9ePfXUU089/z+odR00gObNm/8rRUD+rexK3kVS4VUEvTl7TgST260cJ7kaDn0KwJmgaeSetqODjx0KmRSC+iJIFTQijYLr0cSkN2fmJrE44vOd/WjqaQfXjoAqDywcoEGnv+W4BEHg4No48m6UknQhh8O/nqEsRzQwHL07sPnrSK7H5ImaOcDV89kolOZI5WYU52QDIDdrSMSEByBj+g+l9PhxMBhQBgZUqkV2OxatW4NUijYlBW16OgoPD/SlYtFiAGUDWwwlJajO/4nCZwBmwX1w/7BXJdEJg0pnrCdl2fJWuJZNdx90WSrKzmeR+3M0tr0aYNOzwUPxGt2JoDOQ+3MMmqRCVDG5WDZ3qfQirL5prJj52WHV2g19QTlFu5Mp+DMRuZOFSW6SrkCN+ma4onUH8ZwqfGwgMhtNauXiwxV9A5RFZmPTq4HxvN3uQXuYmDWwxaq9B6Un0inYmIBtn4YIWgMyezMUnv++mlP3i9zJApeXWpC/IR7VhWzMgxwqSfM/TCRSCQoPK7F4dopo1FdVY7Ceeuqpp5567odaTftNnz7dWGCxNsyYMYO8vLx7HlQ9ovdsyU3vmSa3CxqtGb+euQ4nloK6EJyD+V0v5mm1aXhzBtncDomfWDi4j/Qs474/RVqBCi97C17tfbPIa0V4Y1B/kD26F5vbuRFfQN6NUuRKKQ7ulpQXRwICUnkDjm7I5Xq0aJz5NHGkzQBfbJ3N0WpkSGS3ama0HTIKc+v/blJ+yc3wRuvONReClllbY960KXArzFGTInrP5C4WSM0kpE2bjjpyG4KuDInCDk1yWaV+VJdyQC8gd7M08QpJJBIchjfCqoMHCFC0J4Xcn2MwqGtOytXcKCHj87NkfHGW4sNp1eZ4VYcgCOT/mYDmphiGoNajiq38TKnwJpk3Ej2pNj19sGjhAgaB3NXRFGxLQpstHm/pyQwQwMzfDoWbeIxKH7Gulya12CSvVhAEY98geuq0txlxRg/aQzbQQKwnJrVRostRkb8xHhDD+mpb7Pu/hlQpw3FUMC4vtTCG4T5Kbi+2LbNTYub394vm1FNPPfXU89+iVgbaV199RVlZ5Ze66li0aBEFBQX3OiYT0tLSGDt2LE5OTlhYWNC8eXPOnDljXC8IAjNnzsTDwwMLCwt69+5NfHz8A9n338mOaztIKkxCJlihyRdzkDYdj0E4IcqK0+1Nztx8EW/d8LYwv4owR9lpsorFYrdzH2+GpVIOggAxN5UQQwY9mgOpgksHxPDL4PbujJgRhkwWA4DCKgxLWyWt+zVk7Icdeex/LWn/mD9j53TksVdb4t+6N0jMsHVpTsdh1Yf9/dsRBMFYoNqqhvDGCoxhjhUG2m3hjZnzP6H0yBEkShmWoaIhXxHmdzul5yvEDlwrvfhL5FIchgbi8EQjkEtQR+eStSgSbWbVkzZlkVlkL7mALqsMXWYZhVuvkj7vJLm/xFJ+taCSwFBVlBy5QdmZTJCA8uYL8J1hhoLWQPlV0YAzvxnqKpFIcHyiEUpfW4RyPSWHUsn87CzZyy9SelI87opizgBKD2uQSm6GzN0qDq3LLBMVAhVSY45Txf4Nah36m4WkFTeLnj9MpOZy7B/zB0RDFcD8/1l4451IJBLMGtg+Uu9ZBYrb1GItb4YD11NPPfXUU8+DpFa/boIgEBQUVOsZ27p422oiPz+f8PBwevTowfbt23FxcSE+Ph6H28QNFixYwNdff82PP/6In58f77//PhEREURHR/9rRUv0Bj1LLywV/ynsCgZzZFIJ/Uo2IlEUgktjchsOIClnPwCtGtxmoAUPgK3TaSVNwIV82oc2oUfwzRCcjEtQmAJyC/Dv8YiPSqQkv5yrkWKYYvPu3lw5cQRNWQk2Ti4899WzyGSySi88EqkEn8aO+DTujvalcGQS6X/ae6A6dw5dZiYSc3Ms27a5a3vLdu3IXbGSslOngVsCIbqMGPJ//hkAzwWfYNmqGaqYM5Rfyafk2A2sOnogkUjQFaiNnirLltWHa1m1cUfhZkXuz9HoslVkfnkO88aOWLVzxzxINP4KtydRckQ0wM2CHLBo4kjpqQy0N0pRRWajisxG7myBVTt3LFu7IbOq7AVVxeZRuO0qAHYD/TEPtCfzy3Oo4/IwlGmNcubl1woRtAaktkrkbrcMJYlChsuEUNRxeZSeykAdl2c05GR2SsxDnG5rK0XhYYU2rQTN9WLk9uIzoyK8Uelnh2U7d1RRuZRdyMZuoJ8xvFFmp3xk0uoWzZwxb+yIOjYPqaUcM996r83fheI2D1p9eGM99dRTTz0Pg1oZaKtWrapzx25ubnXe5k4++eQTfHx8TPZ/e80BQRD48ssvee+99xgyRBQ9WL16NW5ubvz555+MGjXqvsfwyFEXsv30V1wruoaNwpYbme2RSyW80MaR5y9sF9t0e4uz18WX8Eau1tjd/pJo6wFebSDtDC95xDFo8Ihb62Jves8Ce4Hy4c/8V0XUkTQEg4BHoB1OXtbsWCyGXLbo0x+54u6Xo0Lx7w9rLE8qRNALmPnbVTJGBa2WjA/nI/dshWX7pkjNqpeMr8CiVWuQydBev47mehqa62IoXv5PXwPgMm0atn1EhU+rDh6UHk+nYHMimtRiHB4PpOymwWzmb4fcvub9KX1scH05jPzfrqCOy0cdk4c6Jk80VmyUxjBAmx4+2PZpiEQqwbqDJ5rUYkpPZVAWmY0uR0XhtiQKd17DoqkTyga3Fck1CBTtTQEBrNq5G4s0Kzys0KaXUnYpB+v2Yv6Y+rbwxkpeP5kEiyZOWDRxQldQTtmZDNRx+Vh39UIiM22r9La+aaCVYNncxbTvIAfMAx2QWikwlGpRxxegz1cDjya80Xg8Egn2jweSvz4Oi+YulY6hnkeHws0Sy9ZuSM1lj/QaqKeeeuqp5/8PtTLQxo0b97DHUSWbN28mIiKCESNGcPDgQby8vHjppZeYMGECAElJSWRkZNC7d2/jNnZ2drRv357jx49Xa6CVl5dTXn4rnKmoSDR2tFotWm3dcmUeOOtGs0x3FZQKOtv2Zr3BnMaeNryo3I6tpIw4gzcSx+6cPieGa7VqYFdpzNKgAcjSzjDO4TJ6c6lxvTxmCxJA16g/wt9wnHqdgajDonelSRcPUuNiyEi4glQup3GXHn//uX8E6PPV5Hx3EQwgczDDorUr5q1ckNko0d4opeDngygCJqJUmIO5jPJCFVLLu9ymZkrMmjah/OIlCvedAZ0jgrYUQ+ENbAYPwvbZ8cZza9W/ARI7JSU7kyk7l4UmoxShXAybMwt1qt13YCbBbmwwVtkqVGezUJ3PRl+oESXHlVJshwVi3tQRnV4HYtdI3MyxHuyLZV8f1JdyUZ3JRJdWiupiDqqbtdduR+Fni1X/BsYClGahTmjTSyk9l4lZK7GumzpOzElTBNjUPG4rKRbdPLHoJoY23tlW5iFOVpRfL0Kr1SJo9MZC0HJ/G3QGHWbNnVCdyKD0bAYSc7Gsg9TV4tFes5ZS7MeHVHkM9TxabIaKE4X/5u/h3zz2eh49ubm5hISEcOrUKXx9ff/u4dTzH+LatWv4+flx/vx5WrZs+cD6Xbp0KVu3buWvv/56YH0+Sv4elYhacvXqVZYsWcL06dN55513OH36NP/73/9QKpWMGzeOjIwMoLK3zs3NzbiuKj7++GNmz55dafmuXbuwtPx7PEsAzsXR5OWc55qrM3Z6PdPOfU+yxAZbnTfW55YB8JVuGKXrj5JSKgEkyPJT2LYt2aQfa7UVvQCSDpK5SJTSl2DAqyAKA1J2XZOgTd32aA8OKEuXoyqyQGpmIPbGabL+PAiApbcvB44ee+Tj+TtwzFbiZxBDpPT55ZTsuU7xnhTKzQ2Yq2WAIxIFCBhABTErj5AccPf8T2dHRxyBrEOXsHPphj43AVXDhsS3b4+wfXul9jYhcvyvWMMNMVzPIBE4lHYWfebd88PuRNIc7POUWBfJyXZXo04+Acl32agBWDjJcMo2Q6Ex9QZpzAxkOOWj33XNuExRLqE59miTi9nzxw4EiUBolgMCAgevnkZ/ve7jrsC8TEZT7FAnF7Jt6zZsCxQ00ttQbqZn16n9IAHLEhkh2FEWlYPaXI8lci5nXCF/2+V73m899fyd1CWv/L/E+PHj+fHHHwGQy+V4e3szYsQI5syZ88DSIg4ePMjs2bOJjIxErVbj5eVFp06d+O6771AqlYAYAfTdd9+xcuVKoqKikMvlBAYGMnbsWCZOnIilpSUffPABs2fP5sUXX2Tp0qXG/iMjIwkLCyMpKQlfX1/jC66LiwuJiYnY2NgY27Zs2ZKhQ4fywQcfVDr+CiIiItixY0eNx/TRRx8xZMgQE+Ps9OnTvP3225w9exaJREK7du1YsGABLVq0ACAuLo5JkyYRHR1NYWEhnp6ejBkzhlmzZtUYDfO///2Po0ePcvnyZUJCQoiMjDRZX3Fe7sTS0tKYYrN7926mTJlCRkYGQ4YMYeXKlcZzX1hYSNu2bdm9ezcNGzas8bjryunTpxkyZAg3btzgxo0bBAQEUFhYaNz338Hy5ctZu3Yt586do7i4mPz8fOzt7e+rz4EDBzJkyBAmTpzIxIkT8fb2ZubMmQ9mwLXgwoULzJ8/nyNHjpCTk4Ovry+TJk3ilVdeMbZ57rnn+PDDDzl8+DBdutQsuPZP5B9toBkMBtq0acO8efMACAsL4/LlyyxduvS+vHozZswwKbRdVFSEj48Pffv2xdbWtoYtHyKCgPTnxYy0E/f/jN4SD0Maa5QfkSdricKgotguiO2Z7bAuUFKuMwAGnh3cFV+nymE2wnerkWZF4V1w0nSFfzf6PDbyERxQZTZ/cQEoomVPX5p2ceD7DT8A0H/c83g0avy3jOlRU7T1GqqEDCzauKJoaIPqTBba5GLM1TIEQY8u9QxSi2yc3nqTgpXROGeZ02hwK5S+NV+Xpba2pB84iKVGNP4EbTYhP/5Ac6fqxST0BeUUrI1Dl16GRVNnIh7r+ECP9X5oUcWy/IJoNFeL6ODYHJmNgqJzV1F62xAx5P7GLRgEsmNOI9MY6Nu2O2Wns1CRgX1zDwYMFAV6BEEgN/0C5KqxLBMfm20jOpnkvtVTz7+JisiR/4/069ePVatWodVqOXv2LOPGjUMikfDJJ5/cd9/R0dH069ePl19+ma+//hoLCwvi4+PZsGEDer3e2O7pp5/mjz/+4L333uPbb7/FxcWFCxcu8OWXX+Lr68vQoUMBMDc3Z+XKlbz22ms0atSoxn0XFxezcOHCKo2Xqo6/ArO7hNKXlZWxcuVKdu7caVxWUlJCv379eOyxx1i8eDE6nY5Zs2YRERHB9evXUSgUKBQKnnnmGVq1aoW9vT0XLlxgwoQJGAwG43tddTz33HOcPHmSixcvVlr3+uuvM2nSJJNlvXr1om3btoD47jhmzBhmzJhBREQETzzxBMuXL2fq1KkAvP3220yaNOmBG2cAx48fJzxc/N04fPgwbdq0+VuNMxC/v379+tGvXz9mzJhx3/0JgsCJEydYsGABIB7nt99+e9/91oWzZ8/i6urKzz//jI+PD8eOHWPixInIZDLj96xUKhkzZgxff/11vYH2oPHw8KBJkyYmy0JCQtiwYQMA7u7uAGRmZuJxW62ozMzMGt2kZmZmVT6QKh4ofwtXD3Iu8zxXPN0wl5kxYtRf/LXwBQZLjuCafw4Aq77v0nCbNddyxZlPJyslgW52VQtmjFoDCXtAMNxaJpUhDR6I9AEeo06r58DPcaTdJkkOIJNL8Q11pklnTxw9rMhJLSHjahFSqYTQbj5c3PMHeq0WV98AfEKaPVTRj+LDqZRfLcRxVGOkZrKHtp/aoL/psbIIdMCypSu2bT3RZpZSuO0IOV+8B2jw2/QnZn5OaNu5U3oqg+LNSbi90gqJvHrRVdt27UiXyZA5imp/zhNHYHHz/qgOhYsCt5daoorOwyzQHtk/PL/PqpU7mqtFlF/MMeb+mAc7PpB7VuFljSapCEO6Gm3CTcGUxk4mfVuFuVK0J0X8RybB3MMGiay+QHE9/07+C/m894qZmZnx/cHHx4fevXuze/duo4FmMBj45JNPWL58ORkZGQQFBfH+++/zxBNPAKKA2dSpU9m1axclJSV4e3vzzjvv8Oyzz7Jr1y7c3d2NL68AAQEB9OvXz/j/+vXrWbNmDX/++acxfx7A19eXxx57zMR4Dg4OxtXVlXfffZf169fXeFwvv/wyn3/+OVOmTMHVtXoBm9uPvzZs27YNMzMzOnToYFwWGxtLXl4ec+bMwcfHB4BZs2YRGhpKcnIygYGB+Pv74+/vb9ymYcOGHDhwgMM3y8hUx9dfi/nT2dnZVRpo1tbWWFvfEuu5cOEC0dHRRi9jTk4OOTk5vPTSS5ibm/PYY48REyOqRR87dozTp08/NIPi2LFjRgPtyJEjxr9r4vfff2f27NkkJCRgaWlJWFgYmzZtwspK/J37/vvv+eyzz0hISMDR0ZHhw4fXafyvvvoqAAcOHKjz8VRFXFwcgiDQpEkTcnJySEhIoH379jVuU9M9cy8899xzJv/7+/tz/Phx/vjjD6OBBjB48GD69OmDSqXCwsLinvb1d/GPfrsIDw8nLi7OZNmVK1eMsx5+fn64u7uzd+9e4/qioiJOnjxJx47/HG/AXREEOPAxv9iKD5wB/gPJLrPm5fLJfGx4BkEiA58OSEMeY2yHWzM+rRpWFkcw4ugH7SZA+xdvfdq+IIqIPLBhC+z/KZbYEzcozlNTkl9u/BRmq7iw9zrrZp/kj4VnOfKbWPrAr6UL2SnRHN+wDoDWA4c8VONMEASK9l0XxSyicx/afoz70xsQDFWH2wk6A5obooiG0vtWCIrUXEfeig8RNCU4TXoRs5tCOHb9fJFaK9Blqyg+cL3G/UqtrLDu1g+phQNIBKw7hdTYvgKJQoZlC5cq1RT/aVg0cwK5FF22CtXN79I8yOEuW9WOiu9DdUkUMUEKZoH2Jm1uV+xTuFrWG2f11HMbgiBQpi175J/alO2oicuXL3Ps2DETL8fHH3/M6tWrWbp0KVFRUUybNo2xY8dy8KAYlv/+++8THR3N9u3biYmJYcmSJTg7i7mx7u7upKenc+jQoWr3uWbNGoKDg02MswokEgl2dqYqrfPnz2fDhg0mJYaqYvTo0QQGBjJnzpwa2x04cABXV1eCg4OZPHkyubk1/zYePnyY1q1bmywLDg7GycmJlStXotFoUKlUrFy5kpCQkGpz1BISEtixYwfdunWrcX91ZcWKFQQFBRm9JC4uLnh4eLBr1y7Kyso4fPgwoaGhaLVaJk+ezLJly5DJHtxk7ZEjR7C3t8fe3p7ff/+dd999F3t7e5YuXcrXX3+Nvb098+fPr3Lb9PR0Ro8ezXPPPUdMTAwHDhxg2LBhxut6yZIlTJkyhYkTJ3Lp0iU2b95MYGCgcfvx48fTvXv3B3YsNTFo0CDs7e1p06YNhYWFODg44Ofnh16vx9vbu8awyZrumarw9fU1huXWlsLCQhwdHU2WtWnTBp1Ox8mTJ6vZ6p9LnT1ohYWF6PX6SichLy8PuVz+QEMEp02bRqdOnZg3bx4jR47k1KlTLF++nOXLlwPig+zVV19l7ty5NGrUyCiz7+npaQwP+FeQdJDstJPs9vECYFTwKCKTCgAJkV5jkDzzIcjNQSplRGsfFu6KQ601mNY/+xs4uyOZuJNpaIrXYW5loOvYqbj6ioVjS/LLiTmWTvKlHNJveiQAGjaVsOWL+QgGA0269iSky8OV+zeUahFUotCE+kr+Q5XF1pdqyVoUidRMhuvLYZUUGrWZZaATkFjIkTmZo8vPp3DjnxT8+iv63FyUAQE4vfCCsb3UUoH94ADy1sVStP86Fi1cULhUH1Ln8Nx0Cn5PROFti0Tx93oKHwZSczkWTRxFURG9gMRcbmLo3g8VBavVcTfl9auosSV3skDZwAZNSrFJMe966qkHVDoV7dfWPIv+MDg55iSWirqFGm/ZsgVra2t0Oh3l5eVIpVKjR6K8vJx58+axZ88e40Svv78/R44cYdmyZXTr1o2UlBTCwsJo00Ysg3K7QTJixAh27txJt27dcHd3p0OHDvTq1YtnnnnG+H4UHx9PcHDti6y3atWKkSNH8tZbb5lMSN+JRCJh/vz5DB48mGnTphEQEFCpTb9+/Rg2bBh+fn4kJibyzjvv0L9/f44fP16t0ZKcnIynp6fJMhsbGw4cOMDQoUP58MMPAWjUqBE7d+5ELjd9dnbq1Ilz585RXl7OxIkT72pA1gW1Ws2aNWt4++23jcskEgnr169n2rRpvPLKKwwYMIDnnnuO+fPn06NHD8zNzQkPDycnJ4eXX37ZxONyL7Rp04bIyEhiY2MZM2YMZ8+eJS8vz3jc5ubm1Rov6enp6HQ6hg0bZnQ+NG/e3Lh+7ty5vPbaaya5VRWhnCBGmhkMt0VKPURWrFiBWq1m0qRJdOjQgfHjxzNz5kzs7e1N0oaqoqZ7pioCAgJqNODu5NixY/z6669s3brVZLmlpSV2dnYkJ98tMf6fR50NtFGjRjF48GBeeuklk+Xr169n8+bNbNv24MQn2rZty8aNG5kxYwZz5szBz8+PL7/8kqeeesrY5s0336S0tJSJEydSUFBA586d2bFjx7+nBpogwP6P+d3GGp1EQkuXloQ4hfDzoUsAtPSxBwt7Y3M7SwWv9g5i/enrDAp9cN6wupJ4PouTm65i0FxB0GejKoLdyz6ix/iJtOjTH9eGtvi3dKEkX03MsXSunMrEzgWOrf+S8rJSPIOb0Gfiyw+9npkuS2X8Wx2fj2AQHlph2cJtSejz1OgB7Y2SSsaD5noxAHJ7uPHa6xTv3m1U05Ta2OD50Vykd8SqW4Q6Y37OAXVcPvm/x2Pd2fRH8nbUUaJxYdbwb8qjfARYhrkaVR/NG9k/MLn5O7+r6jxztr0bkv9HPJat7r+MSD311PP30KNHD5YsWUJpaSlffPEFcrmc4cOHA6KXp6ysjD43S5NUoNFoCAsLA2Dy5MkMHz6cc+fO0bdvX4YOHUqnTp0AkMlkrFq1irlz57Jv3z5OnjzJvHnz+OSTTzh16hQeHh735PWbO3cuISEh7Nq1q8bwxYiICDp37sz777/P2rVrK62/Xd26efPmhIaGEhAQwIEDB+jVq1eVfapUqkrvVCqViueff57w8HDWrVuHXq9n4cKFDBw4kNOnT5uEk/36668UFxdz4cIF3njjDRYuXMibb75Z11NQJRs3bqS4uLiSLkHnzp05ffq08f8rV66wevVqzp8/T9euXXnllVfo378/zZo1o2vXroSGhlbqu3///sZwzIYNGxIVFVXlGMzNzfH19WX9+vX0798fPz8/jh07RpcuXWjcuOb8+hYtWtCrVy+aN29OREQEffv25YknnsDBwYGsrCxu3LhR7fcCorf3UeHu7o5Wq+XEiRN88803+Pr6cvz4cVatWnVXg6ume6YqapqIuJPLly8zZMgQZs2aRd++fSutt7Cw+FeKItXZQDt58iSff/55peXdu3fn3XfffSCDup1BgwYxaNCgatdLJBLmzJnzQGdkHilX96O9foLfK7xnjcWH58VU0esU6m1faZNJ3QKY1K3yzNijIjulmD2rogFQmkWjLQNbF1eKsrPYu3IxmVfj6fXcZORKJdYO5rQd6EerCG82fDSTgox0bF1cGfLaO8gfQQ6ENvvWTWko0aJNL0XpZV3DFveGOrGAsrOZt/6Py6/WQCs9spXyS+JEhnnTptiPHIntwIHIrCt7ZSQSCfZDAsn84iya5CLyku+e2K9s+GC8Sv9EzIMckFrKMZTpMG/04DzIMgczpFZyDKU6436q27/H2+0e2H7rqee/goXcgpNjHn0YkYW87nklVlZWxjCx77//nhYtWrBy5Uqef/55SkrEMPStW7fi5eVlsl1F7nr//v1JTk5m27Zt7N69m169ejFlyhQWLlxobOvl5cXTTz/N008/zYcffkhQUBBLly5l9uzZBAUFERsbW6cxBwQEMGHCBN5++21WrlxZY9v58+fTsWNH3njjjbv26+/vj7OzMwkJCdUaAs7OzuTnm+aZr127lmvXrnH8+HGkUqlxmYODA5s2bTIxBCty1Jo0aYJer2fixIm89tprDyTMcMWKFQwaNOiutXdffPFFPvvsMwwGA+fPn2fEiBFYWlrSrVs3Dh48WKWBtmLFClQqcZK3ppzNiny4Cm/spk2b0Gg0CIKAtbU1Xbp0YXsVasogGvS7d+/m2LFj7Nq1i2+++YZ3332XkydP1smD9LCZN28e8+bNE0OZy8qMkxWlpaVEREQgkUjYvn17tWIctbln7oXo6Gh69erFxIkTee+996psk5eXh4uLy33t5++gzgZaeXm5sTbR7Wi1WuOFXE8tEQQ4MJ/9lhZkyWU4mjvSp2Ef1Fo9Menii3gLH7u7dPJoKS0oZ+vii+g0Blx9VKRcTEEmlzNm7mdEH9rH4bU/cnn/brKuXcWnyS03fW5qCtejL6Ewt2DomzOxtLN/JOPVZZnOmqiv5N+zgaaOz8dQpsMi1NnE8ydoDRRsTABAZmeGvrAcdXw+tr0amGyvSRUNNF12AsrAADznf4JFs6Z33a/c0RyHEUGUHE8Xr5ma2jqYY9G4euXGfzsSmRSHYY1Qx+Vj0fLBPXAlEglKbxvUcflIrRQoPB+8EV9PPf9lJBJJnUMN/wlIpVLeeecdpk+fzpgxY2jSpAlmZmakpKTUmCvl4uLCuHHjGDduHF26dDF6hqrCwcEBDw8PowT8mDFjGDVqFJs2baqUhyYIAkVFRZXy0ABmzpxJQEAAv/zyS43H1K5dO4YNG2YS9lcdqamp5Obmmgit3UlYWBg///yzybKysjKkUqnJb2HF/zWF3BkMBrRaLQaD4b4NtKSkJPbv38/mzZtrbLdy5UocHR157LHHjIZmRR1ArVZroq55O3ca6NURGRmJTqejZcuW7NmzB3d3d7p06cLixYtp3rz5XcUpJBIJ4eHhhIeHM3PmTBo2bMjGjRuZPn06vr6+7N27lx49Hm46yN2YNGkSI0eOZPHixaSmpjJv3jx+++03du3axXfffQfc/XzV5Z6pDVFRUfTs2ZNx48bx0UcfVdkmMTERtVptNCj/TdTZQGvXrh3Lly/nm2++MVm+dOnSSkmk9dyFlONw/SS/eIhqSk8EPYFSpuR8Wj46g4CTlRIv+3+O6oxWo2fbkouUFpTj4G6JpW0kAEEdOmNl70Dbx4bj4uvP1q8WkJWUSFZSomkHEgmDXnkTlwa+j27M2Tdnvzys0KaXor6Sh20Pnzr3oytQk7PqMhjA4qITDiODkJqJt0/R/hR0OSqkNkqcxjUh6+vzaFKKMKh1xjwmQ7neaCwa8q/hOOrZWhlnFViGumAZ+u+bAXoYWDRzxqLZg59ZVPraoY7LxzzY4aGFwdZTTz3/PEaMGMEbb7zBokWLeP3113n99deZNm0aBoOBzp07U1hYyNGjR7G1tWXcuHHMnDmT1q1b07RpU8rLy9myZQshIaIw07Jly4iMjOTxxx8nICAAtVrN6tWriYqKMr43jRw5ko0bNzJ69Gjee+89+vbti4uLC5cuXeKLL77g5ZdfrjKP3s3NjenTp/Ppp5/e9Zg++ugjmjZtapIPVlJSwuzZsxk+fDju7u4kJiby5ptvEhgYSERERLV9RUREMGPGDPLz83FwEKML+vTpwxtvvMGUKVN4+eWXMRgMzJ8/H7lcbjQm1qxZg0KhoHnz5piZmXHmzBlmzJjBk08+afRIVaSx3O5RTEhIoKSkhIyMDFQqlbEOWpMmTUzEXL7/P/bOOyyq4/vD7wILS0eaYAMsVBV7V2IDjRqNxhoRo4nRqLFHTWI3akyMJsYajcafJmqK0VhiLyh2wAJWpFhQRJDOsmV+f6xs3FAExZbvfZ9nn2Tnzsw9c9l177nnzOf8+COurq507NixSNuTkpKYPXs2x44dA3TOso+PD4sWLSIwBvj+yQAA3jpJREFUMJD9+/c/c/ZX9erVOXHiBOXLl6dFixYkJCSQkZFBly5dCuzH+zcnT55k//79BAYG4uzszMmTJ7l//77+8zR9+nSGDh2Ks7MzHTt2JCMjg2PHjjFy5EhAVzbq9u3brFu3rshz3L17l7t373L9uu5B8oULF7C2tqZKlSoF9CSKwt7eHnt7e6Kjo+nduzfVq1fn2rVrBAYGGoiWFEVx35nCaNu2LW+//XaR+wMvXrxImzZtCAoKYuzYsfrax8bGxgbRstDQUKpWrVrofsxXnVI7aLNnz6Zdu3acO3dOHw7fv38/p0+fZs+ePWVu4H8ZceoHrsvlnFaYYiwzpqdnTwDO3XwIgH9lu+e+R6ukCK1g/9pLJMVnoLCU0zbEg41TdDLCdYI66fu5165L8LxvuXhoH2pVnsEc7rXrUaVmwTSC54n6UYqjVfOKpP52lbz4DAPHqaRknbwLjx4K5kQ9QLXkHA7BPiAg4/AtAOzeqoppBStMHM1RJ+egvP5Q70iobmeCAG1uKkKZhmXLFmW3SIkywbpFBYxMjTCv8/yEZCQkJF49TExMGDFiBPPnz2fYsGHMmjULJycn5s6dy40bN7Czs6NevXp8+umngK6+0uTJk4mLi8Pc3JyWLVvqo1qNGjXi6NGjDB06lDt37mBlZYWfnx9//vmnPiInk8n4+eefWblyJT/++CNffPEFJiYm1KhRgwEDBhTrLI0fP55ly5aRm5tb7Jo8PT0ZNGiQXlQNdDev58+f56effuLhw4dUqFCBwMBAZs2aVWwttFq1alGvXj02b97Mhx9+CIC3tzd//fUXM2bMoGnTphgZGVG3bl3+/vtvfTTOxMSEL7/8kqtXryKEwM3NjREjRjBmzBj93GlpaQXUut9//329Yiagj37kF+YGXSRu7dq1DBw4sNhI3KhRoxg3bpyByMnatWsJCQnhu+++Y8KECQaiG0/LoUOHaNWqFaArVN60adMnOmcANjY2HDlyhEWLFpGeno6bmxsLFizQO50hISHk5uaycOFCxo8fj6Ojo77cA+hERhISEoo9R35qbT75dq5Zs4aBAwcCum1K7u7urF27tsh51Go1x44dY8mSJfp1Dh48+IlrhOK/M4URExNDcnJykcd/++037t+/z/r16w2iu25ubsTFxenf//LLL3zwwQclsvFVQyaeYrdqZGQkX331FZGRkZibm1O7dm0mT578xCKKryr56QRpaWkvrlB1xl3EN358YW/NJhtrqlk04c+eujDx2E2R/BFxmzHtPBnV7tW4pif/usGZHXEYGcvoOroOty8d4MiGNTi7V6P/vEWvjCP5ONo8DXemhYEA188bc3/ZOdQPcnEI9sXcr+RpgEKtJXHuKbRZKqzfqEzW2XtoM/KQmRljbGeG+l42Cm97HEJ8kclkPNwWQ2bYHSwbuVCuu+7vl3HkFmk7Y1HdCUd1fTM1joYiM5Jk2iUkJF4OL+V3T+K1ZceOHUyYMIGLFy/q95xJ/Hdwc3NjxowZeoftv0B+CuTVq1cLTRl+1XmqQtV16tRhw4YNZW3L/xZnfyIbDVutdIIOFy/XZF/0Pdr5lify1kMAapfh/rMHdzLZ/v05agVUol6Q25MHPMbV03c5syMOgIB+XrhUs2HndzqRizodOr2Szhmgq2clwMjCBGMrU8w8y6E+nkju1ZRSOWg5F5J1cv3abO4vHIpNp7cR1vVQ3clFfS8bmakRdt2q6a+DmWc5MsPukHs1FSEEMplMLxCiTY3DskVzyTmTkJCQkHht6NSpE9euXeP27dt60Q+J/wZRUVHY2toyYMCAl21KmZKYmMi6deteS+cMnsJB27lzJ8bGxgVC8Lt370ar1RabCyzxCI0Kzq5hn6UFuUaAygl1VjVGbYxgzXuNuHFft5HYvxAFx6LITM1FYSnHxLTwUH/43/Fkpig5szOOmq0qYmpe+J8+5U4Webn/iMA8vJfKgXUXAQvqtK+Cb/MK3Ag/TVrSPRSWVng3a1ViG180+emNJo9qhyk8y5F1PNHAccpHqLRo8zSFFmzOPH4HgLwre1HFx/Ng6SIwlmMV+DEyc09sO1fFxO4fCWKzqrZgIkPzUIn6fg5yZwu9QIgmNRarFoOe15IlJCQkJCSeC6NHj37ZJkg8B/z8/Dh//vzLNqPMadeu3cs24ZkotYM2adKkQiuiCyGYNGmS5KCVhMvbISORP110OdFtK3UkSTgSFvOAAT/qZIor25tjb2la3Cx6bkan8Nf356jkZUeXj+sUiGhlp+dxPTwJAJVSw+UTd6ndulJBs04ksn/tJf17IVTkpa9DaNOwsKuGvUsPNGo3IndvB8CvdXvkZq9uvTnVoxpoJk46oRWzqnZgLEOTqkSdnKMv+qxJzyNpaSTaLBWO79cyqCOWdzuTvIQMkAlUcaGYenhg4uRE9qlTZO5aADIjjM16Ydlwqv66G5kaY+Zui/L6Q3KvpmJkYYImVYkQWjQPE7Bs3vzFXggJCQkJCQkJCYnXhlLnWV27dg1fX98C7d7e3nqFGIkncGoVScbGnHkkVNHbtytL362Hh6MluSqdEkVJo2eqPA2Hfr6M0ApuXkrl1pXUAn2ij91BqxYYmegciIuHbxUolKlRazm1LRYAS1tTbBwVyE0uIbS6emzZD2PY+d18VgwbSOy5cJDJqNP+zada/osiP4Imd9Y5YkZmxpi565wv5VXddRIqDcnrotA8VCJUWh6si0ad8s/m6/zoGepbCGU6Np074bbuJ6ru3In9wIGA4OEvG0ldb5jym19HK/dqKnm3dHV1tJn3UHh6YOLw35XBl5CQkJCQkJCQeDZK7aDZ2tpy48aNAu3Xr1/H0rJgoV2Jf3EvGuKPstPKCmQgct1pXKkGdhamrA5pgM0jp61OZbsSTXdmRyzpyf84FKf/ijVwvrQaLVFHbgPQvEcN5GbGpN7N5va/HLnLxxPJSMnFwtaU/rOa0mdqfYT6LADNer1Lkx59sCpnT056GgiBh3897FyKrpvyKqC+bxhBA0PHSQhByq9XUd3KxMjCBLmLBdosFck/RaFVqtFmq8iOvK/rf3EHAJaNdEWKzap6UH7SRJzHjwfg3ty5ZIaGFjiP8kYaylidk6tNjcWyhaTeKCEhISEhISEhUTSldtC6du3K6NGjiYn5p8bV9evXGTduHG+99VaZGvef5PQqAP6000l5uxo1x+hRzaWqTlZseL8JH7T0oHfDJ2/CTb6VScTem4BOvMNYbkRiTBq3Lv/jfMWdf0BmqhKFlRzfFq54NdHVXLtw6La+j0at5cyuOADqBblhYmrM+b1/k/UwFRsnZxp1fYfmvfrzwZI1dJ0whXpvdqXt4I+e/Vo8R4RW/FMDzfmf4qlmnrqaH8obaaTviSfnfDIYybB/1weH92piZC1HfS+blF+ukHX6Lqi1GDvIUcWGIzMzQ+Hvb3Ae+0HvYdu9O2i13B4zFuWjKLJJeQuMbUxBrSXrlK4+hyY1HitJXl9CQkJCQkJCQqIYSu2gzZ8/H0tLS7y9vfHw8MDDwwMfHx8cHByeqSL4/wS56XB+E9flcmKMlAhhTEPnNwy61Kpky2edfLFWFBSreBytVnBogy61sWpdJ2q2qohfS92etlOPRdEuPKrR5du8AiZyY2oG6Cq9x567T8ajVL5LYYlkpiixsDXFr0UFVHlKTm/7DYDGb/fC2ERni5GxMdUbNKZ1yAfYOpcvm2vynNA8VIJaC8YyjMv9s09O7mKBkbUpQqUl46DOuS33dnUU1ewwsTXDcYAfmBiRezmFtN1xABib6/bvmdeti5Gp4b5AmUyG6/RpWDRogDYzk5vDPkKdmopMJsPsURRN5OhEV0TuXczr1HnOK5eQkJCQkJCQkHideaoUx7CwMHbs2MFHH33EuHHj2L9/PwcOHMDOzu45mPgfInID5GWyw0kXHVNnelGvUkGxjpIQdeQ292LTkSuMadnLE9BFv4zlRty9kcatS6mk3s3i1uVUZDLwa6Vz3hwqWFHR0w4hICr0NhqVlrOPomf1O+RHz3Y9ip6Vp1JmNZLXRSNUmmdf/wtEla/g6GiOzOgf0RSZTKZPPwSwalERy4Yu+vemla2x76m7nmhBpjAmL+YIABaNCi9mKTM1peLi75BXrozq5k1uDfsIdUqKwXmEVo3CrxIyefGOt4SEhISEhISExP82T1WMSSaTERgYyIQJExgxYoS+KrlEMWTeh0Pz0AI7LHV7otRpdfB1sUar0ZZuqlQlx//UpZg26VoNq3JmAFjamlGzpS5Cdmr7DS4c1qUxutVyxMbhn31YNQN0TmH00TtcPHKbzFQllram+LaogEqZy6mtuuhZkzd7kX38LrnRD0jff/Pp1/4MiFJem3zUSQXTG/Ox8HcCQOHrgO2bHoUet2mvqxVn1bQC2adOAP/sPysMk3LlqLxsKUbW1uRERhL7zjsI9V145Btq025h1aLZU61FQkJCQkJCQkLif4enKlSdlZXF4cOHSUhIIC8vz+DYxx9/XCaG/efYPRlyHxJewZdEdQZCY4Z5th8nv7vAJQcFb4+vr9+LVhRZD5VcCksk6uhtVLkaynvY6FMW86kbVIWLobe5eyOdpDhd7a1abxj28ajjiKWtKVlpeYT9rtszVa+DOyZyY85s30Z22kNsncvj4erPQ64BkHHkFhZ1nJC7vBghGE2WipRNV8iLS9NJ31exefKgx/inBpp5gWMKz3K4Tm6EkbWpQXTtcWzaVsGiQXnUSQloHjxAplCgqF272HOaVa+O+88buDViJHnx8dx8Lxib7l+jzTFDkxqLpVT/TEJCQkLiNeTBgwf4+Phw6tQp3N3dX7Y5Ev8hDh06ROvWrUlNTS3TTLzly5ezY8cO/vrrrzKb80VS6ghaREQE1atXp2/fvowYMYLZs2czevRoPv30UxYtWvQcTPwPcH0fXPgVZEZsr1ofAFVGLVoobMlOy+PujXSun7lX5PDbV1LZuew8P30axsltN8hMUWJuLad1f+8CTp2lrRk1W+kcMq1WYFfegsre9gZ9jI2N8Husj6WdGb4tXFEpczm97XcAGnfvjeqRg4eRDLSC1D+uIbSG8vwlRXUvy0C+vjjybmeStDgC5dVURN4/e8VKdb58iX2nghE0AGNbsyKds3xMbM3IPn0aAPO6dQrsPysMsxo1cP91M1YBAQilkqxDP6LNug+qWEyfMp1VQkJCQqJsGDhwIDKZDJlMhlwux8PDg08++YTc3JL9PpWEw4cP06ZNG+zt7bGwsKBGjRqEhIQYPNAWQrBy5UoaN26MlZUVdnZ2NGjQgEWLFpGdrfv9mj59OjKZjKFDhxrMHxkZiUwmIy4uDoC4uDhkMhnOzs5kZGQY9K1Tpw7Tp08v1M6hQ4cik8lKdO/2xRdf0LVrVwPn7PTp07Rt2xY7OzvKlStHUFAQ586dMxh3/vx5WrZsiUKhoHLlysyfP7/Y85w7d46+fftSuXJlzM3N8fHx4dtvvy3Qb8mSJfj4+GBubo6Xlxfr1q0zOL537148PT2xsbEhODjY4NqnpaXh6elJfHz8E9ddWk6fPk2FCrotJXfu3MHc3LxAIONlIYSgY8eOyGQy/vzzz2eay8/Pjz179gAQGBhY4Po/b3Jzcxk4cCC1atXCxMSEbt26FegzaNAgwsPDCX1MYft1otQO2pgxY+jSpQupqamYm5tz4sQJ4uPjqV+/viQSUhh52bB9LADKhoPZkxQOgDqtLtXyjPXdTu+IQ1uI85MQ9YA/F0YQey4ZoRW4VrOl7UAfgr9ohkNFq0JPWTewCiZy3Z+2ZquKhToivi0qYGSsa6/fwQ0TuTFHNqzVRc/Ku+Dbsg3KGzp5eLsuVZGZGZOXkKFXJCwNuVdTufdtOEnLIhHq4lMWs8LvkbTsHJqHSowfpW7mXk4psXOXT36Ko0khKY6lIfuUzkErLr3x3xjb2FBp2VIcP/oIdWIEWXs/w6J+9WeyQ0JCQkKibOjQoQOJiYncuHGDhQsXsmLFCqZNm1Ymc0dHR9OhQwcaNGjAkSNHuHDhAosXL8bU1BSN5p+93MHBwYwePZquXbty8OBBIiMjmTJlClu3btXf+AIoFApWr17NtWvXnnjujIyMEt+HbdmyhRMnTuidieLIzs5m9erVDB48WN+WmZlJhw4dqFKlCidPnuTo0aNYW1sTFBSESqUCID09ncDAQNzc3Dh79ixfffUV06dPZ+XKlUWe6+zZszg7O7N+/XqioqL47LPPmDx5Mt9//72+z7Jly5g8eTLTp08nKiqKGTNmMHz4cH2kRKvV0q9fP4YOHcrx48c5c+aMwTknTZrE0KFDcXNzK9G1Kg3Hjx+nefPmAISGhtKgQQNMS/Bw90WwaNEiZLLiH0yXhIcPH3L16lWaNGmCRqMxWPOLQqPRYG5uzscff0y7du0K7WNqakq/fv347rvvXqhtZUWpHbTIyEjGjRuHkZERxsbGKJVK/VORTz/99HnY+HpzZD48jAebioR6BpChykAuyiHL8sA8RfePmLHciIf3srl22jCKpsrTcPiXKwB4+DvSZ2ojuk+oj3cTV+SmxgVOlY+lrRmtg73xbVEB35aF/+NraWtGQF8var1RCd/mFYjcvYPI3dsBaB3yAWRrdXXEZLo9WbaBun/I0v6ORZNe8qdBqqRsHvx8CbSgzVDpnb5/I4Tg4fYbpG6+CmotCm97yn9cD7PqdiAg62Riic+pyVKhzdJdWxPHgimOJUUIQfapUwBYNG5cqrEyIyOcPh5JpWVLse7QAfuBIU9th4SEhIRE2WFmZoaLiwuVK1emW7dutGvXjr179+qPa7Va5s6di4eHB+bm5vj7+/Pbb7/pj6empvLuu+/i5OSEubk5NWrUYM2aNQDs2bMHFxcX5s+fT82aNalWrRodOnTghx9+wNxc93u0efNmNmzYwC+//MKnn35Kw4YNcXd3p2vXrhw4cIDWrVvrz+Xl5UXr1q357LPPnriukSNH8s0335CUlFRsv9u3bzNy5Eg2bNiAvATCVTt37sTMzIwmTZro2y5fvkxKSgozZ87Ey8sLPz8/pk2bxr179/SRqQ0bNpCXl8ePP/6In58fffr04eOPP+abb74p8lyDBg3i22+/JSAggKpVq9K/f3/ee+89/vjjD32f//u//+PDDz+kd+/eVK1alT59+jBkyBC+/PJLAJKTk0lOTuajjz7Cz8+Pt956i0uXLgEQFhbG6dOnGTVq1BPX/TSEhYXpnZWjR4+WyHH57bffqFWrFubm5jg4ONCuXTuysrL0x/Ovn5mZGa6urowYMaLUdkVGRrJgwQJ+/PHHUo/9NydOnMDPzw8bGxsiIyOxtLSkWrVqxY6Jj4+nS5culCtXDktLS/z8/Ni5c+dT22BpacmyZcv44IMPcHFxKbJfly5d2LZtGzk5OU99rpdFqR00uVyOkZFumLOzMwkJCYBO3fHmzZcjJPHKci8KwhYDkNp+OgvOLQVAk1EHD5UJaATWDgoavOkOwJmdcQaCIflFqK3KmdHuPV8cKhQeMSsMz0YutO7vXawj59uiAq36eHLz0jkOrF0BQIu+IVSr3xhl7EMA5K6WGFnIsWxaAXklK0Suhod/xRQ55+NoHhV9Frka/SctJ/pBoX2VN9LIPKoTNbFuUxmHAb4YmZtg1VRXDDvr9F2EqmSCIepk3RfR2NYMI7Oi1/8k8q5fR5OSgkyhwLxmzaeaw7p1ayotWiilN0pISPynEUKgzc5+4a/8kjJPy8WLFwkLCzOIcsydO5d169axfPlyoqKiGDNmDP379+fw4cMATJkyhejoaHbt2sWlS5dYtmwZjo6OALi4uJCYmMiRI0eKPOeGDRvw8vKia9euBY7JZDJsbW0N2ubNm8fvv//OmTNnil1L3759qV69OjNnziyyj1arJTg4mAkTJuDn51fsfPmEhoZSv359gzYvLy8cHBxYvXo1eXl55OTksHr1anx8fPRpkMePH6dVq1YG1zYoKIgrV66QmppKSUlLS8Pe/p+tGkqlEoVCYdDH3NycU6dOoVKpcHJywtXVlT179pCdnU1oaCi1a9dGpVIxbNgwVqxYgbHx098b/JujR49iZ2eHnZ0dv/32G5999hl2dnYsX76c7777Djs7O+bNm1fo2MTERPr27cugQYO4dOkShw4donv37vrP9bJlyxg+fDhDhgzhwoULbNu2jerV/8nIGThwIG+88Uax9mVnZ9OvXz+WLFlSrDPzJGrXro2dnR3du3cnKioKOzs7WrVqRXJyMnZ2dtQuZp/+8OHDUSqV+qjyl19+iZVV0fe0MpmMtWvXPrWt+TRo0AC1Ws3Jkyefea4XTalFQurWrcvp06epUaMGAQEBTJ06leTkZP7v//6Pmk95E/ufRAj4azRo1ai83mTM7Z3cyryFi0UFrl9tQXO17tJX9XeidutKnNt3Ux9F82rialCEulUfT0wVT6Xnoic7PY39Py7H1smZWm0CKeeq24P24PZNti+ch9Bq8W3VhkZd3wHQR7rMqtoBIDOSUa57DZK+jyDnQjI5l1Mw/9feNoPlq7U8WH8JzYNcjMuZYdPOjdRfr5IT/QC7t6oVSLvMjtA98bNoUB7bQHd9u8LbAWNbMzRpSrLP38eyvmH9tazweyivPcT2TQ+MrXU/AuqkRwIhzk8fPQPIyo+e1auL7BVJUZCQkJB4FRE5OVypV//JHcsYr/CzyCxKl8q+fft2rKysUKvVKJVKjIyM9Cl0SqWSOXPmsG/fPpo2bQpA1apVOXr0KCtWrCAgIICEhATq1q1LgwYNAAz2ZfXs2ZPdu3cTEBCAi4sLTZo0oW3btgwYMAAbG53Y1bVr1/Dy8iqxvfXq1aNXr15MnDiR/fv3F9lPJpMxb948unTpwpgxYwqNanz55ZeYmJiUStAtPj6+QCqktbU1hw4dolu3bsyaNQuAGjVqsHv3bkxMdPcrd+/excPDUCm5fPny+mPlypXjSYSFhbFp0yZ27NihbwsKCmLVqlV069aNevXqcfbsWVatWoVKpSI5ORlXV1c2b97MmDFjGDVqFG+++SaDBg1i3rx5tG7dGoVCQfPmzUlOTmbkyJFPFZF6nAYNGhAZGcnly5fp168fZ8+eJSUlhWbNmhEeHo5CoShS/CIxMRG1Wk337t31KZe1atXSH589ezbjxo0ziPg1bPhPyR9XV1e02uIfXo8ZM4ZmzZoV+kCgNOzcuRO1Wk3nzp0ZPXo07dq1Y9CgQXTo0IFevXrp/+6FkZCQQI8ePfRrq1q1arHn8vLyKvCg4mmwsLDA1tb2uew3fN6UOoI2Z84cXF11UY0vvviCcuXKMWzYMO7fv19sXvH/HPei4NYphImCWa4VOXvvLFZyKwZWm4VMbUkNte7pTdW6jpgqTKjTXlcb7fTOODRqrUERao9HsvDPQsSubVw9Hsrpbb/z4+gP+XXWp0QfOcCf82eizM6igpcv7YeM1OcnK2PyHbR/viCmFaywaqFz7B7+eR1tXuG10YQQPNwaQ15sGjIzYxxD/LDwd0JmZow2PY+8W4abmIVKQ86FZAAs6xk6YDJjGZZNdE98Mk8YpjnmXEwmdfNVsiOSeLAuWh9hU91/JLFfhEBISck++chBa1S69EYJCQkJiVeX1q1bExkZycmTJwkJCeG9996jR48eAFy/fp3s7Gzat2+PlZWV/rVu3TpiYnTZI8OGDWPjxo3UqVOHTz75hLCwMP3cxsbGrFmzhlu3bjF//nwqVqzInDlz8PPzIzFR9xv2NFG/2bNnExoaarA/rTCCgoJo0aIFU6ZMKXDs7NmzfPvtt6xdu7ZUe5FycnIKRKxycnIYPHgwzZs358SJExw7doyaNWvSqVOnMksnu3jxIl27dmXatGkEBgbq26dMmULHjh1p0qQJcrmcrl27EhKi20aQn+HVokULTp8+TWxsLEuWLCE2NpZ169Yxe/ZsgoODGTJkCKGhocycOZPz588Xev6OHTvq//7FRRsVCgXu7u6cP3+ejh074uHhweXLl2nZsiXe3t64u7sX6aD5+/vTtm1batWqRc+ePfnhhx/00cWkpCTu3LlD27Ztizx3frS3KLZt28aBAwfKRMSvUqVKKBQKYmJi6NOnD66urpw+fZq+ffvi7u5OpWIyhT7++GNmz55N8+bNmTZtWpHXPJ/Lly/z9ttvP7PNoIuu5gvvvE6UOiyT/8QIdCmOf//9d5ka9J8hRveUa52bH1vid2MkM+KrgK84e6kcldQPMNWCwkqOSzU7AGq9UYnIvTdJS8ph+/fnChShfhaEEFw6eggAJzcP7ifEkXDxPAkXdV8QGydnuo77FJNHueiadKUuTVAGZu6G8vY27dzIOZ+M5qGS9L3x2HUq+BQk8+gdsk7raoDZ9/XWS/MrvMqRcz6Z3OgHBrL5OZdSEEoNxnZmmLoXlNO3bOhC+r4EVDczyLuZgWlla/JuZ5KySbc/Dxnk3cwg5ber2PfxKpMImtBq9QqOFqUQCJGQkJD4X0Rmbo5X+NmXct7SYmlpqU8T+/HHH/H399eLYGRmZgKwY8cOKlY0LFFjZqYTrurYsSPx8fHs3LmTvXv30rZtW4YPH24g0FGxYkWCg4MJDg5m1qxZeHp6snz5cmbMmIGnpyeXL18ulc3VqlXjgw8+YNKkSaxevbrYvvPmzaNp06ZMmDDBoD00NJSkpCSqVKmib9NoNIwbN45FixbpVSH/jaOjY4GUxJ9//pm4uDiOHz+ud4p+/vlnypUrx9atW+nTpw8uLi7cu2e4tz7//ZNS7aKjo2nbti1Dhgzh888/Nzhmbm7Ojz/+yIoVK7h37x6urq6sXLkSa2trnJwKf6D94YcfsmDBArRaLREREfTs2RMLCwsCAgI4fPhwoel5q1at0jubxe3Vy0/Vy4/Gbt26lby8PIQQWFlZ0bJlS3bt2lXoWGNjY/bu3UtYWBh79uxh8eLFfPbZZ5w8eVKfNvssHDhwgJiYmAIOYo8ePWjZsiWHDh0q0TxDhw5l/fr1aLValEolLi4uun362dn4+PgAur/Z45+tx3n//fcJCgpix44d7Nmzh7lz57JgwQJGjhz5LMsrESkpKUV+Ll5lnqpQtUQJuL6PQ+bmLNDeB+CThp/QomILou6kUV2li5551HbUy+SbKkyoG6j7YN+6rPuHsGm3f4pQPwt3rl4mLekecoU5fWd9xQffr6bpO32xsnfA3NqGbp9MxcLWTt8/P71RXsEKIwvDf5SMTI2xe1v3w5Z57DZ5tzMNjudcTiFt5w0AbN+sapAGae7noOsTZbgPTZ/eWMe5UMVJYytTLGrrvlyZx++gSc/jwboohEqLWQ07HAfVBCMZOefuk3Hg5mM10J4+gqa8fh1Naioyc3PMa0mpuxISEhLFIZPJMLKweOGvZ1WlMzIy4tNPP+Xzzz8nJycHX19fzMzMSEhIoHr16gavypUr68c5OTkREhLC+vXrWbRoUbEZROXKlcPV1VUv/NCvXz+uXr3K1q1bC/QVQpCWVriY1tSpU7l69SobN24sdk2NGjWie/fuTJo0yaA9ODiY8+fPExkZqX9VqFCBCRMmsHv37iLnq1u3LtHR0QZt2dnZGBkZGVz//Pf5KXdNmzblyJEjelVH0Mnfe3l5FZveGBUVRevWrQkJCeGLL74osp9cLqdSpUoYGxuzceNGOnfurHcWH2f16tXY29vz1ltv6ZU0821SqVQG6pqPU7FiRf3fvjjFx8jISM6cOYOxsTH79+8nMjISBwcHNm/eTGRkJKtWrSpyLOi+O82bN2fGjBlERERgamrKli1bsLa2xt3dvdi01icxadKkAn9zgIULF+qFbUrCzJkziYyM1Kc3RkZGMnDgQPr372/wWSqOypUrM3ToUP744w/GjRvHDz/88NTrKikxMTHk5uZSt27d536uskZy0J4Hykyyb57kUycHBNDTsyf9vPsBEHU7nRoq3WX3qGPo0dcMqIjCSucQlfew0dcqe1YuhR4EoEajpsjNFNg4OtOs57sMWbqWoSv+D6cq7obm5+8/8yg8/9fcyx7z2o6ghdQt/9RGU93NIuXnyyDAspELVi0Mv6wKL3swlqG+n4PqUZRLk6Ui94rOIbWoW/QTDstHYiHZ5++T/FMUmrQ8TJzMcejng6JGOey66XLt0/fG6yX5nyXFMe13XT04i3r1kJVA5UpCQkJC4vWkZ8+eGBsbs2TJEqytrRk/fjxjxozhp59+IiYmhvDwcBYvXsxPP/0E6BylrVu3cv36daKioti+fbs+irBixQqGDRvGnj17iImJISoqiokTJxIVFUWXLl0A6NWrF71796Zv377MmTOHM2fOEB8fz/bt22nXrh0HDx4s1M7y5cszduzYEsmGf/HFFxw4cIArV67o2xwcHKhZs6bBSy6X4+LiUuyeuKCgIKKiogyiaO3btyc1NZXhw4dz6dIloqKieO+99zAxMdGrUPbr1w9TU1MGDx5MVFQUmzZt4ttvv2Xs2LH6ebZs2YK3t7f+/cWLF2ndujWBgYGMHTuWu3fvcvfuXe7fv6/vc/XqVdavX8+1a9c4deoUffr04eLFi8yZM6eA7UlJScyePZvFi3WCbeXKlcPHx4dFixZx/Phx9u/f/8wS8dWrV+fhw4eUL1+eFi1aYGpqSkZGBl26dKF69eoFIrGPc/LkSf1nICEhgT/++IP79+/rP0/Tp09nwYIFfPfdd1y7dk3/Wcxn8uTJDBgwoMj5XVxcCvzNAapUqVJgf2BxODs7U716dc6fP69f16VLl3jzzTf1Tmxxe9BGjx7N7t27iY2NJTw8nIMHD+rXWBje3t5s2bKlWJuio6OJjIwkJSWFtLQ0Awc0n9DQUKpWrfpElclXEclBex7EHSVCLiPD2IjyFuWZ3HgyMpmM1Kw81A9ysRFGmJgaUdnb8AmSqcKEgL5euFa3pW2IT4Ei1EWh1Wi4djKM9OSC0roatYorx3VF+nxatjY4JpPJMCpEyegfgZCiN2jadamGTGGM6lYmmWF30GTmkbw2CpGnwayqrU4I5F9PNo0UJpg9SunMV3PMuXAftAK5qyXy8pZFns+0sjXyilagFqhuZ2JkYYLjQD+MzHX/IFg1csWq+SOHUIDMzBgj66dzrB7++ScpP+lyuu1693qqOSQkJCQkXg9MTEwYMWIE8+fPJysri1mzZjFlyhTmzp2Lj48PHTp0YMeOHfobWlNTUyZPnkzt2rVp1aqVPoIDuuhVZmYmQ4cOxc/Pj4CAAE6cOMGff/5JQEAAoPvt/fnnn/nmm2/07bVr12b69Ol07dqVoKCgIm0dP358sep3+Xh6ejJo0KAyKcBdq1Yt6tWrx+bNm/Vt3t7e/PXXX5w/f56mTZvSsmVL7ty5w99//63XKbC1tWXPnj3ExsZSv359xo0bx9SpUxkyZIh+nrS0NAMn8rfffuP+/fusX78eV1dX/etxYQyNRsOCBQvw9/enffv25ObmEhYWZiDWks+oUaMYN26cQXRn7dq1+ojbhAkTDOZ+Wg4dOkSrVq0AXaHypk2bFuuw5GNjY8ORI0d488038fT05PPPP2fBggV07NgRgJCQEBYtWsTSpUvx8/Ojc+fOBjXxEhMT9Wrqz4K7u3uRBc3zuXv3LrGxsTRp0oS8vDxOnDihX/OT0Gg0DB8+XP998vT0ZOnSpUX2v3LlSpGR5HzefPNN6taty19//cWhQ4eoW7dugUjZL7/8wgcffFAiG181ZOJZNWr/A6Snp2Nra0taWppeZemZ2DmBRdc2sdrOlreqvcUXLXQh+qPXkln2/VmaKeVUq+tEhw9rPWGiJ5OTkc72b+eTcCESawcnBi5Ygqn5P5Gj62dOsvWrWVjalWPIsrUYGRUvLatJU5I49xTIoMLUpnoHqDAyTybycMt1ZKbGmDibo7qViYmDAqeP6mBsWbhzlD/GtLI1zsPrkLTsHHnx6di+6YF1q+Kl6LNO3yX192tgJMPp/Zp6hcl8hEbwYF0UuVdSMa1ijfNHdYqdrzCyw8NJCBmIUKlw+PBDnMeMLvUcEhISEq86Zf67J/GfZseOHUyYMIGLFy8WmkYo8fqSnZ2Ng4MDu3bteqJk/+tEVFQUbdq04erVq2WiCPmieTbtdonCub6f048Ujxq5/CMwEXkzlRr5+8/qlGzDolar4cTvGzE2keMb0AZr+382jd6LjWHbgjmk39dtus14cJ9jmzfoCk0/Ij+90bt5wBOdMwBl7GP7z4pxzkAn3pEdnkRefDqqW5nIFMY4hPgV6ZwBmPs68PDP6+TdzEAZl0ZefLquGHYJrodFvfKoHyoxrWJdwDkDneKjfV9vMo7cQlFMCYCiyLt1m1sjRiJUKqzbt8dpVMlliCUkJCQkJP6rdOrUiWvXrnH79m2DvXgSrz8HDx6kTZs2/ynnDHTRxXXr1r2Wzhk8pYO2f/9+9u/fT1JSUoH6C2VRpTyf6dOnM2PGDIM2Ly8vvfpRbm4u48aNY+PGjSiVSoKCgli6dKm+zsZLISWWrNQbRLnpokENXBoghOCnsDjW7r7Oe1ozkIFbTYcSTXcj/AzHf/sFgGOb1lO1fkNqt+1AbmYGe1d+j1qVh115V+p26MzBn34gYtdf+LZsTfmq1VFmZxFzVlec79/pjUVRmLx+Uehqo1Xn3ncRIAQO7/ogdy5+35extalOhTEhg9Rfr+rOVc0OY5sni6HIjGXYti96oy7o0igfr6NWUjSZmdwaNgxNSgpmvj5U+HIeMukpoYSEhISEBKDbRyTx36NTp0506tTpZZtR5rRr1+5lm/BMlNpBmzFjBjNnzqRBgwa4uro+s4LSk/Dz82Pfvn3694/n9I4ZM4YdO3bw66+/Ymtry4gRI+jevTvHjh17rjYVS8x+IhRmaGQyKlpVxMHMhXG/nuOPs7dpnauLLFXwtENhKScnM4Md387HvmIl2gz8sNDprp86DoC5jS056WnEnDlJzJl/KqJ71KlPh4GjydyWQAv/3hw9t4k9Kxfz7hffcO1kGBqVCvuKlXF2L74oYD7KGw+BkjloAPLyljgP8weh2ydWEsz9HMhLyED9QJcbb1HXuUTjnhdCCO5MnITy2jVMnJyovHQpRqUsfCohISEhISEhISFRFpTaQVu+fDlr164lODj4edhTABMTk0LrZaSlpbF69Wp+/vln2rRpA8CaNWvw8fHhxIkTNGnS5IXY9zj3UrOxjt7DaYUuGlTDpg7vLA/j8q10uuSY4p2nSzH0beqKRq3mr2/mcjPqPPHnI6jboQvlXAxVD7UaDTHhumLJXUZPxMKuHBf27ybq8H5yMzNo/HZvmvXqR9rWG+TFplPJrCoKS2uSYmOI+Psvbjwa69uydYkcaXWaUuc0yYpWcCwM00olc8zyUfg5krYrDgCZ3Egvv/+ySN+xk8z9+5HJ5VRaugT5E+qzSEhISEhISEhISDwvSu2g5eXl0axZs+dhS6Fcu3aNChUqoFAoaNq0KXPnzqVKlSqcPXsWlUplEML09vamSpUqHD9+vFgHTalUolQq9e/T09MBXT2Mx+t1lIaff71M5pH72Jt04KaLDaZW59h1xgLLlAwG5ChwUMuQGclo2t0D97r27Fu1lJtR/1RSjzpygMZv9zaY81b0RXIz0lFYWeFczRMjY2Oa9w2h8Tv9yM3MwKqcPXkPcsg6o9uDJpRaAtqHsPvP7zm66f9Q5+UBUL1x8xKtKyviLgAmFSzRGAs0T3ktnoitCcZO5mju52DqVe75nusJaNLSuPdImrfckCGYeHs/9WdAQkJC4nVB+ndOQkJC4tWl1A7a+++/z88//8yUKVOehz0GNG7cmLVr1+Ll5UViYiIzZsygZcuWXLx4kbt372JqalqgOnr58uW5e/dusfPOnTu3wN42gD179mDxlKltt45bYIcxKWp3qt1yp8qdHlyXa6imMsNUK8PIVItD3VwSss5xftEGksN1qYvW7tXJiLtO+J6dJJtaGUS67p/V9ZE7ufJ3EUUkq8RY4KRR6N/n3TVG4VSe3EfCIQonF46ePvNE+63STPC8ZI0MGTfkSZzcufOprkNJKWdrSoUMc6JlN8jZee3JA54Tzr//gV1KCkpnZ05UcIXnvG4JCQmJV4Hs7OyXbYKEhISERBGU2kHLzc1l5cqV7Nu3j9q1ayP/VxHfb775psyMy68DAVC7dm0aN26Mm5sbmzdvxtzc/KnnnTx5skGhxPT0dCpXrkxgYOBTyQ3fjkvn1q5zgAaXcpuIzm2DfY4LPo+CdE5u1rQf7INVOTPizp3lr19WA9Ci30Bqtglk1fD3UGWkU9+7Bi7VPAHdvqi1e/4EoFW3HlSr37jAeTUPlSSfjAQElq0qkHXkDi7Z1vQY9ym/fDYOrUZNsy5vU7NNYLH2qx/kkLLiIkJoUNR2oME7jZ/73sJ8ipf8eL7knD3L7VO6NNCq87/Er379l2iNhISExIsjP3NEQkJCQuLVo9QO2vnz56lTpw6gq/j+OM/7pt7Ozg5PT0+uX79O+/btycvL4+HDhwZRtHv37hW6Z+1xzMzMMDMrqBool8sLOJwl4fjh2wA4mUUT77KXzbYn6WU7EO9LzuRlJ+LgbEPEznAQEHV4H0Joqdm6PY3e6oFMJqN6gyZcPnaYa8ePUtnbT7eO2Bgyku9jYmpGtboNCrUrMzQOtAKz6nbYBXqQffIe2gwVDsZOdBg+hltRF6jZul2xa9Jmq3iw/ioiR4NpZWscenojk//31Qu1eXncnzUbALue72DzEvYsSkhISLwsnua3TkJCQkLixVBqB+3gwYPPw44SkZmZSUxMDMHBwdSvXx+5XM7+/fvp0aMHoKs8npCQQNOmTV+YTUIruH8xBWOgnvkutpjrZPRrKBQknNsEwN1/ZfBV8qlJu/c/0ju0vi1bc/nYYS6HHSEgeDDGJiZcP30CAHf/esjNFPwbdUqufu+ZTbsqyEyMUHiVI+d8MrnRD/DpEIBP84DibddoefDzZdTJORjbmuEwwPd/wjkDeLBqFXkxMRg7OOA8fvzLNkdCQkJCQkJCQkICeMZC1bdu3QKgUqVKZWLMvxk/fjxdunTBzc2NO3fuMG3aNIyNjenbty+2trYMHjyYsWPHYm9vj42NDSNHjqRp06YvRMFx2bllPMh5QLDdhxjnatHKVDgpzhJt6oKxRkba9tOATgbf2aOafpzCyppabQIxNpEjNFpSt1ynnLWDXkY//kIEVes2JOa0bv9Z9YaFryXj4E199MzMXae4aO7nSM75ZHKiHmDbwcOgvzpNServ19Bm/7MxXCg1qO/nIDM1wiHEF2Nr0zK9Ri8DTVoaiZ9/jnW7dth27VpoH2VMDA+WrwCg/OTJGL+mRQwlJCQkJCReBHl5efj6+rJu3boXKhQn8XoTFxeHh4cHERER+uy7kjJlyhTu3bvHypUrn49xRfD3338zadIkwsPDMXpUDzcvLw9PT09+++03GjRo8ELsKHW4RKvVMnPmTGxtbXFzc8PNzQ07OztmzZpVoGj1s3Lr1i369u2Ll5cXvXr1wsHBgRMnTuDk5ATAwoUL6dy5Mz169KBVq1a4uLjwxx9/lKkNhZGck8zSyKVsurKJn7ftAqC6WRjnzI3QyqBlfGUyk5OxdnCi85hJtOgzQP9q0PltzCwsAcg6e4/sM/fIPHiLpl5vA3Ap9BAP793lfkIcMiMjqtZvVOD86pRcss4+ip49VrhZ4VUOjGWo7+egSvpnA7gQgod/XEN5NRXVrUz9S30/B2Rg39sL0wpWz+tyvVDStm4lY+8+7kyaTMahQwWOax4+5OZHHyHy8rBs0QKbTm++eCMlJCQkJF4KAwcORCaTIZPJkMvleHh48Mknn5Cbm1tm5zh8+DBt2rTB3t4eCwsLatSoQUhICHmPlJVB97u8cuVKGjdujJWVFXZ2djRo0IBFixbpBVymT5+OTCZj6NChBvNHRkYik8mIi4sDdDfBMpkMZ2dnMjIyDPrWqVOH6dOn699nZmYyYsQIKlWqhLm5Ob6+vixfvvyJa1q+fDkeHh565+zQoUP66/jv1+nTpw3s+vfrxIkTxZ4rISGBTp06YWFhgbOzMxMmTECtVuuPR0REULduXaysrOjSpQspKSn6Y2q1mvr163Pq0f7ysuT+/fuYmpqSlZWFSqXC0tKShISEMj/P0zJ06FBkMhmLFi16pnk6deqkd4qGDBnCzJkzy8C60nH37l2+/fZbPvvsM33bkSNH6NKlCxUqVEAmk/Hnn3+Wet64uDgGDx6Mh4cH5ubmVKtWjWnTphl8Nzt06IBcLmfDhg36NlNTU8aPH8/EiROfaV2lodQO2meffcb333/PvHnziIiIICIigjlz5rB48eIyV3bcuHEjd+7cQalUcuvWLTZu3Ei1ao9FoxQKlixZQkpKCllZWfzxxx9P3H9WFpy7fw4AY60JZvH2ANQy38dpRzfKpctxu6JLXWw7eCimisLFTIRaS8aBm/r3TsnlqWhRg+unTxB95AAAlX1rYm5lWGNMq1ST+ud1XfSshh1mbv+ImhgpTDCrZgdATtQDfXvOhWRyr6SCsQz7Pl44DPTTv1zGN8Dcz/EZr8irQ2boUd3/CMGdsePIvXpVf0yoVNwaNRpVfALyChWo8OW8FyaGIiEhISHxatChQwcSExO5ceMGCxcuZMWKFUybNq1M5o6OjqZDhw40aNCAI0eOcOHCBRYvXoypqSkajUbfLzg4mNGjR9O1a1cOHjxIZGQkU6ZMYevWrezZs0ffT6FQsHr1aq5de7LacUZGBl9//XWxfcaOHcvff//N+vXruXTpEqNHj2bEiBFs27atyDFCCL7//nsGDx6sb2vWrBmJiYkGr/fffx8PD48CEYZ9+/YZ9KtfjCCXRqOhU6dO5OXlERYWxk8//cTatWuZOnWqvs/7779PmzZtCA8PJy0tjTmPSuUALFiwgObNm9OoUcGH28/K8ePH8ff3x9LSkvDwcOzt7alSpUqZn+dp2LJlCydOnKBChQpP7lwMQghOnDhB8+bNAQgNDdX//4tk1apVNGvWDDe3f4IQWVlZ+Pv7s2TJkqee9/Lly2i1WlasWEFUVBQLFy5k+fLlfPrppwb9Bg4cyHfffWfQ9u6773L06FGioqKe+vylodQO2k8//cSqVasYNmwYtWvXpnbt2nz00Uf88MMPrF279jmY+OoRmRQJQO3sZphpLMg0TeWC4wNO21ei2UUHZAJqNGpWqPJiPlln76F5qMTIWo5lI51T2dT5Layw5dTWXwGo1sBwL50qOYekJedQXtU5W7ZB7gXmzS/6nBOtc9C0OWoe/hUDgPUblbGo44y5t73+ZeLw9GqYrxra3FyyHz25M6tRA212NreGfYT6wQOEENydOYvskycxsrCg0rJlmDi83ALZEhISEhIvHjMzM1xcXKhcuTLdunWjXbt27N27V39cq9Uyd+5c/VN2f39/fvvtN/3x1NRU3n33XZycnDA3N6dGjRqsWbMG0JXrcXFxYf78+dSsWZNq1arRoUMHfvjhB7369ObNm9mwYQO//PILn376KQ0bNsTd3Z2uXbty4MABWrdurT+Xl5cXrVu3NogkFMXIkSP55ptvSEpKKrJPWFgYISEhvPHGG7i7uzNkyBD8/f2LjTidPXuWmJgYOnXqpG8zNTXFxcVF/3JwcGDr1q289957BR58Ojg4GPQtTqBmz549REdHs379eurUqUPHjh2ZNWsWS5Ys0Uc5Ll26xAcffICnpyd9+/bl0qVLANy4cYPVq1fzxRdfPPFaPQ1hYWF6Z+Xo0aMlclwOHTpEo0aNsLS0xM7OjubNmxMfH68//tdff9GwYUMUCgWOjo68/fbbpbbr9u3bjBw5kg0bNjyz+M+VK1cQQuDr60tycjLXr1+nceOi72Wh+O/D07Jx40a6dOli0NaxY0dmz579VNconw4dOrBmzRoCAwOpWrUqb731FuPHjy+QfdelSxfOnDlDTEyMvq1cuXI0b96cjRs3PvX5S0OpHbSUlBS8vb0LtHt7exuEmf/L5Dtore7VA+Ca41mmOluhvXAPp4dmmCgUtH5vSJHjhVqr20MGWAdUxq5rdcxq2GEsM6Fl+R7Itbq9YI/vP8u5nELS9xGok7IxsjbFaUhtTCtZF5jb3NcBZKC6mYEmTUna37FoM1SYOJpj80blsroEryTZZ84icnMxKV+eKut+Qu5WBdXt29wa+TEpq1fz8NdfQSajwoKvUXh5vmxzJSQkJP4zCCFQKTUv/CWEeCa7L168SFhYGKam/+zBnjt3LuvWrWP58uVERUUxZswY+vfvz+HDhwHd3pjo6Gh27drFpUuXWLZsGY6OukwUFxcXEhMTOXLkSJHn3LBhA15eXnQtZJ+0TCbD9l/7oufNm8fvv//OmTPF1zTt27cv1atXLzYlrVmzZmzbto3bt28jhODgwYNcvXqVwMCiy/GEhobi6emJtXXBe458tm3bxoMHD3jvvfcKHHvrrbdwdnamRYsWxUbqQBelqlWrFuXLl9e3BQUFkZ6ero9c+Pv7s3fvXtRqNfv376d27dqALsVv/vz5xdpZWhISErCzs8POzo5vvvmGFStWYGdnx6effsqff/6JnZ0dH330UaFj1Wo13bp1IyAggPPnz3P8+HGGDBmid2B37NjB22+/zZtvvklERAT79+83iPxNnz4dd3f3Yu3TarUEBwczYcIE/Pz8nnqdnTt31qfZpqWlUa5cOTw8PNBoNFSqVKlAzeHHKe77UBju7u4Gabf/JiUlhejo6Be21ystLQ17e3uDtipVqlC+fHlCQ0MN2hs1alSg7XlRapEQf39/vv/++wKhv++//x5/f/8yM+xVJU+TR9SDKMxUFqiSdOIoSTY3MMpWU/eKMwCt+g3E2r7oD+c/0TNTrBq7IDOW4dDPh8TvzmCRakPL8j1INUtGFqUkg1uoH+aSdSIRBJi62eDwrg/GNoULehhbm2Ja2Zq8hAzS/o4jO0L3JM3u7er/eYXGrKO69EbLli0wKVeOysuWEde7Dznh4eSEhwPgPGEC1o89nZSQkJCQeHbUeVpWjjr8ws875NsA5GbGpRqzfft2rKysUKvVKJVKjIyM+P777wFQKpXMmTOHffv26RWhq1atytGjR1mxYgUBAQEkJCRQt25d/Q3k4zfRPXv2ZPfu3QQEBODi4kKTJk1o27YtAwYM0NdZvXbtGl5eXiW2t169evTq1YuJEyeyf//+IvvJZDLmzZtHly5dGDNmjMGWkHwWL17MkCFDqFSpEiYmJhgZGfHDDz/QqlWrIueNj49/Yurc6tWrCQoKMhCNs7Ky0qccGhkZ8fvvv9OtWzf+/PNP3nrrrULnuXv3roFzBujf3717F9Clv3300Ud8/fXXNG/enMmTJ/N///d/WFhY0LBhQ4KCgoiJiaFPnz7Mnj27WLufRIUKFYiMjCQ9PZ0GDRpw8uRJLC0tqVOnDjt27KBKlSpYWRW+hz89PZ20tDQ6d+6s/1v4+Pjoj3/xxRf06dOHGTNm6Nsev492dHQs9G/4OF9++SUmJiZ8/PHHz7JMVq1aRW5uLkOHDqVJkyYMHDiQqVOnYmdnZ1A3uDCK+z4URrVq1Yp14BISEhBCPHO6Zkm4fv06ixcvLjQ1uEKFCgbRzqLanheldtDmz59Pp06dDP7xOn78ODdv3mTnzp1lbuCrRvSDaFRaFQ2S66NFjsY4leqKd2h0cg2mahkaF0v823cscvzje8+s36iETK77YTEyN6H8YH9ufh2GvZkr9riStivWYKxlE1fsOldFZlK8o2Xu50heQobeObOoXx7Fo71p/2Uyj+qeali1aAGAWdWqVFy0kJtDPgSNBtt3emD/3sCXaKGEhISExMumdevWLFu2jKysLBYuXIiJiYm+XM/169fJzs6mffv2BmPy8vKoW7cuAMOGDaNHjx6Eh4cTGBhIt27d9OIZxsbGrFmzhtmzZ3PgwAFOnjzJnDlz+PLLLzl16hSurq5PFfWbPXs2Pj4+7NmzB2dn5yL7BQUF0aJFC6ZMmcLPP/9c4PjixYs5ceIE27Ztw83NjSNHjjB8+HAqVKhAu3btCp0zJycHhaJguZ98bt26xe7du9m8ebNBu6Ojo8HNfcOGDblz5w5fffVVkQ5aSfDz89NHMwEePHjAtGnTOHLkCCNHjqRZs2b88ccfNGzYkMaNGxdIlQNdtG39+vX695mZmYWey8TEBHd3dzZv3kzDhg2pXbs2x44do3z58sU6tQD29vYMHDiQoKAg2rdvT7t27ejVqxeurq6ATuzlgw8+KHL8iBEjGDFiRJHHz549y7fffkt4ePgz76d3cXFBpVJx4sQJFi9ejLu7O8ePH2fNmjVPdLiK+z4URnEPGUD3eQOK/cyVBbdv36ZDhw707Nmz0L+Dubm5XrCnuLbnRakdtICAAK5evcqSJUu4fPkyAN27d+ejjz56Id7uyyY/vdH3vm6T6yXVLWqEHkKoZWBnztujPsXIqOineVln7qFJexQ9a2QoaGLiaI5VHzeS917FqZI7RsaP5pHJUHiVw6K2U4lsVPg56J07I0sTbN/0eMKI1x9VYiJ512PAyAjLx+rgWTVvTuUVK8i9FI1DSIgkCiIhISHxHDAxNWLIt8XX3nxe5y0tlpaWVK9eHYAff/wRf39/Vq9ezeDBg/U36jt27KBixYoG48zMzADdXpj4+Hh27tzJ3r17adu2LcOHDzd4Cl+xYkWCg4MJDg5m1qxZeHp6snz5cmbMmIGnp6f+/qmkVKtWjQ8++IBJkyaxevXqYvvOmzePpk2bMmHCBIP2nJwcPv30U7Zs2aLfT1a7dm0iIyP5+uuvi3TQHB0duXDhQpHnW7NmDQ4ODiVyuho3bmyw3+/fuLi4FNgPd+/ePf2xwhg7diyjR4+mUqVKHDp0iNmzZ2NpaUmnTp04dOhQoQ7azJkzGV+CGqh+fn7Ex8ejUqnQarX6yKtarcbKygo3N7diRSPWrFnDxx9/zN9//82mTZv4/PPP2bt3L02aNNHvSXxaQkNDSUpKMhAq0Wg0jBs3jkWLFulVPp/EnDlzmDNnDkIIsrOz9Q8isrKyCAoKQiaTsWvXLlq2bFno+JJ8H0pDfnQtNTVVr9pe1ty5c4fWrVvTrFmzImX8U1JSCpy/sLbnxVPVQatQocJz24T5qhORFIFCZYV5ZjVUOYeorgxHAB51G/DmiPEoigh1g+HeM5vHomeP41SnOk51qj+TjXJHc+QVrVDdzsS2czWMLZ9t0+jrQOaj9Ebz2rUL1DWzatEcqxYvXoVIQkJC4n8FmUxW6lTDVwEjIyM+/fRTxo4dS79+/fD19cXMzIyEhAQCAop2OJ2cnAgJCSEkJISWLVsyYcKEIm9Iy5Urh6urK1lZWQD069ePPn36sHXr1gL70IQQpKenF9iHBjB16lSqVav2RJGCRo0a0b17dyZNmmTQrlKpUKlU+tpO+RgbGxdbJqlu3bosW7YMIUSBh5xCCNasWcOAAQNKJFARGRmpjyAVRtOmTfniiy9ISkrSRwr37t2LjY0Nvr6+Bfrv37+fS5cu6UUpNBoNKpVKv96icHZ2LjYSmc/OnTtRqVS0bduW+fPnU79+ffr06cPAgQP1cuxPom7dutStW5fJkyfTtGlTfv75Z5o0aULt2rXZv39/ofv2SkJwcHABpzooKIjg4OBSzTl06FB69erF0qVLuXXrFnPmzOHXX39lz549/PDDDwAFHlb8m9J8H55EtWrVsLGxITo6Gk/PstcLuH37Nq1bt6Z+/fqsWbOmwPcBIDc3l5iYGL2zms/FixcLtD0vSuSgnT9/npo1a2JkZMT58+eL7Zu/WfO/iBCCyPuRVE71QpW5Da1aF6Vq0qMPzd7ph6yQP/LjZJ19FD2zMcWyUdH/QJUFDsG+qJNzUFS3e67neVXIOnoMAMtH6Y0SEhISEhIloWfPnkyYMIElS5Ywfvx4xo8fz5gxY9BqtbRo0YK0tDSOHTuGjY0NISEhTJ06lfr16+Pn54dSqWT79u36vUUrVqwgMjKSt99+m2rVqpGbm8u6deuIiopi8eLFAPTq1YstW7bQt29fPv/8cwIDA3FycuLChQssXLiQkSNH0q1btwJ2li9fnrFjx/LVV189cU1ffPEFfn5+mJj8c5tnY2NDQEAAEyZMwNzcHDc3Nw4fPsy6dev45ptvipyrdevWZGZmEhUVRc2aNQ2OHThwgNjYWN5///0C43766SdMTU31N7R//PEHP/74I6tWrdL32bJlC5MnT9ZHFAMDA/H19SU4OJj58+dz9+5dPv/8c4YPH66PYOaTm5vLiBEj+OWXX/Q32c2bN2fJkiUMHz6c33//vdh1lQQ3Nzfu3r3LvXv36Nq1KzKZjKioKHr06FGsowkQGxvLypUreeutt6hQoQJXrlzh2rVrDBgwAIBp06bRtm1bqlWrRp8+fVCr1ezcuVNfa+v7779ny5YtRaYEOjg44PAvNWq5XI6Li0up9jja29tjb29PdHQ0vXv3pnr16ly7do3AwEB9pLk4ivs+FEbbtm15++23i0zfNDIyol27dhw9etTge5CZmcn169f172NjY4mMjCxVuYPbt2/zxhtv4Obmxtdff839+/f1xx6P0J44cQIzMzP9Vq58QkNDmTVrVonO9cyIEiCTycS9e/f0/29kZCRkMlmBl5GRUUmme+VIS0sTgEhLSyu2X3xavKi5tqaYNGqC+LpXJzG/V1cxf8WvJT7P/TUXxc2JR0T6oYRnNVniMbQqlbjcoKGI9vIW2ZGRL9scCQkJiVeekv7u/dcICQkRXbt2LdA+d+5c4eTkJDIzM4VWqxWLFi0SXl5eQi6XCycnJxEUFCQOHz4shBBi1qxZwsfHR5ibmwt7e3vRtWtXcePGDSGEEOHh4aJ///7Cw8NDmJmZCQcHB9GqVSuxbds2g/NpNBqxbNky0bBhQ2FhYSFsbGxE/fr1xbfffiuys7OFEEJMmzZN+Pv7G4xLS0sTjo6OAhCxsbFCCCFiY2MFICIiIgz6DhkyRABi2rRp+rbExEQxcOBAUaFCBaFQKISXl5dYsGCB0Gq1xV63Xr16iUmTJhVo79u3r2jWrFmhY9auXSt8fHz062vUqJH49VfDe6Y1a9aIf9+KxsXFiY4dOwpzc3Ph6Ogoxo0bJ1QqVYH5J02aJMaNG2fQdu3aNdGwYUNhY2Mjhg0bJjQaTbHrKgm//PKLaNGihRBCiCNHjojq1auXaNzdu3dFt27dhKurqzA1NRVubm5i6tSpBjb9/vvvok6dOsLU1FQ4OjqK7t27649NmzZNuLm5lcpWNzc3sXDhQoO2gIAAERISUuw4lUolrKysxPXr14UQQlStWlUcPXq0ROcs7vtQ2GfTzc3N4DNZGDt37hQVK1Y0uFYHDx4UQIHX42t70jXL/7wV9nqcIUOGiA8//NCgLSwsTNjZ2em/n88bmRBP3q0aHx9PlSpVkMlkT1Qvebyo3OtCfjpBWlqaXmWpMLbFbOOzI58zcF9dUD/ginU9Bn86isZVn1xPSwhB4uyTaLNUOH3kj1mVos8jUTqywyOI79cPY1tbaoQdQ2b8+qXZSEhISLxISvq7JyEBukyq9u3bExMTU6RqocSriZubGzNmzGDgwIEv25QSI4SgcePGjBkzhr59+5Z4XMgjrYFnqcucnJyMl5cXZ86cwcPjHw2H3r174+/vX6Co9fOiRCmOjztd8fHxNGvWzCBsDrp6D2FhYa+lg1ZSIu9F4JdQEdQPADnHyvmzuIpdicZqUpVos1RgJMPUVfrHrSzJeqTeaNGsqeScSUhISEhIlDG1a9fmyy+/JDY2llq1ar1scyRKSFRUFLa2tvq0ytcFmUzGypUrixWn+TdCCA4dOsTRR5oET0tcXBxLly41cM7y8vKoVasWY8aMeaa5S0OJImiPY2xsTGJiYoHNlQ8ePMDZ2RmNRlOmBr4ISvok8e1fO1B/uyXmuUoyLBqw16sVxya1KdE5ss/fJ+Xny8grWlF+5IvZYPi/Qmyv3uSeP4/rF19g16P7yzZHQkJC4pVHiqBJSEhIvLqUWp9WFKLiAzoHzdLSskyMehVJz0tHdSMF81wlYMpFG3/cHS1KPD7vVgYAppXLrsL964zq9m0erF6NNjf3meZRp6aS++gJi6Wk1CghISEhISEhIfGaU2KZ/e7ddZEJmUzGwIEDDdR0NBoN58+fL7Yw3evOubuR1LlaDgBjRV2umZrRyaHkDmneTV1tFdNKUnojQNLCRaRv3442Nxen4cOfep6ssDAQAjNPT+Tly5ehhRISEhISEhISEhIvnhI7aPk1OYQQWFtbGxTYMzU1pUmTJsVWRH/dCT/wO+Uy5YApwrYeacYCd4eSRdCEVqC6LUXQHif30iUAMvbuezYH7Yhu/5kkry8hISEhISEhIfFfoMQOWn4RQHd3d8aPH/+fTmf8N0KrJfPYNRQYYayoS6KVJWizqGJfsmugTspG5GmRmRph4lTytMj/KiIvj7xHaqDKy5fJu3UL00qVSj2P8vp10nbuBMC69RtlaKGEhISEhISEhITEy6HUe9CmTZv2P+WcAVw7cwJFuhFCJsfErD7RQledvqR70PL3n8krWiMzKrh/73+NvPh4UKv17zP27Sv1HEKrJXHqNFCpsGrdGvMGDcrSRAkJCQkJCQkJCYmXQokjaI/z22+/sXnzZhISEsjLyzM4Fh4eXiaGvUpcPL0HABNTX4zlCi5rc0AGVexL6KDdlNIbH0f5WCV4gMx9+3EopD6HUKtR37uHvGLFAsce/vobOeHhyCwscJnyeaHCNRISEhISEhISEhKvG6WOoH333Xe89957lC9fnoiICBo1aoSDgwM3btygY8eOz8PGl05iXDQAMiMHrCtbo5KBs7UZFqYl82/zbkkCIY+jvKZz0CybNQUgOzwcdUpKgX53Jk7iett2JE6dhvaxBwHq+/dJWrAAAKePRyKvUOEFWC0hISEhISEhISHx/Cm1g7Z06VJWrlzJ4sWLMTU15ZNPPmHv3r18/PHHpKWlPQ8bXzq5qTkAyIzLQXmdeqV7CRUchUqLKjELkCJo+eRH0CxbtkLh6wtaLZkHDxr0ybkYRfqOHQA83LyZhOABqO4lAXBv7jy06ekofH2x79//xRovISEhISHxP0ZeXh7Vq1cnLCzsZZsi8R/j0KFDyGQyHj58WKbzTpo0iZEjR5bpnC+SUjtoCQkJejl9c3NzMjJ06XvBwcH88ssvZWvdK4BWo0FkagEwMi5Hio0xAG4lVHDMS8wErcDIUo6xndmTB/wPkO+gmVWvjlW7tgBk7Ntv0Cf5++8BMK9bFyMbG3LOnSO2Rw+Sly8nfedOMDLCZdZMZCZPlaUrISEhIfE/yMCBA5HJZMhkMuRyOR4eHnzyySfkPmNNzsc5fPgwbdq0wd7eHgsLC2rUqEFISIjBlhAhBCtXrqRx48ZYWVlhZ2dHgwYNWLRoEdnZ2QBMnz4dmUzG0KFDDeaPjIxEJpMRFxcHQFxcHDKZDGdnZ/09WT516tRh+vTpBm2XLl3irbfewtbWFktLSxo2bEhCQkKxa1q+fDkeHh76+7/8m+rCXqdPnwbgypUrtG7dmvLly6NQKKhatSqff/45KpWq2HMlJCTQqVMnLCwscHZ2ZsKECagf27cOsGHDBvz9/bGwsMDV1ZVBgwbx4MED/fG9e/fi6emJjY0NwcHBBtc+LS0NT09P4h+JlZUlp0+fpsKjrJ47d+5gbm5eYCvQiyQlJYWRI0fi5eWFubk5VapUKZOAip+fH3v26Lb/BAYGsm7durIwt8QcOnSIrl274urqiqWlJXXq1GHDhg0GfcaPH89PP/3EjRs3XqhtZUWpHTQXFxdSHqWjValShRMnTgAQGxuLEKJsrXsFSL+fhEzIAGOMzOXEqXVfNHfHkkXQVI/tP/tf2SeljI0lceo0VHfvFjimfUzB0axGdazbtgMg69gxtFm6SGPOhYtkHjoERka4zvkCj99+xczTE01yMvcXfQuAfXAw5n5+L2ZBEhISEhL/GTp06EBiYiI3btxg4cKFrFixgmnTppXJ3NHR0XTo0IEGDRpw5MgRLly4oM840mg0+n7BwcGMHj2arl27cvDgQSIjI5kyZQpbt27V3/gCKBQKVq9ezbVr15547oyMDL7++uti+8TExNCiRQu8vb05dOgQ58+fZ8qUKSgUiiLHCCH4/vvvGTx4sL6tWbNmJCYmGrzef/99PDw8aPBItEsulzNgwAD27NnDlStXWLRoET/88EOx11qj0dCpUyfy8vIICwvjp59+Yu3atUydOlXf59ixYwwYMIDBgwcTFRXFr7/+yqlTp/SlnrRaLf369WPo0KEcP36cM2fOsHLlSv34SZMmMXToUNzc3Iq/oE/B8ePHad68OQChoaE0aNAAU1PTMj9PSblz5w537tzh66+/5uLFi6xdu5a///7b4G9ZWh4+fMjVq1dp0qQJGo3GYM0virCwMGrXrs3vv//O+fPnee+99xgwYADbt2/X93F0dCQoKIhly5a9UNvKDFFKBg8eLKZPny6EEOL7778X5ubmol27dsLOzk4MGjSotNO9EqSlpQlApKWlFTh2I/y0+LpXJ7Ggb4hY//WvosfSY8Jt4naxLfJ2ieZ+sPGyuDnxiEjbG1fWZr+SaLVaEdu7j4j28haJM2YUOJ5z+YqI9vIWl+s3EFqtVmi1WnGtfaCI9vIWaX/vFkIIkTDkQxHt5S1uf/KJfpwmK0vcHD1aRHt5i6utWwtNZuYLW5OEhITEf43ifveeBq1WK/Jycl74S6vVlsrOkJAQ0bVrV4O27t27i7p16+rfazQaMWfOHOHu7i4UCoWoXbu2+PXXX/XHU1JSRL9+/YSjo6NQKBSievXq4scffxRCCLFw4ULh7u5erA2bNm0SgPjzzz8LvY4PHz4UQggxbdo04e/vL9q3by969uyp7xMRESEAERsbK4QQIjY2VgBiwoQJwsrKSty7d0/f19/fX0ybNk3/vnfv3qJ///7FX6R/cfr0aWFkZCTS09OL7JOXlyecnJzEzJkzi51rzJgxokWLFkUe37lzpzAyMhJ3797Vty1btkzY2NgIpVIphBDiq6++ElWrVjUY991334mKFSsKIYS4d++eAEROTo4QQohPPvlEfPTRR0IIIY4dOybq168v1Gp1sXY+Lb179xYLFy4UQggxYsQIMXHixCeO+fXXX0XNmjWFQqEQ9vb2om3btiLzsXuc1atXC19fX2FqaipcXFzE8OHDn8nGzZs3C1NTU6FSqZ5q/K5du4S/v78QQogzZ86I8uXLP3FMXFyc6Ny5s7CzsxMWFhbC19dX7NixQwghxMGDBwUgUlNTn8qefN58803x3nvvGbT99NNPolKlSs8078ui1PlhK1euRKvVpfwNHz4cBwcHwsLCeOutt/jwww/LznN8RUiKvwmAzMiOKnVMiDuuSz0o6R40vcT+/8j+s6xjYeRERur+/9SpAsfzYv5Jb8yPKFq3bUvKmjVk7NuHvIIrmYcPg7ExjsOG6ccZWVhQ8ZtvyO7dB7NqVTH6Hyv1ICEhIfEqo1Yq+S7knRd+3o9/+g15MdGfJ3Hx4kXCwsIMoilz585l/fr1LF++nBo1anDkyBH69++Pk5MTAQEBTJkyhejoaHbt2oWjoyPXr18nJ0e3V93FxYXExESOHDlCq1atCj3nhg0b8PLyomvXrgWOyWQybG1tDdrmzZtHw4YNOXPmjD46VRh9+/Zl7969zJw5k+8fbRN4HK1Wy44dO/jkk08ICgoiIiICDw8PJk+eTLdu3YqcNzQ0FE9PT6yti76P2bZtGw8ePOC9994rss/169f5+++/6d69e5F9jh8/Tq1atShfvry+LSgoiGHDhhEVFUXdunVp2rQpn376KTt37qRjx44kJSXx22+/8eabbwLg5OSEq6sre/bsoV27doSGhhISEoJKpWLYsGH8+OOPGBsbF2lDaTl69CidO3cGIDMzk7/++ovp06eTlZWFXC5n+fLlTJo0iUmTJhUYm5iYSN++fZk/fz5vv/02GRkZhIaG6jPSli1bxtixY5k3bx4dO3YkLS2NY8eO6ccPHDiQuLg4Dh06VGJ709LSsLGxwaSUW0Rq166tV29XqVTY2dmhUqlQKpXY2dlRpUoVzp8/X+jY4cOHk5eXx5EjR7C0tCQ6Ohorq6KF82QyGWvWrGFgIQrfxa3Lx8fHoK1Ro0bcunWLuLg43N3dSzzXq0CpHTQjIyOMjP7JjOzTpw99+vQpU6NeJWIjrwKQa2aCc/UKJO+9D0CVEuxB0+aoUd/X/aNtWum/76AJIUhevFj/Pu96DOoHDzBxcNC36fef1aiub7Nup3PQMg8dQvMofda2SxdM//VlkslkWDZp/BxXICEhISHxX2f79u1YWVmhVqtRKpUYGRnpHRqlUsmcOXPYt28fTZvqlIarVq3K0aNHWbFiBQEBASQkJFC3bl29s/T4jV/Pnj3ZvXs3AQEBuLi40KRJE9q2bcuAAQOwsbEB4Nq1a3h5eZXY3nr16tGrVy8mTpzI/v37i+wnk8mYN28eXbp0YcyYMVSrVs3geFJSEpmZmcybN4/Zs2fz5Zdf6h2mgwcPEhAQUOi88fHx+n1VRbF69WqCgoKoVKlSgWPNmjUjPDwcpVLJkCFDmDlzZpHz3L1718A5A/Tv7z7aNtG8eXM2bNhA7969yc3NRa1W06VLF5YsWaK/Dps3b2bMmDGMGjWKN998k0GDBjFv3jxat26NQqGgefPmJCcnM3LkSEaMGFHs2p5EgwYNiIyM5PLly/Tr14+zZ8+SkpKiX7dCocDOzq7QsYmJiajVarp3765/SFCrVi398dmzZzNu3DhGjRqlb2vYsKH+/11dXfVBk5KQnJzMrFmzGDJkSClXCTt37kStVtO5c2dGjx5Nu3btGDRoEB06dKBXr17FOnwJCQn06NFDv7aqVasWey4vL68CDyqKY/PmzZw+fZoVK1YYtOd/buPj4/+bDlpRHnFh1K5d+6mNedUQWkFSnC6CdtPhLpnCFbiPvaUptubyJ47Pj54Z2yswtnxy/9edrKNHyTl3DplCgYmDA6rbt8k+fRqbDh30ffIl9s2q/+Ogmdepg7GDA5oHD8g6duxR9GxogfklJCQkJF5NTMzM+Pin317KeUtL69atWbZsGVlZWSxcuBATExN69OgB6KI82dnZtG/f3mBMXl4edevWBWDYsGH06NGD8PBwAgMD6datm148w9jYmDVr1jB79mwOHDjAyZMnmTNnDl9++SWnTp3C1dX1qfbrz549Gx8fH/bs2YOzs3OR/YKCgmjRogVTpkzh559/NjiWfyPftWtXxowZA+hERMLCwli+fHmRDlpOTk6xe9Ru3brF7t272bx5c6HHN23aREZGBufOnWPChAl8/fXXfPLJJ8Wutziio6MZNWoUU6dOJSgoiMTERCZMmMDQoUNZvXo1AC1atNCLlQBcvXqVdevWERERQatWrRg1ahQdO3akZs2atGrVqtB7144dOxIaGgqAm5sbUVFRhdqjUChwd3dn8+bNdOzYEQ8PD8LCwmjZsiXe3t7FrsXf35+2bdtSq1YtgoKCCAwM5J133qFcuXIkJSVx584d2rZtW+T4uXPnPvF65ZOenk6nTp3w9fUtIBxTEipVqsTdu3eJiYmhT58+yOVyTp8+zU8//UTlypWLHfvxxx8zbNgwfVSzR48exfoLly9fLrFdBw8e5L333uOHH37A71/aBObm5gB64Z3XiRI5aHXq1EEmkyGEeKLQxeObYF934qMeoFLqIjo3na+TlKG7XCUuUP0/VP9MCMH9xbonkOX69EFoNKT+3/+RdfKkoYP2KIJm+piDJjM2xrpNax7+qvtxt33rLUyfw+ZdCQkJCYnng0wme6ZUwxeJpaUl1R/9Bv3444/4+/uzevVqBg8eTGam7nd7x44dVKxY0WCc2SNnsGPHjsTHx7Nz50727t1L27ZtGT58uIFAR8WKFQkODiY4OJhZs2bh6enJ8uXLmTFjBp6enqW6AQWoVq0aH3zwAZMmTdI7IUUxb948mjZtyoQJEwzaHR0dMTExwdfX16Ddx8eHo0ePFjmfo6MjFy5cKPL4mjVrcHBw4K233ir0eP7Nu6+vLxqNhiFDhjBu3LhC0wxdXFw49a/tEffu3dMfA51T0rx5c/36ateujaWlJS1btmT27Nm4uroWmPfDDz9kwYIFaLVaIiIi6NmzJxYWFgQEBHD48OFCnYVVq1bpU1fl8qIfsuen6uVHY7du3UpeXh5CCKysrGjZsiW7du0qdKyxsTF79+4lLCyMPXv2sHjxYj777DNOnjyJo6NjkecsLRkZGXTo0AFra2u2bNlS7HoKY+jQoaxfvx6tVotSqcTFxQUhBNnZ2fq0wujoaKpUqVLo+Pfff5+goCB27NjBnj17mDt3LgsWLHhmGfzDhw/TpUsXFi5cyIABAwoczxc1dHJyeqbzvAxKpOIYGxvLjRs3iI2N5ffff8fDw4OlS5cSERFBREQES5cupVq1avz+++/P1dh58+Yhk8kYPXq0vi03N1e/F87KyooePXrov8zPyvkDcaBN172xziXuQf7+sxI6aI8pOP7XyQoNJff8eWQKBQ7vD8aikS4En33qnydY2rw88h5J+T4eQQOwyn9CJEXPJCQkJCReEEZGRnz66ad8/vnn5OTk4Ovri5mZGQkJCVSvXt3g9XiUwMnJiZCQENavX8+iRYsMVAL/Tbly5XB1dSXrkVJxv379uHr1Klu3bi3QVwhRpAT61KlTuXr1Khs3bix2TY0aNaJ79+4F9jyZmprSsGFDrly5YtB+9erVYhUN69aty+XLlwuN/AkhWLNmDQMGDCjRTb9Wq0WlUhWZlte0aVMuXLhAUlKSvm3v3r3Y2NjoHcvs7GyDrTaA3tkrzMbVq1djb2/PW2+9pQ8i5Ev9q1SqIgMLFStW1P/ti7s+kZGRnDlzBmNjY/bv309kZCQODg5s3ryZyMhIVq1aVeRY0D3caN68OTNmzCAiIgJTU1O2bNmCtbU17u7uxaa1loT09HQCAwMxNTVl27ZtxUZDi2LmzJlERkbq0xsjIyMZOHAg/fv3JzIyksjIyCemwVauXJmhQ4fyxx9/MG7cOH744YenXRKgk9rv1KkTX375ZZEpmxcvXkQulxeIrL0WlFZVpGHDhnrllcfZsWOHqFev3tPLlTyBU6dOCXd3d1G7dm0xatQoffvQoUNF5cqVxf79+8WZM2dEkyZNRLNmzUo1d2FqVg+TssV3728SX/fqJOb0e1P0XVNfTPztnHCbuF18s+dKiea988UJcXPiEZF742Gp7Hnd0Gq14sY7PUW0l7e4O+9LIYQQ6tRUEe3tI6K9vIXq/n0hhBA5ly/rFBwbNCygvKVVq8Xd+fNF6m+/vXD7JSQkJP7XKGsVx9eFwlQcVSqVqFixovjqq6+EEEJ89tlnwsHBQaxdu1Zcv35dnD17Vnz33Xdi7dq1QgghpkyZIv78809x7do1cfHiRdG5c2fRqFEjIYQQy5cvF0OHDhW7d+8W169fFxcvXhSffPKJMDIyEocOHRJC6H4ze/fuLczNzcUXX3whTp8+LeLi4sRff/0l2rRpI7Zs2SKE+EfF8XGmTJkiFApFoSqOERER+n5XrlwRJiYmQqFQGKg4/vHHH0Iul4uVK1eKa9euicWLFwtjY2MRGhpa5DVLTk4WcrlcXLhwocCxffv2CUBcunSpwLH169eLTZs2iejoaBETEyM2bdokKlSoIN59910De7y8vPTv1Wq1qFmzpggMDBSRkZHi77//Fk5OTmLy5Mn6PmvWrBEmJiZi6dKlIiYmRhw9elQ0aNBA/zd4nHv37gl3d3dx+/Y/yts+Pj5i+vTpIiwsTFhZWYlTp04VufaScvz4cVGlShUhhBDx8fHC0tKyRCqJJ06c0H8G4uPj9QqLO3fuFEIIsXbtWqFQKMS3334rrl69qv8s5jNp0iQRHBxc5PxpaWmicePGolatWuL69esiMTFR/3oaJUsvLy9x4MABIYQQrVu3Fj///HOJxo0aNUr8/fff4saNG+Ls2bOicePGolevXkKIwlUcvby8xB9//FHkfAcOHBAWFhZi8uTJBmt68OCBQb9p06aJNm3alHKVrwaldtAUCoWIjo4u0B4dHS0UCkWZGPVvMjIyRI0aNcTevXtFQECA3kF7+PChkMvlBvK3ly5dEoA4fvx4iecv7Ifq6G/XxLfvLRdf9+okJn7QTgz/v5ai94ow4TZxu/gj/OaTbT52W9yceETc/DRUaJTPR871VSH94EER7eUtLvnXEarkZH17TNduOvn8Rw79w7+2i2gvbxHbp+/LMlVCQkJCQkgO2r+ZO3eucHJyEpmZmUKr1YpFixYJLy8vIZfLhZOTkwgKChKHDx8WQggxa9Ys4ePjI8zNzYW9vb3o2rWruHHjhhBCiPDwcNG/f3/h4eEhzMzMhIODg2jVqpXYtm2bwfk0Go1YtmyZaNiwobCwsBA2Njaifv364ttvvxXZ2dlCiMIdtLS0NOHo6PhEB00IIYYMGSIAAwdNCJ1se/Xq1YVCoRD+/v6Fyv3/m169eolJkyYVaO/bt2+RD8U3btwo6tWrJ6ysrISlpaXw9fUVc+bM0cvfC6Fztv4dK4iLixMdO3YU5ubmwtHRUYwbN66As/Pdd98JX19fYW5uLlxdXcW7774rbt26VcCGPn36iMWLFxu0nTx5Unh7ewt7e3sxo5ByQE/D3Llz9eUL1q1bJ9q1a1eicdHR0SIoKEg4OTkJMzMz4enpWcDe5cuX6z+Lrq6uYuTIkfpjISEhIiAgoMj5852fwl75nx8hhHBzcyvwOfk3iYmJwtTUVGRnZwulUinMzc0LveaFMWLECFGtWjVhZmYmnJycRHBwsEh+dL9YmIMGiDVr1hQ5X0hISKFr+ve18PLyEr/88kuJbHzVkAlRut2q9erVo2bNmqxatUpffC8vL4/333+fixcvEh4e/gzxvMIJCQnB3t6ehQsX8sYbb1CnTh0WLVrEgQMHaNu2LampqQYKOW5ubowePVq/CfbfKJVKlEql/n16ejqVK1cmOTkZGxsb1HkaNkw5RVZKGOqco8RUyMShiSX7bowlMS2XzR80om4Vu0LnBlBef8jDdZdBgFVQFSxbFB/2fVVQ373L/S/mYDsgGIvHVIKKQ5ORwe33BpF35Qp2A0NwHDdOf+z+l1+Stn4DNr164jxlCg8Wf0/qypXY9OiB8/SyKQoqISEhIVF60tPTcXR01EtuS0gUx/nz52nfvj0xMTHFyqNLvH5kZ2fj4ODArl27eOONN162OWXGrl27GDduHOfPny91SYFXgVJbvHz5crp06UKlSpX0myrPnz+PTCbjr7/+KnMDN27cSHh4uIEaTz53797F1NS0gHxp+fLl9XKshTF37lxmzJhRoH3Pnj1YWFiQddMEZbY5yFIBSLdUY5upITEtF4BrEWEkXix8bkW2EV4XbTARRiQ7KTmbFgk7I0u01peN4/Yd2IeGkhwby82Phj2xv+m9JCr83/9hev8+GjMzzlaujGbnTv1xSyMjKgL3Dx7iTP36uB47hjVwPU/Jmcf6SUhISEi8WF5HVTOJl0ft2rX58ssviY2NNZCBl3j9OXjwIG3atPlPOWcAWVlZrFmz5rV0zuApHLRGjRpx48YNNmzYoFch6t27N/369cOyjIsH37x5k1GjRrF3796n2tRYFJMnT2bs2LH69/kRtMDAQGxsbNjydSSQgYVVDunZkG6pooJTDbgGVmYm9HyrfaFqltpsFSkrLqLRKJG7WeM7sBF+JiXSYXklSPhhFXmA+a1bBLVogXExT1Uz9x/g3vLliOxsTMqXp9KihXjVrGnQR9O8ObH/tx6z+/cJbNiQ28uWoQLqdHkLi6ZNnu9iJCQkJCSKJD09/WWbIPGaUZqiwRKvD506daJTp04v24wy55133nnZJjwTT+VWWlpaPlWRu9Jy9uxZkpKSqFevnr5No9Fw5MgRvv/+e3bv3k1eXh4PHz40iKLdu3dPL8daGGZmZnq53MeRy+WYmJiQcluntJSX8wDQRdBkRjq5UzcHC31q5+MItZb7Gy+hSVFibK/AMdgXY/OC/V5VVPfukfdIAh+NhrwzZ7EJCizQT2i13F+8mAfLlgNg0bAhFRctNChGnY/c0REzb2+Uly6hPHESVYKuppyFt1epJV4lJCQkJMoO6d9gCQkJiVeXEjlo27Zto2PHjsjlcrZt21Zs36LqYDwNbdu2LVB747333sPb25uJEydSuXJl5HI5+/fv1xeZvHLlCgkJCTRt2vSpzqnO06JRaxHaXJQZOqnbdAsV2Rqdg+buUDBKqMlSkbLxMnmxacjMjHEM8cXY6vVxzkBXZNrwfWihDlrq+g1658w+ZADO48cjK+aH3rJRQ5SXLvFw0ybQajGytcXkNaxHISEhISEhISEhIfEiKJGD1q1bN+7evYuzszPdunUrsp9MJivTQtXW1tbU/FfanKWlJQ4ODvr2wYMHM3bsWOzt7bGxsWHkyJE0bdqUJk2eLoUuJzNP9z8ynXOWa6pGJRfcV/4TQXucvDuZPPi/aDSpSmRyIxze9UFevmxTPV8EmY8cNIV/bXLPnSfz6LEChcmFEDz8dTMATmPG4Pjhk6OoFo0bk/LTOnLOnQN09c+eVOxcQkJCQkJCQkJC4n+VEjlojxcULKq44Mti4cKFGBkZ0aNHD5RKJUFBQSxduvSp51NmqQEwMUlHCTy01L2/lW4LaAwiaNkRSaT+cQ2h0mLsoEtrlLu8fs6Z0GjICjsOgPPo0dz8cCjqxETyYmIMCkorr1xBee06Mrmccn37lGhui/r1QSaDR2KhZtWqlf0CJCQkJCQkJCQkJP4jvHbSJocOHTJ4r1AoWLJkCUuWLCmT+fMjaEaPImjpVipkQnA71QTQUOVRBC1tbzwZ+xN0NniVw763F0YWr2dOf+6FC2jT0jCyscGiYUMsGjYk69gxMo8eNXDQ0rbpVDqt3nijWAGRxzG2tcXMxxtl9CUAg/kkJCQkJCQkJCQkJAwpkYP23XfflXjCjz/++KmNeRXIzVIBILSPJPYt1NhhxO1UnePm7mCJJjNP75xZt66MTXs3ZEavb9peZqguvdGyaVNkJiZYtmhB1rFjZB09hsMj1Sah0ZC+YwcANm91KdX8lo0a/+Og1ZAcNAkJCQkJCQkJCYmiKJGDtnDhwhJNJpPJXn8HLVPnoKnzUgCdxL4dchK0AoXcCGdrM3LO3QdAXtEK2yD3l2VqmZEvEGLVsoX+v0lffkn26dNoc3MxUijIPn0a9b17GNnYYBUQUKr5LRo1ImXtWkCKoElISEhISEhISEgUR4kctNjY2OdtxytDbqYKIQSqnGQA0izVuMt0Ndjc7C0xMpKhvKJz3hQ1yr00O8sKzcOH5DxSyrRsoXPQTKtVw8TFBfXdu2SfPoNVyxb69EabDh0wKqTMQHFYNGqIiasrJo6OGDs6lu0CJCQkJCQkJJ4rDx48wMfHh1OnTuHu7v6yzZH4D3Ho0CFat25NamqqQcmsZ2X58uXs2LGDv/76q8zmfJG8PlWUXxC5mSoQ2WjVSgAyLFQo0Al/VHGwQGgFudceAqDwtHtJVpYdWcePg1aLWY3qyB/VjpPJZPpoWtbRULS5uWTs3g2AbSnTGwGMrayotmsn7hvWSwqOEhISEhIvjYEDByKTyZDJZMjlcjw8PPjkk0/Izc0ts3McPnyYNm3aYG9vj4WFBTVq1CAkJIS8vDx9HyEEK1eupHHjxlhZWWFnZ0eDBg1YtGgR2dnZAEyfPh2ZTMbQoUMN5o+MjEQmkxEXFwdAXFwcMpkMZ2dnMjIyDPrWqVOH6dOnA6BSqZg4cSK1atXC0tKSChUqMGDAAO7cufPENX3xxRd07dpV75ytXbtWfx3//UpKSgIgMTGRfv364enpiZGREaNHjy7xNVy7di21a9dGoVDg7OzM8OHD9ceuXLlC69atKV++PAqFgqpVq/L555+jUqn0ffbu3Yunpyc2NjYEBwcbXPu0tDQ8PT2Jj48vsT0l5fTp01SoUAGAO3fuYG5ubnDuF01KSgojR47Ey8sLc3NzqlSpwscff0xaWtozzevn58eePXsACAwMZN26dWVhbonJzc1l4MCB1KpVCxMTk0IV5gcNGkR4eDihoaEv1Lay4qkctFu3brF06VImTZrE2LFjDV6vO7lZKoRGt/8MCy1aY5BpdA5aNScrVHcy0WapkJkZY1qlZEIZrzL58vqWzVsYtOe/zzx6jMyDB9FmZSGvUAHzx4qGlwYjhQJZKSNvEhISEhISZU2HDh1ITEzkxo0bLFy4kBUrVjBt2rQymTs6OpoOHTrQoEEDjhw5woULF1i8eDGmpqYGZYiCg4MZPXo0Xbt25eDBg0RGRjJlyhS2bt2qv/EFnRDa6tWruXbt2hPPnZGRwddff13k8ezsbMLDw5kyZQrh4eH88ccfXLly5Yn1a7Ozs1m9ejWDBw/Wt/Xu3ZvExESDV1BQEAEBATg7OwOgVCpxcnLi888/x9/f/4n25/PNN9/w2WefMWnSJKKioti3bx9BQUH643K5nAEDBrBnzx6uXLnCokWL+OGHH/R/Q61WS79+/Rg6dCjHjx/nzJkzrFy5Uj9+0qRJDB06FDc3txLbVFKOHz9O8+bNAQgNDaVBgwaYvsR7nzt37nDnzh2+/vprLl68yNq1a/n7778N/pal5eHDh1y9epUmTZqg0WgM1vyi0Gg0mJub8/HHH9OuXbtC+5iamtKvX79S6Wi8UohSsm/fPmFhYSFq1qwpTExMRJ06dYSdnZ2wtbUVrVu3Lu10rwRpaWkCEGlpaeLPheFi0cBF4utencS8Ye1FzbU1Rf+l7wq3idvFnxG3RNqBeHFz4hFx/6eol232M6PVasXVlq1EtJe3yDh61OCYOi1NRPv6iWgvb3Gjew8R7eUt7i345iVZKiEhISFRljz+u1cWaLVaoVGqX/hLq9WWys6QkBDRtWtXg7bu3buLunXr6t9rNBoxZ84c4e7uLhQKhahdu7b49ddf9cdTUlJEv379hKOjo1AoFKJ69erixx9/FEIIsXDhQuHu7l6sDZs2bRKA+PPPPwu9jg8fPhRCCDFt2jTh7+8v2rdvL3r27KnvExERIQARGxsrhBAiNjZWAGLChAnCyspK3Lt3T9/X399fTJs2rUhbTp06JQARHx9fZJ9ff/1VODk5FbumpKQkIZfLxbp16wo9HhAQIEaNGlXsHELorq25ubnYt2/fE/s+zpgxY0SLFi2EEELcu3dPACInJ0cIIcQnn3wiPvroIyGEEMeOHRP169cXarW6VPOXlN69e4uFCxcKIYQYMWKEmDhx4hPH/Prrr6JmzZpCoVAIe3t70bZtW5GZmak/vnr1auHr6ytMTU2Fi4uLGD58+DPZuHnzZmFqaipUKtVTjd+1a5fw9/cXQghx5swZUb58+SeOiYuLE507dxZ2dnbCwsJC+Pr6ih07dgghhDh48KAARGpq6lPZU9h3Op/Dhw8LU1NTkZ2d/VRzv0xKLbM/efJkxo8fz4wZM7C2tub333/H2dmZd999lw4dOpSl7/hSeDyClm2hS3lIzrIGwNvFhtwTNwBQeL7++8+U166hTkpCplBg0aCBwTFjGxvMa9cmJyKC3Kgo4OnSGyUkJCQk/vsIlZY7U8Ne+HkrzGyGzNT4qcdfvHiRsLAwg2jK3LlzWb9+PcuXL6dGjRocOXKE/v374+TkREBAAFOmTCE6Oppdu3bh6OjI9evXycnJAcDFxYXExESOHDlCq1atCj3nhg0b8PLyomvXrgWOyWQybG1tDdrmzZtHw4YNOXPmDA3+9Vv9OH379mXv3r3MnDmT77//vkTrT0tLQyaTFbv3JzQ0lPr16xc7z7p167CwsOCdd94p0XmLYu/evWi1Wm7fvo2Pjw8ZGRk0a9aMBQsWULly5ULHXL9+nb///pvu3bsD4OTkhKurK3v27KFdu3aEhoYSEhKCSqVi2LBh/PjjjxgbP/1n5t8cPXqUzp07A5CZmclff/3F9OnTycrKQi6Xs3z5ciZNmsSkSZMKjE1MTKRv377Mnz+ft99+m4yMDEJDQxGPascuW7aMsWPHMm/ePDp27EhaWhrHjh3Tjx84cCBxcXEFSlAVR1paGjY2NpiYlM4FqF27NgkJCeTl5aFSqbCzs0OlUqFUKrGzs6NKlSqcP3++0LHDhw8nLy+PI0eOYGlpSXR0NFZWVkWeSyaTsWbNGgY+UhJ/Who0aIBarebkyZO88cYbzzTXi6bUDtqlS5f45ZdfdINNTMjJycHKyoqZM2fStWtXhg0bVuZGvkhyM1V6if00c90+tIdKO+TGMtytzbifoMvv/i84aFmP5PUtGjbEyMyswHHLFs3JiYgAwMzXR1JglJCQkJB47dm+fTtWVlao1WqUSiVGRkZ6h0apVDJnzhz27dtH06ZNAahatSpHjx5lxYoVBAQEkJCQQN26dfXO0uOiGT179mT37t0EBATg4uJCkyZNaNu2LQMGDMDmUf3Qa9eu4eXlVWJ769WrR69evZg4cSL79+8vsp9MJmPevHl06dKFMWPGUK1atWLnzc3NZeLEifTt21dvW2HEx8fr91UVxerVq+nXrx/m5ubFL+YJ3LhxA61Wy5w5c/j222+xtbXl888/p3379pw/f94gXbBZs2aEh4ejVCoZMmQIM2fOBHTXYfPmzYwZM4ZRo0bx5ptvMmjQIObNm0fr1q1RKBQ0b96c5ORkRo4cyYgRI57J5gYNGhAZGcnly5fp168fZ8+eJSUlRW+fQqEo0gFOTExErVbTvXt3/UOCWrVq6Y/Pnj2bcePGMWrUKH1bw4YN9f/v6uqKVqstsa3JycnMmjWLIUOGlHKVsHPnTtRqNZ07d2b06NG0a9eOQYMG0aFDB3r16lWsw5eQkECPHj30a6tatWqx5/Ly8irwoOJpsLCwwNbW9rnsN3zelNpBs7S01G94dHV1JSYmBj8/P0D3h3/d0UXQHgJw31K34TRd7Ux1Z2u0semgFZg4mmNir3iJVhaP0GhIXrqMnIhwbDp1wqZjR4wsLP45LgQ5Z8+S9ucW4B95/X9j1bIlyYt1P1q2XYrPUZeQkJCQ+N9FJjeiwsxmL+W8paV169YsW7aMrKwsFi5ciImJCT169AB00Zjs7Gzat29vMCYvL4+6desCMGzYMHr06EF4eDiBgYF069aNZs10azc2NmbNmjXMnj2bAwcOcPLkSebMmcOXX37JqVOncHV11UdHSsPs2bPx8fFhz549+j1ehREUFESLFi2YMmUKP//8c5H9VCoVvXr1QgjBsmXLij13Tk4OCkXR9zzHjx/n0qVL/N///d+TF/IEtFotKpWK7777jsDAQAB++eUXXFxcOHjwoMFetE2bNpGRkcG5c+eYMGECX3/9NZ988gkALVq04PTp0/q+V69eZd26dURERNCqVStGjRpFx44dqVmzJq1ataJ27doFbOnYsaNeYMLNzY2oR9lE/0ahUODu7s7mzZvp2LEjHh4ehIWF0bJlS7y9vYtdr7+/P23btqVWrVoEBQURGBjIO++8Q7ly5UhKSuLOnTu0bdu2yPFz584tdv7HSU9Pp1OnTvj6+uqFY0pDpUqVuHv3LjExMfTp0we5XM7p06f56aefioxu5vPxxx8zbNgwfVSzR48ehV7zfC5fvlxq+4rC3NxcL7zzOlFqB61JkyYcPXoUHx8f3nzzTcaNG8eFCxf4448/aNKkyfOw8YWhztOgUmoQWp26TaKVbkNvtrocPi7W5F7TRdZe5eiZOjWVO+PGkxWmSzXJCjvOvTlzsXmrC7ZdupBz/jwPN/9K3g1dqqbM3ByrNm0KnUvh54fcrQqaBynYdHrzha1BQkJCQuL1QiaTPVOq4YvE0tKS6o8yQn788Uf8/f31IhiZmZkA7Nixg4oVKxqMM3uUadKxY0fi4+PZuXMne/fupW3btgwfPtxAoKNixYoEBwcTHBzMrFmz8PT0ZPny5cyYMQNPT89S34BWq1aNDz74gEmTJrF69epi+86bN4+mTZsyYcKEQo/nO2fx8fEcOHCg2OgZgKOjI6mpqUUeX7VqFXXq1HliGmRJcHV1BcDX11ff5uTkhKOjIwkJCQZ9850CX19fNBoNQ4YMYdy4cYWmL3744YcsWLAArVZLREQEPXv2xMLCgoCAAA4fPlyos7Bq1Sp96qpcLi/S5vxUvfxo7NatW8nLy0MIgZWVFS1btmTXrl2FjjU2Nmbv3r2EhYWxZ88eFi9ezGeffcbJkydxLMOyRBkZGXTo0AFra2u2bNlS7HoKY+jQoaxfvx6tVotSqcTFxQUhBNnZ2fj4+AA6gZwqVaoUOv79998nKCiIHTt2sGfPHubOncuCBQsYOXLkM6/tSaSkpODk5PTcz1PWlPrR0zfffEPjxo0BmDFjBm3btmXTpk24u7s/8R+NV53cLBUIJaAGIMVC95RLaKzxdrEi96ruHyizV9RBy718mbievcgKC0Nmbo59yADkVaqgzcri4S8bie/3LknzviTvxg1k5ubYvtMD919+xrRSpULnkxkb475xI1V3bEdezBM7CQkJCQmJ1xEjIyM+/fRTPv/8c3JycvD19cXMzIyEhASqV69u8Ho8SuDk5ERISAjr169n0aJFBiqB/6ZcuXK4urqSlZUFQL9+/bh69Spbt24t0FcIUaQE+tSpU7l69SobN24sdk2NGjWie/fuhe55ynfOrl27xr59+3BwcCh2LoC6desSHR1d6LHMzEw2b978TKqAj5OvBnjlyhV9W0pKCsnJycWqLuZH3gpL91u9ejX29va89dZbeiXNfEl+lUploK75OBUrVtT/7Ys7d2RkJGfOnMHY2Jj9+/cTGRmJg4MDmzdvJjIyklWrVhW7ZplMRvPmzZkxYwYRERGYmpqyZcsWrK2tcXd3LzattSSkp6cTGBiIqakp27ZtKzYaWhQzZ84kMjJSn94YGRnJwIED6d+/P5GRkURGRj4xDbZy5coMHTqUP/74g3HjxvHDDz887ZJKTExMDLm5ufro9+tEqSNoj+eNWlpasnz58jI16GWSm6VCCN0/oHIzORpjgVwLaM2oZaFAk6oEYxlmVZ89L7asSdu+g8TPP0fk5iKvXJlK3y9G4eWF88SJZJ86xcPNm8k4cBDTqh6U69ULm86dMS5mg2Y+JuVeTWdUQkJCQkKiLOjZsycTJkxgyZIljB8/nvHjxzNmzBi0Wi0tWrTQCzPY2NgQEhLC1KlTqV+/Pn5+fiiVSrZv366PIqxYsYLIyEjefvttqlWrRm5uLuvWrSMqKorFixcD0KtXL7Zs2ULfvn35/PPPCQwMxMnJiQsXLrBw4UJGjhxZaF2n8uXLM3bsWL766qsnrumLL77Az8/PYF+QSqXinXfeITw8nO3bt6PRaLh79y4A9vb2RcrBBwUFMXnyZFJTUyn3r3uCTZs2oVar6d+/f6FjIyMjAZ0jd//+fSIjIzE1NdVHyLZs2cLkyZP1EUVPT0+6du3KqFGjWLlyJTY2NkyePBlvb29at24N6ERW5HI5tWrVwszMjDNnzjB58mR69+5dIDKUlJTE7Nmz9cIa5cqVw8fHh0WLFhEYGMj+/fv57LPPnng9i6N69eqcOHGC8uXL06JFCxISEsjIyKBLly5PFOI4efIk+/fvJzAwEGdnZ06ePMn9+/f1n6fp06czdOhQnJ2d6dixIxkZGRw7dkwfeZo8eTK3b98usg5ZvnOWnZ3N+vXrSU9PJz09HdA9ZCipWIqzszPOzs6cP3+eYcOGUb16dS5dusQHH3ygj0YXx+jRo+nYsSOenp6kpqZy8OBB/RoLw9vbm7lz5/L2228X2Sc6Opq8vDxSUlLIyMjQf9bq1Kmj7xMaGkrVqlWfuB/zlaS0so+DBw8WBw8eLEslyZdOvtxw1OlY8e2gNeLrXp3Esg97iJpra4oWP9QWbhO3izv748TNiUdE0g/nX7a5BUg/eFBEe3mLaC9vET/4faF+SqlSCQkJCYn/DcpaZv91oShJ7rlz5wonJyeRmZkptFqtWLRokfDy8hJyuVw4OTmJoKAgcfjwYSGEELNmzRI+Pj7C3Nxc2Nvbi65du4obN24IIYQIDw8X/fv3Fx4eHsLMzEw4ODiIVq1aiW3bthmcT6PRiGXLlomGDRsKCwsLYWNjI+rXry++/fZbvSR4vsz+46SlpQlHR8dCZfYjIiIM+g4ZMkQAepn9/H6FvZ50X9eoUSOxfPnyAu1NmzYV/fr1K3JcYedyc3PTH1+zZo34961oWlqaGDRokLCzsxP29vbi7bffFgkJCfrjGzduFPXq1RNWVlbC0tJS+Pr6ijlz5uhl9R+nT58+YvHixQZtJ0+eFN7e3sLe3l7MmDGj2HWXlLlz54r+/fsLIYRYt26daNeuXYnGRUdHi6CgIOHk5CTMzMyEp6dnAXuXL1+u/yy6urqKkSNH6o+FhISIgICAIufPl7Av7JX/+RFCCDc3t2LLMQghRGJiol6yXqlUCnNzc3Hr1q0SrXPEiBGiWrVqwszMTDg5OYng4GCRnJxsYOPjMvuAWLNmTbFzurm5FbquxwkMDBRz584tkY2vGjIhSrdbtWvXruzevRsnJyf69OlD//79S1WA8FUkPT0dW1tbwg9eI/Snv1Fl/421ixmL613FJdeMlKS5/F3RFeXVVGzf9MC6VeEpgS8DbVYWMV26oL6TiF3PnrhMn4asDOVjJSQkJCT+e+T/7uVLbktIFMeOHTuYMGECFy9exMio9MIsEq8u2dnZODg4sGvXrtdOir44oqKiaNOmDVevXi0TRcgXTam/ZVu3biUxMZEpU6Zw+vRp6tWrh5+fH3PmzCEuLu45mPjieDzFUZjq8pNN1ApqlrciL1aXE/6qCYTc/24x/9/encdFVa9/AP/MDDMw7PsugiKiooi45FJqLqhJbuFakVm2WL/S22a3sm6ldu8tW665lXm9am5l5VZuKLkjiuICgoAogiD7Ogwz398fNCdGQEF2+7xfL14vOOfMOc85IM7D8/0+34ob6VB6eMDl7flMzoiIiKhRPfLII5g9ezbS0tJaOhRqZBEREXj44Yfvq+QMqFzCYO3atW0yOQOAelfQbnf9+nV8//33WL16NRISElBRUdFYsTUbw18SD2w+i7Pbt0CnOQNVRy1Wdr4Bz3x3PGb3CUIuFEJurYLb/L6QyWQtHTIAoPT8BaRMngzo9Wi3aiUsH3ywpUMiIqI2gBU0IqLWq0F1aq1Wi1OnTuHEiRNISUmBi4tLY8XVIjRFFRD6ygpaqUlla1VdhRW66isfk5mvbatJzkRFBTLeew/Q62E9ZgyTMyIiIiKi+8A9JWgRERF49tln4eLigqeeegrW1tbYsWMHrl+/3tjxNavSYi2EvnINlEJlGQBAU2ELl8rRjlC6WrRUaNXkrFuHsosXIbe2hsvb81s6HCIiIiIiagT1brPv4eGBnJwcjBo1CitXrkRoaKi0eGNbV16iBf6Yg5b3R4JWqnOAulALHQATJ3ULRvcn7Y0byPqysl2v82t/g0kjLmZIREREREQtp94J2vvvv4+wsDDY2to2QTgtq7SoXKqg3VLrAMhhofaE7lZlsqZ0Nm/B6CoJIZDx4UcQJSVQ9+oF28cea+mQiIiIiIiokdR7iOOzzz57XyZnAFBaWASgckX5m38UywJtvIAKPaCQQWFX/9XX60tXUICi33+HqGVl+8I9e1EUEQEolXD74H3I2O6WiIiIiOi+wXf3VZQWVbbSV5mZIVtV2Qwk2MwZAGDiqIZM3vQNQtJeew3Xnp2Nmx9/XG2frrAQNz/6CADg8MwsmHbq1OTxEBERERFR82GCVkVFWSEAQG2ugv6Pbo1dFJXth5tjeGPJmTMojvwdAJC74XvkrF9vtD9ryeeoyMqCsr0XHJ97rsnjISIiIiKi5sUErao/Wuwr/xjeqNbJ4KqrfETN0SDk1lf/qby+pycA4ObCRSg6fAQAUBoTg9zvvwcAuL3/PuRmTT/ckoiIiKi8vBy+vr44evRoS4dCbYy3tzc+//zzRj3nrVu34Ozs3Oa7x98JE7QqxB8dHHUm5QAAtU4FVX7l501dQSs5fRrFR48CJibwWvMdbMaPB3Q6pM2di7L4y0h/bwEgBGzGjYNF//5NGgsREdH96KmnnoJMJoNMJoNSqYSPjw/eeOMNlJWVNdo1Dh06hIcffhj29vYwNzdHp06dEB4ejvLycukYIQRWrlyJfv36wdLSEra2tujduzc+//xzlJSUAKhsyiaTyfD8888bnT8mJgYymQwpKSkAgJSUFMhkMjg7O6OwsNDo2J49e+L999+Xvv7xxx8xcuRIODg4QCaTISYmpk73tHz5cvj4+GDAgAHSNWfNmgUfHx+o1Wp07NgRCxYsMLrHgwcPYty4cXBzc4OFhQV69uyJ9beNDKrNmjVr0KNHD5iZmcHZ2Rlz5syR9qWkpOChhx6ChYUFHnroIek5GIwdOxY//PBDna5TH3q9HtbW1rh8+TIAwM/PD5GRkY1+nfqIjIxEaGgo3N3dIZPJ8NNPPzX4nP/6178wffp0AMCGDRvw8MMPN/ic9bVy5UoMGTIE1tbWkMlkyMvLM9rv6OiIJ598EgsWLGj22JoLE7QqhL7yl6JGXvmL2gJqVGRVLlht4tS0Cdqt/1RWz2wnTIDK0xOu//gA6uBg6AsLkTJlCjSXL0Nhawvnt95s0jiIiIjuZ6NGjUJ6ejqSkpKwZMkSrFixotHe6F28eBGjRo1C7969ERkZidjYWHz11VdQqVTQVWn+9cQTT+DVV1/FuHHjEBERgZiYGLz77rv4+eefsWfPHuk4MzMzfPvtt0hISLjrtQsLC/Hvf//7jscUFxdj0KBB+OSTT+p8T0II/Oc//8GsWbOkbXFxcdDr9VixYgUuXLiAJUuWYPny5Xj77belY44ePYoePXrghx9+wLlz5zBz5kw8+eST2LFjxx2v99lnn+Hvf/873nrrLVy4cAH79u1DSEiItP9vf/sbPDw8EBMTAzc3N7z22mvSvk2bNkEul2PSpEl1vr+6On/+PMzMzODn54ebN2/i6tWr6NOnT6Nfpz6Ki4sRGBiIpUuXNto5jx07hoEDBwIAfv/9d+nz5lRSUoJRo0YZ/TzdbubMmVi/fj1ycnKaMbJmJFqxr7/+WnTv3l1YWVkJKysr8cADD4hdu3ZJ+0tLS8WLL74o7O3thYWFhZg4caLIyMio93Xy8/MFALFw8gvi35MfEZ/NHyoC1gSIp1ZNFNfejBTX3owUurKKxrw1I8WnTomLnf3FxW4BQnPturRdm50tEh4eVrmvs7/I/XFbk8VARER/HYb/9/Lz8xvlfHq9Xmg0mmb/0Ov19YozPDxcjBs3zmjbxIkTRVBQkPS1TqcTCxcuFN7e3sLMzEz06NFDbNmyRdqfk5Mjpk+fLhwdHYWZmZnw9fUVq1evFkIIsWTJEuHt7X3HGDZt2iQAiJ9++qnG55iXlyeEEGLBggUiMDBQjBgxQoSFhUnHnDlzRgAQycnJQgghkpOTBQDx+uuvC0tLS3Hz5k3p2MDAQLFgwYJq1zG85syZM3eMVQghoqKihFwuFwUFBXc87p///Kfw8fG54zFjxowRM2fOrHV/Tk6OUKvVYt++fbUe06VLF7F7924hhBC7du0SXbt2FUIIkZubK3x9fUVqauodY7hXy5Ytk352tm7dKvr163fX18TExIghQ4YIS0tLYWVlJXr16iWioqKk/YcPHxaDBw8WarVa2NraipEjR4qcnJx7ig+A2LZt2z29tipXV1fp5yIgIEB61rXR6/ViwYIFol27dkKlUgk3Nzfx8ssvS/vbt28vlixZck+xRERECAAiNze3xv0+Pj7im2++uadzt3b1XgetOXl6emLx4sXo1KkThBD473//i3HjxuHMmTPo1q0b5s6di507d2LLli2wsbHBSy+9hIkTJ+LIkSP3dD2hLwHkQKmycqhjR1kHAIDCxhRyU0Wj3dftsgzVs4kTofL0kLab2Nuj3fJlSH16FtQ9A2EzflyTxUBERHSvtFotFi5c2OzXffvtt6FSqe759efPn8fRo0fRvn17aduiRYuwbt06LF++HJ06dUJkZCQef/xxODk5YfDgwXj33Xdx8eJF7N69G46OjkhMTERpaeVoG1dXV6SnpyMyMhIPPfRQjddcv349OnfujHHjqv+fLpPJYGNjY7Rt8eLF6NOnD06dOoXevXvXei/Tpk3D3r178Y9//AP/+eN9RWP4/fff4efnBysrqzsel5+fD3t7+7se06VLl1r37927F3q9HmlpaejSpQsKCwsxYMAAfPrpp2jXrh0AIDAwEPv27cPIkSOxZ88e9OjRAwDw+uuvY86cOdJxjcWwtFRZWRmEELC1tYVGo4FOp4OtrS0GDRpUa1VwxowZCAoKwrJly6BQKBATEwOlUgmgcqjqsGHD8PTTT+OLL76AiYkJIiIipErrmjVrMHPmTAghGvV+arJ48WIsXrwYQOX3aPDgwZDJZMjPz8fkyZMhl8uxY8cODBo0qNprf/jhByxZsgQbN25Et27dkJGRgbNnz9Z6raeeegopKSk4ePBgg+Pu27cvfv/9d6Pq7v2iVSdooaGhRl9//PHHWLZsGY4fPw5PT098++23RuNjv/vuO3Tp0gXHjx/HAw88UP8L/jEHrVRVOcSxo8wbAGDi3HQNQkpOnULJseOAUgnH52ZX22/aqRN8Iw9BJmv6Fv9ERET3ux07dsDS0hIVFRXQaDSQy+VSQqPRaLBw4ULs27cP/f+Y792hQwccPnwYK1aswODBg5GamoqgoCApWfL29pbOHRYWht9++w2DBw+Gq6srHnjgAQwbNgxPPvkkrK0ru0InJCSgc+fOdY63V69emDx5Mt58803s37+/1uNkMhkWL16M0NBQzJ07Fx07dqzvo6nR1atX4e7ufsdjEhMT8dVXX91xiOXmzZsRFRWFFStW1HpMUlIS9Ho9Fi5ciC+++AI2NjZ45513MGLECJw7dw4qlQr//ve/8dxzz8Hb2xs9evTAihUrEBkZiZiYGHzyySeYPHkyTp06hZEjR+LLL79sUAIPVCZSQggEBwdjw4YN8Pf3x8iRI/H+++9jwIABMLtD07bU1FS8/vrr8Pf3BwB0qrI80j//+U/07t0bX3/9tbStW7du0uc2Njb1+jlpiOeffx5Tp07FmjVrcPz4cSxfvhy7du3CmjVrsHnzZgCVf3yoSWpqKlxdXTF8+HAolUp4eXmhb9++tV7Lzc0Ner2+UeJ2d3fHmTNnGuVcrU2rTtCq0ul02LJlC4qLi9G/f39ER0dDq9Vi+PDh0jH+/v7w8vLCsWPH7pigaTQaaDQa6euCggIAgNAXAwo5itTlAEzgoav8YZQ7mEGr1TbJfWV+9RUAwHr8eMDZucmuQ0REZNDY/9colco7zhdpKoZqRH0MHToUy5YtQ3FxMZYsWQITExNpzlJiYiJKSkowYsQIo9eUl5cjKCgIAPDCCy9g0qRJOH36NEaOHInx48dLzTMUCgW+++47fPTRRzhw4ABOnDiBhQsX4pNPPsHJkyfh5uZ2TxWRjz76CF26dMGePXvg7Oxc63EhISEYNGgQ3n33XWzYsKHe16lJaWnpHZOQtLQ0jBo1CmFhYXj22WdrPCYiIgIzZ87EqlWrjJKQ2+n1emi1Wnz55ZcYOXIkAOD777+Hq6srIiIiEBISAg8PD6OKlUajQUhICP773//io48+gpWVFeLj4zFq1CisWLECL7/8crXrLFy40Kjie/HiRXh5edUYk7e3N06ePAlzc3OMGjUK169fx40bNzBp0iSYmprWei8AMG/ePDzzzDP43//+h+HDhyMsLExKnGNiYhAWFlbraydMmIAJEybc8fyNxdbWFra2tjh58iQmTZoEb29vnDlzBo8++qjRHyBqEhYWhs8//xwdOnTAqFGjMGbMGISGhsLEpOYUY9GiRY0Wt1qtlprq3G9afYIWGxuL/v37o6ysDJaWlti2bRu6du2KmJgYqFQqqfRs4OLigoyMjDuec9GiRfjggw9q2KMDIMcts8rM3iSrsodK3M0ruLXrYiPcjTGLixfhceIkhEKBmI4dUbFrV6Nfg4iI6HaN/aZGJpM1uFLRXCwsLODr6wsAWL16NQIDA/Htt99i1qxZKCoqAgDs3LkTHh4eRq8zvBkfPXo0rl69il27dmHv3r0YNmwY5syZY1Q98vDwwBNPPIEnnngCH374Ifz8/LB8+XJ88MEH8PPzQ1xcXL1i7tixI5599lm89dZb+Pbbb+947OLFi9G/f3+8/vrr9bpGbRwdHREbG1vjvhs3bmDo0KEYMGAAVq5cWeMxhw4dQmhoKJYsWYInn3zyjtdyc3MDAHTt2lXa5uTkBEdHR6Smptb4moULF2LkyJEIDg7Gs88+i48++ghKpRITJ07EgQMHakzQnn/+eUyePFn6urYK4ejRo/H777+joqICFRUVsLS0hE6ng0ajgYODAwBIPzM1ef/99zF9+nTs3LkTu3fvxoIFC7Bx40ZMmDABanXTL99UF7///jtGjx4NoPL3wsGDBzF37lyUlpZCqVRi8eLFePvtt2v9A0y7du0QHx+Pffv2Ye/evXjxxRfxr3/9C4cOHbqnP6DUR05ODpycnJr0Gi2l1SdonTt3RkxMDPLz87F161aEh4fj0KFDDTrn/PnzMW/ePOnrgoICacyyiUqNbFXlcEJ3mRMAgZ5DekPVwaamU9VICAHNhQso/PkXKJydYPfMM9WGKOpLSpC65HNUALB78kl0mjG9QfdERERUV4aRI391crkcb7/9NubNm4fp06eja9euMDU1RWpqKgYPHlzr65ycnBAeHo7w8HA8+OCDeP3112sd3mdnZwc3NzcUF1dOo5g+fTqmTp2Kn3/+udo8NCEECgoKqs1DA4D33nsPHTt2xMaNG+94T3379sXEiRPx1ltv3e3268Qwh0oIYfReJi0tDUOHDkVwcDC+++47yOXVG4MfPHgQY8eOxSeffILZs6tP47idoWNgfHw8PP9YEzYnJwe3bt0ymidocOnSJWzYsEFaLkCn00nVYa1Wa9Q5syp7e/u7zpcDgG+++QalpaUIDw/HxIkTMW7cOLz22mvw9/fHM888c9fXA5Xt+P38/DB37lxMmzYN3333HSZMmIAePXpg//79tRQMmk/v3r0RExOD6OhovPHGG9i/fz9SU1Px6KOP4vTp05DL5Xd9Vmq1GqGhoQgNDcWcOXPg7++P2NhY9OrVq0ljP3/+PIYMGdKk12gprT5BU6lU0l+6goODERUVhS+++AJTpkxBeXk58vLyjKpoN2/erHWcrIGpqWmtZWml2hw5CgWUehMoCiqHIZi5WUNRh78C6AoLUbBjB3I3b4Hm0iVpu0JhUm1+2c2vl6EiIwNKT0+4/N/LkDfxXxmIiIgMmvov221JWFgYXn/9dSxduhSvvfYaXnvtNcydOxd6vR6DBg1Cfn4+jhw5Amtra4SHh+O9995DcHAwunXrBo1Ggx07dkiNL1asWIGYmBhMmDABHTt2RFlZGdauXYsLFy7gqz+mNEyePBnbtm3DtGnT8M4772DkyJFwcnJCbGwslixZgpdffhnjx4+vFqeLiwvmzZuHf/3rX3e9p48//hjdunWrNswsJycHqampuHHjBoDKRAionF9U23unoUOHoqioCBcuXEBAQACAyuRsyJAhaN++Pf79738jKytLOt5wnoiICIwdOxavvPIKJk2aJI1uUqlU0hv+bdu2Yf78+VJF0c/PD+PGjcMrr7yClStXwtraGvPnz4e/vz+GDh1qFJcQArNnz8aSJUtgYWEBoDLBW7VqFfz8/LB27VpMmzbtrs/qTjw8PFBRUYFz585h3bp18PHxwblz5/Dmm29K701rU1paitdffx2PPfYYfHx8cP36dURFRUnDaefPn4/u3bvjxRdfxPPPPw+VSoWIiAiEhYXB0dGx2rOpSVFRERITE6Wvk5OTERMTA3t7+1qHbN5OrVbD19cXW7duxZAhQ6QFyQcOHAg/P7+7vn7NmjXQ6XTo168fzM3NsW7dOqjV6hoTasN9p6WlYe3atbWeMyMjAxkZGdK9xcbGwsrKCl5eXtLPTklJCaKjo1ukOVGzaLH+kfdo6NChIjw8XOTl5QmlUim2bt0q7YuLixMAxLFjx+p1TkO74Y8mjBQrX3pGBKwJEI8sHyGuvRkpri84Uqc2vvm7fxWXgnpJLfEvde8hUp56Svo6/7ffpGNLYs+Li126ioud/UVhZGS9YiUiImqoxm6z31bU1GZfCCEWLVoknJycRFFRkdDr9eLzzz8XnTt3FkqlUjg5OYmQkBBx6NAhIYQQH374oejSpYtQq9XC3t5ejBs3TiQlJQkhhDh9+rR4/PHHhY+PjzA1NRUODg7ioYceEr/88ovR9XQ6nVi2bJno06ePMDc3F9bW1iI4OFh88cUXoqSkRAjxZ5v9qvLz84Wjo2ONbfZvb5k/e/ZsAcCozf53330nAFT7qKkVf1WTJ08Wb7311l3PU/VtZXh4eI37Bw8eXO08t9/j008/LWxtbYW9vb2YMGFCja3zly9fLiZNmmS07ebNm2LYsGHCyspKhIWFieLi4jveV10cO3ZMeHp6CiGEuHbtmjA3Nxfl5eV3fZ1GoxFTp06V2s+7u7uLl156SZSWlkrHHDx4UAwYMECYmpoKW1tbERISIrWUr+nZ3M7Qhv72j/DwcOmYBQsWiPbt29813pCQEKll/dNPPy0++uiju75GCCG2bdsm+vXrJ6ytrYWFhYV44IEHjJZJuL3Nfnh4uNHPQE0WLFhQ431999130jEbNmwQnTt3rlOMbZFMiGbo33mP5s+fj9GjR8PLywuFhYXYsGEDPvnkE/z2228YMWIEXnjhBanLjLW1tTTO+OjRo/W6jmE4wUcTRsLFxwtf9DiOB/OD8PaNZ6FqZwXnOT3v+PrSs2dx9YknIcrLofLtCLvJk2Hz6KNQ2Noi48OPkLt+PWRqNbzXr4Opnx9SJk9B2cWLsB4zBh6ffXqvj4eIiOieGP7fy8/Pl7oLEtXm3LlzGDFiBK5cuQJLS8uWDofqITw8HDKZDGvWrGnpUBrVAw88gP/7v//D9On35xShVj3EMTMzE08++STS09NhY2ODHj16SMkZACxZskRaMd7Qxadqu9J7IVTlAICO5ZUTVU2c7jyJU3vjBq7NeQmivByWw4bB86svIasyDttl/lsoT0lB8ZEjuPbCi7B59FGUXbwIubU1XN6e36BYiYiIiJpajx498MknnyA5ORndu3dv6XCojoQQOHjwIA4fPtzSoTSqW7duYeLEiQ0ewtqateoKWnOpWkGzD7DC1x3j8d71WehfGAzrUd6wHlLzoof64mKkzHgcmrg4mPr7w3v9Osj/GAddla6gAClTp6E8KUna5vqPD2BXpYMQERE1raysLFy7ds1om0KhgL+//13bZTeFa9euwcbGpkUqWKygERG1Xq26gtYSKkwqWw97lFdOclXWUkETej3S3ngTmrg4KBwc0O7rpTUmZwCgsLZGu+XLkBI2Gbr8fKh79YLtY481zQ0QEZERIQSio6Oxa9euGhdI9ff3x9SpU5s1ptTUVKxevRpubm547rnnmvXaRETUujFBu02ZshgQgIu2cl0FE2fzGo/LWvI5ivbvh0ylQrul/4GyljU0DFReXmj3zSrkrlsPx5dfMhoGSURETUOr1WLXrl04c+YMgMqubObmf/5ev3LlCuLi4nDp0iWpE19zMLQFT09PR2FhIaysrJrt2kRE1LoxQbtNmbIEjhV2MNWrALkMJvZm1Y4pv34d2d98AwBw+/hjqHv2rNO51d27Q/3J4sYMl4iIapGfn4/NmzcjLS0NMpkMw4YNw8CBA43Wctq3bx8OHz6MXbt2wcfHB2Zm1X/nNzatVosLFy5IX1+9elVqX05ERMQyzm2KVCVop3EBAJg4mEGmqP6I8jZuBISAxYD+sAkd29whEhHRXaSkpGDlypVIS0uDmZkZZsyYgUGDBhklZwAwePBg2NnZobCwEAcOHGiW2BISEqDRaKSvk5OTm+W6RETUNjBBq0KhNEexSQXa/TH/zMSp+vBGvUaDvK0/AADsZsxo1viIiNqa5u5DJYTAiRMnsHbtWhQXF8PFxQWzZ8+udVFZpVKJsWMr/9B28uRJpKWlNXmM586dAwA4OzsDqEwmiYiIDJigVaFSW6NQoYdneWUFTelcvUFIwa7d0OXlwcTdDZZDhjRzhEREbUdkZCQWLlxYrXNiVREREVi8eDFu3LjR4OtptVr89NNP2L17N/R6PQICAjBr1izY29vf8XUdO3ZEjx49AADbt2+HTqdrcCy1KSkpQUJCAgDgkUceAQBkZ2ejsLCw0a6xefNmfPXVVygtLW20cxIRUfNhglaFqdoSeXLFn0Mca6ig5W7YAACwmzIVMoWiWeMjImor0tPTERERAa1Wi6ioqBqP0el0OHHiBMrKyrBv3756nT8zMxOJiYnSx+XLl7F69WqcPXsWMpkMISEhmDRpElQqVZ3OFxISArVajYyMDBw/frxesdTHxYsXodPp4OLigvbt28PVtXLERmNV0QoKCnDx4kVkZ2cjLi6uUc5JRETNi01CqlCpzZGrkMNTGuJoXEErPXcOZbGxkCmVsA1jm3wiopro9Xps375dGt54+fJl6HQ6KG77o9bVq1dRVlYGAEhKSkJqaiq8vLzuev7jx4/j119/rXGfubk5wsLC4OPjU6+YLSwsMGLECPzyyy84ePAggoODm6RhiGF4o6Fi5+3tjYyMDKSkpDTKAsCJiYnS53FxcQgKCmrwOYmIqHmxglaFytQERVDBscIWAKp1cMxdX1k9sxo9CiZ3GTJDRG1LWVkZTp06haKiopYOpVVKSkpCUlJSnY49efIkbty4AVNTU6jVapSVleHq1avVjjNUeOR/LDsSERFx13NfvnwZv/32GwDAyckJrq6u0oe/vz9mz55d7+TMICgoCA4ODtBqtdIwxMaUm5uL1NRUAJCSMUOsjVVBu3LlitHn5eXljXJeIiJqPqygVaUScNDZVn5uIoPcQintqsjNRcHu3QAA++nTWyA4ImoqOp0OGzduREpKCq5fv47x48e3dEitSlFREdatWwchBJ555hl4eHjUemx+fr7UDXH48OG4ceMGzpw5g7i4OHTo0EE6TgghJWijRo3Cr7/+iuTkZFy9ehXt27ev8dyZmZnYunUrhBDo1asXQkNDq3VlbAiZTAZ/f38cOXIEcXFxjVLRqio2NhZAZVJmbW0NAFLFMDs7GwUFBdL2e6HX66UETaFQoKKiAleuXGnW9d2IiKjhWEGrQpiUwUlbWRkzsTUz+o8/b+tWiPJymHXrBrPAwJYKkYgamRACO3fulCoYCQkJ0Ov1LRtUDcrLy7Fz584mqezczZUrV6DX6yGEuGsTjd27d6O8vByenp4IDg6Gv78/gMpqWdWOjjdu3EBBQQGUSiWCgoKkoXgHDx6s8bzFxcXYsGEDysvL0b59e4wZM6ZRkzMDQzKTkJCAioqKRjuvEKLa8EYAUKvVcHNzA9DwKlpaWhrKyspgZmaG3r17AwDnoRERtUFM0KooVxbAscIOAKCw+XNiudDpkPf9RgCA3fTpTfKmgIhaxokTJ3D69GkAlVWH4uJi3Lx5s4Wjqu7kyZOIiorCzp07m711fdV5TRkZGThx4kSNx126dAlxcXGQy+UIDQ2FXC5Hhw4doFQqUVBQgPT0dOlYQ+LQqVMnKJVKPPjgg5DL5UhOTq6WqFRUVGDTpk3Iy8uDnZ0dpkyZAhOTphkA4u7uDktLS5SXlzfq+mTp6em4desWTExMqlW0vL29ATQ8QTN8nzp06ICuXbsCAOLj45u0KyURETU+JmhVaBS5cNIaEjRTaXvBr79Ce+MGFDY2sH5kTEuFR0SNLCEhQZrPNHLkSHTs2BGAcULSHMrKyvDNN99g7969Ne7X6/VSJ8S8vDxkZ2c32rW1Wi02btyItWvX1lgxqjpsLvCP0QMRERHIy8szOi4rKwu7du0CAAwYMAAuLn8sV6JUSmuQXbp0STrekKAZKmy2trbo1asXgD+raBUVFbhw4QL++9//IjU1Faamppg+fTrMzat32G0scrncqOrXGHQ6HQ4fPgwA6Ny5c7XmI42VoBm+Tx07dkS7du1gbm5e6/w/IiJqvZigVVFikg9nQ4JmW5mglV2+jIx33wMA2E6bCnkTdPUiouaXmZmJLVu2QAiBoKAg9O/fX0okqjZaaA6JiYm4fv06jhw5goyMjGr7L1++jPz8fOnrxorPMGQxLi4OSUlJNQ6fzMjIQElJCVQqFUJDQ+Hl5QWtVmtUybt48SJWrVqFwsJCODg4YPDgwUbnMFSMDAlPdnY2srKyIJfL0alTJ+k4QxUtJSUF27Ztw2effYYtW7bg2rVrUCgUCAsLg5OTU6Pc+51UTdAaOty1qKgIa9euxcWLFwFAGnpYlZeXF2QyGXJyclBQUHBP1ykpKZEW2fb19YVcLkfnzp0BcJgjEVFbwwStimJR9OcQR1tTVGRn4/rzL0BfUgLzvn3h9OKLLRwhETUGnU6HTZs2SfOZHnnkEchkMilBS01NhUajabZ4DG+sgZrnYBmqZxYWFgAar8J3+PBhaV4UAKPPDQzX8vHxgYmJiTR0MSEhARcuXMD+/fuxefNmlJeXw9vbGzNnzoRSqTQ6R6dOnSCXy5GVlWW0Ppe3tzfU6j+XM7GxsZGqaGfPnkVJSQksLS3x0EMP4eWXX5a+P03N29sbpqamKC4uxvXr1+/5PNevX8eKFStw9epVqFQqTJ06tcYOk2q1usHroSUlJUEIAScnJ9jY2ABArfP/iIiodWMXxypKRKk0xFFuocD1l16G9sYNKNt7weOLzyGr44KnRNS6nTt3DtnZ2TA3N8fkyZOl+Uz29vawt7dHTk4OkpOTpTe4d5KWlgaFQiG9wb4XVRO0uLg4pKenS40jbt26JVXMQkNDpW6TWq22WiJUHxcvXsT+/fsBAH369EFUVBQuX76M0tJSo6TJkKAZkiMnJyc8+OCDOHToEH744Qfpjf8DDzyAESNGVFvrDKhMQLy9vZGUlIS4uDhpqGNNz3fw4MHIyMiAWq1GcHAwOnXqVOM5m5KJiQn8/PwQGxuLuLi4u67NlpeXh+TkZKNqW1FRESIjI6HT6eDg4ICpU6fesfrn4+OD9PR0pKSkGDURqelaOTk58PHxMZoPffv3CUC1+X/u7u53vXciImp5TNCqKEK5lKDlrl2J0jNnILeyQrtly2BiZ9fC0RFRY9DpdDh06BAAYNCgQVJVyqBjx47IyclBYmLiXRO0/Px8rF69Gnq9HiNGjED//v3r3URIp9NJzTPc3d1x48YNHDx4ENOmTQMAnDp1CkBlFapz586wtLREUVERUlNTpTlz9XXjxg1s27YNANC3b1+MHj0aKSkpyMrKwqVLl6QqVllZmVRBqvrGf9CgQTh//jyys7NhYmKCRx999I5JBVCZjCUlJeH06dPSHLqanq+VlRWeeeaZe7qvxuTv7y8laCNGjKj2fdXpdLh8+TKio6PvWNHs3LkzJkyYcNdFr729vXH06NE7NiYpKyvD6tWrUVBQgNGjR6Nfv34AKoeqVp1/ZmCY/3fp0iVcunSJCRoRURvBIY5VaGECK33lm7WCnT8ACgU8Pl8C0ypr9xBR23b27Fnk5eXBwsKixvlAhkQkMTHxrsPCzp8/D51OByEE9uzZgx9++KHawsC3bt3CoUOHam2Pf+vWLWi1WqhUKowfPx4ymQzx8fFIT09HeXk5zpw5A6Aykao6DPNe56EVFRXh+++/h1arRceOHRESEgKZTCYlWFWHORqqQg4ODrCr8kcqpVKJKVOmoHfv3pg1a9ZdkzPgz2TMkJx5eHg0aM2vpubr6wuFQoGcnBxkZWVJ23U6HSIjI7FkyRJs2rRJSs48PT3h5+dn9DFq1ChMmTLlrskZ8Oc8tNzcXKP5hlVFRERIc9R+/fVX6WcqMzMThYWFMDExqbaG3O3z/4iIqPVjBa0Kub7yDYheWwJUlMHlnXdgOXBgC0dFRI3F8OYaAAYOHAhVDcOWvb29IZfLpaFkDg4OtZ7PkMx06tQJV65cwfnz55GZmYmwsDBkZGQgOjpamlOkVCrx5ptvVmsPbxje6O7uDmdnZwQEBCA2NhYHDx5Ep06doNFoYGdnJ1VGfH19ERMTg8TERIwcObLez+DEiRMoLCyEo6MjwsLCpOGD3bt3x/79+5GSkoK8vDzY2tpKyUdNlTpnZ2eMHTu2zte1traGh4eHdL91GT7akkxNTdGhQwckJCQgLi4Ozs7OKC4uxtatW6Uql4WFBXr27IlevXrd8eekLszMzODh4YHr169j9+7dmDx5MuTyP/+GmpaWJi1v4OXlhdTUVGzduhWzZs2Svk/e3t53nf/X0DiJiKjpsYJWhUJULlItSnIBALZhj7VkOETUyGJiYu5YPQMq35gbqhB3Grp28+ZN3Lx5EwqFAhMnTkR4eDgsLCyQmZmJpUuX4ocffkBKSgpkMhkUCgW0Wi1SU1OrnceQsHh4eAConINlqKIZhmL26dNHerPe4Y+KfmZm5j11/DPM/3rooYeMKju2trbSfZ8/fx5CiBrnNTVE1aSstSdowJ8xXrp0CTdu3MDKlSuRnJwMpVKJcePGYe7cuRgxYkSjJT0hISFQKBSIi4vDgQMHpO06nQ7bt28HULnI9ZNPPgkvLy9oNBp8//33UofImr5Phvl/AKtoRERtBRO0Ksz0fyRopTkwcXGB3NT0Lq8gotro9XqUlZUZfWi12ia71t1UVFRI1bNBgwbVWD0zqMt6aFWrZ2q1Gu3bt8dzzz0nJVrW1tYYPHgwXnnlFQQEBNR6vqoVNABwdHRE9+7dAUAathYUFCQdb25uLl2jvt0cb926hVu3bkEul8PPz6/afsNQxbNnzyI7Oxv5+flQKBTSG/yG6tatG5RKJTw8PJqlXX5DGdrUp6enY/Xq1cjPz4e9vT2effZZBAUFNfpi2e3atcOjjz4KoLLD5tmzZwFUVj0NjVNCQkJgYmKCKVOmwNbWFrm5udLPUG1zEg2J5uXLlxs1XiIiahoc4liF3R8t9vWluVB6erZwNERtV3l5OZYvX46cnByj7XK5HI8//rhUBWoMSUlJ2LhxIwIDA/HII4/UetzZs2eRn58PS0vLWqtnBr6+vti3bx9SUlJQUVFR7Y24Xq9HbGwsABjNv7K2tsbTTz+NzMxMODs7S8MHfX19cfbs2WrDErVaLTIzMwH8WUEDKqtbsbGxEEKge/fuRl0VDedLS0vDlStXpIYedWGooPj4+NQ4L6pr167YtWsXsrKycOTIEQBA+/bt75jM1oe9vT1efvnlRjtfU7O0tJSGE1ZUVMDPzw8TJkyo9v1oTIGBgcjKysLhw4fxyy+/QCaTISIiAgAwYsQIqamNhYUFpk+fjm+//RYajQY2NjZwdHSs8Zxdu3aFpaXlPTeVISKi5sUKWhWOWlsAlRU0FRM0ug9kZWU1WdXqTq5evVotOQMqE5vff/+90a5z69YtaQ2uqKioWhtn3F49u1t7ehcXF1haWtY6LPHq1asoKCiAmZmZ0ULLAKBQKODm5mbUGt7wxvj2YYkZGRnQ6/WwsLCQ1q4CKqtoAwYMgKWlJQbWMA+2aqOQ+iykbEjQahteqFarpcqaoTlJY7+pt7a2rlPTjNaib9++MDU1xeDBgzF16tQmTc4MHn74Yfj7+0On0+HHH3+EVqtF+/btjSqpQOU8wLCwMJibm0tNZGpiaWmJrl27wpSjQoiI2gQmaFU4VNgCAPSlOVC2a9eywRA1UFJSEpYuXYodO3Y0+7UNjTECAwPxzjvv4J133sHLL78MmUyG5ORko65496qkpAQbNmxAWVmZlHDt2LGjxoQ0MjJSqp4FBwff9dxVuyXWNIzQMLyxa9eudVqLrOqwxKpJZNX5Z7e/uR4xYgRee+21Gqsi7u7uMDMzQ1lZmdEaandSWFgotcw3DN2rye0dGZtrcejWKiAgAG+99RaGDh1q1LSjKcnlckycOFFaW0+hUCA0NLTGBMzX1xevv/56jYk8ERG1TUzQqnD8I0ETpblQtWMFjdo2QwvuCxcuVGv93tQMCZqPjw9MTExgYmICBwcHqToTFRXVoPPrdDps3rwZOTk5sLGxwQsvvAArKyvk5uZKlTKDc+fOSdtGjhxZ58Wdq85Dq9puX6vVSk0Z6tJevqbzGdzeIKSuFAqFNEy0rvPQ4uPjpWvdqb19p06dpAqXlZUVnJ2d6xXb/ai+a9s1BpVKhWnTpqFz584YO3ZsrcMXgZaJj4iImg4TtCoctIY5aKygUdt348YNAJXD++51zax7UVZWJl379uYSffr0AVDZTVGj0dzT+YUQ2LlzJ1JSUqBSqTB9+nTY29tjzJgxAIAjR47g5s2bAIBr167h559/BlDZVr++CZVMJkNmZiZ++uknqTJ3+fJlaDQaWFtbw8vLq87nq2lY4u0NQuqjvuuhGbo3GtbFqo2JiQm6desmXYNv/luOjY0Npk2bVm1oIxER3d9adYK2aNEi9OnTR/or7vjx46W/AhuUlZVhzpw5cHBwgKWlJSZNmiS9OasvM1E5cV2wSQi1MomJidi+fTvKysrqdLxOp5OSJKB522tfu3YNQgjY2dnB1tbWaF+HDh1gb2+P8vJyowWR6+P48eM4ffo0AGDSpElwcXEBUJl4dO7cGXq9Hjt27EBeXh42btwInU6Hzp07Y9iwYfW6jrm5OUaPHg2ZTIazZ89i9erVyMvLk+Lu0aNHvYa8eXh4wNTUVEpgS0tLpXl69a2gAX9W5NLS0rB27VrpY/369dWqamVlZdLaXXVpbz98+HAMHTq03s+MiIiIGq5VJ2iHDh3CnDlzcPz4cezduxdarRYjR45EcXGxdMzcuXOxfft2bNmyBYcOHcKNGzcwceLEe76mvqwAMqUCJm2gBTT9dfz666+Ijo6uNnyvNrdu3TKaixUfHw+dTtdU4RkxDG+sqTW7XC5H3759AQAnT540GjpYF5cvX8aePXsAVA5XvH0u1ZgxY6BSqXDt2jWsWLECxcXFcHFxwcSJE+9p/lDfvn3xxBNPQK1WIz09HStXrpSGjtanGgdUH5ZoSKDt7Oxgbm5e79hsbGzg7u4OIQSSkpKkj4SEBHz//fe4du2adGxCQgL0ej0cHR3vOFTOQK1WY/DgwbC0tKx3XERERNQwrTpB+/XXX/HUU0+hW7duCAwMxJo1a5Camoro6GgAQH5+Pr799lt89tlnePjhhxEcHIzvvvsOR48exfHjx+/pmqI0B0pPTw7roXqrqKjAunXrsHXr1nonHndSWFiIW7duAahMaoqKiu76GsPQOS8vL5ibm6OsrAxXr15tlHg0Go1Uqampg6ChUlPb2lmBgYFQKpXIysoyiqmiogK7d+/Gl19+WWPFLzMzU3q2QUFB6N+/f7VjbGxs8PDDDwMASktLYWFhgWnTpjWoe12HDh3w3HPPwdXVFSUlJdDr9XB1db2nuVlVG4/c6/yzqqZOnYqJEycaffj6+kKn02Hjxo3Iy8sDcPfujURERNR6tKl10PLz8wFUrqUDANHR0dBqtRg+fLh0jL+/P7y8vHDs2DE88MADNZ5Ho9EYzX+p2vZaX5oLEw+PFmlNTm1bdHS0NLRs4MCBdapU1EVSUpL0eUVFBX7//Xejn/maGKon7u7usLOzw9mzZ3Hx4kW0q8PcSq1WC71eX2NSo9frsWXLFimmuLg4ozbzGo0G6enpAABPT88a/x2ZmJggICAAZ86cwYkTJ+Dh4YHCwkL88MMPUtKyceNGPPjgg3jwwQchk8lQXFyMDRs2oLy8HF5eXggJCUFFRUWN8QcFBeHChQu4efMmHnvsMVhYWDT437OFhQWefPJJ7N69G7GxsQgODr6ncxqS1rS0NKmi5+rqes/xqdXqanPKOnbsiP/+97/IzMzEhg0bMGPGDKnq5+vry99tBAD8OSAiasVkojH/1N+E9Ho9Hn30UeTl5eHw4cMAgA0bNmDmzJnVmg307dsXQ4cOxSeffFLjud5//3188MEH1bZffHU3TK8fR4bVNWSNe7Txb4LuW3q9HhcvXpTe9Hh4eDRa97vU1FRkZ2dDrVajtLQUMpkM3bp1u2M3wri4OJSWlsLb2xtyuRxJSUlQKpXo1q3bHavDRUVFSE5Ohl6vh5eXF+zs7Iz2p6WlSQsrA5Vd/qq2Yc/Pz0dSUhJUKpXUaKImpaWlUlXH29sb169fR0VFBRQKBaytrZGbmwsAUiOO5ORkFBcXQ6VSoXPnztUWjr6dEAJ6vd5oLbLGotPpGnTeS5cuGc0l7NSpU6MPJSwvL0d8fDwqKipgamoKjUZTp+8//XWUlJRg+vTpyM/Pv2NXTyIian5tpoI2Z84cnD9/XkrOGmL+/PmYN2+e9HVBQYFUWdCX5qLT6IHo80dHOKK6OHXqFM6ePSt9bWpqKnUVbKjly5cDAB555BEcPXoUN27cgIWFRa1VtIqKCimWsWPHwtzcHEuWLIFWq0WvXr3g5uZW7TVCCOkeDMMWU1JS4ObmhiFDhkAulyMmJkZavHjo0KGIiIhAYWEhHnjgAamqvX//fiQlJaFLly53vf+1a9fi2rVr0pw1JycnPPbYY7C3t8e5c+ewe/duFBQUIC4uTko0nnrqqUarTLYUpVKJkydPAqhsjz5+/HioVKpGv05aWhr+97//SX/A6tGjB0aNGtXo16G2qerIESIial3aRIL20ksvYceOHYiMjIRnle6Krq6uKC8vR15enlG3uJs3b0oLfNbE1NS01jkpojQHZt7edV4riaiiogJHjx4FUNlGPioqCqmpqQDQ4J+jwsJCZGdnA6gcumZmZoZ169YhOjoagwYNgpWVVbXXZGRkQK/Xw8LCAg4ODtKiy5cuXUJiYmK11vBarRY7d+6UkrqAgABYWVnh2LFjOHbsGDIzM9G7d2/s3r0bADBkyBAMHjwY165dQ2JiIs6cOSO98Tfcd8eOHe9673379pWGYnbr1g2PPvqo9O8yODgYbm5u2LRpE/Lz8yGTyRAWFlZjctnW+Pn5SQmas7MzLCwsmuQ63t7eGDduHH788UcAdV9Um/4a+LNARNR6teoETQiBl19+Gdu2bcPBgwfh4+NjtD84OBhKpRL79+/HpEmTAFR2q0tNTa2xgUBd6EtzoPRgi/3mptVqcfToUbi6ulbrzNfanT59GoWFhbCyssLIkSMRHx+PgoICXL161Wj4370wVJdcXV2hVqvRsWNHeHp64vr16zhy5EiNFZGqzScMw9n8/f1x6dIlxMXFSU00ACAvLw+bNm1Ceno6ZDIZRowYgf79+0Mmk8Hd3R0///wzrly5Iq211a1bNwwePBhAZYKVmJiImJgYPPzww9Dr9dL8s/bt29/13rp164acnBxYWVkhKCio2tA7d3d3zJ49G5GRkfD29m7ws2wt2rdvDxMTE1RUVDSoQUhd9OjRAzqdDrm5udV+fxIREVHr1KoTtDlz5mDDhg34+eefYWVlhYyMDACVndrUajVsbGwwa9YszJs3D/b29rC2tsbLL7+M/v3719og5G5EaS5Unk37pomMVU0STE1N8cYbbzTJ3KGmoNVq8fvvvwMAHnzwQSiVSnTs2BFnzpxBYmJioyVohuYSMpkMQ4YMwbp163Dq1CkMHDiwWhWtpsWP/fz8IJfLkZmZiezsbDg4OCA5ORlbtmxBSUkJ1Go1wsLCpDbwANC9e3c4OTlJ3QDd3d0xfvx4KZHy9fWFnZ0dcnNzERsbCysrKwghYG9vDxsbm7vem1wul5K92lhYWGD06NF3PVdbYvgZiY+Pr1Mi21Bc5JiIiKhtadUJ2rJlywBUDqmq6rvvvsNTTz0FAFiyZAnkcjkmTZoEjUaDkJAQfP311/d0PSH0UKhNIG+iIUdUXdUkAajsAnjt2rVaW7TfTVFREbZv3w5PT08MHDjwnta+qoler8euXbuQn5+PwMBA+Pv7w8TERKqeWVtbo1evXgAqE5czZ85IVaeGMCRoVasfVatohw8frpbAGNbXqlqdUavV8Pb2RlJSEuLi4iCXy7Fnzx4IIeDq6oopU6ZUawgCVFbunnvuOVy+fBl+fn5Gw6Lkcjl69+6NvXv3IioqSorxXr93fyWhoaHo3r07unbt2tKhEBERUSvTqhO0ujSYNDMzw9KlS7F06dKGX68sH6p27nc/kBpMCIFjx45h7969UpJgbm6OpKQkXLly5Z7f5B89ehTx8fHSUNeJEydCrVY3ON6YmBicOnUKQOWiv+bm5ujZsydiY2MBVFbPDJ0FO3ToAJlMhqysLOTn59epmlSTgoICaf5Z1XljMpkMQ4cOxf/+9z+pimbowlZaWiq95vbhc/7+/khKSkJERITUor5Hjx4IDQ2943wUtVqNwMDAGvcFBQUhIiICGRkZ0ppbTNDuztLSEgEBAS0dBhEREbVCrXqh6uYmSnOhrMM6UdRwERERUgUnMDAQs2bNkpIAw1pi9aXVaqUugzKZDAkJCVi1ahVu3rzZoFiLioqwZ88eAJVDBa2srFBSUoKjR49K1bOqw8jUarXUzOZe7wX4s3rm5uZWLcns0KED2rVrB51OhyNHjkjbDdUzOzs7mJubG73GMLevoqICMpkMo0ePxoQJExrULMDc3FxKNAyt45mgEREREd07JmhV6MvyoGzHBiFNLSMjQ5q3FRISgvHjx0vzcgAgPT0dRUVF9T7v+fPnUVpaChsbGzzzzDOwsbFBTk4OvvnmG1y4cOGe4/3tt99QVlYmDQV89dVXMW3aNPj5+cHU1BSjRo2qti6X4V4aI0GrKeExzEUDKlv8G1pmV20QcjsbGxsEBATAxsYG4eHh6NevX6OsidW3b1/pc8NcUCIiIiK6N0zQqqhsEMIKWlPS6/XYvn07hBDo2rWr1DEQqBz2ZVgeob7zt4QQUuvyPn36wMPDA7Nnz4aPjw+0Wi22bNkiVZfq48qVK4iNjYVMJkNoaCgUCgUUCgU6d+6M6dOnY/78+TXOIzI0B0lKSoJOp6v3dYE7J2hAZRXNy8sLOp1OWh/QcI9VG4RU9dhjj+HVV19t1CqXu7u7VDFkp0AiIiKihmGCVoW+NA9KT1bQmlJUVBTS0tKkytPtDIlNfRO0tLQ0pKenQ6FQSMMNLSws8Pjjj0tD+wwJXF2Vl5djx44dACqrRPVpie7u7g61Wg2NRiNVtYDKBPXs2bNISkq64+sLCgqQk5MDmUxWa6e/qlW06OhoFBQU3LGCVvV1jW306NHw8/O75+UtiIiIiKgSE7SqynKh4hDHJlNQUID9+/cDAIYNG1bjUDhDgpaYmAi9Xl/ncxuSr4CAAKOFfxUKBQYNGgQAiI2NlbpF1kVkZCRyc3NhbW1ttHZYXcjlcqllvWGYY1lZGTZt2oRt27Zh7dq12LdvX633WHX+mZmZWa3X8fHxkapou3btQmFhIWQyWbMv6Ozh4YHp06fD0dGxWa9LREREdL9hglZFhSYfJi4uLR3GfWvXrl0oLy+Hp6cnevfuXeMxnp6eUKlUKCkpkda9M9BoNNi5cyeioqKMOnwWFRVJc8yqzoeqek43NzfodDqcPn36rnFqNBqcOnUKR48eBQCMGTMGpqamdb5Pg6rVwKysLKxatQrx8fFS6//Dhw9j/fr1NSaNdxveaGDo6AgAcXFxAABnZ2eoVKp6x0tERERELY8JWhXFphWQtZEFktuauLg4af2t0NDQWtcnMzExkeYx3d5g48CBA4iKisLOnTuxdetWaDQaAMCZM2eg0+ng7u5e49A+mUyGPn36AKhsqFFb1erGjRvYvn07Pv30U+zYsQN6vR5dunSBv7//Pd2zoVFIWloaVq1ahezsbFhbW2PWrFmYOHEiTExMcOXKFaxatapaMpqcnAygbh0Rvb29jYZB1mcoJhERERG1Lq16HbTmprGzbOkQ7juFhYWIiYnBsWPHAAD9+/eHy12qlL6+voiPj8eVK1fw0EMPAahMck6cOAGgcvjghQsXkJWVhcmTJ0vrk9VUPTMICAjAnj17kJeXh4SEBGleGlDZdn7Lli2Ij4+Xttnb2yM4OPiO57wba2truLi44ObNmygvL0f79u0RFhYGS0tLeHh4wNnZGRs3bkRubi5WrFhh1AlSq9VCJpMZrX9WG8NctP/+978AmKARERERtWVM0KqQuXH+WWMQQuDKlSuIjo5GfHy8VLFycnLC4MGD7/p6Q+Xp2rVrKCsrg1KpxPbt2wEA3bt3R58+fbB582ZkZmZi2bJl0Ol0UKvV6NatW63nVKlUCAoKwrFjxxAVFSUlaEII7Nq1Sxp62LVrVwQHB8Pb27tRmmkEBgZiz5496NevH0aOHAlFlQqtq6srZs+ejR9//BGJiYnQarVGr+3UqdMd559V5ePjgy5duuDKlSvS8yMiIiKitocJWhVmHt4tHcJ94eTJk9i9e7f0taenJ4KDg9GtW7c6zY2yt7eHvb09cnJykJycjNzcXGRkZECtViMkJASWlpaYPXs2Nm/ejOvXrwMAevXqddcFl/v06YNjx44hMTER2dnZcHBwwPHjx3H69GnIZDJMnToVfn5+Dbv52wwYMADBwcG1zmEzNzfH448/joKCAqN2/DKZrN7riYWFhUGv11dbk42IiIiI2g6+k6vCsg7DydqK/Px85OTktMi6VNHR0QAqq12DBg2665DGmvj6+uLkyZM4ffq01DBjxIgRsLSsHIZqbW2Np556Cvv370dGRgYeeOCBu57T3t4enTp1QkJCAqKiotChQwfs2bMHADBy5MhGT84M6tJgpDEWd5bL5bXO7SMiIiKitoEJWhWW3vdHgqbX67Fu3TpkZWXh8ccfl7oJNofs7GxkZmZCLpdjzJgxUKvV93Sejh074uTJk0hISAAAtG/fXlrfzMDExAQhISH1Om+fPn2QkJCAM2fO4PTp0xBCoFevXnVK8IiIiIiImhr/3F6FbYf7I0FLSkpCVlYWAOD48ePNem1Dq3dvb+97Ts4MrzfM11IoFBg7dmyjzAnz9fWFnZ0dNBqN1LhjzJgxTbJ4MxERERFRfTFBq8LM1qalQ2gUUVFR0ueJiYnIyclptmsbErR7bU1vYGpqKg3PHDRoEJycnBocG1A5DNDQct/Ozg5TpkzhnC0iIiIiajX4zvQ+k5eXh8uXLwOoXLA4MzMTUVFR9R4KWJuUlBTs27cPDz/8MDp06GC0r7CwENeuXQMAozb29+rRRx9Famoqunbt2uBzVdWvXz+Ym5ujY8eOMDc3b9RzExERERE1BCtorYwQotaFlOvi1KlTEELAx8cHw4cPB1C5kHN5eXmdXl+1k+Dtbt26hY0bN+L69evYsWNHtWMNiaG7uztsbBpejbS2tkZAQECjN75QKBTo2bMnrKysGvW8REREREQNxQStlSgrK8PJkyexfPlyfPzxx0hMTKz3ObRaLU6fPg2gctFmX19f2NraoqysDOfPn7/r65OTk7Fw4UL88MMP1RK6kpISbNiwAWVlZQCAnJycaue8dOkSAKBLly71jp2IiIiIiJigtbj09HT89NNP+Pe//41du3bh5s2b0Ol0+OWXX6DRaOp1rosXL6KkpATW1tbw8/Mzmm918uRJCCHu+Pro6GjodDrExsbim2++keau6XQ6bNmyBTk5ObCxsUH//v0BAIcOHZKqaGVlZUhOTgbQ8PlnRERERER/VUzQWtCNGzewatUqxMTEoKKiAk5OTggJCYGtrS0KCgoQERFRr/OdPHkSANC7d2+pA2JQUBBMTEyQkZEhLepck4qKCqmlvUqlQmZmJlauXImEhATs2rULycnJUKlUmDZtGoYMGQK1Wo2cnBzExsYCqGxGotPp4ODgAEdHx3t5HEREREREf3lM0FqIXq/H9u3bodfr0b59ezz99NN48cUX0b9/f4wdOxYAcOLECdy4caNO50tLS0NaWhoUCgV69eolbTc3N0dAQACAPxO4mqSkpECj0cDS0hJz5syBh4cHysrKsH79emnh6UmTJsHV1RWmpqYYOHAgACAyMhI6nc6oeyNb1hMRERER3RsmaC3k5MmTSE9Ph5mZGR577DF4eXlJiY2vry8CAgIghMD27dvv2LjDwNBav2vXrrC0tDTa17dvXwDAhQsXUFRUVOPrDfPHOnfuDBsbG8ycORPBwcHS/hEjRhh1ZuzTpw/Mzc2Rk5ODM2fOSA1COLyRiIiIiOjeMUGrwZEjR7Bt2zYkJiY2qKNibfLz83HgwAEAwPDhw2vsJjhq1CiYmZkhPT39jpUvoLKBh6FhhyEZq8rd3R0eHh7Q6/VSNawqvV6P+Ph4AH8mWCYmJggNDcWUKVMwfvx4DBgwwOg1Vatov/76K8rLy2FpaQkPD4+73T4REREREdWCCdptTp48ib179+Ls2bNYt24dvvzyS0RGRqKwsLBRzi+EwK5du1BeXo527doZDUesytLSEiNGjAAAHDhwAHl5ebWe88yZM6ioqICrqys8PT1rPMaQuJ04caJah8a0tDQUFRVBpVJJi0MbdOnSBT179qxx2KKhilZRUQGgMrlr7Jb4RERERER/JXw3XUVSUhJ2794NAOjYsSNMTU2Rl5eHAwcO4LPPPpNa2DfEpUuXEB8fD7lcjtDQ0DsmNEFBQfDy8oJWq8Wvv/5a4zF6vV4a3ti3b99a538FBATAzs4OJSUl0vEGhvljfn5+MDGp+9rlKpVKqqIBHN5IRERERNRQTNCq2LZtG4QQCAwMxOOPP46//e1vGD9+PDw9PSGEwO7du5Gbm1vr6/Py8u44JLKsrExKAAcOHAhnZ+c7xiOXyzF27FjIZDLExcXV2IUxISEBeXl5MDMzk5qB1EShUOChhx4CUDmE01BFE0JI88/uJcHq06cPHB0d4eDgAG9v73q/noiIiIiI/sQErQrDsMPQ0FDIZDKoVCr07NkTs2bNQvv27aHVarFr164a1xP77bff8Pnnn9c4JDIvLw8RERH4+uuvUVhYCHt7eylZuhtnZ2f06NEDQOW6Y7czVMOCgoKgUqnueK4ePXpIVTTDvLZbt24hJycHCoUCvr6+dYqpKpVKhRdeeAFz5sypV/WNiIiIiIiqa/UJWmRkJEJDQ+Hu7g6ZTIaffvrJaL8QAu+99x7c3NygVqsxfPhwaT2v+rKxscGUKVOqJRoymQxjx46FXC5HQkICLl68aLT/1KlTOHbsGAAYDYncuHEj1q9fjy+++AKHDh1CQUEBzM3NMX78eCiVyjrH9dBDD0EmkyEhIcGoipadnY3ExEQAkBakvhOFQoHBgwcDAI4ePQqNRiNVz3x8fGBmZlbnmG4/L+eeERERERE1XKt/V11cXIzAwEAsXbq0xv3//Oc/8eWXX2L58uU4ceIELCwsEBISgrKysnpf67HHHqvWot7AyckJDz74IABg9+7dKC0tBQAkJydj165dACoTqfHjx6Ndu3YQQiAuLg4JCQkQQsDb2xuTJk3CvHnz4OXlVa+4HBwcEBgYCAA4ePCgtN1QPfP19YW9vX2dztW9e3fY29tLc9Gqrl9GREREREQtq9WPSRs9ejRGjx5d4z4hBD7//HO88847GDduHABg7dq1cHFxwU8//YSpU6fW61p3mxM2aNAgnD9/HtnZ2di/fz/69++PTZs2Qa/XIyAgAEOHDoVMJkPPnj2RmZmJs2fPQi6XIzAwEI6OjvWK5XYPPfQQzp49i8TERFy7dg0uLi6IiYkBUHNr/doY5qL99NNP+P3336HRaADAaI0zIiIiIiJqGa0+QbuT5ORkZGRkYPjw4dI2Gxsb9OvXD8eOHas1QdNoNFJiAgAFBQUAAK1WC61We8drjh49GuvWrcOpU6dw+fJllJWVwd3dHWPGjJHazQOAnZ0dhgwZIn19t/PejZWVFXr06IGzZ88iIiIC/v7+KCsrg62tLby9vet1/i5duiAyMhI5OTkAAE9PT5iZmTU4RiIiahv4+56IqPVq0wlaRkYGAMDFxcVou4uLi7SvJosWLcIHH3xQbfuePXtgbm5+1+va29sjJycHBQUFUCqVsLe3x969e+sZff0Z/kNNSkpCamoqAMDc3FzqDFkfVlZWUoKm1+ulYZpERHT/KykpaekQiIioFm06QbtX8+fPx7x586SvCwoK0K5dO4wcORLW1tZ3fX1JSQlWrVqF8vJyPPHEE3B1dW3KcI0olUqcPXsWFRUVMDExwdSpU6FWq+t9Hr1ej9WrVyMnJwcTJkyAra1t4wdLREStkmHkCBERtT5tOkEzJEY3b96Em5ubtP3mzZvo2bNnra8zNTWFqalpte1KpbJO3RVtbGzw4osvQq/X19pUpKkMGTIEsbGx0Ov16N69e50Syto8/fTT0Gq1zX4PRETUsurTSZiIiJpXq+/ieCc+Pj5wdXXF/v37pW0FBQU4ceIE+vfv36TXNjc3b5HExs7ODg8++CCsra0xcODABp3L1NSUyRkRERERUSvS6itoRUVF0lpfQGVjkJiYGNjb28PLywuvvvoqPvroI3Tq1Ak+Pj5499134e7ujvHjx7dc0E1s6NChGDp0aEuHQUREREREjazVJ2inTp0ySkYMc8fCw8OxZs0avPHGGyguLsbs2bORl5eHQYMG4ddff73nRZeJiIiIiIhaikwIIVo6iJZWUFAAGxsb5OfnN2hOFxERUVvA//eIiFqvNj0HjYiIiIiI6H7CBI2IiIiIiKiVYIJGRERERETUSjBBIyIiIiIiaiWYoBEREREREbUSTNCIiIiIiIhaCSZoRERERERErQQTNCIiIiIiolaCCRoREREREVErwQSNiIiIiIiolWCCRkRERERE1EowQSMiIiIiImolmKARERERERG1EkzQiIiIiIiIWgkmaERERERERK0EEzQiIiIiIqJWggkaERERERFRK8EEjYiIiIiIqJVggkZERERERNRKMEEjIiIiIiJqJZigERERERERtRJM0IiIiIiIiFoJJmhEREREREStBBM0IiIiIiKiVoIJGhERERERUSvBBI2IiIiIiKiVuG8StKVLl8Lb2xtmZmbo168fTp482dIhERERERER1ct9kaBt2rQJ8+bNw4IFC3D69GkEBgYiJCQEmZmZLR0aERERERFRnd0XCdpnn32GZ599FjNnzkTXrl2xfPlymJubY/Xq1S0dGhERERERUZ2ZtHQADVVeXo7o6GjMnz9f2iaXyzF8+HAcO3asxtdoNBpoNBrp6/z8fABATk4OtFpt0wZMRETUwgoLCwEAQogWjoSIiG7X5hO0W7duQafTwcXFxWi7i4sL4uLianzNokWL8MEHH1Tb7uPj0yQxEhERtUbZ2dmwsbFp6TCIiKiKNp+g3Yv58+dj3rx50td5eXlo3749UlNT+R9VEykoKEC7du1w7do1WFtbt3Q49yU+46bHZ9w8+JybXn5+Pry8vGBvb9/SoRAR0W3afILm6OgIhUKBmzdvGm2/efMmXF1da3yNqakpTE1Nq223sbHhm4EmZm1tzWfcxPiMmx6fcfPgc256cvl9MRWdiOi+0uZ/M6tUKgQHB2P//v3SNr1ej/3796N///4tGBkREREREVH9tPkKGgDMmzcP4eHh6N27N/r27YvPP/8cxcXFmDlzZkuHRkREREREVGf3RYI2ZcoUZGVl4b333kNGRgZ69uyJX3/9tVrjkNqYmppiwYIFNQ57pMbBZ9z0+IybHp9x8+Bzbnp8xkRErZdMsMcuERERERFRq9Dm56ARERERERHdL5igERERERERtRJM0IiIiIiIiFoJJmhEREREREStxF8+QVu6dCm8vb1hZmaGfv364eTJky0dUpu1aNEi9OnTB1ZWVnB2dsb48eMRHx9vdExZWRnmzJkDBwcHWFpaYtKkSdUWGae6W7x4MWQyGV599VVpG59x40hLS8Pjjz8OBwcHqNVqdO/eHadOnZL2CyHw3nvvwc3NDWq1GsOHD0dCQkILRty26HQ6vPvuu/Dx8YFarUbHjh3x4YcfomrfKj7j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ggkaEbUpBw8ehEwmQ15eXkuHQkRERNTomKARERERERG1EkzQiIiIiIiIWgkmaERUL3q9HosWLYKPjw/UajUCAwOxdetWAH8OP9y5cyd69OgBMzMzPPDAAzh//rzROX744Qd069YNpqam8Pb2xqeffmq0X6PR4M0330S7du1gamoKX19ffPvtt0bHREdHo3fv3jA3N8eAAQMQHx/ftDdORERE1AyYoBFRvSxatAhr167F8uXLceHCBcydOxePP/44Dh06JB3z+uuv49NPP0VUVBScnJwQGhoKrVYLoDKxmjx5MqZOnYrY2Fi8//77ePfdd7FmzRrp9U8++SS+//57fPnll7h06RJWrFgBS0tLozj+/ve/49NPP8WpU6dgYmKCp59+ulnun4iIiKgpyYQQoqWDIKK2QaPRwN7eHvv27UP//v2l7c888wxKSkowe/ZsDB06FBs3bsSUKVMAADk5OfD09MSaNWswefJkzJgxA1lZWdizZ4/0+jfeeAM7d+7EhQsXcPnyZXTu3Bl79+7F8OHDq8Vw8OBBDB06FPv27cOwYcMAALt27cIjjzyC0tJSmJmZNfFTICIiImo6rKARUZ0lJiaipKQEI0aMgKWlpfSxdu1aXLlyRTquavJmb2+Pzp0749KlSwCAS5cuYeDAgUbnHThwIBISEqDT6RATEwOFQoHBgwffMZYePXpIn7u5uQEAMjMzG3yPRERERC3JpKUDIKK2o6ioCACwc+dOeHh4GO0zNTU1StLulVqtrtNxSqVS+lwmkwGonB9HRERE1JaxgkZEdda1a1eYmpoiNTUVvr6+Rh/t2rWTjjt+/Lj0eW5uLi5fvowuXboAALp06YIjR44YnffIkSPw8/ODQqFA9+7dodfrjea0EREREf1VsIJGRHVmZWWF1157DXPnzoVer8egQYOQn5+PI0eOwNraGu3btwcA/OMf/4CDgwNcXFzw97//HY6Ojhg/fjwA4G9/+xv69OmDDz/8EFOmTMGxY8fwn//8B19//TUAwNvbG+Hh4Xj66afx5ZdfIjAwEFevXkVmZiYmT57cUrdORERE1CyYoBFRvXz44YdwcnLCokWLkJSUBFtbW/Tq1Qtvv/22NMRw8eLFeOWVV5CQkICePXti+/btUKlUAIBevXph8+bNeO+99/Dhhx/Czc0N//jHP/DUU09J11i2bBnefvttvPjii8jOzoaXlxfefvvtlrhdIiIiombFLo5E1GgMHRZzc3Nha2vb0uEQERERtTmcg0ZERERERNRKMEEjIiIiIiJqJTjEkYiIiIiIqJVgBY2IiIiIiKiVYIJGRERERETUSjBBIyIiIiIiaiWYoBEREREREbUSTNCIiIiIiIhaCSZoRERERERErQQTNCIiIiIiolaCCRoREREREVErwQSNiIiIiIiolfh/nsuUycA/vjoAAAAASUVORK5CYII=", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "fig, ax = plt.subplots()\n", - "\n", - "for label in list(sorted_labels):\n", - " _ = np.round(architectures_TM[label]['epochs_acc'][-1], 2)\n", - " nb_skip = nb_skip_conns[label]['nb_skip_conns']\n", - " nb_skiped_l = nb_skip_conns[label]['nb_jumped_layer']\n", - " txt = f'{label} ({_}% - # sc: {nb_skip}, # sl: {nb_skiped_l})'\n", - " ax.plot(np.arange(len(architectures_TM[label]['epochs_x'])), architectures_TM[label]['epochs_acc'], label=txt)\n", - "\n", - "ax.set_ylim(0, 100)\n", - "ax.set_yticks(np.arange(0, 110, 10))\n", - "ax.set_ylabel('validation acc [%]')\n", - "ax.set_xlim(0, 100)\n", - "ax.set_xlabel('epoch')\n", - "\n", - "pos = ax.get_position()\n", - "ax.set_position([pos.x0, pos.y0, pos.width * 0.9, pos.height])\n", - "ax.legend(loc='center right', bbox_to_anchor=(1.8, 0.5), framealpha=0)\n", - "ax.grid(axis='y')\n", - "\n", - "plt.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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xozh2muv5cEHH2wwv/aXZVVt2IrUZDKhn9RjUX0XXHABL7/8cvjC4+TyvvHGG8ycOfOMasw3b95Menp6s8vHjRvH448/TlFRUbhG+osvviA2NpZBgwaF19u/fz8ejydce94SnT7UWq3W8FXYyJEjWbduHc899xzXX389Pp+P8vLyBrW1x48fb3QFcDKbzRa+SqvPYrGc9U8fnUnqL/6X6vnz8axfj2/1apynOInPxtjvXMc3y7/i4MZ1VBQcJalndnjZ8OHD2bRpE7t27eLKK6885wb+Qggh2k9bfdfFxcW1e5it7/vf/z4PPPAAL774Ivfffz/3338/99xzD7quM2HCBCoqKli5ciWxsbHMmjWLhx9+mJEjRzJ48GC8Xi+ffPIJAwcOBODVV19l8+bNfOc736F37954PB7eeustduzYwZ/+9CcArrvuOt5//31uvPFGfvOb3zB9+nSSk5PZtm0bzzzzDHfddRfXXHNNo3KmpqZy77338uSTT572PT3++OMMHjwYs7kussXGxnLxxRfzwAMPYLfbycrKYunSpbz11ls8/fTTze5rypQpVFdXs2PHDoYMGdJg2eLFizl48CC3hkYsre/NN9/EarWGg+d7773H66+/zl/+8pfwOu+//z6zZ88O11xPnz6dQYMG8aMf/Yg//vGPFBYW8pvf/IY77rijQQZbvnw5vXr1onfv3qf9LE6nU98o1hRd1/F6vYwcORKLxcKiRYvCy3bv3k1+fj7jxo3rwBJ2HEtGBgk//CEARU89jVGvH72WSMzoQb8xwTZGaz/8T4NlmZmZxMfH4/P52L17d6scTwghhDgXZrOZO++8kz/+8Y/U1NTw2GOP8dvf/pY5c+YwcOBALrvsMj799FNycnKAYMXZ7Nmzyc3NZdKkSZhMpnDt6ZgxY6iuruZ//ud/GDx4MBdffDFff/01H3zwQbjmV1EU3n77bZ5++unw/NzcXH73u9/x7W9/mxkzZjRb1vvvvx+n03na99SvXz9uueWWRoNKvPPOO4wePZqbbrqJQYMG8cQTT/D44483GuChvm7duvGd73yHf/zjH42W/fWvf+Wiiy5iwIABTW772GOPMXLkSMaOHcuHH37Iu+++26CHhIqKigY5wGQy8cknn2AymRg3bhw//OEPmTlzJr///e8b7Pef//wnt91222k/hzOhGOfSyrmdzJ49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SBFnzpw5jB49mpiYGFJSUrjmmmvYvXt3Rxcrorz88svk5uaGBwMYN24c8+fP7+hiRbQnnngCRVG4++67O7ooEeV3v/sdiqI0eAwYMKCjiyVEqzivQ+27777LvffeyyOPPMLGjRsZNmwYM2bMoKioqKOLFjFqamoYNmwYL774YkcXJWItXbqUO+64g6+//povvvgCv9/P9OnTqamp6eiiRYwePXrwxBNPsGHDBtavX88ll1zCt7/9bXbs2NHRRYtI69at49VXXyU3N7ejixKRBg8eTEFBQfixYsWKji6SEK3ivO7Sa+zYsYwePZoXXngBCI5ElpmZyV133cWDDz7YwaWLPIqi8P7773PNNdd0dFEiWnFxMSkpKSxdupRJkyZ1dHEiVmJiIk8++SQ/+clPOrooEaW6upoRI0bw0ksv8X//938MHz6cZ599tqOLFTF+97vf8cEHH7B58+aOLooQre68ran1+Xxs2LCBSy+9NDxPVVUuvfRSVq9e3YElE6JlKioqgGDoEq1P0zTeeecdampqZCjuNnDHHXdwxRVXNPi3WbSuvXv3kpGRQa9evbjpppvIz8/v6CIJ0SoiYkSxc1FSUoKmaY1GHUtNTWXXrl0dVCohWkbXde6++27Gjx/PkCFDOro4EWXbtm2MGzcOj8eD0+nk/fffZ9CgQR1drIjyzjvvsHHjRtatW9fRRYlYY8eOZd68efTv35+CggIeffRRJk6cyPbt24mJieno4gnRIudtqBUiEt1xxx1s375d2si1gf79+7N582YqKir4z3/+w6xZs1i6dKkE21Zy+PBhfvGLX/DFF18QFRXV0cWJWJdffnl4Ojc3l7Fjx5KVlcW//vUvaUojurzzNtQmJSVhMpk4fvx4g/nHjx8nLS2tg0olxLm78847+eSTT1i2bBk9evTo6OJEHKvVSp8+fQAYOXIk69at47nnnuPVV1/t4JJFhg0bNlBUVMSIESPC8zRNY9myZbzwwgt4vV5MJlMHljAyxcfH069fP/bt29fRRRGixc7bNrVWq5WRI0eyaNGi8Dxd11m0aJG0kxNdimEY3Hnnnbz//vssXryYnJycji7SeUHXdbxeb0cXI2JMnTqVbdu2sXnz5vBj1KhR3HTTTWzevFkCbRuprq5m//79pKend3RRhGix87amFuDee+9l1qxZjBo1ijFjxvDss89SU1PDzTff3NFFixjV1dUNagAOHjzI5s2bSUxMpGfPnh1Ysshxxx138Pbbb/Phhx8SExNDYWEhAHFxcdjt9g4uXWSYPXs2l19+OT179qSqqoq3336bJUuWsGDBgo4uWsSIiYlp1A48Ojqabt26SfvwVnT//fdz1VVXkZWVxbFjx3jkkUcwmUzceOONHV00IVrsvA61119/PcXFxTz88MMUFhYyfPhwPv/880Y3j4lzt379eqZMmRJ+fe+99wIwa9Ys5s2b10Gliiwvv/wyAJMnT24w/4033uDHP/5x+xcoAhUVFTFz5kwKCgqIi4sjNzeXBQsWMG3atI4umhBn5ciRI9x4442cOHGC5ORkJkyYwNdff01ycnJHF02IFjuv+6kVQgghhBCR4bxtUyuEEEIIISKHhFohhBBCCNHlSagVQgghhBBdnoRaIYQQQgjR5UmoFUIIIYQQXZ6EWiGEEEII0eVJqBVCCCGEEF2ehFohRJeyZMkSFEWhvLy8o4sihBCiE5FQK4QQQgghujwJtUIIIYQQosuTUCuEOCu6rjNnzhxycnKw2+0MGzaM//znP0Bd04BPP/2U3NxcoqKiuPDCC9m+fXuDffz3v/9l8ODB2Gw2srOzeeqppxos93q9/OpXvyIzMxObzUafPn3461//2mCdDRs2MGrUKBwOBxdddBG7d+9u2zcuhBCiU5NQK4Q4K3PmzOGtt97ilVdeYceOHdxzzz388Ic/ZOnSpeF1HnjgAZ566inWrVtHcnIyV111FX6/HwiG0euuu44bbriBbdu28bvf/Y7f/va3zJs3L7z9zJkz+ec//8nzzz/Pzp07efXVV3E6nQ3K8etf/5qnnnqK9evXYzabueWWW9rl/QshhOicFMMwjI4uhBCia/B6vSQmJvLll18ybty48Pxbb70Vl8vFT3/6U6ZMmcI777zD9ddfD0BpaSk9evRg3rx5XHfdddx0000UFxezcOHC8Pa//OUv+fTTT9mxYwd79uyhf//+fPHFF1x66aWNyrBkyRKmTJnCl19+ydSpUwH47LPPuOKKK3C73URFRbXxpyCEEKIzkppaIcQZ27dvHy6Xi2nTpuF0OsOPt956i/3794fXqx94ExMT6d+/Pzt37gRg586djB8/vsF+x48fz969e9E0jc2bN2Mymbj44otPWZbc3NzwdHp6OgBFRUUtfo9CCCG6JnNHF0AI0XVUV1cD8Omnn9K9e/cGy2w2W4Nge67sdvsZrWexWMLTiqIAwfa+Qgghzk9SUyuEOGODBg3CZrORn59Pnz59GjwyMzPD63399dfh6bKyMvbs2cPAgQMBGDhwICtXrmyw35UrV9KvXz9MJhNDhw5F1/UGbXSFEEKI05GaWiHEGYuJieH+++/nnnvuQdd1JkyYQEVFBStXriQ2NpasrCwAfv/739OtWzdSU1P59a9/TVJSEtdccw0A9913H6NHj+axxx7j+uuvZ/Xq1bzwwgu89NJLAGRnZzNr1ixuueUWnn/+eYYNG0ZeXh5FRUVcd911HfXWhRBCdHISaoUQZ+Wxxx4jOTmZOXPmcODAAeLj4xkxYgQPPfRQ+Of/J554gl/84hfs3buX4cOH8/HHH2O1WgEYMWIE//rXv3j44Yd57LHHSE9P5/e//z0//vGPw8d4+eWXeeihh7j99ts5ceIEPXv25KGHHuqItyuEEKKLkN4PhBCtprZngrKyMuLj4zu6OEIIIc4j0qZWCCGEEEJ0eRJqhRBCCCFElyfND4QQQgghRJcnNbVCCCGEEKLLk1ArhBBCCCG6PAm1QgghhBCiy5NQK4QQQgghujwJtUIIIYQQosuTUCuEEEIIIbo8CbVCCCGEEKLLk1ArhBBCCCG6PAm1QgghhBCiy/v/itrxIleeIsYAAAAASUVORK5CYII=", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "fig, ax = plt.subplots()\n", - "epoch_lim = 6\n", - "\n", - "for key, val in architectures_TM.items():\n", - " y_avg = []\n", - " for y in val['epochs_y']:\n", - " y_avg.append(np.mean(y))\n", - " _ - np.round(y_avg[-1], 2)\n", - " ax.plot(np.arange(len(val['epochs_x']))[:epoch_lim], y_avg[:epoch_lim], label=f'{key} ({_})', marker='.')\n", - "\n", - "ax.set_ylim(0, 100)\n", - "ax.set_yticks(np.arange(0, 110, 10))\n", - "ax.set_ylabel('loss')\n", - "ax.set_xlim(0, epoch_lim-1)\n", - "ax.set_xlabel('epoch')\n", - "\n", - "pos = ax.get_position()\n", - "ax.set_position([pos.x0, pos.y0, pos.width * 0.9, pos.height])\n", - "ax.legend(loc='center right', bbox_to_anchor=(1.4, 0.5), framealpha=0)\n", - "ax.grid(axis='y')\n", - "\n", - "plt.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAssAAAHHCAYAAABJIhU9AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8fJSN1AAAACXBIWXMAAA9hAAAPYQGoP6dpAADGYklEQVR4nOzdd1iV5RvA8e85h8PeGxRkO1HcO/feq7RMK8uGlWY/28tRplmZLdOc5Ww4UjPNbSrurSjbATjY+6zfHy8cJEDBLLXuz3WdS3jH8z4vqNw8537vW2UymUwIIYQQQgghylDf7QkIIYQQQghxr5JgWQghhBBCiApIsCyEEEIIIUQFJFgWQgghhBCiAhIsCyGEEEIIUQEJloUQQgghhKiABMtCCCGEEEJUQIJlIYQQQgghKiDBshBCCCGEEBWQYFkIIYQQQogKSLAshKi0PXv28N5775Genn7X5vDSSy/RqFEjXF1dsbW1pXbt2rz33ntkZ2fftTkJIYT491KZTCbT3Z6EEOL+MGPGDCZMmEBcXBwBAQF3ZQ5t2rShcePGhISEYG1tzZEjR5g/fz5NmjRh586dqNWyBiCEEOLOsbjbExBCiKrYvXt3mW3BwcH873//Y//+/bRo0eIuzEoIIcS/lSzBCCEq5b333mPChAkABAYGolKpUKlUxMfHA6DX65k8eTLBwcFYWVkREBDAG2+8QUFBQalxAgIC6N27N5s2bSIiIgJra2vq1KnDzz//fNtzK17lvpvpIUIIIf6dJA1DCFEpx48f58MPP2TZsmV8+umnuLu7AzBgwADs7Ox47LHHWLRoEYMHD6ZDhw5ERkayePFi+vfvz6pVq8zjBAQEYGVlxZUrV3jmmWfw9PRkwYIFnDp1io0bN9KlS5dbzkWv15Oenk5hYSEnT55k7NixXLp0ifj4eFxdXf+2r4EQQoj/HgmWhRCVVlHO8rFjx4iIiODJJ59k7ty55u0TJkxgxowZbN26lQ4dOgBKsJyQkMBPP/3EwIEDAcjMzKRWrVp4e3tz+PDhW85j3759tGzZ0vx5zZo1mT17Nu3bt78zNyqEEEIUkTQMIcRftmHDBgDGjx9favvLL78MwPr160tt9/X1ZcCAAebPHR0dGTFiBEeOHCE5OfmW16tTpw6bN29m9erVvPLKK9jZ2Uk1DCGEEH8LecBPCPGXJSQkoFarCQkJKbXd29sbZ2dnEhISSm0PCQlBpVKV2hYWFgZAfHw83t7eN72eo6MjnTt3BqBfv34sXbqUfv36cfjwYRo0aPBXb0cIIYQwk5VlIcQd8+cA+J9SnM6xfPnyu3J9IYQQ/14SLAshKq2iYLhGjRoYjUbOnz9fantKSgrp6enUqFGj1Pbo6Gj+/LjEuXPnAG6rfnNBQQFGo5GMjIwqnyuEEELcjATLQohKs7OzA8qWaOvZsycAM2fOLLX9k08+AaBXr16ltl++fLlUhYzMzEwWL15MRETETVMw0tPT0el0ZbZ/++23ADRp0qRyNyKEEEJUkuQsCyEqrXHjxgC8+eabDB06FK1WS58+fWjQoAEjR45kzpw5pKen065dO/bv38+iRYvo37+/uRJGsbCwMEaNGsWBAwfw8vJi/vz5pKSksGDBgptef/v27bz44osMHjyY0NBQCgsL2bVrFz///DNNmjRh+PDhf9u9CyGE+G+S0nFCiCqZMmUKs2fPJikpCaPRaC4jp9fr+eCDD1i4cCEXL17E29ub4cOH8+6772JlZWU+PyAggHr16vHiiy8yYcIEoqKiCAwMZPLkyQwePPim146JiWHSpEns3r2bpKQkTCYTwcHBDB48mAkTJphXvoUQQog7RYJlIcQ/qjhYXrdu3d2eihBCCHFLkrMshBBCCCFEBSRYFkIIIYQQogISLAshhBBCCFGBuxos79y5kz59+uDr64tKpWL16tWl9ptMJt555x18fHywsbGhc+fOZeq4pqam8sgjj+Do6IizszOjRo2StrdC3MPi4+MlX1kIIcR9464Gyzk5OTRo0IAvv/yy3P3Tp09n1qxZzJ49m8jISOzs7OjWrRv5+fnmYx555BFOnTrF5s2bWbduHTt37mT06NH/1C0IIYQQQoh/sXumGoZKpWLVqlX0798fUFaVfX19efnll/nf//4HQEZGBl5eXixcuJChQ4dy5swZ6tSpw4EDB8zNCDZu3EjPnj25ePEivr6+d+t2hBBCCCHEv8A925QkLi6O5ORkOnfubN7m5ORE8+bN2bt3L0OHDmXv3r04OzuX6trVuXNn1Go1kZGRDBgwoNyxCwoKKCgoMH9uNBpJTU3Fzc2twna+QgghxL+FyWQiKysLX19f1Gp5fEmIm7lng+Xk5GQAvLy8Sm338vIy70tOTsbT07PUfgsLC1xdXc3HlGfq1KlMnDjxDs9YCCGEuL9cuHCB6tWr3+1pCHFPu2eD5b/T66+/zvjx482fZ2Rk4O/vT1xcHA4ODndxZkIIIcTfLysri8DAQPmZJ0Ql3LPBsre3NwApKSn4+PiYt6ekpBAREWE+5sqVK6XO0+v1pKamms8vj5WVVan2u8VcXV1xdHS8A7MXQggh7l1arRZAUg+FqIR7NlEpMDAQb29vtmzZYt6WmZlJZGQkLVu2BKBly5akp6dz6NAh8zFbt27FaDTSvHnzf3zOQgghhBDi3+WurixnZ2cTHR1t/jwuLo6jR4/i6uqKv78/48aNY8qUKYSGhhIYGMjbb7+Nr6+vuWJG7dq16d69O0899RSzZ89Gp9Px/PPPM3ToUKmEIYQQQggh/rK7GiwfPHiQDh06mD8vziMeOXIkCxcu5JVXXiEnJ4fRo0eTnp5OmzZt2LhxI9bW1uZzlixZwvPPP0+nTp1Qq9UMGjSIWbNm/eP3IoQQQggh/n3umTrLd1NmZiZOTk5kZGRIzrIQQoh/Pfm5J0Tl3bM5y0IIIYQQQtxtEiwLIYQQQghRAQmWhRBCCCGEqIAEy0IIIYQQQlRAgmUhhBBCCCEqIMGyEEIIIYQQFZBgWQghhBBCiApIsCyEEEIIIUQFJFgWQgghhBCiAhIsCyGEEEIIUQEJloUQQgghhKiABMtCCCGEEEJUQIJlIYQQQgghKiDBshBCCCGEEBWQYFkIIYQQQogKSLAshBBCCCFEBSRYFkIIIYQQogISLAshhBBCCFEBCZaFEEIIIYSogATLQgghhBBCVECCZSGEEEIIISogwbIQQgghhBAVkGBZCCGEEEKICkiwLIQQQgghRAUkWBZCCCGEEKICEiwLIYQQQghRgXs+WM7KymLcuHHUqFEDGxsbWrVqxYEDB8z7TSYT77zzDj4+PtjY2NC5c2fOnz9/F2cshBBCCCH+Le75YPnJJ59k8+bNfPfdd5w4cYKuXbvSuXNnLl26BMD06dOZNWsWs2fPJjIyEjs7O7p160Z+fv5dnrkQQgghhLjfqUwmk+luT6IieXl5ODg4sGbNGnr16mXe3rhxY3r06MHkyZPx9fXl5Zdf5n//+x8AGRkZeHl5sXDhQoYOHVqp62RmZuLk5ERGRgaOjo5/y70IIYQQ9wr5uSdE5Vnc7QncjF6vx2AwYG1tXWq7jY0Nu3fvJi4ujuTkZDp37mze5+TkRPPmzdm7d2+FwXJBQQEFBQXmzzMzMwHQ6XTodLq/4U6EEEKIe4f8rBOi8u7pYNnBwYGWLVsyefJkateujZeXF8uWLWPv3r2EhISQnJwMgJeXV6nzvLy8zPvKM3XqVCZOnFhm+6ZNm7C1tb2zNyGEEELcY3Jzc+/2FIS4b9zTwTLAd999xxNPPEG1atXQaDQ0atSIYcOGcejQodse8/XXX2f8+PHmzzMzM/Hz86Nr167ydpQQQoh/veJ3VIUQt3bPB8vBwcHs2LGDnJwcMjMz8fHx4aGHHiIoKAhvb28AUlJS8PHxMZ+TkpJCREREhWNaWVlhZWVVZrtWq0Wr1d7xexBCCCHuJfKzTojKu+erYRSzs7PDx8eHtLQ0fvvtN/r160dgYCDe3t5s2bLFfFxmZiaRkZG0bNnyLs5WCCHEvW7XxV00/b4pq86vuttTEULcw+75YPm3335j48aNxMXFsXnzZjp06ECtWrV4/PHHUalUjBs3jilTprB27VpOnDjBiBEj8PX1pX///nd76kIIIe5hXx39inxDPl8e/RK9UX+3p0N2YTanrp/CaDJWeMy1vGvEpMfcdJz0/HQuZF6409MT4j/rnk/DyMjI4PXXX+fixYu4uroyaNAg3n//ffNbSK+88go5OTmMHj2a9PR02rRpw8aNG8tU0BBCCCGKnbx2kpPXTwKQkpvC9gvb6Vyj881P+hudvn6acdvGkZSThJ+DH4NCB9EvpB/uNu4YjAb2Ju3lx3M/sv3CdgwmA6PqjeKFhi+gUWtKjbPr4i5e3fUq2YXZvNjoRUbVG4VKpbo7NyXEv8Q9XWf5nyL1JoUQ4t9FZ9CxKnoVD1R/AG877zL739z9Jmtj1mKtsSbfkE9z7+Z82+3buzBT+CXmFybunUiBoaDUdguVBa2rteZ82nku51wuc15r39ZMe2AaTlZOmEwmvj3xLZ8f+RwTJT/Wu9TowpTWU7DVlq70JD/3hKi8ez4NQwghhKiqr499zeR9kxmzZQw6Y+mawmn5aWyM2wjA5DaTUavURCZHEpse+4/OUWfU8eH+D3lj9xsUGApoW60tvw/+nUmtJlHfoz56k54dF3dwOecyjpaODK89nFV9VzGt7TSsNdb8cfkPHlr3EEeuHGH89vHMOjILEyYGhw3mzeZvYqG2YHPCZh7Z8AgJmQn/6L0J8W8iK8vIb9hCiMq5kHmBOSfm8HT9p6nuUP22x9l7eS/rY9czoekEnKyc7uAM7z/7kvaxMW4jE5pOwE5rV/5Bp9fA4e/gxlxetQaaPgVhXcscnp6fTrefupGrV2oJj288nsfrPW7eP+/EPGYenklt19qs6L2CsdvGsu3CNobVGsYbzd+45Zy/3h6Dg7UFw1vUqNrNFilOq/jm2DccvXoUgGcaPMOzDZ5FrSpZwzqXdo6tiVupZl+NLjW6YG1Rkl4YlRrF2G1juZR9ybxNq9byZvM3GRQ2CICjV44yfvt4ruZdxUHrwIcPfMgD1R8A5OeeEFVxz+csCyHEvWLBqQWsjl5Nnj6PGe1m3NYYp66d4sWtL5JvyCfUJZSRdUfe4VneP3J1uby681VS81Op4VijVEBrZtDBupcg93rZfSmnYOxx0JT+Ubbo9CJy9bk4aB3I0mXx1dGv6FKjC9UdqmMwGlgZtRKAYbWGoVKpGFprKNsubGNtzFrGNhpbcdAOxFzNZtrGswB0qeOFl2Pln49JyUlhdfRqfj7/szmtwk5rxwdtPqCjf8cyx4e5hBHmElbuWDVda7Ki9wpe2fkKey7vwdPGk087fEp9j/rmYyI8I1jRewXjt4/n6NWjLDi5gLbV2koOsxBVJMGyEEJUUlRaFADbL2wnqzALB0uHKp2fkpNiDpRBecjs3yI1P5Xx28fjYOnAey3fw83G7ZbnrIxaSWp+KgDbLmwrP1iO2aoEynYe0HVKyfbf3oTMSxC1Aer0NW9Oy09j6ZmlgJJiseTMEg4kH2BK5BS+7vQ1uy7t4nLOZZysnOgR2AOAFj4tCHAMID4znnUx63io1kMVzvnYhXTzx5tPp5S7upxRkMHozaNJzEwstT1Xn2uudOFo6Ujf4L48XPth/Bz8lAO2fwinVsHg+eBVt+IvXBEnKye+6vQVkcmR1HWrW+67FB62HszvNp+vjn3FI7UfkUBZiNsgOctCCFEJRpOR82nnASgwFPB7wu9VOj9Pn8cLW1/gSt4Vc5B94tqJvzQnnVFHji7nL41xJxQaCnlp20scSjnE9gvbeWjdQ8ovAiYTZKWUe06uLpcFpxaYPz965SjX8q6VPfD4CnRARt1+0GBoyatx0Yr8/jmlDl90SllVru1am45+HXm7xdto1Vr+uPQHv8X8wvKiQHpAyABzWoNapeahmkqAvDxqOTdmJ5pMplLzujFY/u1Ucrn39umhTzl9/TTZuuxSL6PJSGOvxnzQ5gO2DNnCq81eLQmUL+xXguWrZ2HpQ5B9pdyx/0yj1tDKt1XpQFmXD/kZ5k+1Gi1jG43F3ca9UmMKIUqTYFkIISrhUtYl8vR55s/Xx66v9LlGk5E3d7/JmdQzuFi5ML/bfGXM7EvmldXb8erOV+m4siPxGfG3PcZfZTKZmLxvMoevHMZea0+AYwApuSmM/HUkq1b0h4/D4JsH4OB8yC9psbziyFek5qdS3WCkdkEhJkxsv7C99OD5mXB2Pa94utPp+jaOXDlSsq/x46BSQ/wuuKKkRaTmp7L0rBIMP9vgWVQqFYFOgTxV/ykApux+iz+S9qICHqz5YKlL9Q3pi42FDdHp0RxMOcj1vOssOLmAPqv70GFlB2YdngXA0YslQejemOtk5JV+ePBQyiF+Ov8TALM6zGL9gPXm17YHt7Gw+0L6BPcplX+MQQe/jAVMyj1lXIAVw5Wgt6qMRljYC6YFKEF31K9guPs1pIW4n0mwLIQQlXAu7RwAnraeAOxP3k9yTvkri3/25dEv2ZywGQu1BTM7zKSWay0CHAMAJYf5duTr89l2YRu5+lxWRVfcgS4xM5HDKYdv6xo3On39NAeSD5RpmLHw1EJWR69GrVIzo90MlvVaRnu/9hQaC3mnIJYpbi7oko4peccf14LVY8hd1IcFJ5VfGJ5OTaNrjvIg3pbELaUvenYdsSo9v9vZUmDU8d6e9yg0FCr7nP2gZk/l4wNKybdFpxaRp8+jtmtt2vu1Nw8zqt4oAq1cyVApK8ZtcvPw2zunVBDpaOlI76DeALy+63U6/9iZTw59Yq4iMffEXH46t5ozl5WA38VWi95oYntUyQpwoaGQiXsnAjDYtz0dribif36b+eUev7f8wHXPLLhyGmzd4PGNYO0EFyLhlxeV1fkbJR2H+D8q/D4Rtx0uHVQehjy3EZYNhZnhsO0DSJdGJULcDgmWhRCiEoqD5Va+rWjk2QgTJn6N+/WW50WlRjHnuJIq8F7L92jk1QiAcPdw4Pbzlk9dP2XuOrc+dn25Xd8KDYU8vvFxRm4cyS8xv9zWdUCp3vHw+od54rcn6PlzT7498S3X8q6xLXEbnx76FIBXmr5C62qtsbe05zP3BxiTlo7KZGKFowOjajfjmkco6HLg6PcsTz1CmkaDH1p6d55Bx0IlIIy8vJfswuySCx9fwXKHkrzw2IxY5hcF2QA0fVL589hyUjMSWXZ2GQDPRTxXKjfX0gTvXC1ZwR+WmaUEqN8PhJySBweH1hoKKE1K9EY94e7hTGw10ZxLPXnfRAyWsTjZaBnWzB+ATadK0kzmnZxHXEYcbhZ2jNv7nRLs3vhaMRy+HwA5N6SbpMbCjunKx90+AP/mMGQRqDRwfAXs/gQKsuDgAvimHXzTFhb2hPPlpwFd3KSsgP9iaMm1+k8rAXjWZdgxDX56soLvsBDiZiRYFkIIlHJjnx/5vFQprhsVB8uhzqH0DlZWINfFrrvluMUBXJcaXegX0s+8va678gBXcRe5qroxJSElN4VDKYfKHLMpYRNX8pSVz3f3vFs6jaGS4jLieHnHyxhMBjQqDZeyL/HZ4c/o8kMnJmwbhwkTD4U9yMO1HlZOuHgQ9ZoxPJOeyeeuLbHX2nMkP5kHPRw5OvALcps8xkJ3pUnI063fxSLiYYIaPk5AoQ6dycDui7uUcTKTyInbyVoHpTJFLTulu97c43NL0k6C2oNbKBRmMXfnm+Tp86jrVpd21duVvoljS2lyPZF3MnU8V+8pWvf6CrR2ELcD5rSHpGOAUn3itWavMaLOCH7o8wNLey1lYOhAxjUaR5caXTCY9FhX/45afnq611PuYXvUFfJ1BuIy4ph7fC4AryZfwsloAr/mENaj6NUdLO0hbifMaY/uwmHm7Igm/YcXQJ8Pge2gftGDhcEdoOdHysdbJsGMmrBuHCQdNd9S3qZJpVadC/QGpq/YjE/ydgBm6gfykXE4jD+jPDAY+AA0fqzK338hhATLQggBwIcHPmTO8Tl8dvizcvcXB8thrmF0rdEVrVrLubRz5u3lySzMZEPcBoCSYLLIjSvLt1Pu/tgVJcCztVA6s5UXuC8/uxwAFysXdEYd47aNq/CXgfJkFGTwwtYXyCrMIsIjgh3dvmOyS1Ma6IzoTUYKMNI8L59XI1ei2jUDLh6CZcPAUAA1e9Ku92yW9VpGsFMwV/Ou8vixTxhvVUCasQB/B396BfVSLtR6LB3zldzfraeVnGNO/sg6e1ty1Goo9ODAwY5oC2tTaCxk8r7JytdMpULX9AmmuLnwfepRoOyqMvpC2KmU+RvS5EWebfwi6nqD4MnfwSUQMhJhXlc4tgKAR2o/woSmE6jlWss8hFqlZkrrKTiqAlBb5HDZ6ksCPTR4O1qTU2jgj+irTN43GZ1RR+sCA92zMqFWbyWl4uHlRa8VyjVdg5Wc5PndcN48Huek3RjVltD7U7hx3k1HQbOnlY91OeAWSlqbd+lt+JhckxU2V48xeeZnrDx4gfhrOQybsw/7E4vRqEycs21EjKkaa45dIqNQDfUGwchflAcjhRBVJsGyEOI/LzYj1pxSsT9pf5ngNVeXy4UsJd8zzCUMJysn2lZrC9z8Qb810WvI0+cR6hJKY6/GpfbVdK2JhcqC1PzUclsZ/xLzC89veZ70/PQy+0wmk7mZxdMNlIBqU/ymUu2ST18/zbGrx7BQW7Ck1xJqu9YmNT+V57c8XzrVoQI6o46Xt79MQmYCPpZOzLyWjtPXbeh/+Ce+v3iRn67n845lDT7LKECbnghbp8C3HSHnCnjVg4FzQK0hwCmAJb2W0KVGF/RGPX9c/sM8bwt1UfVSO3c6Bill3HZeO0ahvgDT8eUsc7QHID+1BaAmLbE3JqOW/cn7WRuzlmt51xh1fTcrHJVUjTE1epu/L2ZHl0DGBUz2Xnx0vSVjlhwmp0APXnVg9DYI6aKs7K4aDb++pjxsVw5brS1WqaMw6hxI1yfSb00/1H4fYRv0CW8cGM6B5ANYm+CtK8kYPcMZr3uOievPkK8zlAziWRue2kqCW1u0pkIetNgBwFemgSRQtiU33T6AAd/AYxswjdnP+AttOKnz4SdNdwD6pi3ilR+P0X7Gdk4lXmGoxTYAQnuPo5a3A/k6Iz8cuiFPWcrGCXFbJFgWQvznfXPsG3PO7/X868RlxpXaH50ejQkT7jbuuFq7AphTMSrKFzaajOaV3aFhD6H6UwBupbEizFVpOGEus1Z0jM6oY/qB6ey4uKPch/fiM+NJL0jHSmPF8NrD8bbzJluXzY4LO5RqCJSsKnfx74Kfgx+zOs7Cw8aD6PRoXt31KhkFGWQVZimvgkyyMi+Vek3d8RqRyZHYGk18HnsWt9idysWDO8KQRYS9eIohw9ZhNz5KCej8Wyr77Txh2DKwKsk1ttPa8XG7jxnbaCwqVNR0qUnPwJ6l7im83Tt4GIzkqEzs3/oGB9PPE2NpCUYtxqzGfDeqGc2qh1J4rRMAk/d8yJBfHuTItRPYoeGL5CuMTr5YdlV518cAnAkaxZe7L7P+RBLjVhzFaDSBjYuy4tv2f8rxkV/D4v6QnqiUXit+FeaSXaAnLkVL3sURWGtsuJp3lSzjJTRWV8g1KXnLz6emUc3anZctXuPnU+ks+COewbP3cDEt1zyl3+MK6HD5aT7TDwQgRhPMZ3k9eWLhATLz/xSoayyU1eCA1qw/mcy2qKtYatS0HTkJk4UNDdSxPOh0BoBRLsdwJQscq6Gq2YsRLQMA+G5fgnKvQojbJk1JhBD3jJmHZvLd6e9o59eOwWGDaeHTolT7379DbHrJqnI1+2pcyr7EgaQDBDkFmY8xp2Dc0E3tgeoP4KB1MOcLN/VuWmrcvZf3kpiViL1KQ+9VL4PLF/DgInAtGTfcPZzT109zMmoN3X58EUI7Q78v2XNpD+kF6YBSIeLPzTqOXjkKQF23ulhqLOkV2It5J+ex7vh8ui5/kozAtmzQKeXUih9a87bzZlbHWTy28TF2XtxJm+Vtbvm1UZlMTLtyjZpWrtD8EWg0AlwDSx+ktSmpfZwWD1aOYOtadiyVit7+w5m9zhWtzg29QYXFDd9atb0nHRyCWZkbx5aon8goWi0uzGjEk63q0DbUgxZBbkxZb8sPSUcpsE6mIC8bQ4Enthe70E49FcPZdaQvfwbntk+BbyM48h1kXMBo78XTp+uZr7X5dArTf4vitR61lLbZnd4G3whY9Qwk7FaqR/yJ3rsVPVVNOGHZmtWDNxKTHoO+IJdFy76nnXE/9blMHaOab4PfZ/UxFdZaNTZaDScvZdLn8918+XAjXOwsGbv8CEaTmiuNx2PqMAkHgx1u3xwh5moOzy89wvyRTbDQlP47n5GnY+IvpwF4rkMwATUCoPlo+OMzprmt57ERo6m1/mPIA5o8DhoL+jf0ZeqvZ0i4nsuO81fpUNPzlt9vIUT5ZGVZCFFl1/Ous/vS7lKvwymHMRgNFZ5TaCgkJj2mwv0Xsi6w8NRCCo2FbE7YzNObn6bnzz2Ze3wuGQUZFZ5XKSYTXD4Kurwyu2Yfn40JEx38OtA/pD8AB1IOlDqmvGDZSmNF14CuwJ/yhQ06OLSQ5b+9AEC/9HRsC7Ig+TjM6QDRJVUM6rrWAeBE3GbIToYj38PVqFLjHb96nKu5V0vNpzgFI8IzAsBc8mxX6kkyCrNYfWkHBYZCajoG0NCzofm8eu71mNp2aqU6D1objbyh9qJ937nw0ino/G7ZQPnPXALKDZSLfbktmmsZVuyNzub1n0+USXfp2OhZADbb2bLV1gYAV0N7xnYOBUCrUTOxbwPG1HsD9E7oMiLIjR9DbGE4PxvaoMGI89llMLejUjVixzQANjgN40I2BLrbMX2w0g569o4Yfjh4Q4pC7T7w1FbwKhsoAzgn7+FLy1msNzyN685PaHpoOS2XDmd2/kqGFcZTU2diV70pvH9MySGf+VAEv7zQhnrVHEnL1TF8XiTDv40kp9BAq2A33utbF5WzH55urnw7sgk2Wg07z11l8rrTZVaCp208y9WsAoI87Hi2fbCysdWLoLVDdfkIdc5/jfryIVBroZHSrMXW0oIhjZWGJ9/tTbjpt00IcXOysiyEqJIz18/w2MbHyNXnltnX3Kc5Hz3wES7WLqW2J2YmMnbbWKLTo3ml6Ss8WufRMufOPT4Xg8lAI89G1HStybqYdVzKvsSsI7PYGL+R5b2Wo9Vob2/Sp1fDD4+Be00YugTcleArJj2GjXEbAeXBsOJueAeSD2Aymcxv6ZcXLAP0CurFT+d/Yl3MOpp7N6dnUE9YM4ZLp39kR3VfQMVD3i2h63DY9YlS//b7wdDpHWjyOOH7FyrTs7LEYO+FJjuF7H1fsy1jNwCu1q6k5qey7cK2Uk00ileWiwPhEK0jtfQmzlqo2Fi9DstRfrkYmnAKVdSvUKsk5aFLjS508OugpI5sfF2pUay1hRGrwLOkxbJabYGF1ub2vt7luJyex4oDSnCqVsGqI5cI8bRnTIcQ8zHNAjpj/4cFGRrlc2NODab27oqtZekfVWNad+DpFjsx3BBsZ+Z24oWvvqVDzq/01kRimax0Ryy09eLl2AgA3u9fj1Yh7lxMzWXW1mjeWHWCAHc7mgYUBfgeNeGZXVBcy7lYVhIbvptBo+vr8DakwZ7Pzbty7Pz5PL0Vmyw7kbDfHjAxoVtNutfzAeDHZ1rxxqoT/Hz4EtdzCgl0t+OrRxqhvWH1uF41Jz59qAHPfH+YRXsT2Bp1haFN/RnSpDoXUnNZGqm0zf5gQDhWFkVfHDt3aPYU/DETtk9VttXtD/YlK8iPtqzB/D/i2BZ1hQupufi52lbqeyWEKE1WloUQlXY19yovbH2BXH0u3nbe1HatbX7ZWNgQmRTJ0HVDOXP9jPmcXRd3MXT9UKLTowHKLc92IfMCa2PWAjC+yXjeaP4GWx7cwpTWU3CxcuFc2jkWnlpY7px0Bh0/nvvx5l3sjv+g/HktSll1jFLSLmYfU1aVO/l3opZrLcLdw7HWWJOan0psRiygPExXUbDc2KuxuQHHq7teZcbmF9AfX8EKR0dMKhUtPBsT+OAyqNULHt9QtOpngi0T4dN6BEbvwMZoJE+tJrbruwBsiVlLgaGAQKdA8y8VWy9sNV8zoyDDPDcHgll9IAbj8ofplZGufH1t4KJGhYNJRc+MVFg+DH5/D3JL6gxbqC2wPLwYywPfYglYDvgGS78WWFo5mF93MlAGZVW50GCkZZAbE/spKREf/RbFxpNJ5mO0Gi3NvEse0Kvn2Jv2FaQPWGjUWFlozC8PR2vGPvEY72pepGn+l6zyegFjUCcm8iwFJksGNapOqxCl3fO4zmH0DPdGZzDx9HeH+GRTFJ9sPqe8fj/Ppqg0sLAqebkE8H7uQFoXzOJM+2+gTn8IfxBGrEH14iEWqPoTm2eHwWhiQMNqPFe8+gtYazV8PKQBHwwIp0sdL+Y/1hRnW8sy99O9ng9T+tfDwdqCC6l5fPRbFK2mbuXJRQcBeLBJdVoEuZU+qWh12azZ6FK7A93taBvqjskE3++T1WUhbpcEy0KISsnX5zN221hSclMIdArkp74/sbLPSvNrSc8l+Dn4cTnnMo/++ii/xPzC3ONzGbNlDFmFWTTwaECERwR5+jze3/d+qbfgvzn+DQaTgdbVWtPAowEANhY29Avpx4SmEwAlsE3MTCw1J5PJxMS9E5m4dyIvbH2h/DSQwhyIKeoM51kXCjJh2VCiN73Gb/G/AUprZABLjSUNPJXrH0hWUjFSclPIKszCQmVBoFPpNAS1Ss3M9jN5Mlxp9rDo8nae8fZklbOyUjm07g0r6BZW0HcW9J6pvF1emI3GyZ+6bkoqxkkbW3ALZZ218t9y76DedPTvCEBkUiRZhVkAHLuqlIzzs6/BqPmnMa59EfXFA3TTaVChIqNQ6TDXr/YwbItLj+3+FD6uqTSliN8NMVthwyvKvk7vQJ2+5X/T75BL6XmsLEp5GNc5lEdb1GBkyxoAvLTiGMcvprMt6gqjFx/k14O+ykl6Rz7tM7xK1wnxtOerRxqRrXbgpYSWDMx6mSWpYbjYanmzV23zcWq1io+HRBBezYnUnEJmbY1m1pbz5tfo7w5xIL7kl4urWQVcSs/DqNJQvcUgJfd80FwIao+tlSVtQz0AaOTvzNSB4aUfMkTJ1364uT9zRzQh0N2OigxvUYP9b3RmxpAGNK7hgt5oIi1Xh5udJW/0rF32BDs3JXcZwLs+VG9a5pCRRQ/6rTh4oXRlDiFEpUmwLIS4JZPJxNt/vM2JaydwsnLii45f4GjpWOqYUJdQlvVaRttqbSkwFPDG7jeYdWQWJkwMCRvC/G7zmdR6Elq1ll2XdvFbghKoJmYmmnN0n2vwXOkLF2TT+/RWmjsGUWgsZNK+SaWC7IWnFrImZg2gVIgormlcSsxWpTSYcw0YvR2ajUYPfBb9AyZMdPbvRE3XmubDm3opAUdxsFy8qhzgFIClpuyKoEatYWyjsXzi0hwbo5FIG2vSTTq87bzLNscA5QGsUZugw1swejvhvkoViZPXTnKl4TAira0B6BnQgyCnIAKdAtEb9ey+pKRmFDcWMeT684RuKQM1u9Gb1EzVj6WOSyPzZYbWfhh6TIMhC5VAylAIJ36Ahb3guwFgMihNMNqMLzvHSth9/hpjlx8h4XrOLY/9cls0OoOJVsFuNC9aHX27dx3ahrqTpzPQ94s/eHzBATadTqEwsy6ehQ/xVtPp+DrZV3lebUM9eK+P8gvI0QvpALzZqw6udqW/dzaWGhY+3pQXO4YwomUN86tZUUrGGz+foFCvVBY5flEZJ9jDHgfrsqlA7/Suw8tdwpg3sinWWk2V5/zneQ1uXJ2fnm3FppceYHyXsApXowFo9yp0ehcGfVtuabgOtTyp5mxDeq6OtcfKligUQtyaBMtCiFuafWw2G+M3YqGy4NP2n+Lv6F/ucU5WTnzR6Querq+saGrVWt5r+R7vtHwHS40lgU6BPBX+FADT9k8jszDTvKrcplob6nvULz3glkmoDs3nndiTWGmsiEyKNAfWN7ZaLj5vzvE55hbQZmeKHpar1RssLEnr+AbPhLdlu50tapOJZ5zqlTq8mU8zAA6mHLxpCkYpySfpcuRnll5OoYa18lb/8NrDS+oI/1m1RtBuAti5mTv5nbh2gl/t7TCpVDTMz6f69XgAOvopq8tbE5VUjOJ85RbJx3nRYjUAX1iPZm1WTY6eVoL+dtXbUcNRWbml7gAlD3f0dqWDm2VRAFq9GfSZVeXauyaTia+3xzBifiRrjl5m9o6KH9oEuJiWa36Qblznkq+hhUbNFw83IsRTmY+TjZYnWgey+aX2bHnqLR6q37pK87rRoy0DGFG0ct06xI1BjaqVe5ybvRXju9ZkUr965tecEY1xt7fk/JVs5uxU7u1YUdDdoLpzueP4u9nyQqdQXOwqCGhvU5iXAy92CqWBX/nXBZRqJG3HK/nW5dCoVQxvoXwtlu1PLPcYIcTNyQN+QtwHlp5Zyuro1XzZ6Us8bD3+0WvvvrSbr459BcDbLd8uUyLtz9QqNc83fJ6O/h2x09qVBG1FRoWPYkPcBuIz43lj1xvmFdMyq8oXD8H+OQD4Z13j6SbDmBW/ho8OfISnrSev7npVabVc8yFeavwS3X/qTnxmPL/G/Uqf4D7KGAYdnFMe4KN2b85cP8O4beO4nHMZG5WGKSnJ1Dy5Dho9ab5sPbd65rzlmPSYWwfLRgP8MhZMBkJCerFy4DdEpUUR4RFxqy8tUNLJ73zaeVYVPVjWOztXuffAtnT078i8k/PYdWkXubpcTlw9DsDIwjPoVRZY9JzGE+EjObniGL+fCUdXMJpQ/3JWtH0bKq+uUyBhLwS0Bq11peZYLKdAz4Qfj7HhRLJ52+bTKUzpb0KjLj/o/nJbDDqDidYhbjQLLF0pw8lGy4/PtOTohXRaBLn95VXZG73Xpy5d6ngR4edcJi3iZpxtLXm7dx3GLj/KrK3R9Krvy7GLygOTEX5Od2x+/6SHmvphMBp5qGn5v+QKIW5OVpaFuA8sPLWQM6lnzKuL/6RV55WmGINCBzEwdGClz6vjVqdMoAxKXvA7Ld8BYMfFHRhMBtpWa0u4xw0luwx6JQDFBEWrs4/l6glxDiGtII0nNz1Jnj6PFj4teLXZq9hp7RhZVymZ9c3xb0pWlxP2QH462Lrxi+4aj/76KJdzLuPn4MeSdp/RNTcfYrfBtWjzpbUarbkk257LkUSlKsFyqEto+Td6cL5S5cLSAXpMw1ZrS0PPhqUCtMx8HXmF5eeL+tj54Grtit6kJyYjBguVhq45uXB2PWRcop57PTxtPMnR5bBo5zsUGAtxNBiw19lT+MgaaPokjtZa5jzamBc7hmLIC2L21stczy4o93pYOUBYV7CsOHe2PHHXchjw1R9sOJGMVqNiYt+6OFhbcC27kCOJaeWecyG1/FXlGznbWtK+pucdDZRByUtuG+pRbtrErfRt4EvbUHcK9UbeXHWCY0VpGPUrWFm+17naWfJ8x1A8HKzu9lSEuC9JsCzEPS45J5mkHKViQHFFiX+K3qhnX9I+AHMN4juhqXdTBoQMMH/+XMSfVpX3fQUpJ5QOa72UDmzaqPW82+Id8yEBjgHMaDcDrVoJhobVGoazlTMJmQkluctn16EDpvmF8cYfb1JgKKBttbYs67WM0BrtIKybctyBb8vMD+CzP9YRm6508yt3ZflqFPw+Ufm487vg6FvmkItpubSdto1Gkzfz6o/HOZKYVirvWqVSUc+9JBWkbfUHcPZrqeQUH1qIWl9AB9vqACxMVKp4BOZrOdVrLbYhJY1F1GoVL3UJo351J/J0BubsjC073yoyGk3sPn+NMUsO0/XTHZxLycbTwYrlo1syslUAnWoplSo2nU4p9/zZO2LQG020CXEvKc92H1CpVEzpXw8rCzV7Yq6TnqvDUqOmls+t61MLIf59JFgW4h5X3IACICbj5vmhd9rJayfJLMzE0dKxVEB3J7zc5GWaejdlRJ0RpcdOSyipG9tlslKiy8IG0hOJMFkwJmIMdd3q8nnHz3GyKnlb3E5rx2N1HwOU9tV6g47rUesZ7e3J94VKqbrR9UfzRacvSs5rquRPc3QJFGSbx2rmreQtF1ieApURS5U9XrZepW8gNxWWPgSFWVCjNTR5otz7/HJbNBl5OvJ0BlYcvMCAr/bQ47NdfLc3Hp1BeYCsnlvJ/fcO6g1Ni9JCImfDxzXpeEpJJclVK/9lp9n2oX2TP+V3owR544oaeCzem8C1ilaXbyGnQM9X26NpP2M7w+dFsv5EkvkBvXUvtKFxDaWOdte63gD8diq5TIORjDwdPx9Wvu431lK+X9RwszM3QwGo7eNQUuNYCPGfIsGyEPe4Y1eOmT++WQe8v8Oey3sAaOHTouKH1W6Tk5UT87vNN5eGA5ROe+tfBl0u1GgDDYeDpS2EdFL2n1nHMw2eYXnv5QQ4BZQZc1itYbhYuZCYlcjMnW/wkKOJgzbW2FnYMbPDTF5o+ELp9tnBHZX20wWZcGKleXNdt7pYqKxQqZQAsCDXk4w8Xcl5+kJY8SikxSlVNh5crLRN/hMlDeEiAJP712Ngo2pYWag5m5zF22tO8ci3kVzLLjCnoNhr7Wnn107pJmfvrcwrP4Omlp7YUZJO8EKbHhXm4Xao6UkDP2fydAa+ucXDd+UpTreYvjGKxNRcHKwsGNGyBhtebMvSp1rg6ViS59wuzANLCzUJ13M5l5JdapyfDl0kT2cgzMueFkH3z6ryjZ5qG0RNL2U1+aYP2Qkh/tUkWBbiHldcKgwgNT+V1PzUco/bn7SfL49+ae5Cdyf8cekPANpUa1N6x6GFSq5uVVw5W6Y5RhmnfobozaCxhN6fllRqqNVL+fPs+ptewlZry2P1HgNgUeJGUiwsCFBZsbTXUjr5dyp7glpdsoq7/1slWEfJW7Y1ljSW0OV58+0uJR1DCejHQ8JuTJYOrK83kzXny1/B/XJbNHqjibah7jzaogafPBjB/jc6807vOthbWbA/LpU+n+/GzlCH0fVHM7XtVKw0VqDRwsBvlNXq4T+hHXsMF62y2q1CTbuARuVeD0qvLn+3L4GrWaXndjEtlynrTrP22GUK9KXzqLeeTaHvF7vN6RbTB9cn8s1OTOpXjzq+pUsFAthZWdC2qNHHplMlD/0ZjSZzE4xHWwZU6QG7e4lWo+br4Y14pLk/ox8IutvTEULcJRIsC3EPy9Xlcjb1LKCkGUDFq8vv7nmX2cdm8/D6h4nLiPvL107PT+fk9ZMAtCyqBQzAuU3Kw3frXoLIOZUbzGiEn0YpzTHWjSv/mLw0+PU15eM248HjhhzhsO6g0ih5zGnxN73U0JpDcbVWVjLb5+SyNPxFgpxvEuhEPKykeVw5BYl7AdAbjGSklTycaCzwZsEfcaTlFMLeL+HId6BSsy7sfcb8nsfY5UfNTTeKXUjN5cdDyqryuBvezney1fJEm0BWj2lNsIcdSRn5PDQnEi99f9r7tS8ZIKi98gtDSGdQq0m/qjSlCLCvg43FzbvrtQ/zIMLPmXydsdTq8p7oa/T5fDff7o7jxWVHaDl1Kx9sOEP0lWxmbTnPqEUHycrX07iGC+teaMODTfzKtJr+s651lfSU306XBMu7o68Rey0HeysLBjQsv2zb/SLIw573B4RT3UVaRQvxX3VPB8sGg4G3336bwMBAbGxsCA4OZvLkyaVy40wmE++88w4+Pj7Y2NjQuXNnzp8/fxdnLcSdc+r6KQwmA562njTxagKUHyxfz7vOxWwlMIvNiOXh9Q+z/cL2v3TtfUn7MJqMhDiH4G2n5KZSmKOkSRTb+CpEb7n1YGd/gRQl8Ob0GojaWPaY3ydCzhVwC1Xqxt7I1hVqtCoa69ary4uaT2JWylU+u5aOQ60+xFzN5qFv9vL26pOcvpxZ+gQbF6g/RPl4/1wATl7OJDczwHyIv30IOYUGNq1fCZveAuBM/Vd54aC7+Zg3V51gX+x18+dfbC1ZVW5co2waQoinPavHtKZrHS8K9UZe+ek4n2w+V+49xV/LISkpmMJLI/i4/bSb3j+UXl3+PjKBK1n5zN0Zy/B5kaTl6gj1tMfb0ZrUnELm7Iyl8yc7+GTzOUwmGN7Cn2V/Sre4mc61vVCr4OSlTC6l5wFKvjTA4MbVsbeSCqVCiPvbPR0sT5s2ja+//povvviCM2fOMG3aNKZPn87nn39uPmb69OnMmjWL2bNnExkZiZ2dHd26dSM/P/8uzlyIO6O4AUVDz4YEOytpAeVVxDh1/RQA1eyr0cizEdm6bF7Y+gJfH/0ao8lYtYsW/TL6x2UlBaO17w3NIbZPhYxEcPJTHrwzGeGHx5WqEBUxGmF7UYDnqFR1YMP/Sj1QR+I+OLRA+bjPTKU19J/V6q38eYtgGSDg4hE65OahDmiL0cqZl1ceIzIule/2JdBz1i76ffkHKw4kklNQVGKu+EG/M2shK5l9sdcx5lXHCg88bTx56YG2ALieWgSYSAsdxMDDSlvsES1r0Ku+DzqDiWe/P0TC9RwSr+fy4+HiVeWKm5k4WGuZPbwx47sox8zeEUNmvq7McTvPXwVUNHRvQ6hb5WrltgvzoKG/srrc74s/eH/DGYwmGNioGr+80Ibdr3bg2xFN6FTLE7UKLDVqpg0KZ0r/cCwtKv+jwc3eiiZFvwxsOpXMxbRctp5VqmMUN8MQQoj72T0dLO/Zs4d+/frRq1cvAgICGDx4MF27dmX//v2Asqo8c+ZM3nrrLfr160f9+vVZvHgxly9fZvXq1Xd38kLcAcX5yhEeEYQ4KxUFyltZPnlNWbVt5NmIb7t+y7BawwD46thXjN06lqzCrMpd0GiExf0wfVafPYnbAWhdrShYTjoOe5XmJPT6GPp9Af4toSBDqQpRUS7ymbVKioOVo9Lm2ckfMi6UVLzQFxbVVEZ5oC+gTfnjFOctJ+6FnGsV30PGRTi8yHzOksgEjl5Ix97Kgp7h3mg1Ko5dSOfVn07Q/bOdZOTqwKc++DUHox4OL2ZvzHVAwxMBM/mp70/0Cq9BfR9bmnMCgJfjmpGnM9I21J13etfh4yENaFDdibRcHaMWHWTaxrMYjCYeCPMwV46oiFqt4oWOIYR52VOoN7LxhoYfxXZEXQWgXZjnTce6kUql4qWiQD0pIx8LtVIb+eMhDbDWarDQqOlcx4t5jzVl3+ud2PFK+9tuWlGcirHpVApLIhMxmpTOecXd+YQQ4n52T78/1qpVK+bMmcO5c+cICwvj2LFj7N69m08++QSAuLg4kpOT6dy5s/kcJycnmjdvzt69exk6dGi54xYUFFBQUPLQS2am8rasTqdDpyu7qiPE7So0FHI+/Ty1XGqhKadaws0YTUaOXVUqYYS7hkPRM1LR6dFl/p4ev6J0davtUhuMMKHRBGo51+L9/e+z/eJ2hq0bxscPfEyQ080fUlLFbMEibgfntVquOJuwVlkQ7lIPXUE+mrUvoDYZMNbuhyGwI5iAgQuwWNgNVVocxuWPYHj4R+XhvGImIxbbP0QFGJqOxmjriar7dCxWDMW07yv0tQegjtmC5upZTLbu6Du8CxX9G7TzxsK7Pqrk4+hPr8MU8UjZ+SfsRvPzk6hyr2GydSfJtwvT5iqr3uM7h/BoC3+uZxfw89HLzP8jgQupeSzbH8+o1gGoIh7F4kIkxpM/czBFKcvWJrA6dho79Ho9b4Rn4bgzjzSTPduzqxHkbsfMIeGYjAY0wJfDGjDom0iir2QTfUVZNX+hfWCl/0/pW9+HGZvP8/PhCwyI8DZvL9Ab2VuU3tEqyLlK/0e1CHCid7g3p5MymdyvDs0CXNHr9WWOc7FR/m7e7v9/HcLcmLIe9senciZJ+f/04abV5f/Te5h8b4SovHs6WH7ttdfIzMykVq1aaDQaDAYD77//Po88ovyQTE5WVmC8vErXP/Xy8jLvK8/UqVOZOHFime2bNm3C1lYe4hB3zoa8Dewp2EOoRShDbIdgq678368rhitkFmaiRUvMvhgMGFChIr0gnZXrVmKvVlbtTCYTRzKVFeiMqAw2xCgNOTRoGGU7iqU5S0nISuDh9Q8z2HYwdSzrVHjN5jGf4A3ssFdWQ5vmZJE6dyhZ1tWom3QUncaWLZpOFGzYYD7Hwftp2mZOQpu4h+tfdOZgwHMUapXKCb5p+2l69Qw6jS2bMoLRF53X2Lk51dMjyVs6AruCKwAc9hjMxW17b/o1CVOFUJvjXN21kP2Xb1ixNZkIuvobdS8tR4WRdBt/9geM5aulJ8guUFPD3oTL9ZNs2KCswFcDOnmqWJGt4dttUXiln8bKoKY7atRXz+Cmu4zJwpOYw7uIKy7IcflHAHYZw7G2UPFw9Qx2b9tcan6P1oDPTmnQGVXUdjZy+cQeLp+46S2Z2RUAWBAZl8qSVRtwKcpEOZehIrdQg4PWROzh3cRXsbBEF3voEgrXTu9jw+mqnVsVvrYaLudCep4OZ0sTBXGH2BD/911P/DW5ubl3ewpC3Dfu6WB55cqVLFmyhKVLl1K3bl2OHj3KuHHj8PX1ZeTIkbc97uuvv8748SUPEGVmZuLn50fXrl1xdCxbHkmI26Ez6Pho1UcAnNefZ7FxMTNazyjVCc5kMnHwykFiM2LpH9xfKRtWZFX0KtgPDTwb0KdzHwDmr53PxeyLBDYNpKmX0mXuUvYlctfmYqG24LFej5UaA2Bw/mBe3f0qB68cZGnuUvp598PDxsO8X6vW0j2gO34GIxZHlJXsfUFNIfUErfIK8M/cbT5W3WUinRo/XOZeVbFhmH4ciUf2abonfoh+8CLwDsdi7gfKea3G0PWBISUnZDfGNLsljvlK0wpjYHvqD5uMc1oee2NTGdTQFwtNOVliVwJg7s9455ymt+1RipfbVVfPoL6kBOLGeoOx6/kJptgcjh4+gkat4vMRLan9p+5r7Qv1bPhoJ9fy9TiENqVdmAdkLYP4XXRVHyQh9HF694owH6+Zr7yjlezRigW9mtPI37ns/IDa56+xaG8Cb/aoRZBH1VpK/5p6gP3xaeS41+aRtoEAnPztHBBP57q+9O4VfvMB7qLzVtF8sV3pGvh421D6tJdSa/ey4ndUhRC3dk8HyxMmTOC1114zp1OEh4eTkJDA1KlTGTlyJN7eyluVKSkp+Pj4mM9LSUkhIiKiwnGtrKywsir7AJFWq0Wr1ZZzhhBVtztpNxmFGbhau2JjYcPF7Is8vvlxJrWaRDOfZqyJXsNP538iIVOpHHAx5yKvNXvNfP6JVGVJsqFXQ/PfyxDnEC5mXyQhO4FW1ZXqEGczlNJyNV1qYm9dNkfUU+vJ3G5z+eTQJ3x3+jvWxK4pc8x3Z79jqn1d2mMiN6g9R9KVMdt0/RjWvwp5qVC9GZpmT6JRlxPE1uwCT22B5Y+gSo1Bu7gX1BsMV8+ClROaVs+jufHflkt16DJRKT9nYY26z6eotFrGrdzPiUsZZBUYebZ9cNnr+NYH1yBUqbFo/vik9D6VBrq9j7r5M+QVGpi07hAAT7YJpL5/2WoUTlotDzbxY97uOJbsv0jnur5Qu68SLGsOcipkQsn/BznXIEn5RWL046PBwaPMeMU61fGhUx2fCvffzMBG1dkfn8Yvx5MZ01H5pWpXtJKC0b6W1z39/1PP+tX4Ynsslho1D7cIuKfnKpDvjxBVcE8Hy7m5uaj/9INZo9FgNCpP9wcGBuLt7c2WLVvMwXFmZiaRkZE8++yz//R0xX3sh3M/EJsey0uNX8Lyxpzbv2Bd7DoA+gT14cnwJ3ll5yvsTdrLhJ0TsFBZoDcpuaM2Fjbk6fNYemYpvYN6m1s/F1fCiPCMMI8Z7BzM9ovbibl+FtY8D6FdOJmjlEq8WTtqC7UFrzR9hebezc1d+YqdvHaS49eO80JaJM86O1En7AF0UQupZl+NGnWHQPWWcPJHaPCw0sSjIp614amt8PNoOP8bHP1e2d7yObBxLnt8o8eUahquweAaxOGENE5cygBgzs4YHm1Zo2zZMZUKBn4LJ35Qzi2m1kDdAeDXDKPRxJT1Z7iUnkd1F5tSLYv/bHiLGszbHcf2c1dJvJ6LT2h3tL9OoInqHM4+N7RvjtkGmMCrHjh4VzjeX9Uj3Id31pzibHIWZ5IycbWz5GxyFioVtAlxv/UAd1EdX0c+GxqBi60lHg7lVDMRQoj71D0dLPfp04f3338ff39/6taty5EjR/jkk0944okngKJaouPGMWXKFEJDQwkMDOTtt9/G19eX/v37393Ji/tGvj6fqZFT0Rl1ZBZmMqX1lL/ccSyrMMtc57h3cG+crZ35uvPXzDoyi/kn56M36Ql3D2dQ6CB6BPZg0r5JrI9dz8S9E1nWaxlZhVnEZ8YD0MCjgXlcc/m4S/vg9D448QMnG3QAbh4sF2vn105pp3wDnVHHjA1PsfT6Ib52ccIhVsnNbe3bWvk6OPtBm5cqd+M2zjBsOez4EHZMA1t3aP5M+cfe2D0P+G5vvPnjtFwdi/bEM6ZDSNnzqjdWXuXIzNcxfsUxfj+jlC6b0r/eTZtqBLrb8UCYBzvPXeX7yAS61fVGawykvjqOkNRdEFSUShD9u/JnSDldAO8gJxstHWt5svFUMquPXDJXkwiv5oSb/b0fgPaLuL8bkAghRHnu6WD5888/5+233+a5557jypUr+Pr68vTTT/POO++Yj3nllVfIyclh9OjRpKen06ZNGzZu3Ii1deUK6gtx+vppdEblyfC1MWsJcgpiVPiovzTm7wm/U2gsJMTak5pzu4O+AA3wEtBFa4FlQFvCui0EC2UVe0KTCey+tJuzqWf5/vT31HBU6tMGOwXjZOVkHtdcPi43CRNg1OdzOlV5aque262D5fJoVRa8fimOOlnXmeTpSZZOqeRgLhlXVWo1dHgD6g0CS7vyV5X/5Fp2ARuKSqY90TqQ+X/EMXdXLCNbBVS6qUX0lSxGf3eI2Ks5WFqoeb9/PdrXvHWptREtarDz3FVWHryAtYUag6Ep9dVxqKPWQ5ORSjm9mK3KwcF/b7AM0L9hNTaeSmbN0cvmsnPtwipO+xBCCPH3uqfrLDs4ODBz5kwSEhLIy8sjJiaGKVOmYGlZ8ja5SqVi0qRJJCcnk5+fz++//05YWMVNAIT4s+JaxsUtkj87/BlbEst2pcsqzKp0veLiFIxeBUZUeWmgyzW/6uVmEnZ6vdKYo6gBiJuNGy83VjrjfXXsKzbEKQ+r3ZiCARDgFKBUxFCZuK7REmttSx4mbNWWBDoFVv3mAS4dgqSj9MvTs7jjV/ja+eJp40kLnxbmQ1Iy80t1zqwUj5rgVL1Sh644cIFCg5EIP2fe7FWbIHc70otWl/9MbzASVZSmUPxafeQS/b74g9irOfg4WfPjMy0Z0sSvUtfuUMuT6i42pOfqmLMrlk1GpVMisduhIEvpPJhzBbR24N/ipmPdCR1qeeBobUFyZj6/nkwC4AEJloUQ4q65p1eWhfgnHL16FIAn6j3BhawLrIhaweu7Xmdxj8XUdKnJgeQD/HjuR35P/B1brS2Luy8myLniJ/2Tc5I5kHwAgJ5XlS5uDF0GXnWVjy8dhB9HKY0zPGopOb1A/5D+rIlZw6GUQ2yMV9pB/zlYtrGwobqFHRf02cQENOOya3W4tpc6+Xlo8jOUttBVVdTimXoDqVu9FesGrsNoMmKlsSK3UM9rP51g7bHLvN6jFk+3K+ehu79IbzCyZJ/ykOOIljXQqFW82CmUcSuOMmdnLCNa1sDBWnkYKe5aDk9/d5BzKdnljtU80JUvH2mEexVSFjRqFcNb1ODDX8+SrzNynmoUOgVimRGnpF+kxikHBrYtv7PgHWZloaFXfV+W7VeaezhYWRDh5/y3X1cIIUT57umVZSH+biaTiWNXlCoHEZ4RvNbsNVr6tCRPn8eY38fQZ3UfRm0axa/xv6Iz6sgoyOD5rc+Tnp9e4Zgb4jZgwkRjt3B8s66ASg1B7cGlhvKqNwi6TlEO3vQmnNsEKO+SvNPyHbTqkqfUIzwi/jxhgvOUQDHaty4nnH0BCM/Ngc1vlz42Lx3O/HLzVtQZl+DUz8rHRS2ftWotVhorEq/nMvCrPaw9dhmA7yMTqr66XAm/n7nC5Yx8XO0s6RmuVJHo08CXYA87MvJKVpe3nEmh7xe7OZeSjY1Wg4eDlfnl7WjN0+2C+P7J5lUKlIs92MTP3OLZ1c4KbR2lVB9n15ekYIR0ruDsO29Aw5Lc39Yh7mjLK6MnhBDiHyEry+I/LSEzgbSCNCzVltRxrYOF2oIZ7WfwyPpHlAfs8sBOa0evwF50DejKu3ve5ULWBV7a/hJzusxBqylbfqk4BaO3U01gPbjXBMs/NSNpOQauRcHhxfDjE0obaK86BDkF8WT4k3x97GtcrV3NuctmFw8QkpPBdmcnYqxtOFmcr1xQAEe+hwbDlA56hxbCyZ9Bn6ec598SGj8GdfqBhTXE71aOObMWDIXg27DUQ3M7zl3lxWVHyMjT4W5vSW6hgQupeRxOTKNxjdtYvb6J7/bFA/BQUz+stUonueLV5bHLjzJ3Vxx5OgNfblPafDep4cJXwxvh6XDnnktwtbOkT31ffjp8keaBrqhq94a9s+Dcb0r6DEBwxzt2vVtpUsOFas42XErPkxQMIYS4yyRYFv9pxSkY9dzrmQNfR0tHZneZzdzjc6nvUZ/uAd2x1SrB7hcdv2D4r8M5mHKQKZFTeK/le6UqZ0SlRnE+7TxatZYuuqLVQJ/6ZS+sUkHPj+F6LCTshiWDIfABAJ40GdFb+hEe0LVsVY7jKwguVB5GPJN2nvNpRWXjwvrB0eWwuD8Yb2hj6+yvrB4n7lVev74Ctm6QGltyjE8D6PuF+dNFe+KZ+MspjCZo4OfM7OGN+Oi3KH4+fInVRy7fdrAclZzFyoMX6FDTk1bBbqjVKqKvZPNH9HXUKnikuX+p43vX9+XzrdFEX8k2B8ojWtbgrV51zKvAd9JrPWphZ6VhZKsAcLMFO08lVxnAJRDc7nwKSkXUahUfP9iArWevMKixVJgQQoi7SYJl8Z9WXi1jgGr21Xiv1Xtljg9xCeGjBz7i+a3P8/P5nwlyCmJk3ZJukutj1wPQrno7nFKUxh74NCgzDqBUwnjoO5jbEdLi4NgyACyBFwHO7QP3+iUrmvpCOPkzIQYlGD55XWnd7Grtik/XDyF6G2SngIUN1BuorCRXbwpZSXBkibKKnZEI+RlgaQ/hQ6DxSGVVuUh2gZ4p609jNMHQpn5M7FcXKwsNAxpW4+fDl1h3/DJv9656sJpXaOCpxQdJTM1l3u44/F1teaipH7FXcwDoVNuL6i6lV981ahVjO4XywrIjWFqomdK/Hg9W8qG92+HhYMWkfjdUFKnVU1l9h7+9ZFx5WgS50SLI7R+/rhBCiNIkWBb/aeZg+c+5wTfRtnpb/tfkf0w/MJ2PD37MD+d+MO9LzlHKn/UO6g1HxykbvctZWS5m6wqjNsPJn8BQULI9YS+c+xVWPgZP/g4eYRCzBfJSCbT3Qq1SYyxqylHPvR4qWxd4bD1cOgxh3UqXa3P0hXYToO14iNsBeWkQ2g2synb7Oxifis5gorqLDVMHhptXtlsFu+PhYMXVrAJ2nrtK5zpelf56Aczaep7E1FycbbUYDCYSU3P56LeSXOoRLWuUe16fBr7YWWnwd7Uz1xz+x9Tqc0Ow/M/lKwshhLi3SLAs/rMyCjKIyVDe3m/gWcHqbwWG1x5OQmYCK6JWmNtVF/O09aSta11lFRfAO/zmg9l7QIs/Ne5o/gws6gsX9sHSB5XOeMdXAGBVbzB+ecfN1zU3I3EPVV4VUWtumXe7LzYVgJZBbqVSQDRqFX0b+DJvdxyrjl6qUrB8NjmTuTuVtI/pg+rTJtSd9ceTWLY/kcOJ6dSr5kjr4Iq703WsVbXA/I4JbKuksegLIaDt3ZmDEEKIu06CZfGfdeyqUgUjwLEGrj8+Bdej4emdYO10izOVyhVvtXiLB2s+SHZh6TJmgU6BWF5WxsYloFJNOcqwsIKHvi9J0Vj+CFw+rOyr/yBBZ7PNwXK4+y2C8SrYF3sdoNy3/wc0rMa83XH8fjqFzHwdjtZlH278M6PRxBs/n0BvNNGtrhdd6yqtooc08WNIEz8upefhZKNFrf5rHRP/FhZWyt8Hk6ncVXghhBD/DVKPSPxnFadgNLD3V+rppsWXtDWupDCXMBp5NSr1crF2gaTjygEV5SvfwtnkTLZcMLKvxZfoLewgcQ/o85XKGj4NzJ38AOq61b2ta/xZdoGeE5cyAGgRXDZYruvrSIinPQV6IxtPJldqzCVFq8f2Vha817fsPKs521S6Q99dYeNye7WrhRBC/GtIsCz+s4orYTTMzizZGL31zgyeVLSyfLN85QpEX8mi52e7GLXoIEPXZPFU7nMYTcrKa0L13qBSmYPlavbVlOD8DjgQn4rBaMLf1ZZqzjZl9qtUKnP939VHLt1yvJTMfKb/qjzk+L+uYfg4lR1TCCGEuNdJsCz+9Y5fPc6q86vMD8QB6Iw6Tlw9AUBE/IGSg2O2mFtQlxG7Hc5uqNxFk29/ZXl71FWMJqX2bwM/Z1KrdWCSxQtsNDRlqUF50Kyjf0f6Bvflf03+V+XxK1KSglHxSmrfBkoTlL2x10nKyLvpeBN/OUVWgZ4G1Z14tGXAHZunEEII8U+6h9//FOKvu5J7hac3P022LpvErETGNhoLwLnUc+Qb8nG0sCUwI1F5u12Xr5RZu3K6pDV1seyr8P1gpYbxyF/MNZHLVZAN15T6x7cTLO+NUYLWZ9oFMfoBpbbvb6eCefq7FgTEFvA6YG1hzftt3q/y2Dezr+i6LctJwSjm52pLswBX9sensvbo5QrbX285k8KGE8lo1Co+GBiO5l7MSRZCCCEqQVaWxb/ah/s/JFunPID37Ylv+SXmF6AkBaMBVso/groDIaCNclL0lrIDnfq5pNnHL+OUwLoiKacAE9h7g71nleZrMJrYH1dckaKkQkSrYDcs1Crir+eScD2nSmNWRla+zpyv3Dzw5rV9+xelYvx8+BJGY9lV+JwCPe+sOQXAqDaB1PW99QOTQgghxL1KgmXxr7Xjwg42J2xGo9LQI7AHAO/ueZejV45y5MoRABpeL8q9rf9QSeOJ8h7yO76y5OPUGNj1ccUXLs5Xvo1V5dOXM8kq0ONgZUEdX0fzdgdrLY1qKLnJO89drfK4t3IwPg2jCWq42eJbTr7yjXqF+2CtVROVksWMTVFl9n+6+RyX0vOo5mzDuM43KWUnhBBC3AckWBb/Srm6XN6PVNIURtQZwYdtP6SjX0d0Rh1jt43lQLKSpxyRmwXONcCvWUnjicS9UHjD6u31GLh0EFQa6DlD2bb7U7hytvyLJxcHy1V/uG9v7DUAmgW6lkldaBfmAcCOc9cqNdaGE0l0+ng73+1LuOWxe4vylVtWomOck62WqQOVcnVfbY/h58MXzftOXspg/h9xAEwZUA9bS8n0EkIIcX+TYFncV67nXafgxk53Ffjy6Jck5SRRzb4az9QbhTo/k6ltp1LLtRap+amk5qeiAeoVFEL9B0GlArcQcPIHQyHE7y4ZrHhVObgDNH0SwrorKRnrxoHRWPbif2FlubgpSHl1jouD5b0x1yjUl3PdIgajiWkbz/LcksPEXM1h+q9nySnQ3+K6FddXLs+AhtUZ00HJV37tpxMcSkhFbzDy+s8nMJqgd30fOtSsWgqKEEIIcS+SYFncN45eOUrXH7syetNoDEZDhcedvn6a7898D8CbTV/D9vtB8FEwtocW83mHWbjbKLnAtQoKsTGZIPxB5USV6oZUjKK8ZZPJ3DmP+g8px/ScAVo7ZQX6yOLSF9cXlqw4V7FsnN5g5EBxvnI5D9nV8XHE3d6SnEIDhxLSyh0jPbeQxxce4OvtSmdCW0sNWQV6Vh+tuNRbZr6Ok8X1lSsZLAO83KUm3et6U2gwMnrxIab/FsWJSxk4WFvwTp86lR5HCCGEuJdJsCzuCzqDjvf2vEehsZDDVw6zPGp5ucfpjXom7p2I0WSke0B32iYehYsHwKiHja/ivek9vnhgBvWsvRiRkQm+DcEjrGSA4mA5pihYvnhQ6aCntYNavZRtzn7Q4Q1lXhvfJvtaSRoCV88oq87Wzkqr5Co4nVSUr2xtQW0fxzL71WoVbUOV1eWd58vmLZ9NzqTPF7vZee4q1lo1s4Y1ZHwX5d6+25uAqYKSeAfiUjGaINDdDm8n60rPV61W8clDDajr68j1nELmFLW0fq1HLTwdKj+OEEIIcS+TYFncFxacWkBMRgwWKiUHdtbhWSTnlO0iN+vILE5fP42DpQOvhj0M2z9UdtTuq+QcH19O3TUvsex6Lj1zcpXV4hsFPgBqC6X1dVp8yapy7d5gaVdyXPNnuGAVhlaXSdqXXUg4c0jZnnRDvrKqauXSikvGNS8nX7mYOW85qnSwnF2g5/EFB7iQmoefqw0/P9uavg18GdLYD2utmrPJWRyIL381ujL1lStia2nBtyOb4OlgBUCTGi4Ma1q1XxKEEEKIe5kEy+Kel5CZwDfHvgFgkmtT6lt7kavP5cP9H5Y6bnX0ahacXADA283fwn3LFNDnQUBbeHAxjFgNtm5KQHvllBI81xtU+mLWTlC9mfLxud/g5E/Kx8WpGkW2R6fyWOZTXDK54We6jPvynhz5bdFfanNdmbzhNqFKCsnppEyuZJWUr5vxWxRJGfn4u9ryy/NtzJU0nGy19I9QSr0t3htfwXUrzpOuDB8nGxaPasawZv58+lAEaqmpLIQQ4l9EgmVxTzOZTEzeO5lCYyEtrb3pfXAF70YfxcJkYkviFrYe+gpMJg6lHGLi3okAPF3/aXrk5Col4DSW0Humssob+ACM3gE+EcrgIZ3Kr4NcnIqxYzrkpYKdBwS1N+/OKzTw1uqTxJiqMa/2Ak5Z1sdOlU/DvS9ScHipcpB31YJlvcFoXvm9WdDqbm9FeDWlbvGuoqoYxy6ks6goEH5/QD2cbS1LnfNoyxoAbDyZzJXM0vWhM/J0nLpc9XzlP6vl7cjUgeH4udre9hhCCCHEvUjqOom7YmviVj47/Bm64kYfRcJcwhgYOpDWvq3RqDWsi11HZHIkVmpL3o45jgoIc/BjZMZ15jk78cHRz6kWOY9xDmr0Rj0P+Hbm6P5Qsq48jQNgavsyKveQkgs4+8ETG+H0WghqV/7kQjrB1smQW1Sird5g0JT8U5m55RwX0/LwdbLm5QGtsVJvYd+3L9AiZTlWBqXknMmnPlVZXz15OZPsAj2OFeQr3+iBMHdOXMpg5/mr9Ivw5fWfT2AyQf8IX3NO843q+jrRuIYLhxLSWLo/kXGdS3K0N55MwmiCIHc7vBwlz1gIIYT4MwmWxT/OZDLx+ZHPic2ILbPvQtYFtiRuwcfOh/4h/Vl+VnmQ7xm9NX6F+RDaFR5eyTMX9vHbjhe5aJHPME0BOqOKOgU6Hj0ZT3rqRzho0og2+vLioSYMtohjYKNqJSuuWhto8FCZa5t5NwBb95JguX5JCsbpy5l8u0upIzypXz3srJR/Qi2e/YaDvzSi7sG3SMWBjAJPqlIPojgFo3mQ2y1bQ7cL8+TLbTHsOn+Nb3fHcTopEycbLW/1rviKI1rWUILlyETGdAjBQq3iq+0x5qYiXep4VWG2QgghxH+HBMviH3cu7RzR6dFYGk287TmYgKb9AdAZdWxN3MramLUk5STx9bGvAQixcmfk2cOgtVXKtqlUWPu35O1On/H05qfRqVR4mlTMSrmClyEJNMp13jON5vTVAiatO83Hm6L4aEgDeob73HqCajUEd4QTK8EtVKmYgVK/+I1VJzAYTfSo503nPwWYTfo8zSupIWw8c42hx5OpU92l0l+TqtQ5bujvjL2VBak5hXz0mxLsvtGzFu72VhWe06OeD5Ptz3Alq4BVRy6x9cwVNp5SHpAc1syf8V3DKjxXCCGE+C+TnGXxj1t3fD4A7fLy6H3gcyLy8ojwjKCpd1NebfYqWx/cytS2U2ns1RgPazcmX4pHC0q5Npca5nFa+bbikdqP4GXrxaw+y1hWYzZL9R3JVDtD63F89ebzTO5fj1reDuQUGnhuyWGmbTyLwVh+CbVSmj4J9l7Q7lVzVYslkQkcvZCOg5UF7/WtW+5pnZrUJRN71hy9VOF14q7lkHg91/z5jfWVK1ORQqtR0zpECaoNRhPNAl15sInfTc+xtFAzrJlyzCs/HmfjqWQsNWqmDgxn6sBwrCw0t7yuEEII8V+kMlVUfPU/JDMzEycnJzIyMnB0vHm+qPhrDPpCun7fhCsqEx8mp9MrLxOTrRuqp7aCS0DZE356Ek78oDT4eGpbqdzhG8Vfy6HTJzswGE2seq4VDf1LVnX1BiPTNp5lblH6xANhHswaGlHmQbib+eHgBd5cfZJCvZHJ/eryaMty5goU6A00e38LGXk6ljzZnNYh7qX2n0/Jotes3RQajLQIcmVYM3+8Ha15aM4+nGy0HHm7S6WqSSyJTODNVSfRalT8OvYBQjztb3lOUkYebaZtw2A04eVoxdfDG9PIv/Kr30KIfw/5uSdE5d3zK8sBAQGoVKoyrzFjxgCQn5/PmDFjcHNzw97enkGDBpGSknKXZ/3fsuviLnZd3FWpYw/smMgVlQkHg5GpGW9zwhiAKvc6LB0K+ZklBxoNcHSZEiir1NDnswoDZYAvtkVjMJpoX9OjVKAMYKFR82avOnw2NAJrrZqd567S54vdnE/JuuV8C/VG3llzkgk/HqdQb6RbXS8ebl6jwuOtLDT0qq+keqw6UrZr3swt5yk0KK2q98WmMnb5UYbN3Qco9ZUrW3atf0Q1+jTwZfrg+pUKlEEp8TapX12GNfPjlxfaSKAshBBCVMI9HywfOHCApKQk82vz5s0ADBkyBICXXnqJX375hR9++IEdO3Zw+fJlBg4ceDen/J8SnRbNmC1jeH7r81zIvHDzgzMusi7qBwBcs/y4aKzGk4X/I9PCTel899MoyLgIOz6CzyJg9TPKec1GQ7VGFQ4bfy3HHJjeWOnhz/pFVOPnZ1vj52rDhdQ8nv7+EAX6ittmX8nK55Fv97F4bwIAL3UO4+tHGt/yAbwBDZW6xhtPJpOvKxk/KjmLDSeSAFjweFPGdQ7Fx8ma4myNP69C34ydlQWfD2vIgIbVK30OwCPNazB1YH3psCeEEEJU0j0fLHt4eODt7W1+rVu3juDgYNq1a0dGRgbz5s3jk08+oWPHjjRu3JgFCxawZ88e9u3bd7en/p8w+/hsTJgwmoysiFpx02Pz1v+P3220AJxJ70Wwhx0puDLG9AomC2s4vwk+rQvbpkBGotIyuuXz0Pm9m477+VZlVblDTQ8i/JxvemwdX0dWP9cad3srYq/mMHt72YocoAS2fT7fzYH4NBysLJg3sgljO4dWauW3sb8L1V1syC7Q8/uZknc5Zm05j8kEPcO96VDTk3Gdw9j9akfmP9aEt3rVZlgz6XwnhBBC3Gvuq2oYhYWFfP/994wfPx6VSsWhQ4fQ6XR07tzZfEytWrXw9/dn7969tGjRotxxCgoKKCgoMH+emam8/a/T6dDpdOWeI8qKTo9mU/wm8+erolcxut5obCxsyhyrOrueHZd2kOPpjo3Riay8AEZ09mfG5vPsyvEjuut0Qne+CIDRvyXGiEcx1eqjlHkDqOD7En89h1VHLgIwpn1Qpb5/jlZq3uwRxks/nOCLbefpXseDII+SVtbXsgt4fMF+UjILCPaw4+uHIwh0t6vS340+9b35ekccPx+6SLfaHpxLyWJ90arycw8ElhqrbbArbYNdwWRAp6t4pVsIIe4U+VknROXdV8Hy6tWrSU9P57HHHgMgOTkZS0tLnJ2dSx3n5eVFcnJyheNMnTqViRMnltm+adMmbG2lA1llLc9ZjgkTdbR1uGy4THphOjN+mUFjq8aljrPUZdI+6m3Wuyhf25y0RoCa7IQThNmrOZSvZuoJVx6tORmj2pJsax+4AFzYVmqc5FxYcE7D1Rua0JlMYERFHWcjl47/waXjlZu7ygS1ndWcSVczZuEunq9jRKUCnRG+OKXhcrYKD2sTo2pkcGb/Ds5U8WvjnAtgwfZzV1i5ZgM/xKoBNRFuRmIO7yKmiuMJIcSdlJube+uDhBDAfRYsz5s3jx49euDr6/uXxnn99dcZP368+fPMzEz8/Pzo2rWrPBVcSdHp0ZzccBKAd7u8yx+X/2DW0VmcsT7DW93fQlVUbg19AZolA8kwZLDbVsmvzUtviFaj4rEB3fE7e4VDK44TXWBH60HPlJz3J6k5hQz+JpLkvLwy+ywt1HwwrAV1fav2vavfKpeen+8hOhPyfMIZ1NCXCT+dJD47CUdrC5Y83ZxAd7tbD1SBtVf3cupyFidVARxNvYhKBe8Pa02Yl8NtjymEEHdC8TuqQohbu2+C5YSEBH7//Xd+/vln8zZvb28KCwtJT08vtbqckpKCt7d3hWNZWVlhZVW2gYNWq0Wr1d7Ref9bzT01F4CuNbpSx6MOPg4+zD4+m7NpZzmdfpoIzwhl2XfdC3Axkt9cPNCroJptKGcLPant64CdjRUd6/hgaXGSxNQ84tMKyg0kC/VGXlhxnAtpefi52rDgsWbYWZXUBXaw1mJvVfW/ykGeTrzUOYypv55l2m/niLuex5pjSWjUKr4e3pgwH+fb/fIAMKBhdU5dPsOyA0qaSM9wH+pWv3UdZSGE+LvJzzohKu+ef8Cv2IIFC/D09KRXr17mbY0bN0ar1bJlyxbztqioKBITE2nZsuXdmOZ/QlRqFJsTNqNCxTMNlIoVLtYu9AjsAcDyKKVFNX/MhGPLQKVhnV9tAKppWgGYV4HtrSxoU1QF4reTZVNnTCYTb60+wf641KIH7ZoS4mmPj5ON+XU7gXKxJ9oEUtvHkfRcHXN2Kg/7TepXt0qVKSrSt4Evxc8DqlQwtlPoXx5TCCGEEP+s+yJYNhqNLFiwgJEjR2JhURIYOTk5MWrUKMaPH8+2bds4dOgQjz/+OC1btqzw4T7x131z/BsAugZ0JdSlJAAcVmsYAJviN3H9+HL4fSI64IOGPTiWFY9apaYgswEA9ao5mc/rVldpG73pdNn62N/uimPlwYuoVTDr4YZ3PIVBW9TFrjj747FWATxykzrKVeHpaG0OunuF+0j6hRBCCHEfui/SMH7//XcSExN54oknyuz79NNPUavVDBo0iIKCArp168ZXX311F2b576c36tmcsLlkVbn+M6X213WvS7hbXU5cP8XP299kgFrFy8H1OZymPHU3ttFYvlmrRKU35hd3qu2FSnWCE5cyuJSeRzVnpezaigMX+OBX5dG6t3rVoUNNz7/lviL8nJkxuAGJqbm80DHkjo79bp+6fL8vgec6BN/RcYUQQgjxz5B210jbz1u5lH2Jn879xOro1VzNuwpAj4AeTG83veSga9FweCFrz67kTScr3PUG1BaWXMGAndaOqW2mUs+lFU3f/x2VCk6+1w27G9Inhszew4H4NB5rFUCB3sCao5fJLVTKqA1r5s8HA+pV+PCfEEKIqpGfe0JU3n2xsizuDpPJxMCVLxOd/zug/E7lau1Kv5B+PF3/aeWgnGuwZgyc2whANxXMcPDjmoUGMBDoFMhnHT4j0CmQ7VFXAAhytysVKAN0q+vNgfg0Fu6JN28LcrfjkRY1GNGyhgTKQgghhLgrJFgWFfotdjfR+Up7cUdTXd5u9zid/Dui1RQ9RX35CCwfDpkXQaWG0K5YNX6Mxwou8emRz+jo15H327yPvaU9AKcuK6WK6vo6lblWz3AfZv5+nkKDkR71vBnWzJ/mga4SJAshhBDirpJgWZTLZDLx+eEvAShMbcmllH4c9vSne2BRoHxkCax7CQwF4BoMQ5eAp1Lx4gmgd0hfPGw8SgW7py5nAFCvWtm3/HydbdgxoT0WGjVONlLSSAghhBD3BgmWRbkikyNJzD2FyWhBmHVfTgBzdsYS6mbFkOtfw/45yoFh3Ylu8wlWFi743XC+p23Zh/FOXqp4ZRnAzb5s7WshhBBCiLvpvigdJ/5ZJpOJr44qFUV06c14t0crXuwUCpjQrH/RHCifCHmWvtfG0Pmro3SbuZPE6xW3T83I05GYquyvaqc9IYQQQoi7RYJlUca+pH0cuXIEk9ECy+xORPg5M65TKDOr72Cgehd61Iw1jqfPybYcv5wFQG6hgbfWnKSi4iqni/KVqznb4Gxr+Y/dixBCCCHEX1GpNIy1a9dWeeAuXbpgY2NT5fPE3fXnVeWOgcFYaNRwZh39riktrifqRrDG0IQgdzuGNfOnUQ1nhs2NZOe5q6w9dpl+EdXKjFucryyrykIIIYS4n1QqWO7fv3+VBlWpVJw/f56goKDbmZO4i/Ym7eXo1aOoTFoKr7enXWsPSDoGPz+FChP5EY/j7fQ8y2u4lKpW8XyHED7ZfI7J607TPswTJ9vSD+kVV8K4sXOfEEIIIcS9rtJpGMnJyRiNxkq9bG1t/845i7/JjavKhWnNMOkdaV/NCMuGgS4Xgtpj3WcGYzqE0CLIrVSli2faBRPiac+17EI+3HimzNiysiyEEEKI+1GlguWRI0dWKaVi+PDh0hHoPrQ8ajnHrh7DQmVJwfV2hHnY4P3rU5B5CdxCYcgi0JT/ZoSlhZoPBoQDsGz/BfbHpQKQlJHHZ7+fJ/pKNiAry0IIIYS4v1QqDWPBggVVGvTrr7++rcmIO0dnMJKVr8fVruKH6Qr0BrLz9TjYqPhw/4f8cO4HAGpY9CBN78jLzjvgwn6wcoKHV4CN802v2SzQlaFN/Vh+4AKv/XScIA87tp69grHomb961RzxdJDycEIIIYS4f/ylOss6nY5z585hMBioWbMmVlYSCN0LDEYTj3wbyYH4VP7XtSbPtQ8u0wnvSGIaz35/mLSCq9RqsJrYrFOoUPF8w+eZty4QH5LolKQ80EeX98AtuFLXfr1HbX4/k0LstRxir+UA0DzQlYeb+9Otrrd05BNCCCHEfeW2g+Vdu3YxdOhQdDoder0eCwsLFi9eTPfu3e/k/MRt+G5vvDkN4qPfojhxMYMZDzbA3kr5di/fn8g7a06h18Zj4/8dsVlZ2FnYM73dNLy1DfkgcwfzLBdioc8Bv+bQ6LFKX9vJVsvHD0YwfeNZWgW7MbSZP8Ee9n/HbQohhBBC/O0qHSwbjUbU6pIU53HjxrFkyRLat28PwJw5c3j22WeJi4u745MUlZeUkcdHv0UB0DPcm99PX2HjqWSiv8zmi4cbsmhPAsv2J6LSZOMUuAgDORjyvbDKfZoGbi1ZeeAC3dQH6aQ+BGoL6D0T1FUrx90uzIN2YR5/w90JIYQQQvyzKh0FNW/enMOHD5s/LywsxN/f3/y5v78/+fn5d3Z2olL0Rj1fHf2Kg8kHeXfNKXIKDTTyd+aLYY1Y/nQLvBytiL6STfeZu5RAWQURETswkEOwUyiOaeNJSLHl+aWH2Xs6jve0i5SBW48Frzp39+aEEEIIIe6iSgfLX3zxBU8++SQvvfQSOTk5vPvuuzRu3JgWLVrQuHFjBg0axPvvv/93zlVUYEviFr4+9jVjt/6PTaeTsFCrmDqwPmq1ikb+LvzyQhuaBrgA4GhtwYT+KqJzd6FWqZnSZhLfPtoaG62GXeev8cDF2fioUil0CoAHJtzdGxNCCCGEuMsqnYbRvHlzDhw4wPTp02ncuDHTp08nKiqKyMhIDAYDTZs2pVq1sp3bxN/vyMXdAGTqrqOxjWV0s27U9HYw7/d0sGbJky3YdDqZ2r42PL/jYQCG2QVT77thABx2MHA9pwBfrgOg7TsTtNKBUQghhBD/bSqTyWSq6kkxMTE888wzODo68vnnn+Pr6/t3zO0fk5mZiZOTExkZGfdNfehr2QUYi2qyPb+qLWdQUmCscpuy+8m5WGs15Z4389BM5p2ch6eNB2vPHsPOqC9zzHH3XtR/funfN3khhBB31f34c0+Iu6VK1TBOnTrF2bNnCQ8PZ/PmzSxatIi2bdvy8ssv89xzz/1dcxQ3uJZdwLjlR9kdfQ2ATpq9nAvNg6KSbGq746DSAWWD5XNp51h0SslHfsOrHXanD4F7TehfUhf7Sq6BukEN//4bEUIIIYS4D1Q6Z/mTTz6hadOmfPTRR7Rs2ZK5c+cycuRIIiMj2bdvHy1btuTEiRN/51z/845fTKfv57vNgbKjKpfB9ssxqFR46A1U0+nJMxWw/eL2MucaTUYm7p2I3qSno19HOiWfV3bU6QfVG5tfnmHN0Fho/8G7EkIIIYS4d1U6WJ4+fTrr169n3759HD58mE8++QQAd3d3Fi9ezKRJk3jwwQf/ton+1/1w8AKDZ+/lckY+ge52bH7pAY63PcAF6wIAGnk0oGeO0gRkfcy6sudH/cDxq8ex09rxeuOXIHqLsqNWr3/sHoQQQggh7jeVDpZNJpO5zrJGo+HPqc5dunThyJEjd3Z2ApPJxHtrTzHhx+MU6o10ru3JmudbE6o7B/vncNRa6ZrYMKgbvQuU78nuS7tJy08zj3El9wozD88E4IWGL+CddBp0ueDkBz4N/vF7EkIIIYS4X1Q6WJ4wYQI9e/akVatWREREMH78+DLHWFtb39HJCVh3PImFe+IBGNc5lDmPNsFRq4JfxmLExFFbpTtehHdTggI6UrugEL3JwG/xv5nH+HD/h2Trsgl3D2dozaFwdr2yo1Yvc66zEEIIIYQoq9LB8v/+9z/27dvHSy+9xO7duxk9evTfOS8BGIwmZm45i5X3arq3TGRc5zDUahVEfg0pJ4izdyMLAzYWNoS5hkGt3vTOVlIx1sUqqRg7Luxgc8JmNCoN77R8B43JBFEblAtICoYQQgghxE1VqY9xeHg4Q4YMoVatWn/XfMQN1p9IIj7nKJYu+9ifOZfU/FTIz4CdHwFwJGIAAPXc66FVayGsKz3yClGbTBy7eoyo1Cjej1QaxTxa51FqudaCC/sgLxVsXMC/1V27NyGEEEKI+0GlguXx48eTU/TwWGW8/vrrpKam3vakhLKq/Nnv59DYXABAZ9Tx8/mfYd9sJWB2r8nRorSXCI8I5SRrJzz8W9MiT6m5/Ozvz5KUk4SvnS/PNnhWOaY4BSOsB2iqVDlQCCGEEOI/p1LB8meffUZubm6lB/3yyy9JT0+/3TmVcunSJYYPH46bmxs2NjaEh4dz8OBB836TycQ777yDj48PNjY2dO7cmfPnz9+Ra99N645fJuZqDlZ2l8zbfji7AsO+L5VP2r3C0avHAIjwjCg5sVZvehf9YnM17yoAb7V4C1utLZhMcKaoUkbt3n/7PQghhBBC3O8qFSybTCbCwsJwdXWt1Ksqq9A3k5aWRuvWrdFqtfz666+cPn2ajz/+GBcXF/Mx06dPZ9asWcyePZvIyEjs7Ozo1q0b+fn5d2QOd4PBaOKzLecBE9b2SrCsUWm4nJvMTnUheNQiNbgdCZkJADTwuKGiRc2edMrJw8ZoBKB7QHfaVm+r7Es+ARmJYGEDQR3+yVsSQgghhLgvVep9+AULFlR5YC8vryqf82fTpk3Dz8+v1PUDAwPNH5tMJmbOnMlbb71Fv379AFi8eDFeXl6sXr2aoUOH/uU5/OPyMzi4ZRWXrjrh5FBAvjETC5UFD4X0Z8n5H1nmaE+HNq9y9JrSACbYKRgnK6eS8x19sPVtzPNpUez2b8CrzV4t2Xe2aFU5pBNY2v6DNyWEEEIIcX+qVLA8cuTIv3se5Vq7di3dunVjyJAh7Nixg2rVqvHcc8/x1FNPARAXF0dycjKdO3c2n+Pk5ETz5s3Zu3dvhcFyQUEBBQUF5s8zMzMB0Ol06HS6v/GObk297GGaJ+xmhWUQy2uPZH0WhLqE8nBWHktNJvba2BDtXY/DsWsBqO9ev8yc1WE9GbHtIMNzLTFYOJn3W5xZhwrQh/bAdJfvUwghxN1zt3/WCXE/uaef8IqNjeXrr79m/PjxvPHGGxw4cIAXX3wRS0tLRo4cSXJyMlB2FdvLy8u8rzxTp05l4sSJZbZv2rQJW9u7t+LqnnWa1gm7AYhQx/LbpS/B0RqnTGt8YhbygIc9O2xtmL55BpcMSnqG6rKKDRs2lBrHPt+OTgBxO0j5UikPp8JItfRTGFGzKV6F7mLpc4QQQvx3VOU5JCH+6+7pYNloNNKkSRM++OADABo2bMjJkyeZPXv2X1rtfv3110s1VcnMzMTPz4+uXbvi6Oj4l+d9W0wmNN99DcA6QwuaO6ZyVpsOQI+COLTGPB5S+7GDfE6YTlBoKgRgRKcR+Dv6lx1u7mLUV05RPT2y9I6gdnTpK23JhRDiv6z4HVUhxK3d08Gyj48PderUKbWtdu3a/PTTTwB4e3sDkJKSgo+Pj/mYlJQUIiIiKhzXysoKKyurMtu1Wi1arfYOzPw2xO6AC3spMFkwnRGsfqoHp9Z0AIzUTzoDQOs2b+Af9S2JWYkAuFq7EuQahKq8LnxDl0D072AylmxTa1DX7IX6bt2jEEKIe8Jd+1knxH3ong6WW7duTVRUVKlt586do0aNGoDysJ+3tzdbtmwxB8eZmZlERkby7LPP/tPTvX0mE2yfCsAyQ0daRoSTakolDyM2KgsC9Ubwa4G6dj8eIouPDipNSRp4NCg/UAZwDYRmT/1TdyCEEEII8a9UpQ5+ABkZGeU2HElNTb3jb+u89NJL7Nu3jw8++IDo6GiWLl3KnDlzGDNmDAAqlYpx48YxZcoU1q5dy4kTJxgxYgS+vr7079//js7lbxW3AxL3UmDS8rW+L4+2rMGJomoXdT0j0LwSCyPWgFpNv5B+WGuKmpHcWF9ZCCGEEELccVUOlocOHcry5cvLbF+5cuUdL9XWtGlTVq1axbJly6hXrx6TJ09m5syZPPLII+ZjXnnlFV544QVGjx5N06ZNyc7OZuPGjVgXdbe755lMsE1ZVV5q6Ej1GsHUq+bEyWsnAQh3DwcbZ9Aq9+Nk5cSzEc8S4BhA94Dud2vWQgghhBD/CSqTyWSqygmurq788ccf1K5du9T2s2fP0rp1a65fv35HJ/hPyMzMxMnJiYyMjH/+Ab+YrfDdAPKx5IH8T3lzaAf6RVTjoXUPcfr6aWa0m0G3gG7/7JyEEEL8q93Vn3tC3GeqvLJcUFCAXq8vs12n05GXl3dHJvWfYTLB9g8BWKrviNHei+71vCkwFHAu9RxQtLIshBBCCCHuiioHy82aNWPOnDllts+ePZvGjRvfkUn9ZyTuhQuRFGLJ1/o+DGvmj5WFhqjUKPQmPa7WrvjY+dx6HCGEEEII8beocjWMKVOm0LlzZ44dO0anTp0A2LJlCwcOHGDTpk13fIL/ZsbIOUx1cyGpsAaphS483Fypl1z8cF8993oVV7sQQgghhBB/uyqvLLdu3Zq9e/fi5+fHypUr+eWXXwgJCeH48eO0bdv275jjv1NWMmdiN7Lc0YEd7qnUqXUEHycbAE5dOwUowbIQQgghxJ10/fp1PD09iY+Pv9tT+dvMnj2bPn363JGxqhwsA0RERLBkyRJOnTrFwYMHmT9/PqGhoXdkQv8ZhxZxWlvy5U8wrWT7he3ADSvLbhIsCyGEEBV57LHHUKlUqFQqtFotgYGBvPLKK+Tn59+xa+zYsYOOHTvi6uqKra0toaGhjBw5ksLCQvMxJpOJOXPm0Lx5c+zt7XF2dqZJkybMnDnT3Fr8vffeQ6VS8cwzz5Qa/+jRo6hUKnPgGh8fj0qlwtPTk6ysrFLHRkRE8N5775V7/8Wv7t1vXSnr/fffp1+/fgQEBJi3HThwgE6dOuHs7IyLiwvdunXj2LFj5v1RUVF06NABLy8vrK2tCQoK4q233kKn0930Wi+++CKNGzfGysqq3IZxxV+XP7/s7OzMx2zevJmwsDAcHR159NFHS33tMzIyCAsLIyEhodS4TzzxBIcPH2bXrl23/HrcSpWD5Q0bNvDbb7+V2f7bb7/x66+//uUJ/ScYdHBoAWcsLQFQGW0xYeLVna9yKOUQ8ZnxgKwsCyGEELfSvXt3kpKSiI2N5dNPP+Wbb77h3XffvSNjnz59mu7du9OkSRN27tzJiRMn+Pzzz7G0tMRgMJiPe/TRRxk3bhz9+vVj27ZtHD16lLfffps1a9aUSlG1trZm3rx5nD9//pbXzsrKYsaMGbc8rvj+i1/Lli276fG5ubnMmzePUaNGmbdlZ2fTvXt3/P39iYyMZPfu3Tg4ONCtWzdzMKzVahkxYgSbNm0iKiqKmTNnMnfu3Ep9rZ944gkeeuihcvf973//KzX/pKQk6tSpw5AhQwAwGo08/PDDPPPMM+zdu5eDBw+Wenbutdde45lnnjE3rCtmaWnJww8/zKxZs245v1upcs7ya6+9xocfflhmu8lk4rXXXqNHjx5/eVL/emfXQVYSJ32rAdDe/SlyLfcRmRzJM5uV3zir2VfDxdrlbs5SCCHEf5TJZCJPZ7j1gX8DG62mSs/rWFlZ4e3tDYCfnx+dO3dm8+bNTJs2DVCCrWnTpjFnzhySk5MJCwvj7bffZvDgwQCkpaXx/PPPs2nTJrKzs6levTpvvPEGjz/+OJs2bcLb25vp06ebrxccHFxq9XblypUsWbKE1atX069fP/P2gIAA+vbtW6phW82aNfH09OTNN99k5cqVN72vF154gU8++YQxY8bg6elZqfuvjA0bNmBlZUWLFi3M286ePUtqaiqTJk3Cz88PgHfffZf69euTkJBASEgIQUFBBAUFmc+pUaMG27dvv+XKbXGwevXqVY4fP15mv729Pfb29ubPjx07xunTp5k9ezYA165d49q1azz33HNYW1vTt29fzpw5A8CePXs4cOAAX3zxRbnX7tOnD126dCEvLw8bG5vKfHnKVeVg+fz589SpU6fM9lq1ahEdHX3bE/lP2f8teuCc1gIwMax+G+p4D+GRDY+QkKm8jSAl44QQQtwteToDdd4p+y7yP+H0pG7YWlY5PAHg5MmT7Nmzp9Qq49SpU/n++++ZPXs2oaGh7Ny5k+HDh+Ph4UG7du14++23OX36NL/++ivu7u5ER0ebS+F6e3uTlJTEzp07eeCBB8q95pIlS6hZs2apQLmYSqXCycmp1LYPP/yQpk2bcvDgQZo0aVLhvQwbNozNmzczadKkCoNBgO3bt+Pp6YmLiwsdO3ZkypQpuLm5VXj8rl27ylQvq1mzJm5ubsybN4833ngDg8HAvHnzqF27dqlUjRtFR0ezceNGBg4cWOG1bse3335LWFiY+Tk4Dw8PfHx82LRpE507d2bXrl2MHDkSnU7Hs88+y/z589FoNOWO1aRJE/R6PZGRkbRv3/6251TlNAwnJydiY2PLbI+Oji6VXyIqkHIaEnYTY2mFQW1CbbKmuX8YTlZOfNHxCxwsHQAJloUQQojKWLduHfb29lhbWxMeHs6VK1eYMGECoPSG+OCDD5g/fz7dunUjKCiIxx57jOHDh/PNN98AkJiYSMOGDWnSpAkBAQF07tzZ/GDYkCFDGDZsGO3atcPHx4cBAwbwxRdflFotPn/+PDVr1qz0fBs1asSDDz7Iq6++etPjVCoVH374IXPmzCEmJqbcY7p3787ixYvZsmUL06ZNY8eOHfTo0aNUisifJSQk4OvrW2qbg4MD27dv5/vvv8fGxgZ7e3s2btzIr7/+ioVF6V9cWrVqhbW1NaGhobRt25ZJkyZV8s5vLT8/nyVLlpRKEVGpVKxcuZLJkydTt25dGjZsyBNPPMGHH35Ihw4dsLa2pnXr1tSsWbPMLxW2trY4OTmVyWeuqir/6tavXz/GjRvHqlWrCA4OBpRA+eWXX6Zv375/aTL/CQe+BWCdTS0gDV/bYNQq5XeWAKcA5nady6+xvzIw9M7+piaEEEJUlo1Ww+lJd6d7rI22/FXCinTo0IGvv/6anJwcPv30UywsLBg0aBCgxCe5ubl06dKl1DmFhYU0bNgQgGeffZZBgwZx+PBhunbtSv/+/WnVqhUAGo2GBQsWMGXKFLZu3UpkZCQffPAB06ZNY//+/fj4+FDFRsiAUoa3du3abNq06aYpFt26daNNmza8/fbbLF26tMz+oUOHmj8ODw+nfv36BAcHs337dnN53z/Ly8vD2tq6zLZRo0bRunVrli1bhsFgYMaMGfTq1YsDBw6USmFYsWIFWVlZHDt2jAkTJjBjxgxeeeWVqn4JyrVq1SqysrIYOXJkqe1t2rThwIED5s/PnTvH4sWLOXLkCA888ABjx46lR48e1KtXjwceeID69eubj7WxsTE/ZHm7qhwsT58+ne7du1OrVi2qV68OwMWLF2nbtm2lEtH/0/Iz4fgKAH7BC0ijRbX6pQ6p61aXum5178LkhBBCCIVKpbrtVIh/mp2dHSEhIQDMnz+fBg0amB9gy87OBmD9+vVUq1at1HlWVlYA9OjRg4SEBDZs2MDmzZvp1KkTY8aMKRXTVKtWjUcffZRHH32UyZMnExYWxuzZs5k4cSJhYWGcPXu2SnMODg7mqaee4rXXXmPevHk3PfbDDz+kZcuW5tXymwkKCjKnklQULLu7u5OWllZq29KlS4mPj2fv3r2o1WrzNhcXF9asWVMqKC/Oaa5Tpw4Gg4HRo0fz8ssvV5gKURXffvstvXv3xsvL66bHPf3003z88ccYjUaOHDnCkCFDsLW1pV27duzYsaNUsJyamoqHh8dfmtdtpWHs2bOH9evX89xzz/Hyyy+zZcsWtm7dirOz81+azL/e0SVQmM01mwBSrAoAiPCSwFgIIYS4E9RqNW+88QZvvfUWeXl51KlTBysrKxITEwkJCSn1Kg76QMmLHTlyJN9//z0zZ84st1NxMRcXF3x8fMjJyQHg4Ycf5ty5c6xZs6bMsSaTiYyMjHLHeeeddzh37hzLly+/6T01a9aMgQMH8tprr93y/i9evMj169fx8am4+2/Dhg05ffp0qW25ubmo1epSD1YWf240Giscy2g0otPpbnpMZcXFxbFt27ZSKRjlmTdvHq6urvTt29ecblJcsUOn05VKQYmJiSE/P9/8LsLtuq06yyqViq5duzJhwgSef/75CpPexQ2yr8J2pYrIfF1XNNaXAajtVvtuzkoIIYT4VxkyZAgajYYvv/wSBwcH/ve///HSSy+xaNEiYmJiOHz4MJ9//jmLFi0ClKB1zZo1REdHc+rUKdatW0ft2srP5m+++YZnn32WTf9v797Doqr2N4C/MzDMcL/fVFBUBMxEvCHSySOiaGZ69OctKzTNo2EnxSy1Q2peMLvosVT0hNpFu1iZqZUSKmQhAkoqoqIimAlekDsMyKzfH+Q+TDAICs6A7+d55nmYtdfs/d3Lcl43a6+9fz8uXLiAtLQ0vPbaa0hLS5PmNY8bNw7jx4/HxIkTsWLFCiQnJyMrKwt79uxBcHAwDh48WGedzs7OCA8Pb9DSZsuXL8eBAwdw9uxZqa24uBjz5s3DkSNHcOnSJcTGxmLkyJHo3LkzQkJ0T6EJCQlBWlqa1tXlwYMH49atWwgLC0N6ejrS0tIwZcoUGBsbY+DAgQCqb2T88ssvkZ6ejosXL+LLL7/EggULMH78eCgUCgDV0yi8vb21jnf+/HmkpqYiJycHZWVlSE1NRWpqqtZayUD1bwVcXV3rXVXt2rVrWLZsGd5//30A1f9w8fHxwZo1a5CQkIDY2FgEBgZK/X/++Wd07NhRmjZ8r+7pdywlJSWIi4tDdnZ2rZP917/+dV8FtVr7FgDl+SixewSbrneFqdGPMJGbwMPaQ9+VERERtRrGxsaYNWsWVq1ahZkzZ2Lp0qVwdHREZGQkLl68CBsbG/Ts2RMLFy4EUL0e74IFC3Dp0iWYmprib3/7m3S1t2/fvjh8+DBmzJiBP/74AxYWFnjkkUfw7bffYsCAAQCqLyBu374dmzZtwubNm7F8+XIYGxvD09MTzz33XL3B9ZVXXsGGDRvu+hCVLl264Pnnn9e64m1kZIQTJ07go48+Qn5+Ptq0aYMhQ4Zg6dKl0hSTujz66KPo2bMnvvzyS/zzn/8EUL2i2e7du7FkyRIEBARALpfDz88PP/74o3SV2tjYGG+99RbOnTsHIQTat2+PWbNmYc6cOdK+CwoKtAI9AEybNg1xcXHS+ztXeTMzM6WVNjQaDbZu3YrJkyfXO53j5Zdfxty5c7VuUNy6dStCQ0Oxdu1azJs3D3369JG2ffbZZ3jhhRd07q+hZKKRM9OPHz+OJ554AqWlpSgpKYGdnR1u3LgBMzMzODk51blShqErLCyEtbU1CgoKYGVl1fQHOP8T8OkYQCbHB502Yk3WBZi2245u9t3w2ZP1Lx5ORETU1Jr9e48M2t69ezFv3jycOnVKmqPc2qSlpSEoKAjnzp2rtXxfYzV6hObMmYMRI0bg1q1bMDU1xZEjR5CVlYVevXrxBr+6VJQCe8IBALd7T8PG89aQ/zkFw9veu75PEhERETW54cOHY/r06bhy5Yq+S2k2V69exccff3zfQRm4h2kYqamp2LhxI+RyOYyMjKBWq9GxY0esWrUKoaGhTb44dYsXvwrIzwKs2uJgm+koKj8HG9ccVAHwseN8ZSIiInrwZs+ere8SmlVwcHCT7avRV5YVCoV0yd7JyQnZ2dkAqlfJuHz5cpMV1irkpgG/Vk9CLwqKxNKY3wEIGJv+eXMfwzIRERGRQWv0lWU/Pz8kJSXB09MTAwYMwBtvvIEbN27gk08+Qbdu3ZqjxpZJCGD3bEBzGxqvJzE10QnZeXlo61CBQlEII5kRPG099V0lEREREdWj0VeWV6xYId0ZuXz5ctja2mLmzJm4fv16vesSPnRy04Dfj0IYq7ACU3A0Mw+WSmPMCjEDAHhYe0BlrLrLToiIiIhInxp9Zbl3797Sz05OTvjxxx+btKBW40IsAOCydW98+Jsachnw/tN+SC//GgCnYBARERG1BK1zvRBDcP4nAMDmnOqFsCOe7Iq/eznhzM3qR2LyYSREREREho9huTmoiyGyjwAA4jTd8bS/Oyb37wAASM9LBwB423HZOCIiIiJDx7DcHC4dhqyqAtkaR5RbdsCSpx6BTCZDfnk+rpZcBcCwTERERNQSMCw3hz/nK8druqN/Z0cojKqH+c5VZTdLN1iaWOqtPCIiInp43bx5E05OTrh06ZK+S2k2P/74I3r06AGNRnPf+2JYbg7nq8NynMYXAZ3speaTN04C4FVlIiKipjB58mTIZDLIZDIoFAp4eHjg1VdfRXl5eZMdIy4uDkFBQbCzs4OZmRk8PT0RGhqKiooKqY8QAps2bYK/vz8sLCxgY2OD3r17Y82aNSgtLQUALF68GDKZDDNmzNDaf2pqKmQymRRcL126BJlMBicnJxQVFWn17dGjBxYvXiy9v3Puf329/fbb9Z7T8uXLMXLkSHTo0EFqS0pKwqBBg2BjYwNbW1uEhITgt99+0/qcEALvvPMOunTpAqVSibZt22L58uX1HisvLw+TJk2ClZUVbGxsMHXqVBQXFzdqv8ePH4efnx8sLCwwYsQI5OXlSdtu376NXr164ejRo1r7HDp0KBQKBbZt21ZvfQ1xT2E5NjYWCxcuxLRp0/D8889rvZrSnf+war68vf8XNMvLyxEWFgZ7e3tYWFhgzJgxyM3NbdIaGi0vE8i7gEphhARNV/h72EEIgW3p27AhdQMAwM/JT781EhERtRJDhw7F1atXcfHiRaxevRobN27EokWLmmTfp0+fxtChQ9G7d2/Ex8fj5MmTeP/992FiYoKqqiqp37PPPovZs2dj5MiROHjwIFJTUxEREYFdu3Zh//79Uj+VSoXo6GhkZGTc9dhFRUV455136u1z9epVrdfmzZshk8kwZswYnZ8pLS1FdHQ0pk6dKrUVFxdj6NChcHd3R2JiIg4fPgxLS0uEhISgsrJS6vfyyy/jww8/xDvvvIMzZ87gu+++Q9++feutcdKkSUhLS0NMTAz27NmD+Ph4TJ8+XavP3fY7bdo0BAUF4dixYygoKMCKFSukbe+++y4CAwPrrGPy5MlYu3ZtvfU1iGikxYsXC7lcLvr27StGjhwpRo0apfVqSosWLRKPPPKIuHr1qvS6fv26tH3GjBnCzc1NxMbGiuTkZNGvXz/Rv3//Rh+noKBAABAFBQX3X/TR/wqxyEociegrAlfGirLKMrHw54Wi29ZuotvWbmJe3DxRfrv8/o9DRER0j+76vafRCKEu1s9Lo2nweYSGhoqRI0dqtY0ePVr4+flJ76uqqsSKFStEhw4dhEqlEt27dxc7duyQtufl5Ymnn35aODg4CJVKJTp37iw2b94shBBi9erVokOHDvXW8MUXXwgA4ttvv61jGDUiPz9fCFGdaXx9fcXgwYPF2LFjpT7Hjx8XAERmZqYQQojMzEwBQMybN09YWFiI3Nxcqa+vr69YtGiRzlpGjhwpgoKC6q13x44dwtHRUastKSlJABDZ2dlS24kTJwQAkZGRIYQQ4vTp08LY2FicOXOm3v3XdPr0aQFAJCUlSW0//PCDkMlk4sqVKw3er6mpqUhPTxdCCLF+/XrxxBNPCCGEuHDhgvD09BSFhYV1fi4rK0sAEOfPn29wzXVp9DrLUVFR2Lp1K5599tn7T+oNYGxsDBcXl1rtBQUFiI6Oxvbt2xEUFAQA2LJlC3x8fHDkyBH069fvgdRXU155HsozfgCMjbC30huPdCjGcz88h/S8dBjJjBDeKxzPdn0WMpnsgddGRETUYJWlwIo2+jn2wj8AE/N7+uipU6fw66+/on379lJbZGQkPv30U0RFRcHT0xPx8fF45pln4OjoiAEDBiAiIgKnT5/GDz/8AAcHB5w/fx5lZWUAABcXF1y9ehXx8fF4/PHH6zzmtm3b4OXlhZEjR9baJpPJYG1trdW2cuVK9OnTB8nJyVrPrviriRMnIiYmBm+++SY++OCDu557bm4u9u7di48++qjefj///DN69eql1ebl5QV7e3tER0dj4cKFqKqqQnR0NHx8fKSpGrt370bHjh2xZ88eDB06FEIIBAcHY9WqVbCzs6vzWAkJCdKUlDuCg4Mhl8uRmJiIf/zjHw3ar6+vL2JiYtC5c2fExsaie/fuAIAZM2Zg1apVsLSs+z4wd3d3ODs74+eff0anTp3uOoa6NDosV1RUoH///vd8wMbKyMhAmzZtoFKpEBAQgMjISLi7uyMlJQWVlZUIDg6W+np7e8Pd3R0JCQn1hmW1Wg21Wi29LywsBABUVlZq/bqhMXZf3I1FR/78tY9bWwDHgPJjQDlgo7TBysCV6OvSF7dv376n/RMRETWVe/2uM0R79uyBhYUFbt++DbVaDblcLoVLtVqNFStW4KeffkJAQAAAoGPHjjh8+DA2btyIAQMGIDs7G35+flKgqzmPd+zYsdi3bx8GDBgAFxcX9OvXD4MGDcJzzz0HKysrANU5xcvLq8H19uzZE+PGjcNrr72G2NhYnf1kMhlWrlyJESNGYM6cOXcNex999BEsLS0xevToevtlZWWhTRvtfwhZWlri0KFDGDVqFJYuXQoA8PT0xL59+2BsXB0VL168iKysLOzYsQMff/wxqqqqMGfOHPzf//0fDhw4UOexcnJy4OTkpNVmbGwMOzs75OTkNHi/H374IV588UW88847CAwMxIIFC/DJJ5/AzMwMffr0QUhICC5cuIAJEyZg2bJlWsdr06YNsrKy6h2Tu2l0WJ42bRq2b9+OiIiI+zpwQ/j7+2Pr1q3w8vLC1atXsWTJEvztb3/DqVOnkJOTAxMTE9jY2Gh9xtnZWfoD0CUyMhJLliyp1b5//36YmZndU60fFVf/S85YCMgFoIYCxnLAzagdxijH4MaxG/ge39/TvomIiJrSnZvOdFKYVV/h1QdF476HBw4ciA0bNqCkpASrV6+GsbGxNGf3/PnzKC0txeDBg7U+U1FRAT+/6vuHZs6ciTFjxuDYsWMYMmQIRo0aJV0UNDIywpYtW7Bs2TIcOHAAiYmJWLFiBd566y0cPXoUrq6uEEI0+hSXLVsGHx8f7N+/v1aYrCkkJASPPfYYIiIisH379nr3uXnzZkyaNAkqlarefmVlZbX6lJWVYerUqQgMDMRnn32GqqoqvPPOOxg+fDiSkpJgamoKjUYDtVqNjz/+GF26dAEAREdHo1evXjh79myj/sFQU0P2+8gjjyAuLk76zM2bN7Fo0SLEx8fjpZdeQv/+/fHNN9+gT58+8Pf3x4gRI6S+pqamd//v/S4aHZbLy8uxadMm/PTTT+jevTsUCoXW9vfee+++Cqpp2LBh0s/du3eHv78/2rdvjy+//BKmpqb3vN8FCxYgPDxcel9YWAg3NzcMGTJE+pdiY5RWlmLx14sBAN9cuYrj5f2w2mIuDoT/7Z5rJCIiai53fqOqk0x2z1MhHjRzc3N07twZQHVg9PX1lW5gu7Pqwt69e9G2bVutzymVSgDVWSMrKwvff/89YmJiMGjQIISFhWndXNe2bVs8++yzePbZZ7F06VJ06dIFUVFRWLJkCbp06YIzZ840quZOnTrhhRdewPz58xEdHV1v35UrVyIgIADz5s3T2efnn3/G2bNn8cUXX9z12A4ODrh165ZW2/bt23Hp0iUkJCRALpdLbba2tti1axcmTJgAV1dXGBsbS4EWAHx8qp9GnJ2dXWdYdnFxwbVr17Tabt++jby8PGmK7b3sNzw8HLNnz0a7du1w6NAhLFu2DObm5hg+fDgOHTqkFZbz8vLg6Oh413GpT6PD8okTJ9CjRw8A1XODamruubg2Njbo0qULzp8/j8GDB6OiogL5+flaV5dzc3PrnONck1KplP4nqUmhUNQK/w2RmpOK25rbaKuRoUPlbayp6o6ATvb3tC8iIqLm1lq/n+RyORYuXIjw8HA8/fTT6Nq1K5RKJbKzszFgwACdn3N0dERoaChCQ0Pxt7/9DfPmzdO5EoWtrS1cXV1RUlICAHj66acxYcIE7Nq1q9a8ZSEECgsLa81bBoA33ngDnTp1wueff17vOfXt2xejR4/G/Pnzdfa5cyXW19e33n0BgJ+fHz799FOtttLSUsjlcq0cd+f9nXWKAwMDcfv2bVy4cEGaEnLu3DkA0JojXlNAQADy8/ORkpIizZM+cOAANBoN/P3972m/sbGxSE9Px5YtWwAAVVVV0rSiv04vKi8vx4ULF6TfItyz+7o98AErKioStra24j//+Y/Iz88XCoVCfPXVV9L2M2fOCAAiISGhUfu939Uwlh9ZLrpt7SaWrG0vxCIr0fO1beLrlMv3tC8iIqLm1qSrQOlRXathVFZWirZt24q3335bCCHE66+/Luzt7cXWrVvF+fPnRUpKili7dq3YunWrEEKIiIgI8e2334qMjAxx6tQp8eSTT4q+ffsKIYSIiooSM2bMEPv27RPnz58Xp06dEq+++qqQy+Xi0KFDQojqFS/Gjx8vTE1NxfLly0VSUpK4dOmS2L17twgKChI7d+4UQvxvNYyaIiIihEqlqnM1jOPHj0v9zp49K4yNjYVKpaq1GkZBQYEwMzMTGzZsaNCYnThxQhgbG4u8vDypLT09XSiVSjFz5kxx+vRpcerUKfHMM88Ia2tr8ccffwghqlcV6dmzp3j88cfFsWPHRHJysvD39xeDBw+W9pOYmCi8vLzE77//LrUNHTpU+Pn5icTERHH48GHh6ekpJk6cKG1vyH7vKCsrE97e3lpjM2zYMPHCCy+I1NRU0a5dO/Hll19K2w4ePCgsLCxESUlJg8ZGl/sKy5cvXxaXLzdfKJw7d644dOiQyMzMFL/88osIDg4WDg4O4tq1a0KI6qXj3N3dxYEDB0RycrIICAgQAQEBjT7OvfylsSbmnHh95wmhrqwST3z9hOi2tZv46S1ncSLCV7R/bY+4cqu00XUQERE9CK05LAshRGRkpHB0dBTFxcVCo9GINWvWCC8vL6FQKISjo6MICQkRcXFxQgghli5dKnx8fISpqamws7MTI0eOFBcvXhRCCHHs2DHxzDPPCA8PD6FUKoW9vb14/PHHxXfffad1vKqqKrFhwwbRp08fYWZmJqysrESvXr3Ef/7zH1FaWp0H6grLBQUFwsHB4a5hWQghpk+fLgDUCssbN24Upqam0hJ1DdG3b18RFRWl1bZ//34RGBgorK2tha2trQgKCqp18fHKlSti9OjRwsLCQjg7O4vJkyeLmzdvStsPHjyodS5CCHHz5k0xceJEYWFhIaysrMSUKVNEUVFRo/Z7x/z588XcuXO12jIyMkSfPn2ElZWVmDlzpqiqqpK2TZ8+Xfzzn/9s8LjoIhOicTPTNRoNli1bhnfffVeaC2RpaYm5c+fi9ddfl+a6NIUJEyYgPj4eN2/ehKOjIx577DEsX75cukxfXl6OuXPn4rPPPoNarUZISAjWr19/12kYf3XnVyQFBQUNmrN8vUiNPst/AgA82dMEcWXhMBYCP2f9jk0VY7DL5hnEzRvY+BMmIiJ6ABr7vUety969ezFv3jycOnWqSXObIblx4wa8vLyQnJwMDw+P+9pXo+csv/7664iOjsbKlSsRGBgIADh8+DAWL16M8vLyuz72sDHuNo9HpVJh3bp1WLduXZMdsyGOZf9vYnxcZgzgAviWq1Fo5oONZU9ilId9PZ8mIiIi0p/hw4cjIyMDV65cgZubm77LaRaXLl3C+vXr7zsoA/cQlj/66CN8+OGHeOqpp6S27t27o23btnjxxRebNCwbqpSs6rDsZqWAm0UMTgLwv22MBcoFUMMIAZ0YlomIiMhwzZ49W98lNKvevXvX+9CXxmj0tfe8vDx4e3vXavf29kZeXl6TFGXo7oTljW2+xgWzCgDAnvyJ+PmqEQDAv2PdT7IhIiIiopal0WHZ19e3zscufvDBBw1asqSlU9+uwsnfC/CMUQxKcnaiVC6HSqNCWrEfNALoYG8GV+t7XwOaiIiIiAxHo6dhrFq1CsOHD9d6dGRCQgIuX76M779v/U+oO3WlACZVxfi3ahui/nwwyuMdgpBywwKXbpYioJODniskIiIioqbS6CvLAwYMwLlz5/CPf/wD+fn5yM/Px+jRo3H27Fn87W+t/4l1KVm3MEB+AipU4BfL6kXG/+7+GD6Z6o8ZAzrhpaDOeq6QiIiIiJpKo68sA0CbNm0eihv56pJ86RaeNErCDbkcZ6qnKKN/m/6wNzXD/GG153ITERERUcvVoLB84sQJdOvWDXK5HCdOnKi3b/fu3ZukMEMkhMDJrGt4V56KQ2YqAICPnQ/sTbn6BREREVFr1KCw3KNHD+Tk5MDJyQk9evSATCZDXc8ykclkqKqqavIiDUXWzVJ0KUuFpUkZDlu2BQA81vYxPVdFRERERM2lQWE5MzMTjo6O0s8Pq5SsWxgiT4YAcMRUBYhK9G/TX99lERERETXYzZs34ePjg6NHj6JDhw76LqfRfvzxR8yfPx/Hjh17IE8gbNAR2rdvD5lMBgDIyspC27Zt0b59e61X27ZtkZWV1azF6tuxrJsYbJSCm0Zy5IlKyGVydHdsvdNOiIiIDNnkyZMhk8kgk8mgUCjg4eGBV199FeXl5U12jLi4OAQFBcHOzg5mZmbw9PREaGgoKioqpD5CCGzatAn+/v6wsLCAjY0NevfujTVr1qC0tBQAsHjxYshkMsyYMUNr/6mpqZDJZLh06RKA6ifPyWQyODk5oaioSKtvjx49sHjxYun94sWL4e3tDXNzc9ja2iI4OBiJiYl3Pafly5dj5MiRWkE5KSkJgwYNgo2NDWxtbRESEoLffvtN61h3xrrmy9zcvN5j1fWZmk9oPn78OPz8/GBhYYERI0ZoPbPj9u3b6NWrF44ePaq1z6FDh0KhUGDbtm13Pdem0Og4PnDgwDofPlJQUICBAwc2SVGGquRCIpxk+chUWgEAXMxcYGJkoueqiIiIHl5Dhw7F1atXcfHiRaxevRobN27EokWLmmTfp0+fxtChQ9G7d2/Ex8fj5MmTeP/992FiYqI17fTZZ5/F7NmzMXLkSBw8eBCpqamIiIjArl27sH//fqmfSqVCdHQ0MjIy7nrsoqIivPPOO/X26dKlCz744AOcPHkShw8fRocOHTBkyBBcv35d52dKS0sRHR2NqVOnSm3FxcUYOnQo3N3dkZiYiMOHD8PS0hIhISGorKwEALzyyiu4evWq1qtr164YO3bsXc9ly5YtWp8bNWqUtG3atGkICgrCsWPHUFBQgBUrVkjb3n33XQQGBqJv37619jl58mSsXbv2rsduEqKRZDKZuHbtWq32s2fPCktLy8buziAUFBQIAKKgoEBnn/zSCrHh9UlCLLISOz59UnTb2k1M3Tf1AVZJRETUNO72vafRaERJRYleXhqNpsHnERoaKkaOHKnVNnr0aOHn5ye9r6qqEitWrBAdOnQQKpVKdO/eXezYsUPanpeXJ55++mnh4OAgVCqV6Ny5s9i8ebMQQojVq1eLDh061FvDF198IQCIb7/9ts5xzM/PF0IIsWjRIuHr6ysGDx4sxo4dK/U5fvy4ACAyMzOFEEJkZmYKAGLevHnCwsJC5ObmSn19fX3FokWLdNZy58/1p59+0tlnx44dwtHRUastKSlJABDZ2dlS24kTJwQAkZGRUed+UlNTBQARHx+v81hCCAFA7Ny5U+d2U1NTkZ6eLoQQYv369eKJJ54QQghx4cIF4enpKQoLC+v8XFZWlgAgzp8/X+/xm0KDl44bPXo0gOrL6ZMnT4ZSqZS2VVVV4cSJE+jfv/XO3z2elYch8iQAwFUHdyDnEtwt3fVcFRERUdMru10G/+3+ejl24tOJMFOY3dNnT506hV9//RXt27eX2iIjI/Hpp58iKioKnp6eiI+PxzPPPANHR0cMGDAAEREROH36NH744Qc4ODjg/PnzKCsrAwC4uLjg6tWriI+Px+OPP17nMbdt2wYvLy+MHDmy1jaZTAZra2uttpUrV6JPnz5ITk5G7969dZ7LxIkTERMTgzfffLPOJyf/VUVFBTZt2gRra+t6n6j8888/o1evXlptXl5esLe3R3R0NBYuXIiqqipER0fDx8dH55zmDz/8EF26dGnQMzbCwsIwbdo0dOzYETNmzMCUKVOk6b2+vr6IiYlB586dERsbK62qNmPGDKxatQqWlpZ17tPd3R3Ozs74+eef0alTp7vWcD8aHJbv/GELIWBpaQlT0/890tnExAT9+vXDCy+80PQVGohLZ47h7/Ic3JYpcNmkeuoFwzIREZF+7dmzBxYWFrh9+zbUajXkcrkULtVqNVasWKH11OGOHTvi8OHD2LhxIwYMGIDs7Gz4+flJwbVmOBw7diz27duHAQMGwMXFBf369cOgQYPw3HPPwcqqekpmRkYGvLy8Glxvz549MW7cOLz22muIjY3V2U8mk2HlypUYMWIE5syZozMQ7tmzBxMmTEBpaSlcXV0RExMDBwfdTxPOyspCmzZttNosLS1x6NAhjBo1CkuXLgUAeHp6Yt++fTA2rh0Vy8vLsW3bNsyfP/+u5/vmm28iKCgIZmZm2L9/P1588UUUFxfjX//6F4Dq0P3iiy/inXfeQWBgIBYsWIBPPvkEZmZm6NOnD0JCQnDhwgVMmDABy5Yt09p3mzZtHsj9cg0Oy1u2bAFQ/R/RK6+8ctcJ3a2N6cUfAQC5Dv1wuSQHAOBm6abPkoiIiJqFqbEpEp+++41izXXsxhg4cCA2bNiAkpISrF69GsbGxhgzZgwA4Pz58ygtLcXgwYO1PlNRUQE/Pz8AwMyZMzFmzBgcO3YMQ4YMwahRo6TflBsZGWHLli1YtmwZDhw4gMTERKxYsQJvvfUWjh49CldX1zqX0r2bZcuWwcfHB/v374eTk5POfiEhIXjssccQERGB7du36zz/1NRU3LhxA//9738xbtw4JCYm6txvWVkZVCpVrbapU6ciMDAQn332GaqqqvDOO+9g+PDhSEpK0rpACgA7d+5EUVERQkND73quERER0s9+fn4oKSnB22+/LYXlRx55BHFxcVKfmzdvYtGiRYiPj8dLL72E/v3745tvvkGfPn3g7++PESNGSH1NTU2lGyibU6Nv8Fu0aNFDF5RvV2nQtSAeACD3eRLZRdkAADcrhmUiImp9ZDIZzBRmennd+fV8Q5mbm6Nz587w9fXF5s2bkZiYiOjoaADVN64BwN69e5Gamiq9Tp8+ja+++goAMGzYMGRlZWHOnDn4448/MGjQILzyyitax2jbti2effZZfPDBB0hLS0N5eTmioqIAVN9kd+bMmUbV3KlTJ7zwwguYP3/+XcP2ypUr8cUXX+D48eP1nn+/fv0QHR0NY2Nj6fzr4uDggFu3bmm1bd++HZcuXcKWLVvQp08f9OvXD9u3b0dmZiZ27dpVax8ffvghnnzySTg7OzfgbLX5+/vj999/h1qtrnN7eHg4Zs+ejXbt2uHQoUMYO3YszM3NMXz4cBw6dEirb15enrS0cXO6p8XpvvrqK4wbNw79+vVDz549tV6t0YXzZ/Go7CI0QgZV90EorCgEALSzaKfnyoiIiOgOuVyOhQsX4t///jfKysrQtWtXKJVKZGdno3PnzlovN7f/XfBydHREaGgoPv30U6xZswabNm3SeQxbW1u4urqipKQEAPD000/j3LlzdYZKIQQKCgrq3M8bb7yBc+fOaS2jVpe+ffti9OjRDZryAAAajUZnEAWqr+6ePn1aq620tBRyuVzrHyp33ms0Gq2+mZmZOHjwoNZqGo2RmpoKW1tbrXvf7oiNjUV6ejpmzZoFoPqeuDurcVRWVmqtQFJeXo4LFy5IvyFoTo0Oy2vXrsWUKVPg7OyM48ePo2/fvrC3t8fFixcxbNiw5qhR7279thcAcF7VFb+L6rUbHU0d7/kGBCIiImoeY8eOhZGREdatWwdLS0u88sormDNnDj766CNcuHABx44dw/vvv4+PPvoIQHVo3bVrF86fP4+0tDTs2bMHPj4+AICNGzdi5syZ2L9/Py5cuIC0tDS89tprSEtLk6YDjBs3DuPHj8fEiROxYsUKJCcnIysrC3v27EFwcDAOHjxYZ53Ozs4IDw9v0PJny5cvx4EDB3D27FmpraSkBAsXLsSRI0eQlZWFlJQUPP/887hy5Uq9y7mFhIQgLS1N6+ry4MGDcevWLYSFhSE9PR1paWmYMmUKjI2Nay0LvHnzZri6utaZ+Xbu3Alvb2/p/e7du/Hhhx/i1KlTOH/+PDZs2IAVK1bgpZdeqvXZ8vJyzJo1C5s2bZIeNBIYGIh169bht99+w9dff43AwECp/5EjR6BUKqW56M2qsctneHl5ie3btwshhLCwsBAXLlwQQggREREhwsLCmm6djgfobkvoJESFCbHISiR8MFXsvbBXdNvaTTz3/XMPuEoiIqKm0ZAlU1uCupaOE0KIyMhI4ejoKIqLi4VGoxFr1qwRXl5eQqFQCEdHRxESEiLi4uKEEEIsXbpU+Pj4CFNTU2FnZydGjhwpLl68KIQQ4tixY+KZZ54RHh4eQqlUCnt7e/H444+L7777Tut4VVVVYsOGDaJPnz7CzMxMWFlZiV69eon//Oc/orS0VAjxv6XjaiooKBAODg51Lh13/Phxrb7Tp08XAKSl48rKysQ//vEP0aZNG2FiYiJcXV3FU089JY4ePXrXcevbt6+IiorSatu/f78IDAwU1tbWwtbWVgQFBYmEhIRa59muXTuxcOHCOve7ZcsWUTNa/vDDD6JHjx7CwsJCmJubC19fXxEVFSWqqqpqfXb+/Pli7ty5Wm0ZGRmiT58+wsrKSsycOVPrc9OnTxf//Oc/73quTUEmRONmppuZmSE9PR3t27eHk5MTYmJi4Ovri4yMDPTr1w83b95s+kTfzAoLC2FtbY2CggLp7taakteMR+/8H5HgMQu/9XDDutR1GNV5FJYGLtVDtURERPfnbt971Lrt3bsX8+bNw6lTpx7I46Kb2o0bN+Dl5YXk5GR4eHg0+/EaPUIuLi7SE/zc3d1x5MgRANVzWBqZu1sMZfkNAIDc0hmXiy4D4LJxRERE1DINHz4c06dPx5UrV/Rdyj25dOkS1q9f/0CCMtCIpePuCAoKwnfffQc/Pz9MmTIFc+bMwVdffYXk5GTpwSWtjXll9dVyhbUrLhclA+CycURERNRyzZ49W98l3LPevXvX+0CXptbosLxp0ybpzsiwsDDY29vj119/xVNPPYV//vOfTV6gIbCuqp4Eb2rniuxzXDaOiIiI6GHR6LAsl8u15rdMmDABEyZMaNKiDImoug0bUQDIACNrW9wsr77KzCvLRERERK1fg8LyiRMnGrzDO8/0bi1KC67BXCagETKUqG4DAGyVtrAy4Q0RRERERK1dg8Jyjx49IJPJIIS465N1ai4Y3RoUXrsCcwB5sMKNymsAeFWZiIiI6GHRoNUwMjMzcfHiRWRmZuLrr7+Gh4cH1q9fj+PHj+P48eNYv349OnXqhK+//rpZi125ciVkMpnWpPTy8nJp7rSFhQXGjBmD3NzcJjtmcV71naL5cltkF3K+MhEREdHDpEFXltu3by/9PHbsWKxduxZPPPGE1Na9e3e4ubkhIiICo0aNavIiASApKQkbN26sNc1jzpw52Lt3L3bs2AFra2vMmjULo0ePxi+//NIkx1XfugoAKDK247JxRERERA+ZRq+zfPLkyTrXtfPw8Kj1rPGmUlxcjEmTJuG///0vbG1tpfaCggJER0fjvffeQ1BQEHr16oUtW7bg119/ldZ/vl+3C3MAAGUmdsgu+vPKMqdhEBERET0UGr0aho+PDyIjI/Hhhx/CxMQEAFBRUYHIyEjpWepNLSwsDMOHD0dwcDCWLVsmtaekpKCyshLBwcFSm7e3N9zd3ZGQkIB+/frVuT+1Wg21Wi29LywsBABUVlaisrJSq6/4MyyrVQ64XHgRAOBq6lqrHxERUUvB7zCihmt0WI6KisKIESPQrl07aUrEiRMnIJPJsHv37iYv8PPPP8exY8eQlJRUa1tOTg5MTExgY2Oj1e7s7IycnByd+4yMjMSSJUtqte/fvx9mZmZabU43sgAAV0oFckqr93ku8RyuyFvmU2+IiIhKS0v1XQJRi9HosNy3b19cvHgR27Ztw5kzZwAA48ePx9NPPw1zc/MmLe7y5ct4+eWXERMTA5VK1WT7XbBgAcLDw6X3hYWFcHNzw5AhQ2Blpb0k3MUz7wGVgKx9O0ANWCgs8H/D/++uq4IQEREZqju/USWiu2t0WAYAc3NzTJ8+valrqSUlJQXXrl1Dz549pbaqqirEx8fjgw8+wL59+1BRUYH8/Hytq8u5ublwcXHRuV+lUgmlUlmrXaFQQKFQaLWZV+YBAArNjQF19XzlO9NPiIiIWqK/ftcRkW4NCsvfffcdhg0bBoVCge+++67evk899VSTFAYAgwYNwsmTJ7XapkyZAm9vb7z22mtwc3ODQqFAbGwsxowZAwA4e/YssrOzERAQ0CQ1WFVVh+VbiuoHkvDmPiIiIqKHR4PC8qhRo5CTkwMnJ6d6l4aTyWRN+lASS0tLdOvWTavN3Nwc9vb2UvvUqVMRHh4OOzs7WFlZ4aWXXkJAQIDOm/sa5bYaVqIYAHBLXj2/y92Ky8YRERERPSwaFJY1Gk2dPxuC1atXQy6XY8yYMVCr1QgJCcH69eubZN9VRbkwAlAhjHCj6gYArrFMRERE9DC5pznL+nTo0CGt9yqVCuvWrcO6deua/FhFN/6ADYAbsEZu6R8AgHaW7Zr8OERERERkmBoUlteuXdvgHf7rX/+652IMTfHNK7ABcF1mgz9KqsMyrywTERERPTwaFJZXr17doJ3JZLJWFZbL/3zU9SWVNarETaiMVHA0c9RzVURERET0oDQoLGdmZjZ3HQapsqD6ISS/q8wA3EQ7y3aQyxr9hHAiIiIiaqGY/OpTnAsAuKqqXleZy8YRERERPVzu6Qa/33//Hd999x2ys7NRUVGhte29995rksIMgbz0OgAgx6R6BRAPaw99lkNERERED1ijw3JsbCyeeuopdOzYEWfOnEG3bt1w6dIlCCG0nrTXGijLq5eLyzEuAwTQxbaLnisiIiIiogep0dMwFixYgFdeeQUnT56ESqXC119/jcuXL2PAgAEYO3Zsc9SoN2YVN6EBkINbABiWiYiIiB42jQ7L6enpeO655wAAxsbGKCsrg4WFBd5880289dZbTV6gPlnezsMfxkZQCzWM5cboYN1B3yURERER0QPU6LBsbm4uzVN2dXXFhQsXpG03btxousr0TV0MU5Qjw6T65r5O1p2gkCv0XBQRERERPUiNnrPcr18/HD58GD4+PnjiiScwd+5cnDx5Et988w369evXHDXqx58rYaQpTAFwCgYRERHRw6jRYfm9995DcXExAGDJkiUoLi7GF198AU9Pz1a1EkZ5fg5UANJMGJaJiIiIHlaNDssdO3aUfjY3N0dUVFSTFmQoim9egQrABRNjAIJhmYiIiOgh1Og5y9OmTcOhQ4eaoRTDUpZ3FWUyGXIUAgDQxY5hmYiIiOhh0+iwfP36dQwdOhRubm6YN28efvvtt+aoS+8qC3JwUaGAkAF2KjvYq+z1XRIRERERPWCNDsu7du3C1atXERERgaSkJPTs2ROPPPIIVqxYgUuXLjVDifohinNxzqR69QtPW0/IZDI9V0RERERED1qjwzIA2NraYvr06Th06BCysrIwefJkfPLJJ+jcuXNT16c38tLrUljmfGUiIiKih9M9heU7KisrkZycjMTERFy6dAnOzs5NVZfemZRdx7k/11hmWCYiIiJ6ON1TWD548CBeeOEFODs7Y/LkybCyssKePXvw+++/N3V9eqOquMkry0REREQPuUYvHde2bVvk5eVh6NCh2LRpE0aMGAGlUtkctemPEFCLfOQbuUAGGTrZdNJ3RURERESkB40Oy4sXL8bYsWNhY2PTDOUYiLJbuGhSfdHdSdUOSqNW9o8BIiIiImqQRoflF154oTnqMCzF16QpGB7WnnouhoiIiIj05b5u8GutNEW50s19PvZeeq6GiIiIiPSFYbkOJXl/SFeWuzt567kaIiIiItIXhuU6FOb9jkxFdVjuas+wTERERPSwYliuQ2b+BdyWyaDUyOFq7qrvcoiIiIhITxiW63CxpHq9aMcqSz7mmoiIiOghZtBhecOGDejevTusrKxgZWWFgIAA/PDDD9L28vJyhIWFwd7eHhYWFhgzZgxyc3Pv+7iXbt8EADjA8b73RUREREQtl0GH5Xbt2mHlypVISUlBcnIygoKCMHLkSKSlpQEA5syZg927d2PHjh2Ii4vDH3/8gdGjR9/3cS+hBADgqHC/730RERERUcvV6HWWH6QRI0ZovV++fDk2bNiAI0eOoF27doiOjsb27dsRFBQEANiyZQt8fHxw5MgR9OvX756Pm2VUBUAOF3OusUxERET0MDPosFxTVVUVduzYgZKSEgQEBCAlJQWVlZUIDg6W+nh7e8Pd3R0JCQn1hmW1Wg21Wi29LywsBABUVlaiQl2OPKPqecr2lh1RWVnZTGdERESkH/xuI2o4gw/LJ0+eREBAAMrLy2FhYYGdO3eia9euSE1NhYmJSa3Hbjs7OyMnJ6fefUZGRmLJkiW12vfv3w+lohy3/7yp7/ffC/D999832bkQEREZgtLSUn2XQNRiGHxY9vLyQmpqKgoKCvDVV18hNDQUcXFx97XPBQsWIDw8XHpfWFgINzc3DBkyBMWFaUA8YKIRGDJgEHq3t73fUyAiIjIod36jSkR3Z/Bh2cTEBJ07dwYA9OrVC0lJSfjPf/6D8ePHo6KiAvn5+VpXl3Nzc+Hi4lLvPpVKJZRKZa12hUKBkrLq1TQsNYCTtRkUfz6chIiIqLXgdxtRwxn0ahh10Wg0UKvV6NWrFxQKBWJjY6VtZ8+eRXZ2NgICAu55/zcLrgAAzKpkcDCvHaiJiIiI6OFh0FeWFyxYgGHDhsHd3R1FRUXYvn07Dh06hH379sHa2hpTp05FeHg47OzsYGVlhZdeegkBAQH3tRLGtcKrAAClxhiWKoMeHiIiIiJqZgadBq9du4bnnnsOV69ehbW1Nbp37459+/Zh8ODBAIDVq1dDLpdjzJgxUKvVCAkJwfr16+/rmDeLrwMAlBoTyOV8eh8RERHRw8ygw3J0dHS921UqFdatW4d169Y12THzy28BAJQwbbJ9EhEREVHL1OLmLDe3worqO4SVMnM9V0JERERE+saw/BfFVdVrT6qMrfVcCRERERHpG8PyXxSLcgCAqYLrKxMRERE97BiW/6JYVD8C1EzlqOdKiIiIiEjfGJb/oliuAQBYW7TRcyVEREREpG8MyzVV3UbRnyNiY9VOv7UQERERkd4xLNcgSm+hQF49JE527nquhoiIiIj0jWG5huKi31Elq34QSVtbZz1XQ0RERET6xrBcQ37hFQCAiUbA1cpSz9UQERERkb4xLNeQe+t3AIC5RgZbMxM9V0NERERE+sawXENeUQ4AwLTKGAojDg0RERHRw46JsIa84hsAAJVQ6LkSIiIiIjIEDMs1FKhvAQBUUOm5EiIiIiIyBAzLNRRXFgEAVHJzPVdCRERERIaAYbmGkqoSAIDKyErPlRARERGRIWBYrqFEUw4AMDOx03MlRERERGQIGJZrKEUlAMBC5aDnSoiIiIjIEDAs11AiqwIA2Ji76LkSIiIiIjIEDMs1FP85GrbW7fRbCBEREREZBIblGgr+fBCJsy3DMhERERExLGspklcPh5uNo54rISIiIiJDwLBcg0YmAwC0Z1gmIiIiIjAs16LUANampvoug4iIiIgMAMPyX5hqjPRdAhEREREZCIblvzAVCn2XQEREREQGgmH5L0yh1HcJRERERGQgDDosR0ZGok+fPrC0tISTkxNGjRqFs2fPavUpLy9HWFgY7O3tYWFhgTFjxiA3N/eej2kqM7/fsomIiIiolTDosBwXF4ewsDAcOXIEMTExqKysxJAhQ1BSUiL1mTNnDnbv3o0dO3YgLi4Of/zxB0aPHn3PxzQ1tmyK0omIiIioFTDWdwH1+fHHH7Xeb926FU5OTkhJScHjjz+OgoICREdHY/v27QgKCgIAbNmyBT4+Pjhy5Aj69evX6GOaK2yaonQiIiIiagUMOiz/VUFBAQDAzs4OAJCSkoLKykoEBwdLfby9veHu7o6EhASdYVmtVkOtVkvvCwsLpZ8tlPaorKxsjvKJiIgMAr/niBquxYRljUaD2bNnIzAwEN26dQMA5OTkwMTEBDY2Nlp9nZ2dkZOTo3NfkZGRWLJkSZ3bivJv4/vvv2+yuomIiAxNaWmpvksgajFaTFgOCwvDqVOncPjw4fve14IFCxAeHi69LywshJubGwCgu08fPNHnifs+BhERkaGq+RtVIqpfiwjLs2bNwp49exAfH4927dpJ7S4uLqioqEB+fr7W1eXc3Fy4uLjo3J9SqYRSWfcScW3s2kKh4FrLRETUevF7jqjhDHo1DCEEZs2ahZ07d+LAgQPw8PDQ2t6rVy8oFArExsZKbWfPnkV2djYCAgLu6ZhuNk73VTMRERERtR4GfWU5LCwM27dvx65du2BpaSnNQ7a2toapqSmsra0xdepUhIeHw87ODlZWVnjppZcQEBBwTythAEAbS7umPAUiIiIiasEMOixv2LABAPD3v/9dq33Lli2YPHkyAGD16tWQy+UYM2YM1Go1QkJCsH79+ns+pq3K5p4/S0RERESti0wIIfRdhL4VFhbC2toaPdZ1xfEX0/RdDhERUbO6871XUFAAKysrfZdDZNAMes7yg6YSBn2hnYiIiIgeMIblGsxgou8SiIiIiMiAMCzXoJKZ6bsEIiIiIjIgDMs1mBmb67sEIiIiIjIgDMs1mBtb67sEIiIiIjIgDMs1WJja67sEIiIiIjIgDMs1WJs66rsEIiIiIjIgDMs12Fu30XcJRERERGRAGJZrcLHiNAwiIiIi+h+G5RpcLRmWiYiIiOh/GJZrsFPZ6LsEIiIiIjIgDMs1WCmt9F0CERERERkQhuUaGJaJiIiIqCaG5RoUcoW+SyAiIiIiA8KwTERERESkA8MyEREREZEODMtERERERDowLBMRERER6cCwTERERESkA8MyEREREZEODMtERERERDowLBMRERER6cCwTERERESkA8MyEREREZEODMtERERERDoYfFiOj4/HiBEj0KZNG8hkMnz77bda24UQeOONN+Dq6gpTU1MEBwcjIyNDP8USERERUati8GG5pKQEvr6+WLduXZ3bV61ahbVr1yIqKgqJiYkwNzdHSEgIysvLH3ClRERERNTaGOu7gLsZNmwYhg0bVuc2IQTWrFmDf//73xg5ciQA4OOPP4az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pZ9dXV0BANeuXbvvcyQiIqrJWN8FEFHLUVxcDADYu3cv2rZtq7VNqVRqBeZ7ZWpq2qB+CoVC+lkmkwGonk9NRETUlHhlmYgarGvXrlAqlcjOzkbnzp21Xm5ublK/I0eOSD/funUL586dg4+PDwDAx8cHv/zyi9Z+f/nlF3Tp0gVGRkZ49NFHodFotOZAExER6QuvLBNRg1laWuKVV17BnDlzoNFo8Nhjj6GgoAC//PILrKys0L59ewDAm2++CXt7ezg7O+P111+Hg4MDRo0aBQCYO3cu+vTpg6VLl2L8+PFISEjABx98gPXr1wMAOnTogNDQUDz//PNYu3YtfH19kZWVhWvXrmHcuHH6OnUiInpIMSwTUaMsXboUjo6OiIyMxMWLF2FjY4OePXti4cKF0jSIlStX4uWXX0ZGRgZ69OiB3bt3w8TEBADQs2dPfPnll3jjjTewdOlSuLq64s0338TkyZOlY2zYsAELFy7Eiy++iJs3b8Ld3R0LFy7Ux+kSEdFDjqthEFGTubNSxa1bt2BjY6PvcoiIiO4b5ywTEREREenAsExEREREpAOnYRARERER6cAry0REREREOjAsExERERHpwLBMRERERKQDwzIRERERkQ4My0REREREOjAsExERERHpwLBMRERERKQDwzIRERERkQ4My0REREREOvw/1veEVSQvxd8AAAAASUVORK5CYII=", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "fig, ax = plt.subplots()\n", - "\n", - "for idx in top_indices:\n", - " _ = np.round(architectures_TM[f'ResSCNN{idx+1}']['epochs_acc'][-1], 2)\n", - " ax.plot(np.arange(len(architectures_TM[f'ResSCNN{idx+1}']['epochs_x'])), architectures_TM[f'ResSCNN{idx+1}']['epochs_acc'], label=f'ResSCNN{idx+1} ({_}%)')\n", - "\n", - "ax.set_ylim(0, 100)\n", - "ax.set_yticks(np.arange(0, 110, 10))\n", - "ax.set_ylabel('validation acc [%]')\n", - "ax.set_xlim(0, 100)\n", - "ax.set_xlabel('epoch')\n", - "plt.title(f'top {top_n}')\n", - "\n", - "pos = ax.get_position()\n", - "ax.set_position([pos.x0, pos.y0, pos.width * 0.9, pos.height])\n", - "ax.legend(loc='center right', bbox_to_anchor=(1.45, 0.5), framealpha=0)\n", - "ax.grid(axis='y')\n", - "\n", - "plt.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAsMAAAG2CAYAAACai4utAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8fJSN1AAAACXBIWXMAAA9hAAAPYQGoP6dpAABkJklEQVR4nO3deVhUZf8G8Htm2HfZ98UFXAFFUdQ0d1vcM7NyqbRfpfYq2aJmZrllb1ZumeVbaWpaaqaV+66IiqK4soMLCIgM+zrn98fIKII6AzPMwLk/18V1yTBzzpfDCPc88zzfRyIIggAiIiIiIhGS6rsAIiIiIiJ9YRgmIiIiItFiGCYiIiIi0WIYJiIiIiLRYhgmIiIiItFiGCYiIiIi0WIYJiIiIiLRYhgmIiIiItFiGCYiIiIi0WIYJiIiIiLR0msY/u677xAYGAgbGxvY2NggLCwM//77r+rrxcXFmDRpEhwcHGBlZYURI0bg9u3beqyYiIiIiBoTiSAIgr5OvmPHDshkMrRo0QKCIOCXX37Bl19+iXPnzqFNmzZ4++238ffff+Pnn3+Gra0tJk+eDKlUiuPHj+urZCIiIiJqRPQahmtib2+PL7/8Ei+88AKcnJywYcMGvPDCCwCAq1evolWrVoiIiECXLl30XCkRERERNXRG+i6gUkVFBX7//XcUFBQgLCwMUVFRKCsrQ9++fVX3admyJby9vR8bhktKSlBSUqL6XKFQIDs7Gw4ODpBIJDr/PoiIiPRJEATk5eXB3d0dUimXBhE9id7DcExMDMLCwlBcXAwrKyts27YNrVu3RnR0NExMTGBnZ1fl/i4uLkhPT3/k8RYuXIi5c+fquGoiIiLDdv36dXh6euq7DCKDp/cwHBAQgOjoaMjlcvzxxx8YN24cDh8+XOvjzZgxA+Hh4arP5XI5vL29kZSUBGtra22UTEREZLDy8vLg5+fHv3lEatJ7GDYxMUHz5s0BACEhITh9+jS+/fZbjBo1CqWlpcjJyakyOnz79m24uro+8nimpqYwNTWtdru9vT1sbGy0Xj8REZEhMTY2BgBODSRSk8FNJlIoFCgpKUFISAiMjY2xf/9+1deuXbuG1NRUhIWF6bFCIiIiImos9DoyPGPGDDzzzDPw9vZGXl4eNmzYgEOHDmH37t2wtbXFG2+8gfDwcNWo7pQpUxAWFsZOEkRERESkFXoNwxkZGRg7dizS0tJga2uLwMBA7N69G/369QMAfP3115BKpRgxYgRKSkowYMAArFy5Up8lExEREVEjYnB9hrUtNzcXtra2kMvlnDNMRESNHv/uEWnG4OYMExERERHVF4ZhIiIiIhIthmEiIiIiEi2GYSIiIiISLYZhIiIiIhIthmEiIiIiEi2GYSIiIiISLYZhIiIiIhIthmEiIiIiEi2GYSIiIiISLYZhIiIiIhIthmEiIiIiEi2GYSIiIiISLYZhIiIiIhIthmEiIiIiEi2GYSIiIiISLYZhIiIiIhIthmEiIiIiEi2GYSIiIiISLYZhIiIiIhIthmEiIiIiEi2GYSIiIiISLYZhIiIiIhIthmEiIiIiEi2GYSIiIiISLYZhIiIiIhIthmEiIiIiEi2GYSIiIiISLYZhIiIiIhIthmEiIiIiEi2GYSIiIiISLYZhIiIiIhIthmEiIiIiEi2GYSIiIiISLYZhIiIiIhIthmEiIiIiEi2GYSIiIiISLYZhIiIiIhIthmEiIiIiEi2GYSIiIiISLYZhIiIiIhIthmEiIiIiEi2GYSIiIiISLYZhIiIiIhIthmEiIiIiEi2GYSIiIiISLYZhIiIiIhIthmEiIiIiEi2GYSIiIiISLYZhIiIiIhIthmEiIiIiEi2GYSIiIiISLYZhIiIiIhIthmEiIiIiEi2GYSIiIiISLYZhIiIiIhIthmEiIiIiEi2GYSIiIiISLYZhIiIiIhIthmEiIiIiEi2GYSIiIiISLYZhIiIiIhIthmEiIiIiEi2GYSIiIiISLYZhIiIiIhIthmEiIiIiEi2GYSIiIiISLYZhIiIiIhIthmEiIiIiEi2GYSIiIiISLYZhIiIiIhIthmEiIiIiEi2GYSIiIiISLYZhIiIiIhIthmEiIiIiEi2GYSIiIiISLYZhIiIiIhIthmEiIiIiEi2GYSIiIiISLYZhIiIiIhIthmEiIiIiEi2GYSIiIiISLYZhIiIiIhIthmEiIiIiEi2GYSIiIiISLYZhIiIiIhIthmEiIiIiEi2GYSIiIiISLYZhIiIiIhIthmEiIiIiEi2GYSIiIiISLYZhIiIiIhIthmEiIiIiEi2GYSIiIiISLYZhIiIiIhIthmEiIiIiEi2GYSIiIiISLYZhIiIiIhIthmEiIiIiEi2GYSIiIiISLYZhIiIiIhIthmEiIiIiEi2GYSIiIiISLYZhIiIiIhIthmEiIiIiEi2GYSIiIiISLYZhIiIiIhIthmEiIiIiEi2GYSIiIiISLYZhIiIiIhIthmEiIiIiEi2GYSIiIiISLb2G4YULF6JTp06wtraGs7Mzhg4dimvXrlW5T3FxMSZNmgQHBwdYWVlhxIgRuH37tp4qJiIiIqLGRK9h+PDhw5g0aRJOnjyJvXv3oqysDP3790dBQYHqPtOmTcOOHTvw+++/4/Dhw7h16xaGDx+ux6qJiIiIqLGQCIIg6LuISpmZmXB2dsbhw4fRo0cPyOVyODk5YcOGDXjhhRcAAFevXkWrVq0QERGBLl26PPGYubm5sLW1hVwuh42Nja6/BSIiIr3i3z0izRjpu4AHyeVyAIC9vT0AICoqCmVlZejbt6/qPi1btoS3t/cjw3BJSQlKSkpUn+fm5gIAysrKUFZWpsvyiYiI9I5/64g0YzBhWKFQYOrUqejWrRvatm0LAEhPT4eJiQns7Oyq3NfFxQXp6ek1HmfhwoWYO3dutdv37NkDCwsLrddNRERkSAoLC/VdAlGDolYY/uuvvzQ+cL9+/WBubq72/SdNmoSLFy/i2LFjGp/rQTNmzEB4eLjq89zcXHh5eaF///58u4iIiBq9yndEiUg9aoXhoUOHanRQiUSCuLg4NG3aVK37T548GTt37sSRI0fg6emput3V1RWlpaXIycmpMjp8+/ZtuLq61ngsU1NTmJqaVrvd2NgYxsbGGn0fREREDQ3/1hFpRu1uEunp6VAoFGp9qDsdQRAETJ48Gdu2bcOBAwfg5+dX5eshISEwNjbG/v37Vbddu3YNqampCAsLU7d0IiIiIqIaqTUyPG7cOI2mPLz66qtqTUmYNGkSNmzYgO3bt8Pa2lo1D9jW1hbm5uawtbXFG2+8gfDwcNjb28PGxgZTpkxBWFiYWp0kiIiIiIgeR6+t1SQSSY23//TTTxg/fjwA5aYb7733HjZu3IiSkhIMGDAAK1eufOQ0iYexxQwREYkJ/+4RaaZOYbisrAyxsbGoqKhAQEBAjXN19Y2/FIiISEz4d49IM7Xege7o0aPw9fVFr1698PTTT8PLywu7du3SZm1ERERERDqldhhWKBRVPp86dSrWr1+PjIwMZGdnY968eXj77be1XiARERERka6oHYY7d+6Ms2fPqj4vLS2Ft7e36nNvb28UFxdrtzoiIiIiIh1Sewe65cuXY8KECejZsyfmzZuHOXPmICQkBAEBASgrK8PVq1exbNkyXdZKRERERKRVaofhzp074/Tp01i8eDFCQkKwePFiXLt2DZGRkaioqECnTp3g4eGhy1qJiIiIiLSqVt0kEhIS8NZbb8HGxgbLli2Du7u7LmrTCq6qJSIiMeHfPSLNaNRN4tKlS9iyZQsqKiqwd+9eDB48GE899RRWrlypq/qIiEgH0uRFOJGQhTR5kb5LISLSK7XD8JIlS9CpUyd8+eWXCAsLww8//IBx48YhMjISJ0+eRFhYGGJiYnRZKxERacGm06notugAXv4hEt0WHcCm06n6LomISG/Unibh6uqKjRs3olevXkhJScHAgQNx5coV1df37t2Ld999t8pthoBvFxER3ZcmL0LXRQfw4G9+mUSCYx/1gputuf4KI63h3z0izag9MiwIAqRS5d1lMhkeztD9+vXDuXPntFsdERFpjSAIWH04EQ8PgVQIApKzCvVTFBGRnqndTeL999/Hs88+i6CgIMTGxmLBggXV7mNmZqbV4oiISDuKyyow+8+L+D3qRrWvySQS+Dpa6KEqIiL9UzsMT58+HQMGDMDVq1fRrl07tGzZUpd1ERGRltzKKcJbv0bhwg05pBJgYBtX7LqUDsW9EeL3B/hzigQRiZbaYRgA2rVrh3bt2umqFiIi0rKIhDuYvOEs7hSUws7CGMtHd0D3Fo5Ikxdh3P9OIfZ2PmzMTfRdps6lyYuQlFUAP0dLBn8iqkKtOcPh4eEoKChQ+6AzZsxAdnZ2rYsiIqK6EQQB/zuWhFfXROJOQSlau9lgx+Tu6N7CEQDgZmuO5wOVPeKPxGbqs1Sd23Q6FV3ZPYOIHkGtMPztt9+isFD9xRUrVqxATk5ObWsiIqI6KCqtQPjm8/hs52VUKAQMDXbHlre7wsu+6rzgnv5OAIDj8Vkoq1Doo1SdS5MX4aOtMapFgwoBmLn1IvsrE5GKWtMkBEGAv78/JBKJWgfVZBSZiIi053p2Id76NQqXbuVCJpVg5rOt8Ho33xp/f7f1sEUTC2PcLSxD9PUcdPK110PFupWUVVBj94zEzAJOlyAiAGqG4Z9++knjA7u4uGj8GCIiqr1jcVmYsvEs7haWwd7SBCte7oCwZg6PvL9MKsFTLZzw1/lbOHwts1GGYWNZzYM4S/fHoY27DewsGv98aSJ6PLXC8Lhx43RdBxER1ZIgCPjhaCIW/XsVCgFo52GLVWNC4GH35JHPHv7KMHwkLhPTBwTUQ7X1a8+l21U+l0iULwIik7IxePlxfD8mBK3cuDEFkZhp1E2CiIgMR5q8CFfTcvHryVTsv5oBAHghxBPzhraFmbFMrWP0uLegLuamHHfyS+BgZaqzeutbUWkFNp9R9lX+8oVAeDaxgK+jBe4WlOH/fj2D1OxCDF95AotfCMSgIHc9V0tE+sIwTETUAG06nYoZW2NUvYKlEmDu4DZ4tYuP2us7AMDZxgyt3GxwJS0Xx+KzMCTYQ0cV178d529BXlQGzybmGN7BEzKp8rq42Zpjx+TumLLxHI7GZWHKxnOIuSnHBwMCYCRTe2NWImok+L+eiKiBSZMXVQnClfq2dtEoCFeq7CpxuBG1WBMEAb9EJAMAXu3iowrClewsTPDza6F4++lmAIDVRxIx7qdTyC4ore9SiUjPGIaJiBqYpKyCakFYIQDJWeq3wHxQD3/lVIkjsVlQPHzgBupsag4u3cqFqZEUozp61XgfmVSCDwe2xIqXO8DCRIbj8XcwaNkxXLwpr+dqiUifNA7Dcrm8xg01srOzkZubq5WiiIjo0SxqmA8sk0jg62hRw72frKOPPSxMZMjKL8GV9Mbxe3zdvVHhQUHuaGL5+I4RzwW6Yds73eDjYIGbOUUY8d0JbD17ox6qJCJDoHEYfumll/Dbb79Vu33z5s146aWXtFIUERHVTBAELD+YUOU2mUSCBcPb1rpvromRFF3vtWBrDFMlsvJL8E9MOgBgbJiPWo8JcLXGX5O6o1eAE0rKFQjffB5zd1xCWYUCafIinEjI4kYdRI2UxgvoIiMjsWTJkmq3P/3005g1a5ZWiiIioprtvpSOfVduw1gmwc+vhUJ6b0S4rhtI9PR3wr4rGTgSm4l3nm6upWr1Y9Pp6yitUCDIyw6BnnZqP87WwhhrxnXCN/tisfRAPH46noxD1zKRckc5LUUqARYOb4dRnbx1VzwR1TuNR4ZLSkpQXl5e7faysjIUFfFVMxGRruQWl2HOX5cAAP/Xoxm6NXdEWDMHreyk1uPeIrozyXeRX1L9d3xDUV6hwK8nUwAAY7uoNyr8IKlUgvD+Afh+TAgsTGRV5mdzK2eixknjMBwaGorVq1dXu33VqlUICQnRSlFERFTdf3dfw+3cEvg6WGByb+2O3vo4WMLHwQLlCgERCXe0euz6tO9KBtLkxbC3NMFzgW61Ps6ANq74bHCbardXCEKtFyoSkWHSeJrEvHnz0LdvX5w/fx59+vQBAOzfvx+nT5/Gnj17tF4gEREB51LvYt29Ec/5w9qpvamGJnr6O2FtRAoOx2agX2sXrR+/Pqw7mQwAGNXJq87XqFsLR0glqNK5oy4LFYnIMGk8MtytWzdERETAy8sLmzdvxo4dO9C8eXNcuHABTz31lC5qJCIStbIKBWZsjYEgAMPbe6Bbc0ednKdHi/v9hgWh4bVYi8/Ix/H4O5BKgFc6131er5utORYOb4fKDsUSoE4LFYnIMNVqB7rg4GCsX79e27UQEVEN1hxLwtX0PNhZGGPWc610dp6wZg4wlklwPbsIyXcK4edoqbNz6ULlXOHeLV3g2UQ7o7ejOnnDwcoUE345AyOpBH1bNcwRcyJ6NI1Hhv/55x/s3r272u27d+/Gv//+q5WiiIhI6Xp2Ib7ZFwsAmPlsKzhYmersXJamRujoYw8AONLAWqzll5RjS5SyN7C67dTU1beVCwI9bVGmEPDb6etaPTYR6Z/GYfijjz5CRUVFtdsFQcBHH32klaKIiEj5e3XWnxdRXKZAl6b2GBniqfNz9gxQTpVoaGF427mbyCsph5+jJbrrYBrJmHudKTZEpqKikezSR0RKGofhuLg4tG7dutrtLVu2RHx8vFaKIiIiYMeFNByJzYSJTIr5w9pBIpE8+UF1VDlv+ETCHZSUVx/4MESCIKh2nBvTxQdSqfav06AgdzSxMMbNnCLsv3Jb68cnIv3ROAzb2toiMTGx2u3x8fGwtGxY88uIiAyVvLAMn+1Q9hSe1Ks5mjlZ1ct5W7lZw8naFEVlFYhKvlsv56yryKRsxN7Oh7mxDCN0NHpuZizDi528AEDV1YOIGgeNw/CQIUMwdepUJCTc3w40Pj4e7733HgYPHqzV4oiIxGrRrivIyi9FMydLvPV003o7r0QiqdJVoiFYF6EMp0Pbe8DW3Fhn53m1sw8kEuBoXBYSMvN1dh4iql8ah+HFixfD0tISLVu2hJ+fH/z8/NCqVSs4ODjgv//9ry5qJCISlVNJ2dh4SrlQa8GwdjA10n5P4cepnDesizCcJi/CiYQsre3idju3GLsvpQPQ/sK5h3nZW6B3gDOA+wGciBo+jVur2dra4sSJE9i7dy/Onz8Pc3NzBAYGokePHrqoj4hIVErKKzBzWwwAYFRHL3Ru6lDvNTzV3BESCXA1PQ+3c4vhYmOmleNuOp2KGVtjoBAAqQRYOLwdRnWqWz/gDZGpKFcI6OTbBK3cbLRS5+OMCfPB/qsZ2BJ1A+8PCIClaa06lBKRAanV/2KJRIL+/fujf//+2q6HiEjUVh9ORHxGPhytTDDj2ZZ6qaGJpQkCPWxx/oYcR2IzMbKjV52PmSYvUgVhQLmr28ytF9HD36nWm1iUliuw4VQqAGBsmG+da1RHjxZO8HWwQPKdQvwZfROvdNbtaDQR6V6twnBBQQEOHz6M1NRUlJaWVvnau+++q5XCiIjEJjEzH8sOKrvyzH6+NewsTPRWS09/J5y/IcdhLYXhpKwCPNyRrEIQkJxVWOswvPtSOjLzSuBkbYoBbVzrXKM6pFIJXu3ig3l/X8G6iBS8HOpdL10+iEh3NA7D586dw7PPPovCwkIUFBTA3t4eWVlZsLCwgLOzM8MwEVEtCIKAWdsuorRcgadaOGJwkLte6+nh74SlB+JxLD4LFQoBsjq2K3N6xGYh2QUltT5m5bzd0aHeMDHSeAlMrY0M8cJ/91zD1fQ8nE6+i1A/+3o7NxFpn8a/PaZNm4ZBgwbh7t27MDc3x8mTJ5GSkoKQkBAuoCMiqqUtZ28iIvEOTI2kmDe0rd5HG4O97GBtZoScwjJcuJFT5+Otj0yt8fZ3f4vGT8eTIAiabWRxNT0Xp5KzIZNK8HJo3eYda8rWwhhDgz0AAGvv9TcmooZL4zAcHR2N9957D1KpFDKZDCUlJfDy8sLixYsxc+ZMXdRIRNSoXUnLxad/XQQA/KdvC/g46L9nu5FMqtrJ7UhsVp2Odf56Dn65Fxq/fSkYGyd2wcH3nsbQYHdUKATM3XEZ720+j+Iy9Tf5WHtvVHhAGxe42mpngZ8mxtzrXLHrYjoycou1fnxtd90gokfTOAwbGxtDKlU+zNnZGampylf7tra2uH6de7YTEWli0+lUPPPtUeSXKIOgnQ775Gqqp/+9rZnjat9irbxCgRlbYyAIwLD2HhgS7IGwZg7wc7LE16OCMfv51pBJJdh67iZGfHcCN+4WPvGY8qIybDt7EwAwpotvrWurizbutgjxaYJyhaBaxKctm06notuiA3j5h0h0W3QAm05r9/hEVJXGYbh9+/Y4ffo0AKBnz5745JNPsH79ekydOhVt27bVeoFERI3VxZtyfLQlpspts/+8ZDCjgT3uheFzqXchLyyr1TH+dzwJl9NyYWdhjFnPtaryNYlEgje6+2HdG6GwtzTBpVu5GLTsGE7EP34kekvUDRSVVcDfxQpdmupvvm5lX+MNkakoq1Bo5ZiP6rphKM8JosZI4zC8YMECuLm5AQDmz5+PJk2a4O2330ZmZiZWr16t9QKJiBoThULA0bhMvLM+CoOXH8PDM2UrOywYAnc7c7RwtoJCAI4naD5V4np2Ib7eGwcAmPlMKzg+YhFd12aO2DGlO9p52OJuYRleXROJH44k1jiPWKEQ8Ou97ZDHhPnqdW71M23d4Ghlioy8Euy5dFsrx3xc1w0i0g2Nu0l07NhR9W9nZ2fs2rVLqwURETVGGbnF+D3qBn47nYrr2Y8e5ZNJJPB1tKjHyh6vh78T4jLycfhaJp5t56b24wRBwOztF1FUVoHOfvYY2dHzsff3sDPH72+FYda2i9hy9gbm/3MFF27K8cWIdrAwuf+n6nhCFhKzCmBlaoRh7T1q/X1pg4mRFKNDvbDsQDzWRiTjuUD1r8+jWJtV/7NsaM8Josam/nrREBGJTIVCwKFrGfi/dWcQtugAvtx9Ddezi2BtZoRxYT749z9P4YsR7SC7N7opk0iwYHjbWvfd1YUH5w1r0vHh75g0HLqWCROZFAuGt1NrBNfMWIb/jgzEZ0PawEgqwY7ztzB85Qmk3rk/Klq5cG5EBw9YGcDuby939oZMKkFkUjaupufW6VjFZRWY/eelKrcZ4nOCqLHR/28SIqJGIE1ehKSsAvg5WkIqkWDz6ev47fR13My5Pwoc4tMEo0O98Vw7N5ibyAAArdxs0MPfCclZhfB1tDC40BPqZw9TIynS5MWIy8iHv4v1Ex8jLyrD3B2XAQDv9GqGZk5Wap9PIpFgbJgvWrra4J31UbianodBy49h2ej2sDKVYd9l5XSEym4O+uZma45+rVyw61I61kWkYP6wdrU6jiAI+OCPC4i+ngNbc2P8MDYEFQoY5HOCqLFhGCYiqqNNp1OrLHqSSIDKQVQbMyOMCPHE6FDvRwZJN1tzgw08ZsYydGnqgMOxmTgSm6lWGP5i11Vk5pWgqZMl3n66Wa3OG+pnjx1TuuOtX8/i/PUcjP3fqSpfj0q5i+bOT66lPozt6oNdl9Kx7dxNfPhMS9iYad4RZNmBePx1/haMpBKsejUEoX4OOqiUiGrCaRJERHXw8Op/QBmEgz3t8PWoIJya1RdzBrVRK0QaqsquEodjn9xi7UxyNjbc22BjwbB2MDWS1fq8brbm2Px/XTA4qPpcXEPqsBDW1AEtnK1QWFqBrVE3NH783xfSsGRvLABg3tC2CGvGIEy1V1paiubNm+PEiRP6LkVndu3aheDgYCgU2uniwjBMRFQHNa3+B4APn2mJYe09YWZc+zBoKHr6KzffiEzKRlHpozfGKC1X9hQGgBc7eqJL07qHOlMjGV6qYYc5Q+qwIJFIVNM21p1M0Whu9YUbOXjv92gAwBvd/Wr8XsVq/PjxkEgkkEgkMDY2hp+fHz744AMUF2tvk5PDhw+jd+/esLe3h4WFBVq0aIFx48ahtLRUdR9BELB69Wp07twZVlZWsLOzQ8eOHfHNN9+gsFD5HPz0008hkUjw1ltvVTl+dHQ0JBIJkpOTAQDJycmQSCRwdnZGXl5elfsGBwfj008/VX2+detW9O/fHw4ODpBIJIiOjlbre1q1ahX8/PzQtWtX1W3z589H165dYWFhATs7uxofV3mtH/z47bffHnuu2NhYDBkyBI6OjrCxsUH37t1x8OBB1dd//vnnGo8rkUiQkZEBADh37hzat28PKysrDBo0CNnZ2arHl5eXIyQkBKdOVX1naODAgTA2Nsb69evVuiZPUqswvH//fsycORMTJkzA66+/XuWDiEhMfB2qr/JvbKv/mzlZwcPOHKXlCpxMuvPI+60+koC4jHw4WJpg5rOtHnk/TSnnYVe9zdCu8bD2HrA0kSEhswAnEh59jR6ULi/GhF/OoLhMgV4BTlq9ZrpS3zvjDRw4EGlpaUhMTMTXX3+N77//HnPmzNHKsS9fvoyBAweiY8eOOHLkCGJiYrBs2TKYmJigouL+i74xY8Zg6tSpGDJkCA4ePIjo6GjMnj0b27dvx549e1T3MzMzw5o1axAXF/fEc+fl5eG///3vY+9TUFCA7t2744svvlD7exIEAcuXL8cbb7xR5fbS0lKMHDkSb7/99mMf/9NPPyEtLU31MXTo0Mfe//nnn0d5eTkOHDiAqKgoBAUF4fnnn0d6ejoAYNSoUVWOl5aWhgEDBqBnz55wdnYGAEyYMAG9e/fG2bNnIZfLsWDBAtXxv/rqK3Tr1g2hoaHVzj1+/HgsXbpUncvyRBrPGZ47dy4+++wzdOzYEW5ubnrt8UhEpG938qtuRtEYV/9LJBL08HfExlPXcSQ2E70CnKvdJzmrAEsPxAMAZj/fGnYWJlo7v5utORYOb4eZWy+iQhAM8hpbmxljeAdPrDuZgl9OJKPbva2sH6WotAIT1p5GRl4J/F2ssHR0e8geTvw6IggCijTY+rrSlqgbmPPXJSgEQCoB5g5ugxEhj2+Z9zBzY5lGucHU1BSurq4AAC8vL/Tt2xd79+5VBUSFQoEvvvgCq1evRnp6Ovz9/TF79my88MILAIC7d+9i8uTJ2LNnD/Lz8+Hp6YmZM2fitddew549e+Dq6orFixerztesWTMMHDhQ9fnmzZuxfv16/PnnnxgyZIjqdl9fXwwePBi5ufc7iAQEBMDZ2RmzZs3C5s2bH/t9TZkyBUuWLMGkSZNUofBhY8aMAQDVqLI6oqKikJCQgOeee67K7XPnzgWgHKl9HDs7O9X1fpKsrCzExcVhzZo1CAwMBAAsWrQIK1euxMWLF+Hq6gpzc3OYm9//f5qZmYkDBw5gzZo1qtuuXLmC9evXw9/fH6NHj8bOnTsBAImJiVizZg2ioqJqPP+gQYMwefJkJCQkoFmz2q1NqKRxGF61ahV+/vln1Q+JiHTvwU4FhhQACNhzWTkC8nSAE/6vR7NGu/q/p7+TKgw/TBAEzPozBqXlCjzVwhFDgt21fv5RnbwNuusGoNyRbt3JFOy7chs3c4rgYVdzjQqFgPDN0bh4Mxf2liZYM64TrGux6K62isoq0PqT3XU6hkIAZm+/hNnbLz35zg+4/NmAKn2jNXHx4kWcOHECPj73O4ksXLgQv/76K1atWoUWLVrgyJEjePXVV+Hk5ISePXti9uzZuHz5Mv799184OjoiPj4eRUXKUW1XV1ekpaXhyJEj6NGjR43nXL9+PQICAqoE4UoSiQS2trZVblu0aBE6deqEM2fOVNmX4WGjR4/G3r178dlnn2H58uW1uRw1Onr0KPz9/WFtXbs1CpMmTcKECRPQtGlTvPXWW3jttdce+eLFwcEBAQEBWLt2LTp06ABTU1N8//33cHZ2RkhISI2PWbt2LSwsLFQvVgAgKCgIe/fuRfPmzbF//35VsH7rrbewePHiR34v3t7ecHFxwdGjR+s/DJeWllaZh0JEuvVgpwKpBFg4vB1GdeK8QkOx+5IyDA8Jdm/UC5+6NneETCpBQmYBbtwthGeT+1MUtp27iePxd2BqJMW8oW119o6hIXfdAIAWLtYIa+qAiMQ72BCZgvcHtKzxfl/vi8W/F9NhIpPi+zEh8LI3nOkehmbnzp2wsrJCeXk5SkpKIJVKVeGxpKQECxYswL59+xAWFgYAaNq0KY4dO4bvv/8ePXv2RGpqKtq3b68Kpr6+vqpjjxw5Ert370bPnj3h6uqKLl26oE+fPhg7dixsbGwAAHFxcQgICFC73g4dOuDFF1/Ehx9+iP379z/yfhKJBIsWLcKgQYMwbdq0Ooe5SikpKXB3r92L0c8++wy9e/eGhYUF9uzZg3feeQf5+fl49913a7y/RCLBvn37MHToUFhbW0Mqlao2Y2vSpEmNj1mzZg1efvnlKqPFP/74I9555x3897//Rbdu3TBjxgysW7cOFhYW6NSpEwYMGICEhAS89NJLmDdvXpXjubu7IyUlpVbf74M0DsMTJkzAhg0bMHv27DqfnIge7+FOBQpBuYq+h7+TQYcCsUjKKkDs7XwYSSXoHeCi73J0ysbMGB287XA6+S6OxGbh5c7KF2TZBaWY9/cVAMC7fVrAx8FSn2Xq3dgwH0Qk3sFvp67j3T4tqnXT2B59E8vuTSdZMLwdOvna13uN5sYyXP5sgEaPSZcXo++Sw1UWi0olwL7wnnC1NdPo3Jro1asXvvvuOxQUFODrr7+GkZERRowYAQCIj49HYWEh+vXrV+UxpaWlaN++PQDg7bffxogRI3D27Fn0798fQ4cOVQ3oyWQy/PTTT5g3bx4OHDiAyMhILFiwAF988QVOnToFNzc3jRZDVpo3bx5atWqFPXv2PHIKBAAMGDAA3bt3x+zZs7FhwwaNz1OToqIimJmp//N40IO5rn379igoKMCXX375yDAsCIJqmsfRo0dhbm6OH3/8EYMGDcLp06fh5la1C0xERASuXLmCdevWVbm9TZs2OHz4sOrzO3fuYM6cOThy5AimTJmCrl27YuvWrejUqRM6d+6MQYMGqe5rbm6uWsRYFxovoCsuLsaSJUvQs2dPTJkyBeHh4VU+iEh7aupUYEir6MVuz71R4S5NHWBrUX9vc+tLjxaVLdYyVLct+OcKsgtKEeBijTd7NNVXaQajX2sXuNqY4U5BKf6NSa/ytaiUu3j/jwsAgLd6NsMLGs631RaJRAILEyONPpo6WWHh8Kq7JS4c3g5Nnaw0Oo6m7xpYWlqiefPmCAoKwv/+9z9ERkaq5pvm5+cDAP7++29ER0erPi5fvow//vgDAPDMM88gJSUF06ZNw61bt9CnTx9Mnz69yjk8PDwwZswYLF++HJcuXUJxcTFWrVoFAPD398fVq1c1qrlZs2aYOHEiPvrooyeG6UWLFmHTpk04d+6cRud4FEdHR9y9e1crx+rcuTNu3LiBkpKSGr9+4MAB7Ny5E7/99hu6deuGDh06YOXKlTA3N8cvv/xS7f4//vgjgoODHzmFolJ4eDimTp0KT09PHDp0CCNHjoSlpSWee+45HDp0qMp9s7Oz4eTkVOvvsZLGYfjChQsIDg6GVCrFxYsXce7cOdWHum0/iEg9fo6WePhvh1QCg1pFL2Z77u2G1r9N4x4VrtQzQPlH50T8HZRVKBCRcAd/RN2ARKIc5TSWsVunkUyqGjX/JSJZdfuNu4X4v3VnUFquQP/WLvhggPpvvRuKUZ28ceyjXtg4sQuOfdSr3qdrSaVSzJw5Ex9//DGKiorQunVrmJqaIjU1Fc2bN6/y4eXlpXqck5MTxo0bh19//RXffPMNVq9e/chzNGnSBG5ubigoKAAAvPzyy4iNjcX27dur3VcQBMjl8hqP88knnyA2NvaJrclCQ0MxfPhwfPTRR+pcgidq3749rl69WqsR7YdFR0ejSZMmMDU1rfHrlSOyUmnV//dSqbRa/9/8/Hxs3ry5WpeLh+3fvx9XrlzB5MmTAQAVFRUoK1MuUi4rK6vS5aO4uBgJCQmqdwHqQuNpEg/2jyMi3XKzNUcbNxtcvHV/xXInX3tOkTAAGXnFOJuqHIHp11ocYbituy3sLU2QXVCKyMRsfLL9IgDglc7eCPGpeY6gGL0U6oVlB+JwLjUHF2/K4edoiQm/nEFWfilaudng61HBkNZT5wht0/e87ZEjR+L999/HihUrMH36dEyfPh3Tpk2DQqFA9+7dIZfLcfz4cdjY2GDcuHH45JNPEBISgjZt2qCkpAQ7d+5Eq1bKFnbff/89oqOjMWzYMDRr1gzFxcVYu3YtLl26hGXLlgEAXnzxRWzbtg2jR4/Gxx9/jP79+8PJyQkxMTH4+uuvMWXKlBrbj7m4uCA8PBxffvnlE7+n+fPno02bNjAyqhrJsrOzkZqailu3bgEArl27BkC58O9RHR969eqF/Px8XLp0CW3btlXdnpqaqjpeRUWFavCyefPmsLKywo4dO3D79m106dIFZmZm2Lt3LxYsWFBlFP3UqVMYO3Ys9u/fDw8PD4SFhaFJkyaq62xubo4ffvgBSUlJ1bpZbNq0CeXl5Xj11VcfeR2Ki4sxefJkbNy4URWwu3XrhhUrVmDSpEnYsmULlixZorr/yZMnYWpqqpovXhd1ehl/48YN3Lih+W47RKSeNHkRrqQrG7OP7+oLAIi5KUducdljHkX1Yd/lDAgCEORpK5oXJ1KpBE+1ULYMm7zhLBKzCuBkbfrIhWJi5WxthmfaKudLrjwUjzFrTuFqeh4crUzx47iOsDStXTcFAoyMjDB58mQsXrwYBQUF+PzzzzF79mwsXLgQrVq1wsCBA/H333/Dz88PAGBiYoIZM2YgMDAQPXr0gEwmU43WhoaGIj8/H2+99RbatGmDnj174uTJk/jzzz/Rs2dPAMopJRs2bMCSJUtUtwcGBuLTTz/FkCFDMGDAo+deT58+HVZWVk/8nvz9/fH6669X20zkr7/+Qvv27VXB8qWXXkL79u1VUzhq4uDggGHDhlXbjOKTTz5B+/btMWfOHOTn56N9+/Zo3749zpw5AwAwNjbGihUrEBYWhuDgYHz//fdYsmRJlZ7OhYWFuHbtmmqk1tHREbt27UJ+fj569+6Njh074tixY9i+fTuCgoKqnH/NmjUYPnz4Izf8AJTt35577jkEBwerblu6dCmio6PRo0cPDBo0SDVfHAA2btyIV155BRYWdX+nVCJoOJauUCgwb948fPXVV6r5OtbW1njvvfcwa9asasPl+pabmwtbW1vI5XLV6lCihuKrPdew7EA8OvvZ47c3u2DAN0cQezsfcwa1xmvd/PRdnqiN/+kUDl3LxPsDAjCpV3N9l1NvPvjjPDafuT8I8kpnb8wf1k6PFRmmM8nZeGFVRJXbJj3dDO8P1P0LB/7dE7cLFy6gX79+SEhIUCuMN0RZWVkICAjAmTNnVC986kLj5Dpr1iwsX74cixYtUs0VXrBgAZYtW8YOE0RaVFquwMZT1wEAY8N8lVu+dqndlq+kXXnFZTgRr9xlbIBI5gsDyncq/oiq+m7gb6dS6203sobE3a76iv5VhxN5rUjnAgMD8cUXXyApKUnfpehMcnIyVq5cqZUgDNRizvAvv/yCH3/8EYMHD1bdFhgYCA8PD7zzzjuYP3++VgojErt/L6YhK78ELjamqgVawzp44otd15CYWYDj8XfQvcXjd7ki3Th0LROlFQo0dbREM6fGOfJSk5q7mwDJWYWimSqiruQ71Tu+VHaC4bUiXRs/fry+S9Cpjh07PnZTE01pPDKcnZ2Nli2rv83TsmVLZGdna6UoIgLWRigbiY8O9Vat0rcyNcLwDh4Aqq5Up/p1v4uEq6i2pPdztMTD675kEgm7m9SA14qo4dA4DAcFBdW4deDy5curTZgmotq5dEuOqJS7MJJK8HJo1fZFY8OUUyX239vylepXSXkFDl5V9tkVS0u1Sm625tV6zS4Y3pYjnTXgtSJqODSeJrF48WI899xzVbY/jIiIwPXr1/HPP/9ovUAiMVp3b1R4YFtXONtUnXvY3NkaXZs54ETCHaw/mYIP6mFBTkOSJi9CUlYB/BwtdRI8IhLuIL+kHM7Wpgj2tNP68Q3dqE7e6OHvhOSsQvg6WjDcPQavFVHDoPHIcM+ePREbG4thw4YhJycHOTk5GD58OK5du4annnpKFzUSiYq8sAx/Rt8EoFw4V5PK0eFNp6+jpLyixvuI0abTqei26ABe/iES3RYdwKbTqVo/R+UUiX6tXRpsr9i6crM1R1gzB4Y7NfBaERm+WjU7dHd350I5Ih35Peo6issUaOlqjU6+NW9k0LeVC9xszZAmL8Y/MWkY1l4/27oakjR5ET7aGoPKJhsKAZi59SJ6+DtpLYgoFAL2PjBfmIiIGj61wvCFCxfQtm1bSKVSXLhw4bH3DQwM1EphRGKkUAj49aRyisSYMJ9HLs4ykknxcqg3vtobi19OpDAMAzh/PQcPd5vT9ur9c9dzkJlXAmtTI4Q1ddDKMYmISL/UCsPBwcFIT0+Hs7MzgoODIZFIauxxKpFIquwbTUSaORKXieQ7hbA2NcLQYI/H3velUG8sPRCH6Os5iLkhRztP23qq0vAUl1VgxcGEarfLJNDq6v09l9IBAL1aOsPEyLA2GCIiotpRKwwnJSXByclJ9W8i0o3KhXMvdPR84patTtameLadG7ZH38LaiGR8OVKc3VwEQcDMrTGIuSmHqZEUZRUKVS/cVzr7aG1UWBAE7L4XhsXWRYKIqDFTa2jDx+f+27UpKSnw8PCAj49PlQ8PDw+kpKTotFiiB6XJi3AiIavR7Oh0PbsQB64pW3ZV7jT3JJUL6f46fwt3C0p1Vltt1NfP57vDCdh67iZkUgl+HNcRxz/qjSFB7gCAMyl3tbZTX3xGPpLvFMJEJsXTAc5aOSYREemfxu/z9erVq8bNNeRyOXr16qWVooiepD66BtS3XyNTIAjAUy0c0VTNXc06eDdBazcblJQr8HvUdR1XqL76+vnsupiOxbuuAQA+HdQaT7VQLpb7dHAbWJrIcDktV9X9oa4qR4W7NXeA1RNG7YmIqOHQOAwLglDjop47d+7A0tJSK0URPYpCIeDPczfx4ZYY1VvhlV0DGvIIcXFZBTafVoZZdUeFAeU8/crR4XUnU1Dx8F65epAmL8KMrbr/+Vy8Kce0TdEAgHFhPhjzQBu6JpYmGN9N+fk3++Kg0MJ1qQzVA9hFgoioUVF7eGP48OEAlH98x48fD1NTU9XXKioqcOHCBXTt2lX7FRIByMgtxu9RN7DxVCpu3K0eqrTdNaC+7Th/C3cLy+BhZ44+rTSbjzok2AML/rmC69lFOBybgd4t9TufNSmrAA9nzwpBQEJGvtZ+Phm5xZi49gyKyirwVAtHzH6+dbX7THyqKX45kYIr90aHB7atfYi9lVOECzfkkEig8c+HiIgMm9ph2NZWuVJdEARYW1vD3Pz+HzUTExN06dIFEydO1H6FJFoVCgFH4jKxMTIV+69mqEY9rUxlKCipwIN5S6rlrgH1bd29dmqvdPGGTMONHMxNZHixoxd+PJaEtREpeg/Dfo6WkAB4eCz2632xaO1uC3tLkzodv7isAhPXRSFNXoxmTpZY/nIHGMmqv8llZ2GC17r5YtmBeHyzLxb967BJRmVv4RDvJnCyNn3CvYmIqCFROwz/9NNPAABfX19Mnz6dUyJIZ9Llxdh85jo2nb6Omzn3R4E7+TbB6FDvex0UbmLm1ououLc4ysXGDE5WDTOkRF/PwYUbcpjIpBjV0atWx3i1iw9+PJaEw7GZSLlTAB8H/f3/dLM1h4uNKdJzSwAoX6gYSSWISsnBoGXH8P2YELT1qF0bOEEQMP338zh/PQd2FsZYM64TbM2NH3n/N7r74efjybianoc9l9MxsK1brc6757JyvjCnSBARNT4arwKZM2eOLuogkUqTFyEpqwDe9haIvZ2HDZHXceDqbdXb7LbmxhjRwROjQ73QwsVa9bhRnbzRw98J56/n4P0/LiBNXoyfjidjYo+mevpOam9tRDIA4PlANzjUMtD7Olqip78TDsdm4teTKZj1XPVpA/Ul9U4h0nNLIJUA378agraetsgrLseba88g+U4hRnx3AguHt8PwDppvFPLt/jjsvJAGI6kE370SAl/Hx4f+ytHhpQfi8c2+OPRv7arx6HBOYSlOJioXDfdrzSkSRESNTa2WRP/xxx/YvHkzUlNTUVpatZ3T2bNntVIYNX6bTqdWWWj1oFA/e7wc6o2BbV1hZiyr8fFutuZwszWHvKgMH26JwZK9sRjY1hVe9g1nukR2QSl2XkgDoNxxri7GhvngcGwmNp+5gfB+ATA3qfm66VrlKGpnPwf0uzeS6mYLbJ/cHVN/O4eD1zIRvvk8LtyQY9ZzrWBcwxSHmuw4fwvf7IsDAMwf1hZhzdTbAe6N7k3x073R4V2X0vFsO81Ghw/cm6IT4GL9xPBNREQNj8bdJJYuXYrXXnsNLi4uOHfuHEJDQ+Hg4IDExEQ888wzuqiRGqGHOw5UGt3JC/vCe2Lz/4VhaHuPRwbhB73Y0QuhfvYoKqvAJ9svaq2vbH3YdPo6SssVaOdhi2Avuzod6+kAZ3g2Ub44+Ov8Te0UWAt7LlV2Xag6imprrpzW8G6fFgCAn08k45UfI5GZV/LEY56/noPpv58HAEzo7odRnbzVrsfWwhivdfcDAHxbi84Sj/p+iIiocdA4DK9cuRKrV6/GsmXLYGJigg8++AB79+7Fu+++C7lcrosaqRGqqeMAAAwO9kBzZ/V67FaSSCRYMKwdTGRSHLyWiX9i0rVUpW5VKAT8em/h3JgwnxpbFmpCJpWo2rKtjUjRy4uCrPwSnEm5N6Wghvm1UqkE4f38sXpMCKxMjXAqKRuDlh1D9PWcRx4zTV6EiWvPoKRcgd4tnTHj2VYa1/VGdz9Ymxnh2u08/HtR/edHcVkFDsdmAgD6c74wEVGjpHEYTk1NVbVQMzc3R15eHgBgzJgx2Lhxo3aro0arpt3SZBJJrTtCNHe2wttPNwMAfLrjEuRFZXWqrz4cuJqBmzlFsLMwxuB7O6bV1YsdvWBqJMWlW7k4m5qjlWNqYv8V5Xzvdh628LB7dBu1/m1c8eekbmjqZIn03GK8uCpC1Wf5QYWl5Zjwyxlk5JUgwMUa374UrHG3DUA5Kv16t3ujw/tj1R4dPhqXhaKyCnjYmaONu43G5yUiIsOncRh2dXVV7UDn7e2NkydPAgCSkpIa1NvTpD8l5RX4am8sAKAy1sgkEiwY3rZOfWjffroZmjpaIjOvBIt3XdVCpbpVuXBuVEcvtaaDqKOJpQkG3QvW6+4dvz5VTinor8ZCs+bOVtg+qRv6tXZBaYUCH2y5gI//jEFpuQKAcoOV8E3ncelWLhwsTfDjuI6wNnt054gnef3e6HDs7Xz8czFNrcdU7jrXr7VLnUfuiYjIMGkchnv37o2//voLAPDaa69h2rRp6NevH0aNGoVhw4ZpvUBqfL47lIDEzAI4Wpli99Qe2DixC4591EujeaA1MTOWYf6wdgCA9ZGpiEq5q41ydSIxMx9H47IgkSjbomlT5Y50/8SkqzUfV1vyS8pxND4LgPpTCqzNjPH9qyEI7+cPiQT49WQqRv9wEjE3cjBtczR2XUqHiUyK78eE1HlhpK25MSZ0V3Yb+XZf3BN36yuvUGD/lXvhnvOFiYgaLY3D8OrVqzFr1iwAwKRJk/C///0PrVq1wmeffYbvvvtO6wVS4xKfkY+VBxMAAHMGtYa/qzXCmjlobWeysGYOGBmibNk1c2sMyioUWjmutv16MhUA0CvAWevdLwI97RDkZYfSCgU2nU7V6rEf50hsJkrLFfB1sIC/i/rzvqVSCd7t0wJrxnWEtZkRolLuYtDy49gefQsAMLS9Ozr62mulxte6+8LGzAhxGfn4J+bxo8NnUu7ibmEZ7CyMEaql8xMRkeHROAxLpVIYGd3vyPbSSy9h6dKlmDJlCkxM6razFDVugiBg1rYYlFYo0NPfCc8H1m4DhCeZ+Wwr2Fua4NrtPKw+kqiTc9RFYWk5fo9Szo+tazu1Rxl377jrI1NRXk8vCPbcm1LQv41rraYU9G7pgjXjOla7fUvUTaTJq2/BXRs2ZsaY8NS90eH9jx8drpwi0aelS4073BERUeOgVp/hCxcuqH3AwMDAWhdDjdvvUTcQmZQNM2Mp5g1tq7M5mE0sTfDxc60Qvvk8lu6Pw/OBbnrdke1hf567hbzicvg4WKBnCyednOPZdm6Y9/cVpMmLse9KBga21W0nhNJyBfZfzQBQtxZk5TWE0wpBQHJWodbePRjfzRdrjiUhPiMfOy/cwpBgj2r3EQSBLdWIiERCrTAcHBwMiUQCQRCeGGAqKiq0Uhg1LnfyS7DgnysAgGl9/XW+Mcaw9h7YcvYGjsffwcd/XsTa10MNYgGUIAiqhXNjuvhovBuausyMZRjVyQvfHUrAupPJOg/DkUl3kFdcDkcrUwR7Nan1cfwcLSGVoErbvbp0GamJjZkxJnT3w1d7Y++9WHKv1qHi0q1c3MwpgpmxFE/p6AULEREZBrXe+0tKSkJiYiKSkpKwZcsW+Pn5YeXKlTh37hzOnTuHlStXolmzZtiyZYuu66UGat7fV5BTWIZWbjZ4/d4GCLokkUgwf2g7mBpJcTQuSzX/VN/OpNzF1fQ8mBlLMTLES6fneqWzN6QS4Hj8HcRn5On0XJWjqP1aO9eq9VklN1tzLBzeDrJ7L1y00WWkJuO7+cLW3BgJmQXYeaH6c2PPZeX306OFk9528iMiovqh1siwj8/9eY0jR47E0qVL8eyzz6puCwwMhJeXF2bPno2hQ4dqvUh9SZMXISmrAH6Ollr/YywmR+Myse3cTUgkwMLh7dTefreufB0t8W6fFvhy9zV8vvMyng5wgp2Ffue1f39YOYe5XysX2FrUvk2YOjybWKB3Sxfsu3Ibi3ddw9whbXTyPFYoBNUWzNrYmGJUJ2/08HdCclYhfB0tdFKztZkxJj7lh//uicW3NYwOV85/HsCNNoiIGj2NU0lMTAz8/KqP7Pn5+eHy5ctaKcoQ/HYqFV0XHcDLP0Si26ID9boqvzEpLqvAx39eBACM7eJT5y2HNTXxqabwd7HCnYJSLPxHv72HfziSiH33WnXtjEmrl+eUj4NyesGey7d19jy+cFOO27klsDI1QtdmDlo5pputuVa7jNRkXFdf2FkYIzGzADvO3x8dTr1TiKvpeZBJJejTylln5yciIsOgcRhu1aoVFi5ciNLS+zuIlZaWYuHChWjVSvNtUg1RmrwIM7bGoHIPEYUAfLQ1BvEZ+fotrAFadiAOKXcK4WpjhukDAur9/CZGUiy413t405nriEy8U+81AMrnVOWcaQAQBGDm1ota65LwqHP+dDxJ9blCR+es7LrwdIATTI0azpQC5eiwsrPE0v1xqq4blaPcnf3s9f5OAhER6Z7GYXjVqlXYvXs3PD090bdvX/Tt2xeenp7YvXs3Vq1apYsa690fUTfw8Jp2QQCeW3oUM7ZewIUbOfooq8G5lp6nmhbw6eA2ddo9rC46+trj5c7KDT1mbItBSXn9L/KMz8iv9pyq7JKgK0lZBXi4OYMuzvlgS7WGZlxXXzSxMEZiVgF23Js7rMkuekRE1PBpHIZDQ0ORmJiIefPmITAwEIGBgZg/fz4SExMRGhqqixrr1eVbuVhxML7Gr5WUK7Dx1HUMXn4czy09il9PpiCvuKyeK2wYFAoBM7fFoFwhoF9rF513M3iSDwe2hKOVKRIzC/DdoYR6P39qdvUAqu0uCQ+r7MzwIIkEWj1nfEY+EjILYCyT4OmAhtd1wcrUCBN7VI4OxyMjtxinU5TbzfdrgOGeiIg0p9YCuodZWlrizTff1HYtepeRV4wJv5xGcZkCzZ0tkZipHFmTSSSYP6wt/BwtsfFUKv65mI5Lt3Lx8Z8XMf/vKxgc5I7Rnb0R5GlrEO27DMGGU8rtkC1NZJg7uI2+y4GtuTHmDGqNKRvPYeXBBAwKckczJ/V3SauryjmpEgACdNcl4UGVnRlmbr2IintzfixNjGBnrr23/iunFHRt5ggbPY3819XYMF/8cCQRSVkFmLopGoIAtPOwhYcdF80SEYmBWmH4r7/+wjPPPANjY2P89ddfj73v4MGDtVJYfSsuq8D/rYvCLXkxmjpaYstb3VBYVl5tRXvnpg6YU1CKreduYuOpVMRn5GPTmevYdOY6WrnZ4OVQLwxp74GCknLRdqLIyC3GF7uUi9Xe6x8AdwMJFc8HumHL2Rs4dC0T038/j/f7B8DPSfc/n9jbeTiZmA2pBNj6dlcUlSl01iXhYZWdGRIy8jH9jwtIlxdjfWSKahe2ulJNKWjAG1NYmRrhzR7N8MWuqziRoJxTHtaU2y8TEYmFRBCER+9Heo9UKkV6ejqcnZ0hlT56ZoVEIjG4TTdyc3Nha2sLuVwOGxubGu8jCAKmborG9uhbsDU3xp+TusHP8ck7lgmCgDMpd7ExMhU7Y9JQWq5cgGMkk6C8QnlZpffaiY3q5K29b8rATdpwFn9fSEOgpy22vdOtTn1nte16diF6f3UIZfX485n950WsO5mCAW1c8P2Y6tsN15dNp1Px4ZYYOFqZ4OgHvevcPzddXowuC/dDIgEiZ/aBs7WZliqtfwUl5Qidvw8FpcrfX2L8f0uNhzp/94joPrXmDCsUCjg7O6v+/agPQwvC6lpxMB7bo2/BSCrBd690UCsIA8rw38nXHktGBePUzD6YM6g1/BwtVEEY0N0KfkN18GoG/r6QBqkEWDCsnUEFYaDqCxVA9z+fvOIybD17AwAwLsxXJ+dQ1/AOnvCyN0dWfil+PZlS5+Ptvdcmrr2XXYMOwgCQW1yGwtL7v7/E9v+WiEjM6mf3AwP2T0wa/rsnFgAwd0gbdG3uWKvj2FmY4LVufpg/tF21r+m6a4ChKCwtV/UUfr2bH9p62Oq5ouqSsgrqtavD1rM3UVBagebOVgjTUg/e2jKWSTGlVwsAwPdHElBYWl6n4zXkLhIPq+/nBRERGQ615gwvXbpU7QO+++67tS6mvsXckCN8czQA4LVuvnils8/jH6AGPyflCv4HW1pJtbyC31B9vTcWN3OK4GFnjmn9/PVdTo0qOyzUx89HEASsuzcCO6aLj0EsrhzWwQPLD8YjNbsQv55MwZs9mtXqOPKiMkTcm1/bGHZpq+l5oetuH0REZBjUCsNff/21WgeTSCQNJgzfzi3GhLXKzhFPBzhh1rPa2TDk/gr+GFS+G9/UyQquNrp/G1lf20enyYtw8GoG1hxTbvDw+dA2sDStVaMSnav8+czYGqMKPgPauOrkekUk3EF8Rj4sTWQY3sFD68evDWOZFJN7N8cHf1zA94cT8WoXH1iYaP6zOnQtA+UKAS2crdSeVmTIHu68UR/dPoiIyDCo9VcwKSnpyXdqQIpKKzDhlzO4nVuCFs5WWDq6PYxk2psxUrmCPzLxDj744wLiM/LxZ/RNDGvvqbVzPGzT6VRVwKvPxT8PnhdQtqTq3dKwOwtU/nx+OZGCVYcTEJmUjYKScq0H+LURylHhYR089LbhSE2Gt/fAioPxSLlTiHURKfi/npqPDld2kWgMo8KVKp8XD3eQISKixk10c4YVCgHv/R6NmJty2FuaYM24Tjrpj+pma46h7T3xn77K6QKf77yCuwWlT3hU7VRuH10ZSJWLf2J0vvjn4fMCwKVb8gax6MjN1hzT+/vD18EC2QWlquCqLbdyilQLzMbqeeHcw4xkUkzpXTl3OBEFJZrNHS4uq8ChaxkAGnZLtZq42ZojrJkDgzARkYjUKgzfuHEDK1euxEcffYTw8PAqH4bum/1x+CcmHcYyCVa9GgJvB93OCZz4VFP4u1ghu6AUC/65opNz1LztLvDDkUSd7ZAXezsPn/51qdp5FQIazKKjB0Ph6iMJyNcwFD7OhshUVCgEdGlqD38Xa60dV1uGBrvX+oXAiYQsFJRWwM3WDO0McJEkERGRJjR+X3j//v0YPHgwmjZtiqtXr6Jt27ZITk6GIAjo0KGDLmrUmu3RN7F0fxwAZduvUD/dN9Y3MZJi4fB2GPFdBH6PuoHhHTy13lXgUTtl/e94snL7aC3tkFdUWoG/Y9Kw8d7ucjVpaIuOhgS7Y/nBeCRlFeCXE8mY1Kt5nY9ZUl6B306nAjC8UeFKlS8E3vv9PFYfScDYMB+1p4nsvnhvo43WLgaxKJCIiKguNB4ZnjFjBqZPn46YmBiYmZlhy5YtuH79Onr27ImRI0fqokatOH/9Lt7/4wIA4P96NMXIjl71du4QH3u80lk5f3fWnzEoKddeP2ZBELD8QHyV26QS5W5rzZ2tUFRWgU1nrmPoiuN45tujWBuRDHmRZqPFV9NzMWf7RYQu2Ifpv59HVMpdyKQSDGjjgte6+aKylXBDXHSkDIXKAPzD0UStjA7vupiOrPxSuNiYol9rw51GMCTYHX6OlrhbWIZfIpLVekyFQsC+K5W7zjWe+cJERCReau1A9yBra2tER0ejWbNmaNKkCY4dO4Y2bdrg/PnzGDJkCJKTk3VUau1U7sTTbsY25CqM0beVC74fE1Lvm0HIi8rQd8lhZOaV4D99Wmit9dj3hxOw8N+rkEqAr14MhquNmWrxz6N2yDMzluL5QHeMDvVGB287SCSSap0oCkvLsfOCchT4XGqO6nxe9uZ4qZM3RoZ4wvleh4w0eVGDXnRUXqFA/6+PIDGrAO8PCKjz6PCI704gKuUupvX1x3/6ttBSlbqx9ewNhG8+DzsLYxz7sDesnjA6fDo5GyNXRcDW3BhnPu4LYy0uPCUi7eAOdESa0XiahKWlJUpLlQvB3NzckJCQgDZt2gAAsrKytFudFuUUlcHdyQrfvhSsl13RbM2NMWdQa0zecA7fHUrAoCB3NHe2qtMx916+jUW7rgIAPnm+NYa1r9q+q3KHvE6+9vhkUGtsO3cTG0+lIvZ2Pv6IuoE/om4gwMUaAa5W2HkhDQoBkEiAzn72uHQzF3n3RkmNpBL0b+OC0aHe6NbMEdKHrp+brXmDDMGVjGRSvNunBaZuisYPRxMxNsyn1t0fLt6UIyrlLoykEowOrb93H2prcJA7lh+IR6Ka00R2X1RutNGnpTODMBERNQoa/zXr0qULjh07BgB49tln8d5772H+/Pl4/fXX0aVLF60XqE0ZeSXI1dGCMnU8184NvQKcUFqhwMxtMVA8vPpMA1fScvGf385BEIBXu3hjXFffx96/coe83VN7YMvbYRjRwROmRlJcu52Hv86nqRbCCQJwMjEbeSXl8HGwwIcDWyJiRh+sfCUET7VwqhaEG4tBQe5o6mSJnMIy/HIiudbHWXdvMdrAtq6qkXNDZiSTYkqf+9NEHrfgUhAE7LlcOUXCcKd/EBERaULjMLxkyRJ07twZADB37lz06dMHmzZtgq+vL9asWaP1ArVJ350OJBIJPhvSFubGMpxKysYfUTdqdZzMvBJM+OUMCksr0K25A+YMaqP2QiaJRIIQH3t89WIQTs3qi/GPCNGznm2Fg+89jbefbgYna9Na1dmQyKQS/KePckrDD0eTavWiSV5Yhu3nbwLAE1+cGJLBQR5qvRC4mp6H1OxCmBpJ0cPfqf4KJCIi0iGNw3DTpk0RGBgIQDllYtWqVbhw4QK2bNkCH5+6b2esS4bQ6cDL3gLh9+YLz//nCrLySzR6fHFZBd5cdwY3c4rQ1NESK18OqfXb1bbmxvi/nk3x8GCvTCLB80FujXYU+FGeD3RHMydLyIvK8MvxZI0f/3vUdRSXKdDS1RodfZpov0AdefiFwKNGhys32niqhVOtdq0jIiIyRBqnqAkTJuDQoUM6KEW3DKnTwWvdfNHazQbyojLM23lZ7ccJgoAPt1zAudQc2JobY834TrC1qNuGIZXb0MrujSwb0nWqbzKpBO+qQmGiRqPDCoWAdSeVUyTGhvk2uJZjD74Q+PkRLwT2XFbOF+YUCSIiakw0DsOZmZkYOHAgvLy88P777+P8+fO1PvmRI0cwaNAguLu7QyKR4M8//6zydUEQ8Mknn8DNzQ3m5ubo27cv4uLianWu3dOeqpftidVhJFP2HpZKgD+jb+FoXKZaj1txMB7bo2/BSCrBd690gJ+jpVbqGdXJG8c+6oWNE7vg2Ee9DOY66cPzgcqFjbnF5fjpWLLajzsSl4mUO4WwNjPC0PbuuitQRx58IfDjserTRK5nF+LSrVxIJUDfVgzDRETUeGgchrdv3460tDTMnj0bp0+fRocOHdCmTRssWLBA47ZqBQUFCAoKwooVK2r8+uLFi7F06VKsWrUKkZGRsLS0xIABA1BcXKxp2XA1sJHOIC871YYMs7ZdRFHp43sP/xuThv/uiQUAzB3SBl2bO2q1Hm5Dq/TglIE1xxLV7slcuXDuhRDPBjuFoPKFQE2jw3vvLZzr5GsPe0sTPVRHRESkG7WabNqkSRO8+eabOHToEFJSUjB+/HisW7cOzZtr1p/1mWeewbx58zBs2LBqXxMEAd988w0+/vhjDBkyBIGBgVi7di1u3bpVbQS5oZo+IAButmZIzS7E0gOPHvGOuSHHtM3RAJRTLF7pbNhzsxu6Z9u5oUXl6PDxpCfe/3p2IQ5cywAAjOnScH82VUaHj1Z9IVA5RWIAN9ogIqJGpk6NQsvKynDmzBlERkYiOTkZLi7ae/s0KSkJ6enp6Nu3r+o2W1tbdO7cGREREVo7jz5ZmRph7mBlj+YfjiTianputfvczi3GhLWnUVymwNMBTpj1bKv6LlN0ZFKJarOMNceSnjg6/OvJFAgC8FQLRzR1qlvvaH177oEXApWjw9kFpTiVlA0ABr2jHhERUW3U6v3cgwcPYsOGDdiyZQsUCgWGDx+OnTt3onfv3lorLD1dORL1cMB2cXFRfa0mJSUlKCm536EhN1cZMMvKylBWpr8ew4/Sy98B/Vo5Y++VDMzYcgG/TQhVdXEoKq3AhF9O43ZuCZo7WWLJC20hKCpQptDeds5Us34BjmjhbIm4jAL8eCQe7/au+V2P4rIKbDp9HQDwSidPg3yOaWry003xn80X8OOxRLwa6oG9VzKgEIBWrtZwtTZuFN8jUWPG/6NEmtE4DHt4eCA7OxsDBw7E6tWrMWjQIJiaGk4f2oULF2Lu3LnVbt+zZw8sLPTbVu1RupsDR2QynLsux8c/70J3VwEKAfglToqYO1JYGgkY7SnH0QN79V2qqHSzkyAuQ4YfjiTAPT8WFjX8b4nMkCCnSAZ7UwFFiWfwz5NnVRg8hQC4msuQXlSOWWv340YBAEjha5SDf/75R9/lEdETFBbqr58+UUOkcRj+9NNPMXLkSNjZ2emgnPtcXZVzE2/fvg03NzfV7bdv30ZwcPAjHzdjxgyEh4erPs/NzYWXlxf69+9v0Hu0l7ul4vO/r+LfW6YYPSAEayNSEX0nDcYyCX4Y1wmdfBtO39rGYqBCwIkVEYjNyMdNS3/8p0/V0WFBEPDDqkgAuXi9hz+e7+Gnn0J1QOaTjnc3XcCRDGOUlSsACHhnSHe0dLXWd2lE9ASV74gSkXo0DsMTJ07URR3V+Pn5wdXVFfv371eF39zcXERGRuLtt99+5ONMTU1rHKk2NjaGsXHdevLq0vhuTfHX+TScvyHH8FWRqtuHBnugawtnPVYmblP7+eOd9WfxS0QqJvZoXqWv87nUu7h4KxcmMilGd/Yx6OeXpp4P8sT8f6/hdu79KUeX0vLRzstej1URkToa0+8iovpQpwV0dZWfn4/o6GhER0cDUC6ai46ORmpqKiQSCaZOnYp58+bhr7/+QkxMDMaOHQt3d3cMHTpUn2XrhEwqUe1M96CtZ28iTV6kh4oIAAa2cUVLV2vklZTjx2OJVb5W2U7t+SA3OFgZzlQhbbidV4yM3Kq7I87adpHPRSIianT0GobPnDmD9u3bo3379gCA8PBwtG/fHp988gkA4IMPPsCUKVPw5ptvolOnTsjPz8euXbtgZmamz7J1xtio+o+jQhCQnMX5X/oilUow9V5niZ+OJyOnsBQAcCe/BDsvpAGAql90Y5KUVQDhodv4XCQiosZIr7sDPP300xCEh//k3ieRSPDZZ5/hs88+q8eq9MfP0RJSiXIBUyWZRAJfR8Nc+CcW/VsrR4evpufhx6NJmD4gAJvOXEdphQKBnrYI9rLTd4lax+ciERGJhV5HhqkqN1tzLBzeDjKJsrWaTCLBguFtRb8rnL4pR4eVU1h+Op6ErPwSrD+ZCqBhb7LxOHwuEhGRWEiExw3NNgK5ubmwtbWFXC436G4SD0qTFyE5qxC+jhYMHwZCEAQ8t/QYLqflorWbDS6n5cLGzAinZvWFmbFM3+XpDJ+LRA1PQ/y7R6RPHBk2QG625ghr5sDwYUAkkvu70l1OU7Ytyisux/bom/osS+f4XCQiosaOYZhITe08qo6wCABmbmWHBSIiooaMYZhITcl3qndSYIcFIiKiho1hmEhNlR0WHsQOC0RERA0bwzCRmthhgYiIqPHRa59hooZmVCdv9PB3YocFIiKiRoJhmEhDbrbmDMFERESNBKdJEBEREZFoMQwTERERkWgxDBMRERGRaDEMExEREZFoMQwTERERkWgxDBMRERGRaDEMExEREZFoMQwTERERkWgxDBMRERGRaDEMExEREZFoMQwTERERkWgxDBMRERGRaDEMExEREZFoMQwTERERkWgxDBMRERGRaDEMExEREZFoMQwTERERkWgxDBMRERGRaDEMExEREZFoMQwTERERkWgxDBMRERGRaDEMExEREZFoMQwTERERkWgxDBMRERGRaDEMExEREZFoMQwTERERkWgxDBMRERGRaDEMExEREZFoMQwTERERkWgxDBMRERGRaDEMExEREZFoMQwTERERkWgxDBMRERGRaDEMExEREZFoMQwTERERkWgxDBMRERGRaDEMExEREZFoMQwTERERkWgxDBMRERGRaDEMExEREZFoMQwTERERkWgxDBMRERGRaDEMExEREZFoMQwTERERkWgxDBMRERGRaDEMExEREZFoMQwTERERkWgxDBMRERGRaDEMExEREZFoMQwTERERkWgxDBMRERGRaDEMExEREZFoMQwTERERkWgxDBMRERGRaDEMExEREZFoMQwTERERkWgxDBMRERGRaDEMExEREZFoMQwTERERkWgxDBMRERGRaDEMExEREZFoMQwTERERkWgxDBMRERGRaDEMExEREZFoMQwTERERkWgxDBMRERGRaDEMExEREZFoMQwTERERkWgxDBMRERGRaDEMExEREZFoMQwTERERkWgxDBMRERGRaDEMExEREZFoMQwTERERkWgxDBMRERGRaDEMExEREZFoMQwTERERkWgxDBMRERGRaDEMExEREZFoMQwTERERkWgxDBMRERGRaDEMExEREZFoMQwTERERkWgxDBMRERGRaDEMExEREZFoMQwTERERkWgxDBMRERGRaDEMExEREZFoMQwTERERkWgxDBMRERGRaDEMExEREZFoMQwTERERkWgxDBMRERGRaDEMExEREZFoMQwTERERkWgxDBMRERGRaDEMExEREZFoMQwTERERkWgxDBMRERGRaDEMExEREZFoMQwTERERkWgxDBMRERGRaDEMExEREZFoMQwTERERkWg1iDC8YsUK+Pr6wszMDJ07d8apU6f0XRIRERERNQIGH4Y3bdqE8PBwzJkzB2fPnkVQUBAGDBiAjIwMfZdGRERERA2cwYfhJUuWYOLEiXjttdfQunVrrFq1ChYWFvjf//6n79KIiIiIqIEz0ncBj1NaWoqoqCjMmDFDdZtUKkXfvn0RERFR42NKSkpQUlKi+lwulwMAsrOzUVZWptuCiYiI9CwvLw8AIAiCnishahgMOgxnZWWhoqICLi4uVW53cXHB1atXa3zM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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "fig, ax = plt.subplots()\n", - "\n", - "key = 'ResSCNN1'\n", - "max_epochs = 30\n", - "max_y = 30\n", - "\n", - "_ = np.round(architectures_TM[key]['epochs_acc'][max_y-1], 2)\n", - "ax.plot(np.arange(len(architectures_TM[key]['epochs_x'][:max_epochs])), architectures_TM[key]['epochs_acc'][:max_epochs], label=f'{key} ({_}%)', marker='.')\n", - "\n", - "ax.set_ylim(0, max_y)\n", - "ax.set_yticks(np.arange(0, max_y+10, 10))\n", - "ax.set_ylabel('validation acc [%]')\n", - "ax.set_xlim(0, max_epochs)\n", - "ax.set_xlabel('epoch')\n", - "\n", - "pos = ax.get_position()\n", - "ax.set_position([pos.x0, pos.y0, pos.width * 0.9, pos.height])\n", - "ax.legend(loc='center right', bbox_to_anchor=(1.45, 0.5), framealpha=0)\n", - "ax.grid(axis='y')\n", - "\n", - "plt.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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10cffaT4+Hjt3LnT326ZkJCgzMxMrVy5Updcckml7/fGG2+oQ4cOGj58eIXnbDab3G53uWUzZ85U79699fXXX6tXr16n/Bw33nijli1bpscee6zSDHiu1Siwfvzxx4qKitKAAQMklY24vvzyy+rUqZPmzp2rxo0b12qRAACgYSvwlqrT1H+f1Wv4LGnK4s2asnhztbb7/rGhigitemT68MMPFRUVpZKSEhUVFclut+v5559XUVGRnnzySX3yySfq16+fJOm8887TF198oRdffFEDBw5URkaGLrjgAn94/Hmr5XXXXad///vfGjhwoBISEnTRRRdp8ODB+t3vfqfo6GhJ0o4dO9ShQ4cq13rhhRfq+uuv1x//+EctX778lOvZbDbNnDlTV199tcaNG6c2bdpU+T1qQ41aAiZMmCCPxyNJ2rhxox588EFdeeWV2r17t8aPH1+rBQIAANQngwYNUnp6utauXavU1FTddtttuvbaa7Vz507l5+frsssuU1RUlP/22muvadeuXZKkP/zhD3rrrbfUo0cPTZw4UatWrfK/rsPh0Kuvvqp9+/Zp1qxZat68uZ588kl17txZmZmZkspGoqvr8ccf13/+859y/a2VGTp0qAYMGKApU6ZU+z3OVo1GWHfv3q1OnTpJkt577z395je/0ZNPPqkNGzb4T8ACAACoLeFOh75/bGi1tjmQU6ghs1fI97MMZ7dJn4wfqAR3WLXeuzoiIyP903/+7W9/U/fu3fXKK6+oS5cukqQlS5aoefPm5bZxuVySpCuuuEI//vij/vWvf2nZsmUaPHiwxowZU+6Ep+bNm+uWW27RLbfcohkzZqh9+/aaN2+epk+frvbt22vr1q3VqrdNmza688479fDDD+uVV1457bozZ85Uv379NGHChGq9x9mq0QhraGiof1qETz75RJdffrkkKTY21j/yCgAAUFtsNpsiQkOqdTuvSZTSRnaV40T/qcNmU9rIrjqvSVS1Xqem/auSZLfbNXnyZP3pT39Sp06d5HK5lJGRobZt25a7JScn+7dp0qSJUlNT9frrr2vOnDl66aWXTvn6jRs3VmJiovLy8iRJN910k7Zv367FixdXWNeyLOXk5FT6OlOnTtX27dv11ltvnfbz9OnTRyNHjtTDDz9clY9fa2o0wjpgwACNHz9e/fv311dffaW3335bkrR9+3a1aFG9RmYAAIBzZVTvlrqkfRPtycpX6/gIJbrD67yG6667ThMmTNCLL76ohx56SOPGjZPP59OAAQOUk5OjL7/8UtHR0UpNTdXUqVPVs2dPde7cWUVFRfrwww/VsWNHSdKLL76o9PR0XXPNNWrTpo0KCwv12muvafPmzXruueckSddff70WLlyoG2+8UX/60590+eWXq0mTJtq4caOeeeYZ3XfffRoxYkSFGps1a6bx48frz3/+8xk/zxNPPKHOnTsrJKR8jDx69KgyMjK0f/9+SdK2bdsklZ0slpCQcDa7sGYjrM8//7xCQkL07rvv6oUXXvAPa3/00UcaNmzYWRUEAABQmxLd4erXJi4gYVWSQkJCdO+992rWrFmaNGmSpkyZorS0NHXs2FHDhg3TkiVLlJKSIqnsr9iTJk1St27ddMkll8jhcPhHPfv06aPjx4/r7rvvVufOnTVw4ECtWbNGixYt0sCBAyWVjUS/+eabmj17tn95t27d9Oijj2r48OEaOvTUbRUPPfSQoqKizvh52rdvr9tvv73CxRD++c9/6oILLtBVV10lSbrhhht0wQUXaN68eTXabz9ns2rSnVuPeDweud1u5eTk+M+gAwAgWHHcQzCqUUuAJJWWlmrRokXasmWLJKlz58767W9/K4ejeo3JAAAAwOnUKLDu3LlTV155pX766Sf/XF9paWlKTk7WkiVL6nxuLgAAAASvGvWw3n///WrTpo327t2rDRs2aMOGDcrIyFBKSoruv//+2q4RAAAADViNRlhXrFihNWvWKDY21r8sLi5OM2fOVP/+/WutOAAAAKBGI6wul0u5ubkVlh8/flyhoaFnXRQAAABwUo0C629+8xvdddddWrt2rSzLkmVZWrNmje6++2799re/re0aAQAA0IDVKLA+++yzatOmjfr166ewsDCFhYXp4osvVtu2bTVnzpxaLhEAAAANWY16WGNiYrR48WLt3LnTP61Vx44d/dfNBQAAAGpLlQPr+PHjT/v8Z5995r8/e/bsmlcEAAAA/EyVA+s333xTpfVsNluNiwEAAAB+qcqB9ecjqAAAAEBdqdFJVwAAAEBdIbACAADAaARWAAAAGI3ACgAAAKMRWAEAAGA0AisAAACMRmAFAACA0QisAAAAMFqDCawHcgoCXQIAAABqoMEE1sufWam312UEugwAAABUU4MJrD5L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O1aPP/642rVrp5SUFE2ZMkVJSUkaMWJE4IoOsNPts9jYWE2fPl3XXnutEhIStGvXLk2cOFFt27bV0KFDA1h14IwZM0ZvvvmmFi9erEaNGvn7Ut1ut8LDw+V2u/X73/9e48ePV2xsrKKjo3XfffepX79+uuiiiwJcfWCcaZ/t2rVLb775pq688krFxcXpu+++07hx43TJJZeoW7duAa4eQJUEepqCc+m5556zWrZsaYWGhlp9+vSx1qxZE+iSjDZq1CgrMTHRCg0NtZo3b26NGjXK2rlzZ6DLMspnn31mSapwS01NtSyrbGqrKVOmWM2aNbNcLpc1ePBga9u2bYEtOsBOt8/y8/Otyy+/3GrSpInldDqtVq1aWXfeead14MCBQJcdMJXtK0nWq6++6l+noKDAuueee6zGjRtbERER1jXXXGNlZmYGrugAO9M+y8jIsC655BIrNjbWcrlcVtu2ba0JEyZYOTk5gS0cQJXZLMuy6jIgAwAAANURlD2sAAAACB4EVgAAABiNwAoAAACjEVgBAABgNAIrAAAAjEZgBQAAgNEIrAAAADAagRWAUT7//HPZbDZlZ2cHuhQAgCEIrAAAADAagRUAAABGI7ACKMfn8yktLU0pKSkKDw9X9+7d9e6770r675/rlyxZom7duiksLEwXXXSRNm3aVO413nvvPXXu3Fkul0utW7fW008/Xe75oqIi/fGPf1RycrJcLpfatm2rV155pdw669evV69evRQREaGLL75Y27ZtO7cfHABgLAIrgHLS0tL02muvad68edq8ebPGjRunm2++WStWrPCvM2HCBD399NNat26dmjRpoquvvlper1dSWdC8/vrrdcMNN2jjxo169NFHNWXKFM2fP9+//e9+9zstWLBAzz77rLZs2aIXX3xRUVFR5ep45JFH9PTTT+vrr79WSEiIbr/99jr5/AAA89gsy7ICXQQAMxQVFSk2NlaffPKJ+vXr519+xx13KD8/X3fddZcGDRqkt956S6NGjZIkHT16VC1atND8+fN1/fXXa/To0Tp8+LCWLl3q337ixIlasmSJNm/erO3bt6tDhw5atmyZhgwZUqGGzz//XIMGDdInn3yiwYMHS5L+9a9/6aqrrlJBQYHCwsLO8V4AAJiGEVYAfjt37lR+fr4uu+wyRUVF+W+vvfaadu3a5V/v52E2NjZWHTp00JYtWyRJW7ZsUf/+/cu9bv/+/bVjxw6VlpYqPT1dDodDAwcOPG0t3bp1899PTEyUJB06dOisPyMAoP4JCXQBAMxx/PhxSdKSJUvUvHnzcs+5XK5yobWmwsPDq7Se0+n037fZbJLK+msBAA0PI6wA/Dp16iSXy6WMjAy1bdu23C05Odm/3po1a/z3jx07pu3bt6tjx46SpI4dO+rLL78s97pffvml2rdvL4fDoa5du8rn85XriQUA4HQYYQXg16hRIz300EMaN26cfD6fBgwYoJycHH355ZeKjo5Wq1atJEmPPfaY4uLi1KxZMz3yyCOKj4/XiBEjJEkPPvigevfurRkzZmjUqFFavXq1nn/+ef31r3+VJLVu3Vqpqam6/fbb9eyzz6p79+768ccfdejQIV1//fWB+ugAAIMRWAGUM2PGDDVp0kRpaWn64YcfFBMTowsvvFCTJ0/2/0l+5syZeuCBB7Rjxw716NFDH3zwgUJDQyVJF154od555x1NnTpVM2bMUGJioh577DHdeuut/vd44YUXNHnyZN1zzz06cuSIWrZsqcmTJwfi4wIA6gFmCQBQZSfP4D927JhiYmICXQ4AoIGghxUAAABGI7ACAADAaLQEAAAAwGiMsAIAAMBoBFYAAAAYjcAKAAAAoxFYAQAAYDQCKwAAAIxGYAUAAIDRCKwAAAAwGoEVAAAARiOwAgAAwGj/H5mlPsKfRujAAAAAAElFTkSuQmCC", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "fig, ax = plt.subplots()\n", - "\n", - "val = architectures_TM[key]\n", - "y_avg = []\n", - "for y in val['epochs_y']:\n", - " y_avg.append(np.mean(y))\n", - "_ - np.round(y_avg[-1], 2)\n", - "ax.plot(np.arange(len(val['epochs_x']))[:max_epochs], y_avg[:max_epochs], label=f'{key}', marker='.')\n", - "\n", - "ax.set_ylim(0, 10)\n", - "ax.set_ylabel('loss')\n", - "ax.set_xlim(0, max_epochs-1)\n", - "ax.set_xlabel('epoch')\n", - "\n", - "pos = ax.get_position()\n", - "ax.set_position([pos.x0, pos.y0, pos.width * 0.9, pos.height])\n", - "ax.legend(loc='center right', bbox_to_anchor=(1.4, 0.5), framealpha=0)\n", - "ax.grid(axis='y')\n", - "\n", - "plt.show()" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.10.0" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/tests/test_nonsequential/using_SumPool2d/ARCHITECTURES_SEARCH/main.py b/tests/test_nonsequential/using_SumPool2d/ARCHITECTURES_SEARCH/main.py deleted file mode 100644 index 976aded5..00000000 --- a/tests/test_nonsequential/using_SumPool2d/ARCHITECTURES_SEARCH/main.py +++ /dev/null @@ -1,136 +0,0 @@ -import torch, tonic, sys, random -import numpy as np -from torch.utils.data import DataLoader -from sinabs.activation.surrogate_gradient_fn import PeriodicExponential -from torch.nn import CrossEntropyLoss -from torch.optim import Adam -import os -from tqdm import tqdm - -sys.path.append('../../utils') -sys.path.append('../models') - -from train_test_fn import training_loop_no_tqdm, load_dataset, split_train_validation_used_seed, load_architecture -from weight_initialization import rescale_method_1 - -if torch.cuda.is_available(): - device = torch.device('cuda:0') - print('device: ', torch.cuda.get_device_name(0)) -else: - device = torch.device('cpu') - -torch.backends.cudnn.enabled = False -torch.backends.cudnn.deterministic = True -random.seed(1) -torch.manual_seed(1) -torch.cuda.manual_seed(1) - -### Initialization #################################################### - -total_architectures = 11 - -lr = 5e-5 -batch_size = 8 -num_workers = 4 -n_time_steps = 50 -epochs = 25 -w_rescale_lambda = 0.8 - -spk_thr = 2.0 -v_min = -0.313 -grad_scale = 1.534 -grad_width = 0.759 - -validation_ratio = 0.2 -prev_used_seed = 1 - -loss_fn = CrossEntropyLoss() - -directory = f'./architectures_results_2' - -if not os.path.exists(directory): - os.makedirs(directory) - -with open(f'./architectures_results_2/fixed_parameters.txt', 'w') as file: - file.write(f'lr: {lr}\n') - file.write(f'batch_size: {batch_size}\n') - file.write(f'num_workers: {num_workers}\n') - file.write(f'n_time_steps: {n_time_steps}\n') - file.write(f'epochs: {epochs}\n') - file.write(f'w_rescale_lambda: {w_rescale_lambda}\n') - file.write(f'spk_thr: {spk_thr}\n') - file.write(f'v_min: {v_min}\n') - file.write(f'grad_scale: {grad_scale}\n') - file.write(f'grad_width: {grad_width}\n') - file.write(f'validation_ratio: {validation_ratio}\n') - file.write(f'prev_used_seed: {prev_used_seed}\n') - -### Data Loading ##################################################### - -snn_train_dataset, snn_test_dataset, sensor_size = load_dataset('DVSGESTURE', n_time_steps) -train_dataset, validation_dataset = split_train_validation_used_seed(validation_ratio, snn_train_dataset, prev_used_seed) - -disk_cache_train = tonic.DiskCachedDataset( - dataset=train_dataset, - cache_path='./cached_train' -) -snn_train_dataloader = DataLoader(disk_cache_train, batch_size=batch_size, num_workers=num_workers, drop_last=True, shuffle=True) - -disk_cache_validation = tonic.DiskCachedDataset( - dataset=validation_dataset, - cache_path='./cached_validation' -) -snn_validation_dataloader = DataLoader(disk_cache_validation, batch_size=batch_size, num_workers=num_workers, drop_last=True, shuffle=True) - -disk_cache_test = tonic.DiskCachedDataset( - dataset=snn_test_dataset, - cache_path='./cached_test' -) -snn_test_dataloader = DataLoader(disk_cache_test, batch_size=batch_size, num_workers=num_workers, drop_last=True, shuffle=False) - -### Training Loop ########################################################## - -train_p_bar = tqdm(range(9, total_architectures+1)) - -for iter in train_p_bar: - achitecture = f'ResSCNN_{iter}' - - # instantiate model. - csnn = load_architecture( - achitecture, - sensor_size, - 11, - batch_size, - PeriodicExponential(grad_scale=grad_scale, grad_width=grad_width), - v_min, - spk_thr - ).to(device) - - csnn.init_weights() - csnn.rescale_conv_weights(rescale_method_1, w_rescale_lambda) - - # instantiate optimizer. - optimizer = Adam(csnn.parameters(), lr = lr, betas = (0.9, 0.999), eps = 1e-8) - - # train/test model. - epochs_x, epochs_y, epochs_acc = training_loop_no_tqdm( - device, - n_time_steps, - batch_size, - sensor_size, - snn_train_dataloader, - csnn, - loss_fn, - optimizer, - epochs, - snn_validation_dataloader, - True) - - # export model data. - with open(f'./architectures_results_2/{achitecture}-training_metrics.npy', 'wb') as f: - np.save(f, np.array(epochs_x)) - np.save(f, np.array(epochs_y)) - np.save(f, np.array(epochs_acc)) - - # update progress bar - train_p_bar.set_description(f'{iter}/{total_architectures} - model {achitecture} - acc.: {np.round(epochs_acc[-1], 2)}') \ No newline at end of file diff --git a/tests/test_nonsequential/using_SumPool2d/ARCHITECTURES_SEARCH/model_training.py b/tests/test_nonsequential/using_SumPool2d/ARCHITECTURES_SEARCH/model_training.py deleted file mode 100644 index 84c4144f..00000000 --- a/tests/test_nonsequential/using_SumPool2d/ARCHITECTURES_SEARCH/model_training.py +++ /dev/null @@ -1,92 +0,0 @@ -import torch, random, sys - -import tonic -from torch.utils.data import DataLoader -from torch.nn import CrossEntropyLoss -from torch.optim import Adam - -from sinabs.activation.surrogate_gradient_fn import PeriodicExponential - -import matplotlib.pyplot as plt -import numpy as np - -sys.path.append('../../utils') -sys.path.append('../models') - -from train_test_fn import training_loop, load_dataset, split_train_validation, load_architecture - -if torch.cuda.is_available(): - device = torch.device('cuda:0') - print('device: ', torch.cuda.get_device_name(0)) -else: - device = torch.device('cpu') - -rand_seed = 1 - -achitecture = sys.argv[1] - -torch.backends.cudnn.enabled = False -torch.backends.cudnn.deterministic = True -random.seed(rand_seed) -torch.manual_seed(rand_seed) -torch.cuda.manual_seed(rand_seed) -np.random.seed(rand_seed) - -batch_size = 8 -num_workers = 4 -epochs = 100 -lr = 5e-5 - -spk_thr = 2.0 -v_min = -0.313 - -grad_scale = 1.534 -grad_width = 0.759 - -validation_ratio = 0.2 -n_time_steps = 50 - -snn_train_dataset, snn_test_dataset, sensor_size = load_dataset('DVSGESTURE', n_time_steps) - -train_dataset, validation_dataset = split_train_validation(validation_ratio, snn_train_dataset, rand_seed) - -disk_cache_train = tonic.DiskCachedDataset( - dataset=train_dataset, - cache_path='./cached_train' -) -snn_train_dataloader = DataLoader(disk_cache_train, batch_size=batch_size, num_workers=num_workers, drop_last=True, shuffle=True) - -disk_cache_validation = tonic.DiskCachedDataset( - dataset=validation_dataset, - cache_path='./cached_validation' -) -snn_validation_dataloader = DataLoader(disk_cache_validation, batch_size=batch_size, num_workers=num_workers, drop_last=True, shuffle=True) - -disk_cache_test = tonic.DiskCachedDataset( - dataset=snn_test_dataset, - cache_path='./cached_test' -) -snn_test_dataloader = DataLoader(disk_cache_test, batch_size=batch_size, num_workers=num_workers, drop_last=True, shuffle=False) - -snn = load_architecture(achitecture, sensor_size, 11, batch_size, PeriodicExponential(grad_scale=grad_scale, grad_width=grad_width), v_min, spk_thr).to(device) -snn.init_weights() - -optimizer = Adam(snn.parameters(), lr=lr, betas=(0.9, 0.999), eps=1e-8) -loss_fn = CrossEntropyLoss() - -epochs_x, epochs_y, epochs_acc = training_loop( - device, - n_time_steps, - batch_size, - sensor_size, - snn_train_dataloader, - snn, - loss_fn, - optimizer, - epochs, - snn_validation_dataloader) - -with open(f'./architectures_results/{achitecture}-Training_Validation-TM.npy', 'wb') as f: - np.save(f, np.array(epochs_x)) - np.save(f, np.array(epochs_y)) - np.save(f, np.array(epochs_acc)) \ No newline at end of file diff --git a/tests/test_nonsequential/using_SumPool2d/ARCHITECTURES_SEARCH/single_training.ipynb b/tests/test_nonsequential/using_SumPool2d/ARCHITECTURES_SEARCH/single_training.ipynb deleted file mode 100644 index 33bac3a0..00000000 --- a/tests/test_nonsequential/using_SumPool2d/ARCHITECTURES_SEARCH/single_training.ipynb +++ /dev/null @@ -1,4716 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "import torch, random, sys\n", - "\n", - "import tonic\n", - "from torch.utils.data import DataLoader\n", - "from torch.nn import CrossEntropyLoss\n", - "from torch.optim import Adam\n", - "\n", - "from sinabs.activation.surrogate_gradient_fn import PeriodicExponential\n", - "\n", - "import matplotlib.pyplot as plt\n", - "import numpy as np\n", - "\n", - "sys.path.append('../../utils')\n", - "sys.path.append('../models')\n", - "\n", - "from train_test_fn import training_loop, load_dataset, split_train_validation, load_architecture\n", - "from weight_initialization import rescale_method_1" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "device: NVIDIA GeForce RTX 3070 Ti\n" - ] - } - ], - "source": [ - "if torch.cuda.is_available():\n", - " device = torch.device('cuda:0')\n", - " print('device: ', torch.cuda.get_device_name(0))\n", - "else:\n", - " device = torch.device('cpu')" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "rand_seed = 1" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "achitecture = 'ResSCNN4'" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "torch.backends.cudnn.enabled = False\n", - "torch.backends.cudnn.deterministic = True\n", - "random.seed(rand_seed)\n", - "torch.manual_seed(rand_seed)\n", - "torch.cuda.manual_seed(rand_seed)\n", - "np.random.seed(rand_seed)" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], - "source": [ - "batch_size = 8\n", - "num_workers = 4\n", - "epochs = 125\n", - "lr = 5e-5\n", - "\n", - "spk_thr = 2.0\n", - "v_min = -0.313\n", - "\n", - "grad_scale = 1.534\n", - "grad_width = 0.759\n", - "\n", - "validation_ratio = 0.2\n", - "n_time_steps = 50" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Loading Data" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [], - "source": [ - "snn_train_dataset, snn_test_dataset, sensor_size = load_dataset('DVSGESTURE', n_time_steps)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "getting validation dataset...." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [], - "source": [ - "train_dataset, validation_dataset = split_train_validation(validation_ratio, snn_train_dataset, rand_seed)" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The transformed array is in shape [Time-Step, Channel, Height, Width] --> (50, 2, 128, 128)\n" - ] - } - ], - "source": [ - "sample_data, label = train_dataset[0]\n", - "print(f\"The transformed array is in shape [Time-Step, Channel, Height, Width] --> {sample_data.shape}\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "disk caching samples..." - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [], - "source": [ - "disk_cache_train = tonic.DiskCachedDataset(\n", - " dataset=train_dataset,\n", - " cache_path='./cached_train'\n", - ")\n", - "snn_train_dataloader = DataLoader(disk_cache_train, batch_size=batch_size, num_workers=num_workers, drop_last=True, shuffle=True)\n", - "\n", - "disk_cache_validation = tonic.DiskCachedDataset(\n", - " dataset=validation_dataset,\n", - " cache_path='./cached_validation'\n", - ")\n", - "snn_validation_dataloader = DataLoader(disk_cache_validation, batch_size=batch_size, num_workers=num_workers, drop_last=True, shuffle=True)\n", - "\n", - "disk_cache_test = tonic.DiskCachedDataset(\n", - " dataset=snn_test_dataset,\n", - " cache_path='./cached_test'\n", - ")\n", - "snn_test_dataloader = DataLoader(disk_cache_test, batch_size=batch_size, num_workers=num_workers, drop_last=True, shuffle=False)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Network Module" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [], - "source": [ - "snn = load_architecture(achitecture, sensor_size, 11, batch_size, PeriodicExponential(grad_scale=grad_scale, grad_width=grad_width), v_min, spk_thr).to(device)\n", - "snn.init_weights()" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [], - "source": [ - "# lambda_ = 0.8\n", - "# snn.rescale_conv_weights(rescale_method_1, lambda_)" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [], - "source": [ - "optimizer = Adam(snn.parameters(), lr=lr, betas=(0.9, 0.999), eps=1e-8)\n", - "loss_fn = CrossEntropyLoss()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Training loop" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "7f01930878c74d7eb18bb72c0921d870", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - " 0%| | 0/107 [00:00" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "y_avg = []\n", - "for y in epochs_y:\n", - " y_avg.append(np.mean(y))\n", - "\n", - "plt.plot(np.arange(len(epochs_x)), y_avg, marker = '.')\n", - "plt.xlabel('epoch')\n", - "plt.ylabel('average loss')\n", - "plt.ylim(0,)\n", - "plt.xticks(np.arange(len(epochs_x)))\n", - "for i, txt in enumerate(y_avg):\n", - " plt.text(i, txt, f'{txt:.2f}', ha='center', va='bottom', color = 'k')\n", - "plt.show()" - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "plt.plot(np.arange(len(epochs_x)), epochs_acc, marker = '.')\n", - "plt.xlabel('epoch')\n", - "plt.ylabel('test accuracy')\n", - "plt.ylim(0, 100)\n", - "plt.xticks(np.arange(len(epochs_x)))\n", - "for i, txt in enumerate(epochs_acc):\n", - " if i%5 ==0 or i == epochs-1:\n", - " plt.text(i, txt, f'{txt:.2f}', ha='center', va='bottom', color = 'k')\n", - "plt.show()" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [], - "source": [ - "# with open(f'./architectures_results/{achitecture}-Training_Validation-TM.npy', 'wb') as f:\n", - "# np.save(f, np.array(epochs_x))\n", - "# np.save(f, np.array(epochs_y))\n", - "# np.save(f, np.array(epochs_acc))" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "speck-rescnn", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.10.0" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/tests/test_nonsequential/using_SumPool2d/ARCHITECTURES_SEARCH/train_all.py b/tests/test_nonsequential/using_SumPool2d/ARCHITECTURES_SEARCH/train_all.py deleted file mode 100644 index 9af56038..00000000 --- a/tests/test_nonsequential/using_SumPool2d/ARCHITECTURES_SEARCH/train_all.py +++ /dev/null @@ -1,4 +0,0 @@ -import os - -for i in range(1, 9): - os.system(f'python model_training.py ResSCNN{i}') \ No newline at end of file diff --git a/tests/test_nonsequential/using_SumPool2d/HPO_GAUSSIAN_SEARCH/GS_utils.py b/tests/test_nonsequential/using_SumPool2d/HPO_GAUSSIAN_SEARCH/GS_utils.py deleted file mode 100644 index 2ef3c4b2..00000000 --- a/tests/test_nonsequential/using_SumPool2d/HPO_GAUSSIAN_SEARCH/GS_utils.py +++ /dev/null @@ -1,54 +0,0 @@ -import numpy as np - -def define_probabilistic_model(hyperparams): - prob_model = {} - - for key, data in hyperparams.items(): - prob_model[key] = {'mu': data['value'], 'sigma': data['sigma']} - - return prob_model - -def update_probabilistic_model(max_iter, cur_iter, prob_model, hyperparams_new): - - sigma_scale = update_sigma_scale(max_iter, cur_iter) - - for key, value in hyperparams_new.items(): - prob_model[key]['mu'] = value - prob_model[key]['sigma'] = prob_model[key]['sigma']*sigma_scale - -def update_sigma_scale(max_iter, cur_iter): - _ = np.round(1-(cur_iter/max_iter), 2) - - if _ > 0: - return _ - else: - return 0.01 - -def sample_values_to_eval(iteration, prob_model, hyperparams, nb_samples: int = 5): - new_values = {} - np.random.seed(iteration) - - for hp, data in prob_model.items(): - sampled_values = np.round(np.random.normal(data['mu'], data['sigma'], nb_samples), hyperparams[hp]['precision']) - - fixed_sampled_values = [] - - for val in sampled_values: - if val < hyperparams[hp]['min']: - fixed_sampled_values.append(hyperparams[hp]['min']) - elif val > hyperparams[hp]['max']: - fixed_sampled_values.append(hyperparams[hp]['max']) - else: - fixed_sampled_values.append(val) - - new_values[hp] = fixed_sampled_values - - return new_values - -def get_sampled_set(sampled_values, i): - sampled_set = {} - - for key, val in sampled_values.items(): - sampled_set[key] = val[i] - - return sampled_set \ No newline at end of file diff --git a/tests/test_nonsequential/using_SumPool2d/HPO_GAUSSIAN_SEARCH/gaussian_search_history.csv b/tests/test_nonsequential/using_SumPool2d/HPO_GAUSSIAN_SEARCH/gaussian_search_history.csv deleted file mode 100644 index e87da0e0..00000000 --- a/tests/test_nonsequential/using_SumPool2d/HPO_GAUSSIAN_SEARCH/gaussian_search_history.csv +++ /dev/null @@ -1,57 +0,0 @@ -,learning_rate,spike_threshold,mem_v_min,grad_scale,grad_width,w_rescale_lambda,accuracy -0,0.001,2.75,-2.5,1.55,1.55,0.5,10.576923076923077 -1,0.000947,1.99,-2.82,1.11,2.0,0.344,86.0576923076923 -2,0.000769,1.09,-2.29,1.11,1.83,0.319,87.98076923076923 -3,0.000811,1.01,-1.43,0.85,1.73,0.42,88.9423076923077 -4,0.000811,1.01,-1.43,0.85,1.73,0.42,88.9423076923077 -5,0.000811,1.01,-1.43,0.85,1.73,0.42,88.9423076923077 -6,0.000782,1.87,0.0,0.91,1.9,0.235,92.3076923076923 -7,0.000741,1.87,-0.15,1.16,1.97,0.175,95.67307692307693 -8,0.000741,1.87,-0.15,1.16,1.97,0.175,95.67307692307693 -9,0.000741,1.87,-0.15,1.16,1.97,0.175,95.67307692307693 -10,0.000741,1.87,-0.15,1.16,1.97,0.175,95.67307692307693 -11,0.000741,1.87,-0.15,1.16,1.97,0.175,95.67307692307693 -12,0.000741,1.87,-0.15,1.16,1.97,0.175,95.67307692307693 -13,0.000741,1.87,-0.15,1.16,1.97,0.175,95.67307692307693 -14,0.000741,1.87,-0.15,1.16,1.97,0.175,95.67307692307693 -15,0.000741,1.87,-0.15,1.16,1.97,0.175,95.67307692307693 -16,0.000741,1.87,-0.15,1.16,1.97,0.175,95.67307692307693 -17,0.000826,1.51,0.0,1.06,1.64,0.223,96.15384615384616 -18,0.000826,1.51,0.0,1.06,1.64,0.223,96.15384615384616 -19,0.000826,1.51,0.0,1.06,1.64,0.223,96.15384615384616 -20,0.000826,1.51,0.0,1.06,1.64,0.223,96.15384615384616 -21,0.000826,1.51,0.0,1.06,1.64,0.223,96.15384615384616 -22,0.000826,1.51,0.0,1.06,1.64,0.223,96.15384615384616 -23,0.000826,1.51,0.0,1.06,1.64,0.223,96.15384615384616 -24,0.000826,1.51,0.0,1.06,1.64,0.223,96.15384615384616 -25,0.000826,1.51,0.0,1.06,1.64,0.223,96.15384615384616 -26,0.000826,1.51,0.0,1.06,1.64,0.223,96.15384615384616 -27,0.000826,1.51,0.0,1.06,1.64,0.223,96.15384615384616 -28,0.000826,1.51,0.0,1.06,1.64,0.223,96.15384615384616 -29,0.000797,1.83,-0.09,0.67,1.56,0.121,97.59615384615384 -30,0.000797,1.83,-0.09,0.67,1.56,0.121,97.59615384615384 -31,0.000797,1.83,-0.09,0.67,1.56,0.121,97.59615384615384 -32,0.000797,1.83,-0.09,0.67,1.56,0.121,97.59615384615384 -33,0.000797,1.83,-0.09,0.67,1.56,0.121,97.59615384615384 -34,0.000797,1.83,-0.09,0.67,1.56,0.121,97.59615384615384 -35,0.000797,1.83,-0.09,0.67,1.56,0.121,97.59615384615384 -36,0.000797,1.83,-0.09,0.67,1.56,0.121,97.59615384615384 -37,0.000797,1.83,-0.09,0.67,1.56,0.121,97.59615384615384 -38,0.000797,1.83,-0.09,0.67,1.56,0.121,97.59615384615384 -39,0.000797,1.83,-0.09,0.67,1.56,0.121,97.59615384615384 -40,0.000797,1.83,-0.09,0.67,1.56,0.121,97.59615384615384 -41,0.000797,1.83,-0.09,0.67,1.56,0.121,97.59615384615384 -42,0.000797,1.83,-0.09,0.67,1.56,0.121,97.59615384615384 -43,0.000797,1.83,-0.09,0.67,1.56,0.121,97.59615384615384 -44,0.000797,1.83,-0.09,0.67,1.56,0.121,97.59615384615384 -45,0.000797,1.83,-0.09,0.67,1.56,0.121,97.59615384615384 -46,0.000797,1.83,-0.09,0.67,1.56,0.121,97.59615384615384 -47,0.000797,1.83,-0.09,0.67,1.56,0.121,97.59615384615384 -48,0.000797,1.83,-0.09,0.67,1.56,0.121,97.59615384615384 -49,0.000797,1.83,-0.09,0.67,1.56,0.121,97.59615384615384 -50,0.000797,1.83,-0.09,0.67,1.56,0.121,97.59615384615384 -51,0.000797,1.83,-0.09,0.67,1.56,0.121,97.59615384615384 -52,0.000797,1.83,-0.09,0.67,1.56,0.121,97.59615384615384 -53,0.000797,1.83,-0.09,0.67,1.56,0.121,97.59615384615384 -54,0.000797,1.83,-0.09,0.67,1.56,0.121,97.59615384615384 -55,0.000797,1.83,-0.09,0.67,1.56,0.121,97.59615384615384 diff --git a/tests/test_nonsequential/using_SumPool2d/HPO_GAUSSIAN_SEARCH/main.py b/tests/test_nonsequential/using_SumPool2d/HPO_GAUSSIAN_SEARCH/main.py deleted file mode 100644 index 124b86b0..00000000 --- a/tests/test_nonsequential/using_SumPool2d/HPO_GAUSSIAN_SEARCH/main.py +++ /dev/null @@ -1,202 +0,0 @@ -from GS_utils import * -import torch, tonic, sys, random -import numpy as np -from torch.utils.data import DataLoader -from sinabs.activation.surrogate_gradient_fn import PeriodicExponential -from torch.nn import CrossEntropyLoss -from torch.optim import Adam -import pandas as pd -from tqdm import tqdm - -sys.path.append('../../utils') -sys.path.append('../models') - -from network import SCNN_GS -from train_test_fn import training_loop_no_tqdm, load_dataset, split_train_validation -from weight_initialization import rescale_method_1 - -if torch.cuda.is_available(): - device = torch.device('cuda:0') - print('device: ', torch.cuda.get_device_name(0)) -else: - device = torch.device('cpu') - -torch.backends.cudnn.enabled = False -torch.backends.cudnn.deterministic = True -random.seed(1) -torch.manual_seed(1) -torch.cuda.manual_seed(1) - -### Initialization #################################################### - -max_iter = 100 -nb_samples = 5 -batch_size = 8 -num_workers = 8 -validation_ratio = 0.2 -n_time_steps = 50 -epochs = 40 -validation_rand_seed = 1 -output_csv = 'gaussian_search_history.csv' -params_set_history = {} - -loss_fn = CrossEntropyLoss() - -hyperparams = { - 'learning_rate': {'value': 0.001, 'min': 0.00008, 'max': 0.08, 'precision': 6, 'sigma': 0.0001}, - 'spike_threshold': {'value': 2.75, 'min': 0.5, 'max': 5.0, 'precision': 2, 'sigma': 1.0}, - 'mem_v_min': {'value': -2.5, 'min': -5.0, 'max': 0.0, 'precision': 2, 'sigma': 1.0}, - 'grad_scale': {'value': 1.55, 'min': 0.1, 'max': 3.0, 'precision': 2, 'sigma': 0.5}, - 'grad_width': {'value': 1.55, 'min': 0.1, 'max': 3.0, 'precision': 2, 'sigma': 0.5}, - 'w_rescale_lambda': {'value': 0.5, 'min': 0.1, 'max': 1.0, 'precision': 3, 'sigma': 0.1667}, -} - -prob_model = define_probabilistic_model(hyperparams) - -with open('fixed_parameters.txt', 'w') as file: - file.write(f'max_iter: {max_iter}\n') - file.write(f'nb_samples: {nb_samples}\n') - file.write(f'batch_size: {batch_size}\n') - file.write(f'num_workers: {num_workers}\n') - file.write(f'validation_ratio: {validation_ratio}\n') - file.write(f'n_time_steps: {n_time_steps}\n') - file.write(f'epochs: {epochs}\n') - file.write(f'validation_rand_seed: {validation_rand_seed}\n') - -### Data Loading ##################################################### - -snn_train_dataset, snn_test_dataset, sensor_size = load_dataset('DVSGESTURE', n_time_steps) -train_dataset, validation_dataset = split_train_validation(validation_ratio, snn_train_dataset, validation_rand_seed) - -disk_cache_train = tonic.DiskCachedDataset( - dataset=train_dataset, - cache_path='./cached_train' -) -snn_train_dataloader = DataLoader(disk_cache_train, batch_size=batch_size, num_workers=num_workers, drop_last=True, shuffle=True) - -disk_cache_validation = tonic.DiskCachedDataset( - dataset=validation_dataset, - cache_path='./cached_validation' -) -snn_validation_dataloader = DataLoader(disk_cache_validation, batch_size=batch_size, num_workers=num_workers, drop_last=True, shuffle=True) - -disk_cache_test = tonic.DiskCachedDataset( - dataset=snn_test_dataset, - cache_path='./cached_test' -) -snn_test_dataloader = DataLoader(disk_cache_test, batch_size=batch_size, num_workers=num_workers, drop_last=True, shuffle=False) - -### Baseline Accuracy ################################################ - -# instantiate model. -csnn = SCNN_GS( - batch_size = batch_size, - surrogate_fn = PeriodicExponential(grad_scale = hyperparams['grad_scale']['value'], grad_width = hyperparams['grad_width']['value']), - min_v_mem = hyperparams['mem_v_min']['value'], - spk_thr = hyperparams['spike_threshold']['value'], - rescale_fn = rescale_method_1, - rescale_lambda = hyperparams['w_rescale_lambda']['value'] - ).to(device) - -# instantiate optimizer. -optimizer = Adam(csnn.parameters(), lr = hyperparams['learning_rate']['value'], betas = (0.9, 0.999), eps = 1e-8) - -# train/test model. -best_acc = training_loop_no_tqdm( - device, - n_time_steps, - batch_size, - sensor_size, - snn_train_dataloader, - csnn, - loss_fn, - optimizer, - epochs, - snn_validation_dataloader) - -# initialize parameters history. -best_param_set = { - 'learning_rate': [hyperparams['learning_rate']['value']], - 'spike_threshold': [hyperparams['spike_threshold']['value']], - 'mem_v_min': [hyperparams['mem_v_min']['value']], - 'grad_scale': [hyperparams['grad_scale']['value']], - 'grad_width': [hyperparams['grad_width']['value']], - 'w_rescale_lambda': [hyperparams['w_rescale_lambda']['value']], - 'accuracy': [best_acc] -} - -df = pd.DataFrame(best_param_set) -df.to_csv(output_csv, index=True) - -print(f'> initial accuracy: {best_acc}\n') - -### HPO Loop ########################################################## - -train_p_bar = tqdm(range(1, max_iter+1)) -counter = 1 - -for iter in train_p_bar: - - # sample values to be tested. - sampled_values = sample_values_to_eval(iter, prob_model, hyperparams, nb_samples) - - # test each sampled set. - acc = [] - for i in range(nb_samples): - sampled_set = get_sampled_set(sampled_values, i) - - # instantiate model. - csnn = SCNN_GS( - batch_size = batch_size, - surrogate_fn = PeriodicExponential(grad_scale = sampled_set['grad_scale'], grad_width = sampled_set['grad_width']), - min_v_mem = sampled_set['mem_v_min'], - spk_thr = sampled_set['spike_threshold'], - rescale_fn = rescale_method_1, - rescale_lambda = sampled_set['w_rescale_lambda'] - ).to(device) - - # instantiate optimizer. - optimizer = Adam(csnn.parameters(), lr = sampled_set['learning_rate'], betas = (0.9, 0.999), eps = 1e-8) - - # train/test model. - ith_acc = training_loop_no_tqdm( - device, - n_time_steps, - batch_size, - sensor_size, - snn_train_dataloader, - csnn, - loss_fn, - optimizer, - epochs, - snn_validation_dataloader) - - acc.append(ith_acc) - - # update progress bar - train_p_bar.set_description(f'model {counter}/{max_iter*nb_samples} - best acc.: {np.round(best_acc, 2)}') - counter += 1 - - # get best parameters set. - highest_acc_index = acc.index(np.max(acc)) - best_param_set = get_sampled_set(sampled_values, highest_acc_index) - - # update model. - if acc[highest_acc_index] > best_acc: - best_acc = acc[highest_acc_index] - - update_probabilistic_model(max_iter, iter, prob_model, best_param_set) - - # save to history. - best_param_set['accuracy'] = best_acc - - else: - - best_param_set = {} - for key, val in prob_model.items(): - best_param_set[key] = val['mu'] - best_param_set['accuracy'] = best_acc - - # update history - df = pd.DataFrame([best_param_set], index=[iter]) - df.to_csv(output_csv, mode='a', header=False) \ No newline at end of file diff --git a/tests/test_nonsequential/using_SumPool2d/HPO_GAUSSIAN_SEARCH/network.py b/tests/test_nonsequential/using_SumPool2d/HPO_GAUSSIAN_SEARCH/network.py deleted file mode 100644 index 53a9feab..00000000 --- a/tests/test_nonsequential/using_SumPool2d/HPO_GAUSSIAN_SEARCH/network.py +++ /dev/null @@ -1,83 +0,0 @@ -import torch.nn as nn -from sinabs.activation.surrogate_gradient_fn import PeriodicExponential -from sinabs.exodus.layers import IAFSqueeze -import sinabs.layers as sl - -class SCNN_GS(nn.Module): - def __init__(self, batch_size, surrogate_fn, min_v_mem, spk_thr, rescale_fn, rescale_lambda): - super().__init__() - - self.conv1 = nn.Conv2d(2, 10, 2, 1, bias=False) - self.iaf1 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - self.pool1 = sl.SumPool2d(2,2) - - self.conv2 = nn.Conv2d(10, 10, 2, 1, bias=False) - self.iaf2 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - self.pool2 = sl.SumPool2d(3,3) - - self.conv3 = nn.Conv2d(10, 10, 3, 1, bias=False) - self.iaf3 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - self.pool3 = sl.SumPool2d(2,2) - - self.flat = nn.Flatten() - - self.fc1 = nn.Linear(810, 100, bias=False) - self.iaf4 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - self.fc2 = nn.Linear(100, 100, bias=False) - self.iaf5 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - self.fc3 = nn.Linear(100, 100, bias=False) - self.iaf6 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - self.fc4 = nn.Linear(100, 11, bias=False) - self.iaf7 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - self.init_weights() - self.rescale_conv_weights(rescale_fn, rescale_lambda) - - def detach_neuron_states(self): - for name, layer in self.named_modules(): - if name != '': - if isinstance(layer, sl.StatefulLayer): - for name, buffer in layer.named_buffers(): - buffer.detach_() - - def init_weights(self): - for name, layer in self.named_modules(): - if isinstance(layer, nn.Conv2d) or isinstance(layer, nn.Linear): - nn.init.xavier_normal_(layer.weight.data) - - def rescale_conv_weights(self, rescale_fn, lambda_): - rescale_fn(self.conv2, [(2, 2)], lambda_) - rescale_fn(self.conv3, [(3, 3)], lambda_) - - def forward(self, x): - - con1_out = self.conv1(x) - iaf1_out = self.iaf1(con1_out) - pool1_out = self.pool1(iaf1_out) - - conv2_out = self.conv2(pool1_out) - iaf2_out = self.iaf2(conv2_out) - pool2_out = self.pool2(iaf2_out) - - conv3_out = self.conv3(pool2_out) - iaf3_out = self.iaf3(conv3_out) - pool3_out = self.pool3(iaf3_out) - - flat_out = self.flat(pool3_out) - - fc1_out = self.fc1(flat_out) - iaf4_out = self.iaf4(fc1_out) - - fc2_out = self.fc2(iaf4_out) - iaf5_out = self.iaf5(fc2_out) - - fc3_out = self.fc3(iaf5_out) - iaf6_out = self.iaf6(fc3_out) - - fc4_out = self.fc4(iaf6_out) - iaf7_out = self.iaf7(fc4_out) - - return iaf7_out \ No newline at end of file diff --git a/tests/test_nonsequential/using_SumPool2d/Res-SCNN3.ipynb b/tests/test_nonsequential/using_SumPool2d/Res-SCNN3.ipynb deleted file mode 100644 index 2e507d45..00000000 --- a/tests/test_nonsequential/using_SumPool2d/Res-SCNN3.ipynb +++ /dev/null @@ -1,1509 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "import torch, random\n", - "import torch.nn as nn\n", - "import sinabs.layers as sl\n", - "from tqdm.notebook import tqdm\n", - "\n", - "from tonic.datasets.dvsgesture import DVSGesture\n", - "from tonic.transforms import ToFrame\n", - "from torch.utils.data import DataLoader\n", - "from torch.nn import CrossEntropyLoss\n", - "from torch.optim import Adam\n", - "\n", - "from sinabs.activation.surrogate_gradient_fn import PeriodicExponential\n", - "\n", - "import matplotlib.pyplot as plt\n", - "import numpy as np" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "torch.backends.cudnn.deterministic = True\n", - "random.seed(1)\n", - "torch.manual_seed(1)\n", - "torch.cuda.manual_seed(1)\n", - "np.random.seed(1)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Loading Data" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "batch_size = 3\n", - "num_workers = 1\n", - "epochs = 30\n", - "lr = 1e-4" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "root_dir = \"../DVSGESTURE\"\n", - "_ = DVSGesture(save_to=root_dir, train=True)\n", - "_ = DVSGesture(save_to=root_dir, train=False)" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "n_time_steps = 50\n", - "to_raster = ToFrame(sensor_size=DVSGesture.sensor_size, n_time_bins=n_time_steps)\n", - "\n", - "snn_train_dataset = DVSGesture(save_to=root_dir, train=True, transform=to_raster)\n", - "snn_test_dataset = DVSGesture(save_to=root_dir, train=False, transform=to_raster)" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The transformed array is in shape [Time-Step, Channel, Height, Width] --> (50, 2, 128, 128)\n" - ] - } - ], - "source": [ - "sample_data, label = snn_train_dataset[0]\n", - "print(f\"The transformed array is in shape [Time-Step, Channel, Height, Width] --> {sample_data.shape}\")" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [], - "source": [ - "snn_train_dataloader = DataLoader(snn_train_dataset, batch_size=batch_size, num_workers=num_workers, drop_last=True, shuffle=True)\n", - "snn_test_dataloader = DataLoader(snn_test_dataset, batch_size=batch_size, num_workers=num_workers, drop_last=True, shuffle=False)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Network Module\n", - "\n", - "We need to define a `nn.Module` implementing the network we want the chip to reproduce." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "device: NVIDIA RTX A4000\n" - ] - } - ], - "source": [ - "if torch.cuda.is_available():\n", - " device = torch.device('cuda:0')\n", - " print('device: ', torch.cuda.get_device_name(0))\n", - "else:\n", - " device = torch.device('cpu')" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [], - "source": [ - "class SNN(nn.Module):\n", - " def __init__(self) -> None:\n", - " super().__init__()\n", - "\n", - " self.conv1 = nn.Conv2d(2, 10, 2, 1, bias=False)\n", - " self.iaf1 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - " self.pool1 = sl.SumPool2d(2,2)\n", - " self.pool1a = sl.SumPool2d(6,6)\n", - "\n", - " self.conv2 = nn.Conv2d(10, 10, 2, 1, bias=False)\n", - " self.iaf2 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - " self.pool2 = sl.SumPool2d(3,3)\n", - "\n", - " self.conv3 = nn.Conv2d(10, 10, 3, 1, bias=False)\n", - " self.iaf3 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - " self.pool3 = sl.SumPool2d(2,2)\n", - "\n", - " self.flat = nn.Flatten()\n", - "\n", - " self.fc1 = nn.Linear(810, 100, bias=False)\n", - " self.iaf4 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - "\n", - " self.fc2 = nn.Linear(100, 100, bias=False)\n", - " self.iaf5 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - "\n", - " self.fc3 = nn.Linear(100, 100, bias=False)\n", - " self.iaf6 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - "\n", - " self.fc4 = nn.Linear(100, 11, bias=False)\n", - " self.iaf7 = sl.IAFSqueeze(batch_size=batch_size, min_v_mem=-1.0, surrogate_grad_fn=PeriodicExponential())\n", - "\n", - " self.merge_fc = sl.Merge()\n", - " self.merge_conv = sl.Merge()\n", - "\n", - " def detach_neuron_states(self):\n", - " for name, layer in self.named_modules():\n", - " if name != '':\n", - " if isinstance(layer, sl.StatefulLayer):\n", - " for name, buffer in layer.named_buffers():\n", - " buffer.detach_()\n", - "\n", - " def init_weights(self):\n", - " for name, layer in self.named_modules():\n", - " if isinstance(layer, nn.Conv2d) or isinstance(layer, nn.Linear):\n", - " nn.init.xavier_normal_(layer.weight.data)\n", - "\n", - " def forward(self, x):\n", - " \n", - " con1_out = self.conv1(x)\n", - " iaf1_out = self.iaf1(con1_out)\n", - " pool1_out = self.pool1(iaf1_out)\n", - " pool1a_out = self.pool1a(iaf1_out)\n", - "\n", - " conv2_out = self.conv2(pool1_out)\n", - " iaf2_out = self.iaf2(conv2_out)\n", - " pool2_out = self.pool2(iaf2_out)\n", - "\n", - " merged_conv_out = self.merge_conv(pool1a_out, pool2_out)\n", - "\n", - " conv3_out = self.conv3(merged_conv_out)\n", - " iaf3_out = self.iaf3(conv3_out)\n", - " pool3_out = self.pool3(iaf3_out)\n", - "\n", - " flat_out = self.flat(pool3_out)\n", - " \n", - " fc1_out = self.fc1(flat_out)\n", - " iaf4_out = self.iaf4(fc1_out)\n", - "\n", - " fc2_out = self.fc2(iaf4_out)\n", - " iaf5_out = self.iaf5(fc2_out)\n", - "\n", - " fc3_out = self.fc3(iaf5_out)\n", - " iaf6_out = self.iaf6(fc3_out)\n", - "\n", - " merge_fc_out = self.merge_fc(iaf4_out, iaf6_out)\n", - "\n", - " fc4_out = self.fc4(merge_fc_out)\n", - " iaf7_out = self.iaf7(fc4_out)\n", - "\n", - " return iaf7_out" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [], - "source": [ - "snn = SNN().to(device)" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [], - "source": [ - "snn.init_weights()" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [], - "source": [ - "optimizer = Adam(snn.parameters(), lr=lr, betas=(0.9, 0.999), eps=1e-8)\n", - "loss_fn = CrossEntropyLoss()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Define train and test" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [], - "source": [ - "def train(dataloader, model, loss_fn, optimizer, epochs, test_func, dataloader_test):\n", - " epochs_y = []\n", - " epochs_x = []\n", - " epochs_acc = []\n", - " model.train()\n", - "\n", - " for e in range(epochs):\n", - " losses = []\n", - " batches = []\n", - " batch_count = 0\n", - " train_p_bar = tqdm(snn_train_dataloader)\n", - "\n", - " for X, y in train_p_bar:\n", - " # reshape the input from [Batch, Time, Channel, Height, Width] into [Batch*Time, Channel, Height, Width]\n", - " X = X.reshape(-1, 2, 128, 128).to(dtype=torch.float, device=device)\n", - " y = y.to(dtype=torch.long, device=device)\n", - "\n", - " # forward\n", - " pred = model(X)\n", - "\n", - " # reshape the output from [Batch*Time,num_classes] into [Batch, Time, num_classes]\n", - " pred = pred.reshape(batch_size, n_time_steps, -1)\n", - "\n", - " # accumulate all time-steps output for final prediction\n", - " pred = pred.sum(dim = 1)\n", - " loss = loss_fn(pred, y)\n", - "\n", - " # gradient update\n", - " optimizer.zero_grad()\n", - " loss.backward()\n", - " optimizer.step()\n", - "\n", - " # detach the neuron states and activations from current computation graph(necessary)\n", - " model.detach_neuron_states()\n", - "\n", - " train_p_bar.set_description(f\"Epoch {e} - BPTT Training Loss: {round(loss.item(), 4)}\")\n", - "\n", - " batch_count += 1\n", - " losses.append(loss.item())\n", - " batches.append(batch_count)\n", - "\n", - " epochs_y.append(losses)\n", - " epochs_x.append(batches)\n", - "\n", - " acc = test_func(dataloader_test, model)\n", - " print(f'Epoch {e} accuracy: {acc}')\n", - " epochs_acc.append(acc)\n", - "\n", - " return epochs_x, epochs_y, epochs_acc\n" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [], - "source": [ - "def test(dataloader, model):\n", - " correct_predictions = []\n", - " with torch.no_grad():\n", - " test_p_bar = tqdm(dataloader)\n", - " for X, y in test_p_bar:\n", - " # reshape the input from [Batch, Time, Channel, Height, Width] into [Batch*Time, Channel, Height, Width]\n", - " X = X.reshape(-1, 2, 128, 128).to(dtype=torch.float, device=device)\n", - " y = y.to(dtype=torch.long, device=device)\n", - "\n", - " # forward\n", - " output = model(X)\n", - "\n", - " # reshape the output from [Batch*Time,num_classes] into [Batch, Time, num_classes]\n", - " output = output.reshape(batch_size, n_time_steps, -1)\n", - "\n", - " # accumulate all time-steps output for final prediction\n", - " output = output.sum(dim=1)\n", - "\n", - " # calculate accuracy\n", - " pred = output.argmax(dim=1, keepdim=True)\n", - "\n", - " # compute the total correct predictions\n", - " correct_predictions.append(pred.eq(y.view_as(pred)))\n", - "\n", - " test_p_bar.set_description(f\"Testing Model...\")\n", - " \n", - " correct_predictions = torch.cat(correct_predictions)\n", - " return correct_predictions.sum().item()/(len(correct_predictions))*100" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Training loop (HPO)" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "12d134e3b89e41888c9c47892b8e6491", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - " 0%| | 0/359 [00:00" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "y_avg = []\n", - "for y in epochs_y:\n", - " y_avg.append(np.mean(y))\n", - "\n", - "plt.plot(np.arange(len(epochs_x)), y_avg, marker = '.')\n", - "plt.xlabel('epoch')\n", - "plt.ylabel('average loss')\n", - "plt.ylim(0,)\n", - "plt.xticks(np.arange(len(epochs_x)))\n", - "for i, txt in enumerate(y_avg):\n", - " if i%5 == 0:\n", - " plt.text(i, txt, f'{txt:.2f}', ha='center', va='bottom', color = 'k')\n", - " else:\n", - " pass\n", - "plt.show()" - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjsAAAG2CAYAAACZEEfAAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8fJSN1AAAACXBIWXMAAA9hAAAPYQGoP6dpAABq60lEQVR4nO3dd1hT1+MG8DfsHUW2TAfixK3gqqO46q6jtVWr1bZi62idraPVFrWt7dfROn5urauOOloXrqqooOBEBERBZYhI2DPn9weaGlmJBIH4fp4nT8vNPfecQMx9c+6550iEEAJEREREWkqnohtAREREVJ4YdoiIiEirMewQERGRVmPYISIiIq3GsENERERajWGHiIiItBrDDhEREWk1hh0iIiLSagw7REREpNUYdoiIiEirVWjYOXPmDPr06QMHBwdIJBLs27dP6XkhBObMmQN7e3sYGxujW7duCA8PV9onKSkJw4cPh4WFBapVq4YxY8YgLS3tNb4KIiIiqswqNOykp6fD09MTK1asKPL5xYsXY+nSpVi5ciUuXrwIU1NTdO/eHVlZWYp9hg8fjps3b+LYsWM4ePAgzpw5g3Hjxr2ul0BERESVnKSyLAQqkUiwd+9e9O/fH0BBr46DgwO+/PJLfPXVVwAAmUwGW1tbbNiwAcOGDUNoaCgaNGiAwMBAtGzZEgBw+PBh9OrVCw8ePICDg0NFvRwiIiKqJPQqugHFiYqKQlxcHLp166bYJpVK0aZNGwQEBGDYsGEICAhAtWrVFEEHALp16wYdHR1cvHgRAwYMKPLY2dnZyM7OVvwsl8uRlJSEGjVqQCKRlN+LIiIiIo0RQiA1NRUODg7Q0Sn+YlWlDTtxcXEAAFtbW6Xttra2iufi4uJgY2Oj9Lyenh4sLS0V+xTFz88P3377rYZbTERERBUhJiYGjo6OxT5facNOeZo5cyamTJmi+Fkmk8HZ2RkxMTGwsLCowJYRERGRqlJSUuDk5ARzc/MS96u0YcfOzg4AEB8fD3t7e8X2+Ph4NG3aVLFPQkKCUrm8vDwkJSUpyhfF0NAQhoaGhbZbWFgw7BAREVUxpQ1BqbTz7Li5ucHOzg7+/v6KbSkpKbh48SK8vLwAAF5eXkhOTsbly5cV+5w4cQJyuRxt2rR57W0mIiKiyqdCe3bS0tIQERGh+DkqKgohISGwtLSEs7MzJk2ahAULFqBu3bpwc3PD7Nmz4eDgoLhjq379+ujRowfGjh2LlStXIjc3FxMmTMCwYcN4JxYREREBqOCwExQUhM6dOyt+fj6OZuTIkdiwYQOmTZuG9PR0jBs3DsnJyWjfvj0OHz4MIyMjRZmtW7diwoQJ6Nq1K3R0dDBo0CAsXbr0tb8WIiIiqpwqzTw7FSklJQVSqRQymYxjdoiIiKoIVc/flXbMDhEREZEmMOwQERGRVmPYISIiIq3GsENERERajWGHiIiItBrDDhEREWk1hh0iIiLSagw7REREpNUYdoiIiEirMewQERGRVmPYISIiIq3GsENERERajWGHiIiItBrDDhEREWk1hh0iIiLSagw7REREpNUYdoiIiEirMewQERGRVmPYISIiIq3GsENERERajWGHiIiItBrDDhEREWk1hh0iIiLSagw7REREpNUYdoiIiEirMewQERGRVmPYISIiIq3GsENERERajWGHiIiItBrDDhEREWk1hh0iIiLSagw7REREpNUYdoiIiEqQn5+P2bNnw83NDcbGxqhduzbmz58PIYRin1GjRkEikSg9evToUeJxU1NTMWnSJLi4uMDY2Bje3t4IDAxU2ictLQ0TJkyAo6MjjI2N0aBBA6xcubJcXqc206voBhAREVVmixYtwu+//46NGzeiYcOGCAoKwkcffQSpVIovvvhCsV+PHj2wfv16xc+GhoYlHvfjjz/GjRs3sHnzZjg4OGDLli3o1q0bbt26hZo1awIApkyZghMnTmDLli1wdXXF0aNHMX78eDg4OKBv377l84K1EHt2iIiISnD+/Hn069cPvXv3hqurK9599134+Pjg0qVLSvsZGhrCzs5O8ahevXqxx8zMzMTu3buxePFidOzYEXXq1MG8efNQp04d/P7770p1jxw5Em+99RZcXV0xbtw4eHp6FqqbSsawQ0T0hiivyzF+fn5o1aoVzM3NYWNjg/79+yMsLExpn08++QS1a9eGsbExalhZo0O3njgTGFIeL1PjvL294e/vjzt37gAArl69irNnz6Jnz55K+506dQo2NjaoV68ePvvsMzx58qTYY+bl5SE/Px9GRkZK242NjXH27Fmluvfv34+HDx9CCIGTJ0/izp078PHx0eArfAMIEjKZTAAQMpmsoptCRFRuvv/+e1GjRg1x8OBBERUVJXbt2iXMzMzE//73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DBTPGRgYwNPTE1999ZXmW0hERERUBiqHnZMnTwIouPX7f//7H8e2EBERUZWg9t1Y69evL492EBEREZULtQcoExEREVUlDDtERESk1Rh2iIiISKsx7BAREZFWY9ghIiIircawQ0RERFqNYYeIiIi0GsMOERERaTWGHSIiItJqDDtERESk1Rh2iIiISKsx7BAREZFWY9ghIiIircawQ0RERFqNYYeIiIi0GsMOERERaTWGHSIiItJqDDtERESk1Rh2iIiISKsx7BAREZFWY9ghIiIircawQ0RERFqNYYeIiIi0GsMOERERaTWGHSIiItJqDDtERESk1Rh2iIiISKsx7BAREZFWY9ghIiIircawQ0RERFqNYYeIiIi0GsMOERERaTWGHSIiItJqDDtERESk1Rh2iIiISKsx7BAREZFWY9ghIiIircawQ0RERFqNYYeIiIi0GsMOERERaTWGHSIiItJqDDtERESk1Rh2iIiISKsx7BAREZFWY9ghIiIircawQ0RERFqNYYeIiIi0GsMOERERaTWGHSIiItJqDDtERESk1Rh2iIiISKsx7BAREZFWY9ghIiIircawQ0RERFqNYYeIiIi0GsMOERERaTWGHSIiItJqDDtERESk1Sp12PHz80OrVq1gbm4OGxsb9O/fH2FhYUr7ZGVlwdfXFzVq1ICZmRkGDRqE+Pj4CmoxERERVTaVOuycPn0avr6+uHDhAo4dO4bc3Fz4+PggPT1dsc/kyZNx4MAB7Nq1C6dPn8ajR48wcODACmw1ERERVSYSIYSo6Eao6vHjx7CxscHp06fRsWNHyGQyWFtb448//sC7774LALh9+zbq16+PgIAAtG3bVqXjpqSkQCqVQiaTwcLCojxfAhEREWmIqufvSt2z8zKZTAYAsLS0BABcvnwZubm56Natm2IfDw8PODs7IyAgoNjjZGdnIyUlRelBRERE2qnKhB25XI5JkyahXbt2aNSoEQAgLi4OBgYGqFatmtK+tra2iIuLK/ZYfn5+kEqlioeTk1N5Np2IiIgqUJUJO76+vrhx4wa2b99e5mPNnDkTMplM8YiJidFAC4mIiKgy0qvoBqhiwoQJOHjwIM6cOQNHR0fFdjs7O+Tk5CA5OVmpdyc+Ph52dnbFHs/Q0BCGhobl2WQiIiKqJCp1z44QAhMmTMDevXtx4sQJuLm5KT3fokUL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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "plt.plot(np.arange(len(epochs_x)), epochs_acc, marker = '.')\n", - "plt.xlabel('epoch')\n", - "plt.ylabel('test accuracy')\n", - "plt.ylim(0, 100)\n", - "plt.xticks(np.arange(len(epochs_x)))\n", - "for i, txt in enumerate(epochs_acc):\n", - " if i%5 == 0:\n", - " plt.text(i, txt, f'{txt:.2f}', ha='center', va='bottom', color = 'k')\n", - " else:\n", - " pass\n", - "plt.show()" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "speck-rescnn", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.3" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/tests/test_nonsequential/using_SumPool2d/TOP_2_ARCHITECTURES/single_training.ipynb b/tests/test_nonsequential/using_SumPool2d/TOP_2_ARCHITECTURES/single_training.ipynb deleted file mode 100644 index 30637cad..00000000 --- a/tests/test_nonsequential/using_SumPool2d/TOP_2_ARCHITECTURES/single_training.ipynb +++ /dev/null @@ -1,3837 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "import torch, random, sys\n", - "\n", - "import tonic\n", - "from torch.utils.data import DataLoader\n", - "from torch.nn import CrossEntropyLoss\n", - "from torch.optim import Adam\n", - "\n", - "from sinabs.activation.surrogate_gradient_fn import PeriodicExponential\n", - "\n", - "import matplotlib.pyplot as plt\n", - "import numpy as np\n", - "\n", - "sys.path.append('../../utils')\n", - "sys.path.append('../models')\n", - "\n", - "from train_test_fn import training_loop, load_dataset, load_architecture\n", - "from weight_initialization import rescale_method_1" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": { - "metadata": {} - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "device: NVIDIA GeForce RTX 3070 Ti\n" - ] - } - ], - "source": [ - "if torch.cuda.is_available():\n", - " device = torch.device('cuda:0')\n", - " print('device: ', torch.cuda.get_device_name(0))\n", - "else:\n", - " device = torch.device('cpu')" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "rand_seed = 1" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "achitecture = 'ResSCNN_5'" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "torch.backends.cudnn.enabled = False\n", - "torch.backends.cudnn.deterministic = True\n", - "random.seed(rand_seed)\n", - "torch.manual_seed(rand_seed)\n", - "torch.cuda.manual_seed(rand_seed)\n", - "np.random.seed(rand_seed)" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], - "source": [ - "batch_size = 8\n", - "num_workers = 4\n", - "epochs = 50\n", - "n_time_steps = 50\n", - "\n", - "lr = 5e-5\n", - "spk_thr = 2.0\n", - "v_min = -0.5\n", - "grad_scale = 1.75\n", - "grad_width = 0.5\n", - "w_rescale_lambda = 0.6" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Loading Data" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [], - "source": [ - "snn_train_dataset, snn_test_dataset, sensor_size = load_dataset('DVSGESTURE', n_time_steps)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "getting validation dataset...." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "disk caching samples..." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": { - "metadata": {} - }, - "outputs": [], - "source": [ - "disk_cache_train = tonic.DiskCachedDataset(\n", - " dataset=snn_train_dataset,\n", - " cache_path='./cached_train'\n", - ")\n", - "snn_train_dataloader = DataLoader(disk_cache_train, batch_size=batch_size, num_workers=num_workers, drop_last=True, shuffle=True)\n", - "\n", - "disk_cache_test = tonic.DiskCachedDataset(\n", - " dataset=snn_test_dataset,\n", - " cache_path='./cached_test'\n", - ")\n", - "snn_test_dataloader = DataLoader(disk_cache_test, batch_size=batch_size, num_workers=num_workers, drop_last=True, shuffle=False)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Network Module" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": { - "metadata": {} - }, - "outputs": [ - { - "ename": "ModuleNotFoundError", - "evalue": "No module named 'sinabs.exodus'", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mModuleNotFoundError\u001b[0m Traceback (most recent call last)", - "Cell \u001b[0;32mIn[9], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m snn \u001b[38;5;241m=\u001b[39m \u001b[43mload_architecture\u001b[49m\u001b[43m(\u001b[49m\u001b[43machitecture\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43msensor_size\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m11\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mbatch_size\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mPeriodicExponential\u001b[49m\u001b[43m(\u001b[49m\u001b[43mgrad_scale\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mgrad_scale\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mgrad_width\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mgrad_width\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mv_min\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mspk_thr\u001b[49m\u001b[43m)\u001b[49m\u001b[38;5;241m.\u001b[39mto(device)\n\u001b[1;32m 2\u001b[0m snn\u001b[38;5;241m.\u001b[39minit_weights()\n", - "File \u001b[0;32m~/Documents/github/sinabs/tests/test_nonsequential/using_SumPool2d/TOP_2_ARCHITECTURES/../../utils/train_test_fn.py:281\u001b[0m, in \u001b[0;36mload_architecture\u001b[0;34m(architecture, input_size, nb_classes, batch_size, surrogate_fn, min_v_mem, spk_thr)\u001b[0m\n\u001b[1;32m 279\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m SCNN(input_size, nb_classes, batch_size, surrogate_fn, min_v_mem, spk_thr)\n\u001b[1;32m 280\u001b[0m \u001b[38;5;28;01melif\u001b[39;00m architecture \u001b[38;5;241m==\u001b[39m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mResSCNN_5\u001b[39m\u001b[38;5;124m'\u001b[39m:\n\u001b[0;32m--> 281\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mResSCNN_5\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m SCNN\n\u001b[1;32m 282\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m SCNN(input_size, nb_classes, batch_size, surrogate_fn, min_v_mem, spk_thr)\n\u001b[1;32m 283\u001b[0m \u001b[38;5;28;01melif\u001b[39;00m architecture \u001b[38;5;241m==\u001b[39m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mResSCNN_6\u001b[39m\u001b[38;5;124m'\u001b[39m:\n", - "File \u001b[0;32m~/Documents/github/sinabs/tests/test_nonsequential/using_SumPool2d/TOP_2_ARCHITECTURES/../models/ResSCNN_5.py:3\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mtorch\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mnn\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m \u001b[38;5;21;01mnn\u001b[39;00m\n\u001b[1;32m 2\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01msinabs\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mlayers\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m \u001b[38;5;21;01msl\u001b[39;00m\n\u001b[0;32m----> 3\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01msinabs\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mexodus\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mlayers\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m IAFSqueeze\n\u001b[1;32m 5\u001b[0m \u001b[38;5;28;01mclass\u001b[39;00m \u001b[38;5;21;01mSCNN\u001b[39;00m(nn\u001b[38;5;241m.\u001b[39mModule):\n\u001b[1;32m 6\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m__init__\u001b[39m(\u001b[38;5;28mself\u001b[39m, input_size, nb_classes, batch_size, surrogate_fn, min_v_mem\u001b[38;5;241m=\u001b[39m\u001b[38;5;241m-\u001b[39m\u001b[38;5;241m0.313\u001b[39m, spk_thr\u001b[38;5;241m=\u001b[39m\u001b[38;5;241m2.0\u001b[39m) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m:\n", - "\u001b[0;31mModuleNotFoundError\u001b[0m: No module named 'sinabs.exodus'" - ] - } - ], - "source": [ - "snn = load_architecture(achitecture, sensor_size, 11, batch_size, PeriodicExponential(grad_scale=grad_scale, grad_width=grad_width), v_min, spk_thr).to(device)\n", - "snn.init_weights()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "metadata": {} - }, - "outputs": [], - "source": [ - "snn.rescale_conv_weights(rescale_method_1, w_rescale_lambda)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "metadata": {} - }, - "outputs": [], - "source": [ - "optimizer = Adam(snn.parameters(), lr=lr, betas=(0.9, 0.999), eps=1e-8)\n", - "loss_fn = CrossEntropyLoss()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Training loop" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "metadata": {} - }, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "87b59082674c47e5a466ddd2ca5097ba", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - " 0%| | 0/134 [00:00" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "y_avg = []\n", - "for y in epochs_y:\n", - " y_avg.append(np.mean(y))\n", - "\n", - "plt.plot(np.arange(len(epochs_x)), y_avg, marker = '.')\n", - "plt.xlabel('epoch')\n", - "plt.ylabel('average loss')\n", - "plt.ylim(0,)\n", - "plt.xticks(np.arange(len(epochs_x)))\n", - "for i, txt in enumerate(y_avg):\n", - " plt.text(i, txt, f'{txt:.2f}', ha='center', va='bottom', color = 'k')\n", - "plt.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "metadata": {} - }, - "outputs": [ - { - "data": { - "image/png": "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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "plt.plot(np.arange(len(epochs_x)), epochs_acc, marker = '.')\n", - "plt.xlabel('epoch')\n", - "plt.ylabel('test accuracy')\n", - "plt.ylim(0, 100)\n", - "plt.xticks(np.arange(len(epochs_x)))\n", - "for i, txt in enumerate(epochs_acc):\n", - " if i%5 ==0 or i == epochs-1:\n", - " plt.text(i, txt, f'{txt:.2f}', ha='center', va='bottom', color = 'k')\n", - "plt.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "metadata": {} - }, - "outputs": [], - "source": [ - "# with open(f'{achitecture}-Training_Test-TM.npy', 'wb') as f:\n", - "# np.save(f, np.array(epochs_x))\n", - "# np.save(f, np.array(epochs_y))\n", - "# np.save(f, np.array(epochs_acc))" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "speck-rescnn", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.10.0" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/tests/test_nonsequential/using_SumPool2d/models/ResSCNN_1.py b/tests/test_nonsequential/using_SumPool2d/models/ResSCNN_1.py deleted file mode 100644 index b8f5b838..00000000 --- a/tests/test_nonsequential/using_SumPool2d/models/ResSCNN_1.py +++ /dev/null @@ -1,152 +0,0 @@ -import torch.nn as nn -import sinabs.layers as sl -from sinabs.exodus.layers import IAFSqueeze - -class SCNN(nn.Module): - def __init__(self, input_size, nb_classes, batch_size, surrogate_fn, min_v_mem=-0.313, spk_thr=2.0) -> None: - super().__init__() - - self.conv1 = nn.Conv2d(2, 8, 2, 1, bias=False) - self.iaf1 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - self.pool1 = sl.SumPool2d(2,2) - self.pool1a = sl.SumPool2d(4,4) - - self.conv2 = nn.Conv2d(8, 8, 2, 1, bias=False) - self.iaf2 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - self.pool2 = sl.SumPool2d(2,2) - - self.conv3 = nn.Conv2d(8, 8, 2, 1, bias=False) - self.iaf3 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - self.pool3 = sl.SumPool2d(2,2) - - self.conv4 = nn.Conv2d(8, 8, 2, 1, bias=False) - self.iaf4 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - self.pool4 = sl.SumPool2d(2,2) - - self.flat = nn.Flatten() - - flat_s = SCNN.get_flatten_size(input_size) - - self.fc1 = nn.Linear(flat_s, 100, bias=False) - self.iaf1_fc = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - self.fc2 = nn.Linear(100, 100, bias=False) - self.iaf2_fc = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - self.fc3 = nn.Linear(100, 100, bias=False) - self.iaf3_fc = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - self.fc4 = nn.Linear(100, 100, bias=False) - self.iaf4_fc = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - self.fc5 = nn.Linear(100, nb_classes, bias=False) - self.iaf5_fc = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - # skip - - self.merge1 = sl.Merge() - - @staticmethod - def get_flatten_size(input_size): - conv1_dims = SCNN.conv2d_output_size(input_size, 8, (2, 2)) - pool1_dims = SCNN.pool_output_size(conv1_dims, 8, (2, 2)) - - conv2_dims = SCNN.conv2d_output_size(pool1_dims, 8, (2, 2)) - pool2_dims = SCNN.pool_output_size(conv2_dims, 8, (2, 2)) - - conv3_dims = SCNN.conv2d_output_size(pool2_dims, 8, (2, 2)) - pool3_dims = SCNN.pool_output_size(conv3_dims, 8, (2, 2)) - - conv4_dims = SCNN.conv2d_output_size(pool3_dims, 8, (2, 2)) - pool4_dims = SCNN.pool_output_size(conv4_dims, 8, (2, 2)) - - return pool4_dims[0]*pool4_dims[1]*pool4_dims[2] - - @staticmethod - def conv2d_output_size(input_size, out_channels, kernel_size, stride=1, padding=0, dilation=1): - input_height, input_width, input_channels = input_size - kernel_height, kernel_width = kernel_size - - output_height = ((input_height + 2 * padding - dilation * (kernel_height - 1) - 1) // stride) + 1 - output_width = ((input_width + 2 * padding - dilation * (kernel_width - 1) - 1) // stride) + 1 - - return (output_height, output_width, out_channels) - - @staticmethod - def pool_output_size(input_size, out_channels, kernel_size, stride=None, padding=0): - input_height, input_width, input_channels = input_size - kernel_height, kernel_width = kernel_size - - if stride is None: - stride = kernel_height - - output_height = ((input_height + 2 * padding - kernel_height) // stride) + 1 - output_width = ((input_width + 2 * padding - kernel_width) // stride) + 1 - - return (output_height, output_width, out_channels) - - def detach_neuron_states(self): - for name, layer in self.named_modules(): - if name != '': - if isinstance(layer, sl.StatefulLayer): - for name, buffer in layer.named_buffers(): - buffer.detach_() - - def init_weights(self): - for name, layer in self.named_modules(): - if isinstance(layer, nn.Conv2d) or isinstance(layer, nn.Linear): - nn.init.xavier_normal_(layer.weight.data) - - def rescale_conv_weights(self, rescale_fn, lambda_): - rescale_fn(self.conv2, [(2, 2)], lambda_) - rescale_fn(self.conv3, [(2, 2), (4, 4)], lambda_) - rescale_fn(self.conv4, [(2, 2)], lambda_) - - - def forward(self, x): - # conv 1 - con1_out = self.conv1(x) - iaf1_out = self.iaf1(con1_out) - pool1_out = self.pool1(iaf1_out) - pool1a_out = self.pool1a(iaf1_out) - - # conv 2 - conv2_out = self.conv2(pool1_out) - iaf2_out = self.iaf2(conv2_out) - pool2_out = self.pool2(iaf2_out) - - merge1_out = self.merge1(pool1a_out, pool2_out) - - # conv 3 - conv3_out = self.conv3(merge1_out) - iaf3_out = self.iaf3(conv3_out) - pool3_out = self.pool3(iaf3_out) - - # conv 4 - conv4_out = self.conv4(pool3_out) - iaf4_out = self.iaf4(conv4_out) - pool4_out = self.pool4(iaf4_out) - - flat_out = self.flat(pool4_out) - - # fc 1 - fc1_out = self.fc1(flat_out) - iaf1_fc_out = self.iaf1_fc(fc1_out) - - # fc 2 - fc2_out = self.fc2(iaf1_fc_out) - iaf2_fc_out = self.iaf2_fc(fc2_out) - - # fc 3 - fc3_out = self.fc3(iaf2_fc_out) - iaf3_fc_out = self.iaf3_fc(fc3_out) - - # fc 4 - fc4_out = self.fc4(iaf3_fc_out) - iaf4_fc_out = self.iaf4_fc(fc4_out) - - # fc 5 - fc5_out = self.fc5(iaf4_fc_out) - iaf5_fc_out = self.iaf5_fc(fc5_out) - - return iaf5_fc_out \ No newline at end of file diff --git a/tests/test_nonsequential/using_SumPool2d/models/ResSCNN_10.py b/tests/test_nonsequential/using_SumPool2d/models/ResSCNN_10.py deleted file mode 100644 index 9e631bd4..00000000 --- a/tests/test_nonsequential/using_SumPool2d/models/ResSCNN_10.py +++ /dev/null @@ -1,121 +0,0 @@ -import torch.nn as nn -import sinabs.layers as sl -from sinabs.exodus.layers import IAFSqueeze - -class SCNN(nn.Module): - def __init__(self, input_size, nb_classes, batch_size, surrogate_fn, min_v_mem=-0.313, spk_thr=2.0) -> None: - super().__init__() - - self.conv1 = nn.Conv2d(2, 8, 2, 1, bias=False) - self.iaf1 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - self.conv2 = nn.Conv2d(8, 8, 3, 1, 1, bias=False) - self.iaf2 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - self.pool2a = sl.SumPool2d(2,2) - - self.conv3 = nn.Conv2d(8, 8, 3, 1, 1, bias=False) - self.iaf3 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - self.pool3a = sl.SumPool2d(4,4) - - self.conv4 = nn.Conv2d(8, 8, 2, 1, bias=False) - self.iaf4 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - self.pool4 = sl.SumPool2d(2,2) - self.pool4a = sl.SumPool2d(4,4) - - self.conv5 = nn.Conv2d(8, 8, 2, 1, bias=False) - self.iaf5 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - self.pool5 = sl.SumPool2d(2,2) - self.pool5a = sl.SumPool2d(4,4) - - self.conv6 = nn.Conv2d(8, 8, 3, 1, 1, bias=False) - self.iaf6 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - self.conv7 = nn.Conv2d(8, 8, 2, 1, bias=False) - self.iaf7 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - self.pool7 = sl.SumPool2d(2,2) - - self.conv8 = nn.Conv2d(8, 8, 2, 1, bias=False) - self.iaf8 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - self.pool8 = sl.SumPool2d(2,2) - - self.flat = nn.Flatten() - - self.fc_out = nn.Linear(392, nb_classes, bias=False) - self.iaf_fc_out = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - # skip - - self.merge1 = sl.Merge() - self.merge2 = sl.Merge() - self.merge3 = sl.Merge() - self.merge4 = sl.Merge() - self.merge5 = sl.Merge() - - def detach_neuron_states(self): - for name, layer in self.named_modules(): - if name != '': - if isinstance(layer, sl.StatefulLayer): - for name, buffer in layer.named_buffers(): - buffer.detach_() - - def init_weights(self): - for name, layer in self.named_modules(): - if isinstance(layer, nn.Conv2d) or isinstance(layer, nn.Linear): - nn.init.xavier_normal_(layer.weight.data) - - def rescale_conv_weights(self, rescale_fn, lambda_): - rescale_fn(self.conv5, [(2,2), (2,2)], lambda_) - rescale_fn(self.conv6, [(4,4), (2,2)], lambda_) - rescale_fn(self.conv7, [(4,4)], lambda_) - rescale_fn(self.conv8, [(4,4), (2,2)], lambda_) - - def forward(self, x): - # -- conv block 1 --- - con1_out = self.conv1(x) - iaf1_out = self.iaf1(con1_out) # to CONV 4 - # -- conv block 2 --- - conv2_out = self.conv2(iaf1_out) - iaf2_out = self.iaf2(conv2_out) - pool2a_out = self.pool2a(iaf2_out) # to CONV 5 - # -- conv block 3 --- - conv3_out = self.conv3(iaf2_out) - iaf3_out = self.iaf3(conv3_out) - pool3a_out = self.pool3a(iaf3_out) # to CONV 6 - # -- conv block 4 --- - #print(iaf1_out.shape, iaf3_out.shape) - merge1_out = self.merge1(iaf1_out, iaf3_out) - conv4_out = self.conv4(merge1_out) - iaf4_out = self.iaf4(conv4_out) - pool4_out = self.pool4(iaf4_out) - pool4a_out = self.pool4a(iaf4_out) # to CONV 7 - # -- conv block 5 --- - #print(pool2a_out.shape, pool4_out.shape) - merge2_out = self.merge2(pool2a_out, pool4_out) - conv5_out = self.conv5(merge2_out) - iaf5_out = self.iaf5(conv5_out) - pool5_out = self.pool5(iaf5_out) - pool5a_out = self.pool5a(iaf5_out) # to CONV 8 - # -- conv block 6 --- - #print(pool3a_out.shape, pool5_out.shape) - merge3_out = self.merge3(pool3a_out, pool5_out) - conv6_out = self.conv6(merge3_out) - iaf6_out = self.iaf6(conv6_out) - # -- conv block 7 --- - #print(pool4a_out.shape, iaf6_out.shape) - merge4_out = self.merge4(pool4a_out, iaf6_out) - conv7_out = self.conv7(merge4_out) - iaf7_out = self.iaf7(conv7_out) - pool7_out = self.pool7(iaf7_out) - # -- conv block 8 --- - #print(pool5a_out.shape, pool7_out.shape) - merge5_out = self.merge5(pool5a_out, pool7_out) - conv8_out = self.conv8(merge5_out) - iaf8_out = self.iaf8(conv8_out) - pool8_out = self.pool8(iaf8_out) - # -- output -- - flat = self.flat(pool8_out) - #print(flat.shape) - fc_out = self.fc_out(flat) - iaf_fc_out = self.iaf_fc_out(fc_out) - - return iaf_fc_out \ No newline at end of file diff --git a/tests/test_nonsequential/using_SumPool2d/models/ResSCNN_11.py b/tests/test_nonsequential/using_SumPool2d/models/ResSCNN_11.py deleted file mode 100644 index 209f00bd..00000000 --- a/tests/test_nonsequential/using_SumPool2d/models/ResSCNN_11.py +++ /dev/null @@ -1,112 +0,0 @@ -import torch.nn as nn -import sinabs.layers as sl -from sinabs.exodus.layers import IAFSqueeze - -class SCNN(nn.Module): - def __init__(self, input_size, nb_classes, batch_size, surrogate_fn, min_v_mem=-0.313, spk_thr=2.0) -> None: - super().__init__() - - self.conv1 = nn.Conv2d(2, 8, 2, 1, bias=False) - self.iaf1 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - self.conv2 = nn.Conv2d(8, 8, 3, 1, 1, bias=False) - self.iaf2 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - self.conv3 = nn.Conv2d(8, 8, 3, 1, 1, bias=False) - self.iaf3 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - self.pool3a = sl.SumPool2d(4,4) - - self.conv4 = nn.Conv2d(8, 8, 2, 1, bias=False) - self.iaf4 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - self.pool4 = sl.SumPool2d(2,2) - - self.conv5 = nn.Conv2d(8, 8, 2, 1, bias=False) - self.iaf5 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - self.pool5 = sl.SumPool2d(2,2) - self.pool5a = sl.SumPool2d(4,4) - - self.conv6 = nn.Conv2d(8, 8, 3, 1, 1, bias=False) - self.iaf6 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - self.conv7 = nn.Conv2d(8, 8, 2, 1, bias=False) - self.iaf7 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - self.pool7 = sl.SumPool2d(2,2) - - self.conv8 = nn.Conv2d(8, 8, 2, 1, bias=False) - self.iaf8 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - self.pool8 = sl.SumPool2d(2,2) - - self.flat = nn.Flatten() - - self.fc_out = nn.Linear(392, nb_classes, bias=False) - self.iaf_fc_out = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - # skip - - self.merge1 = sl.Merge() - self.merge2 = sl.Merge() - self.merge3 = sl.Merge() - self.merge4 = sl.Merge() - - def detach_neuron_states(self): - for name, layer in self.named_modules(): - if name != '': - if isinstance(layer, sl.StatefulLayer): - for name, buffer in layer.named_buffers(): - buffer.detach_() - - def init_weights(self): - for name, layer in self.named_modules(): - if isinstance(layer, nn.Conv2d) or isinstance(layer, nn.Linear): - nn.init.xavier_normal_(layer.weight.data) - - def rescale_conv_weights(self, rescale_fn, lambda_): - rescale_fn(self.conv5, [(2,2)], lambda_) - rescale_fn(self.conv6, [(4,4), (2,2)], lambda_) - rescale_fn(self.conv8, [(4,4), (2,2)], lambda_) - - def forward(self, x): - # -- conv block 1 --- - con1_out = self.conv1(x) - iaf1_out = self.iaf1(con1_out) # to CONV 4 - # -- conv block 2 --- - conv2_out = self.conv2(iaf1_out) - iaf2_out = self.iaf2(conv2_out) - # -- conv block 3 --- - conv3_out = self.conv3(iaf2_out) - iaf3_out = self.iaf3(conv3_out) - pool3a_out = self.pool3a(iaf3_out) # to CONV 6 - # -- conv block 4 --- - #print(iaf1_out.shape, iaf3_out.shape) - merge1_out = self.merge1(iaf1_out, iaf3_out) - conv4_out = self.conv4(merge1_out) - iaf4_out = self.iaf4(conv4_out) - pool4_out = self.pool4(iaf4_out) - # -- conv block 5 --- - conv5_out = self.conv5(pool4_out) - iaf5_out = self.iaf5(conv5_out) - pool5_out = self.pool5(iaf5_out) - pool5a_out = self.pool5a(iaf5_out) # to CONV 8 - # -- conv block 6 --- - #print(pool3a_out.shape, pool5_out.shape) - merge3_out = self.merge3(pool3a_out, pool5_out) - conv6_out = self.conv6(merge3_out) - iaf6_out = self.iaf6(conv6_out) - # -- conv block 7 --- - conv7_out = self.conv7(iaf6_out) - iaf7_out = self.iaf7(conv7_out) - pool7_out = self.pool7(iaf7_out) - # -- conv block 8 --- - #print(pool5a_out.shape, pool7_out.shape) - merge4_out = self.merge4(pool5a_out, pool7_out) - conv8_out = self.conv8(merge4_out) - iaf8_out = self.iaf8(conv8_out) - pool8_out = self.pool8(iaf8_out) - # -- output -- - flat = self.flat(pool8_out) - #print(flat.shape) - fc_out = self.fc_out(flat) - iaf_fc_out = self.iaf_fc_out(fc_out) - - - return iaf_fc_out \ No newline at end of file diff --git a/tests/test_nonsequential/using_SumPool2d/models/ResSCNN_12.py b/tests/test_nonsequential/using_SumPool2d/models/ResSCNN_12.py deleted file mode 100644 index adfa33cd..00000000 --- a/tests/test_nonsequential/using_SumPool2d/models/ResSCNN_12.py +++ /dev/null @@ -1,91 +0,0 @@ -import torch.nn as nn -import sinabs.layers as sl -from sinabs.exodus.layers import IAFSqueeze - -class SCNN(nn.Module): - def __init__(self, input_size, nb_classes, batch_size, surrogate_fn, min_v_mem=-0.313, spk_thr=2.0) -> None: - super().__init__() - - self.conv1 = nn.Conv2d(2, 1, 3, 1, bias=False) - self.iaf1 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - self.pool1 = sl.SumPool2d(3,3) - - self.conv2 = nn.Conv2d(1, 8, 3, 1, bias=False) - self.iaf2 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - self.pool2 = sl.SumPool2d(3,3) - - self.conv3 = nn.Conv2d(8, 16, 3, 1, bias=False) - self.iaf3 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - self.pool3 = sl.SumPool2d(3,3) - - self.conv4 = nn.Conv2d(16, 32, 3, 1, bias=False) - self.iaf4 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - self.flat = nn.Flatten() - - self.fc1 = nn.Linear(32, 1024, bias=False) - self.iaf1_fc = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - self.fc2 = nn.Linear(1024, 512, bias=False) - self.iaf2_fc = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - self.fc3 = nn.Linear(512, 256, bias=False) - self.iaf3_fc = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - self.fc4 = nn.Linear(256, 128, bias=False) - self.iaf4_fc = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - self.fc5 = nn.Linear(128, nb_classes, bias=False) - self.iaf5_fc = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - def detach_neuron_states(self): - for name, layer in self.named_modules(): - if name != '': - if isinstance(layer, sl.StatefulLayer): - for name, buffer in layer.named_buffers(): - buffer.detach_() - - def init_weights(self): - for name, layer in self.named_modules(): - if isinstance(layer, nn.Conv2d) or isinstance(layer, nn.Linear): - nn.init.xavier_normal_(layer.weight.data) - - def rescale_conv_weights(self, rescale_fn, lambda_): - rescale_fn(self.conv2, [(3, 3)], lambda_) - rescale_fn(self.conv3, [(3, 3)], lambda_) - rescale_fn(self.conv4, [(3, 3)], lambda_) - - def forward(self, x): - # conv 1 - con1_out = self.conv1(x) - iaf1_out = self.iaf1(con1_out) - pool1_out = self.pool1(iaf1_out) - # conv 2 - conv2_out = self.conv2(pool1_out) - iaf2_out = self.iaf2(conv2_out) - pool2_out = self.pool2(iaf2_out) - # conv 3 - conv3_out = self.conv3(pool2_out) - iaf3_out = self.iaf3(conv3_out) - pool3_out = self.pool3(iaf3_out) - # conv 4 - conv4_out = self.conv4(pool3_out) - iaf4_out = self.iaf4(conv4_out) - flat_out = self.flat(iaf4_out) - # fc 1 - fc1_out = self.fc1(flat_out) - iaf1_fc_out = self.iaf1_fc(fc1_out) - # fc 2 - fc2_out = self.fc2(iaf1_fc_out) - iaf2_fc_out = self.iaf2_fc(fc2_out) - # fc 3 - fc3_out = self.fc3(iaf2_fc_out) - iaf3_fc_out = self.iaf3_fc(fc3_out) - # fc 4 - fc4_out = self.fc4(iaf3_fc_out) - iaf4_fc_out = self.iaf4_fc(fc4_out) - # fc 5 - fc5_out = self.fc5(iaf4_fc_out) - iaf5_fc_out = self.iaf5_fc(fc5_out) - - return iaf5_fc_out \ No newline at end of file diff --git a/tests/test_nonsequential/using_SumPool2d/models/ResSCNN_13.py b/tests/test_nonsequential/using_SumPool2d/models/ResSCNN_13.py deleted file mode 100644 index 8e473dcd..00000000 --- a/tests/test_nonsequential/using_SumPool2d/models/ResSCNN_13.py +++ /dev/null @@ -1,96 +0,0 @@ -import torch.nn as nn -import sinabs.layers as sl -from sinabs.exodus.layers import IAFSqueeze - -class SCNN(nn.Module): - def __init__(self, nb_classes, batch_size, surrogate_fn, min_v_mem=-0.313, spk_thr=2.0) -> None: - super().__init__() - - self.conv1 = nn.Conv2d(2, 16, 3, 1, bias=False) - self.iaf1 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - self.pool1 = sl.SumPool2d(2,2) - - self.conv2 = nn.Conv2d(16, 16, 3, 1, bias=False) - self.iaf2 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - self.pool2 = sl.SumPool2d(2,2) - - self.conv3 = nn.Conv2d(16, 16, 3, 1, bias=False) - self.iaf3 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - self.pool3 = sl.SumPool2d(2,2) - - self.conv4 = nn.Conv2d(16, 16, 3, 1, bias=False) - self.iaf4 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - self.pool4 = sl.SumPool2d(2,2) - - self.conv5 = nn.Conv2d(16, 16, 3, 1, bias=False) - self.iaf5 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - self.pool5 = sl.SumPool2d(2,2) - - self.flat = nn.Flatten() - - self.fc1 = nn.Linear(64, 200, bias=False) - self.iaf1_fc = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - self.fc2 = nn.Linear(200, 200, bias=False) - self.iaf2_fc = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - self.fc3 = nn.Linear(200, 200, bias=False) - self.iaf3_fc = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - self.fc4 = nn.Linear(200, nb_classes, bias=False) - self.iaf4_fc = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - def detach_neuron_states(self): - for name, layer in self.named_modules(): - if name != '': - if isinstance(layer, sl.StatefulLayer): - for name, buffer in layer.named_buffers(): - buffer.detach_() - - def init_weights(self): - for name, layer in self.named_modules(): - if isinstance(layer, nn.Conv2d) or isinstance(layer, nn.Linear): - nn.init.xavier_normal_(layer.weight.data) - - def rescale_conv_weights(self, rescale_fn, lambda_): - rescale_fn(self.conv2, [(2, 2)], lambda_) - rescale_fn(self.conv3, [(2, 2)], lambda_) - rescale_fn(self.conv4, [(2, 2)], lambda_) - rescale_fn(self.conv5, [(2, 2)], lambda_) - - def forward(self, x): - # conv 1 - con1_out = self.conv1(x) - iaf1_out = self.iaf1(con1_out) - pool1_out = self.pool1(iaf1_out) - # conv 2 - conv2_out = self.conv2(pool1_out) - iaf2_out = self.iaf2(conv2_out) - pool2_out = self.pool2(iaf2_out) - # conv 3 - conv3_out = self.conv3(pool2_out) - iaf3_out = self.iaf3(conv3_out) - pool3_out = self.pool3(iaf3_out) - # conv 4 - conv4_out = self.conv4(pool3_out) - iaf4_out = self.iaf4(conv4_out) - pool4_out = self.pool4(iaf4_out) - # conv 5 - conv5_out = self.conv5(pool4_out) - iaf5_out = self.iaf5(conv5_out) - pool5_out = self.pool5(iaf5_out) - # fc 1 - flat_out = self.flat(pool5_out) - fc1_out = self.fc1(flat_out) - iaf1_fc_out = self.iaf1_fc(fc1_out) - # fc 2 - fc2_out = self.fc2(iaf1_fc_out) - iaf2_fc_out = self.iaf2_fc(fc2_out) - # fc 3 - fc3_out = self.fc3(iaf2_fc_out) - iaf3_fc_out = self.iaf3_fc(fc3_out) - # fc 4 - fc4_out = self.fc4(iaf3_fc_out) - iaf4_fc_out = self.iaf4_fc(fc4_out) - - return iaf4_fc_out \ No newline at end of file diff --git a/tests/test_nonsequential/using_SumPool2d/models/ResSCNN_2.py b/tests/test_nonsequential/using_SumPool2d/models/ResSCNN_2.py deleted file mode 100644 index bb9877df..00000000 --- a/tests/test_nonsequential/using_SumPool2d/models/ResSCNN_2.py +++ /dev/null @@ -1,148 +0,0 @@ -import torch.nn as nn -import sinabs.layers as sl -from sinabs.exodus.layers import IAFSqueeze - -class SCNN(nn.Module): - def __init__(self, input_size, nb_classes, batch_size, surrogate_fn, min_v_mem=-0.313, spk_thr=2.0) -> None: - super().__init__() - - self.conv1 = nn.Conv2d(2, 8, 2, 1, bias=False) - self.iaf1 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - self.pool1 = sl.SumPool2d(2,2) - self.pool1a = sl.SumPool2d(4,4) - - self.conv2 = nn.Conv2d(8, 8, 2, 1, bias=False) - self.iaf2 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - self.pool2 = sl.SumPool2d(2,2) - - self.conv3 = nn.Conv2d(8, 8, 2, 1, bias=False) - self.iaf3 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - self.pool3 = sl.SumPool2d(2,2) - self.pool3a = sl.SumPool2d(4,4) - - self.conv4 = nn.Conv2d(8, 8, 2, 1, bias=False) - self.iaf4 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - self.pool4 = sl.SumPool2d(2,2) - - self.flat = nn.Flatten() - - flat_s = SCNN.get_flatten_size(input_size) - - self.fc1 = nn.Linear(flat_s, 100, bias=False) - self.iaf1_fc = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - self.fc2 = nn.Linear(100, 100, bias=False) - self.iaf2_fc = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - self.fc3 = nn.Linear(100, 100, bias=False) - self.iaf3_fc = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - self.fc4 = nn.Linear(100, 100, bias=False) - self.iaf4_fc = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - self.fc5 = nn.Linear(100, nb_classes, bias=False) - self.iaf5_fc = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - # skip - - self.merge1 = sl.Merge() - self.merge2 = sl.Merge() - - @staticmethod - def get_flatten_size(input_size): - conv1_dims = SCNN.conv2d_output_size(input_size, 8, (2, 2)) - pool1_dims = SCNN.pool_output_size(conv1_dims, 8, (2, 2)) - - conv2_dims = SCNN.conv2d_output_size(pool1_dims, 8, (2, 2)) - pool2_dims = SCNN.pool_output_size(conv2_dims, 8, (2, 2)) - - conv3_dims = SCNN.conv2d_output_size(pool2_dims, 8, (2, 2)) - pool3_dims = SCNN.pool_output_size(conv3_dims, 8, (2, 2)) - - conv4_dims = SCNN.conv2d_output_size(pool3_dims, 8, (2, 2)) - pool4_dims = SCNN.pool_output_size(conv4_dims, 8, (2, 2)) - - return pool4_dims[0]*pool4_dims[1]*pool4_dims[2] - - @staticmethod - def conv2d_output_size(input_size, out_channels, kernel_size, stride=1, padding=0, dilation=1): - input_height, input_width, input_channels = input_size - kernel_height, kernel_width = kernel_size - - output_height = ((input_height + 2 * padding - dilation * (kernel_height - 1) - 1) // stride) + 1 - output_width = ((input_width + 2 * padding - dilation * (kernel_width - 1) - 1) // stride) + 1 - - return (output_height, output_width, out_channels) - - @staticmethod - def pool_output_size(input_size, out_channels, kernel_size, stride=None, padding=0): - input_height, input_width, input_channels = input_size - kernel_height, kernel_width = kernel_size - - if stride is None: - stride = kernel_height - - output_height = ((input_height + 2 * padding - kernel_height) // stride) + 1 - output_width = ((input_width + 2 * padding - kernel_width) // stride) + 1 - - return (output_height, output_width, out_channels) - - def detach_neuron_states(self): - for name, layer in self.named_modules(): - if name != '': - if isinstance(layer, sl.StatefulLayer): - for name, buffer in layer.named_buffers(): - buffer.detach_() - - def init_weights(self): - for name, layer in self.named_modules(): - if isinstance(layer, nn.Conv2d) or isinstance(layer, nn.Linear): - nn.init.xavier_normal_(layer.weight.data) - - def rescale_conv_weights(self, rescale_fn, lambda_): - rescale_fn(self.conv2, [(2,2)], lambda_) - rescale_fn(self.conv3, [(4,4), (2,2)], lambda_) - rescale_fn(self.conv4, [(2,2)], lambda_) - - def forward(self, x): - # conv 1 - con1_out = self.conv1(x) - iaf1_out = self.iaf1(con1_out) - pool1_out = self.pool1(iaf1_out) - pool1a_out = self.pool1a(iaf1_out) - # conv 2 - conv2_out = self.conv2(pool1_out) - iaf2_out = self.iaf2(conv2_out) - pool2_out = self.pool2(iaf2_out) - - merge1_out = self.merge1(pool1a_out, pool2_out) - # conv 3 - conv3_out = self.conv3(merge1_out) - iaf3_out = self.iaf3(conv3_out) - pool3_out = self.pool3(iaf3_out) - pool3a_out = self.pool3a(iaf3_out) - # conv 4 - conv4_out = self.conv4(pool3_out) - iaf4_out = self.iaf4(conv4_out) - pool4_out = self.pool4(iaf4_out) - - merge2_out = self.merge2(pool3a_out, pool4_out) - - flat_out = self.flat(merge2_out) - # fc 1 - fc1_out = self.fc1(flat_out) - iaf1_fc_out = self.iaf1_fc(fc1_out) - # fc 2 - fc2_out = self.fc2(iaf1_fc_out) - iaf2_fc_out = self.iaf2_fc(fc2_out) - # fc 3 - fc3_out = self.fc3(iaf2_fc_out) - iaf3_fc_out = self.iaf3_fc(fc3_out) - # fc 4 - fc4_out = self.fc4(iaf3_fc_out) - iaf4_fc_out = self.iaf4_fc(fc4_out) - # fc 5 - fc5_out = self.fc5(iaf4_fc_out) - iaf5_fc_out = self.iaf5_fc(fc5_out) - - return iaf5_fc_out \ No newline at end of file diff --git a/tests/test_nonsequential/using_SumPool2d/models/ResSCNN_3.py b/tests/test_nonsequential/using_SumPool2d/models/ResSCNN_3.py deleted file mode 100644 index 0975a51a..00000000 --- a/tests/test_nonsequential/using_SumPool2d/models/ResSCNN_3.py +++ /dev/null @@ -1,151 +0,0 @@ -import torch.nn as nn -import sinabs.layers as sl -from sinabs.exodus.layers import IAFSqueeze - -class SCNN(nn.Module): - def __init__(self, input_size, nb_classes, batch_size, surrogate_fn, min_v_mem=-0.313, spk_thr=2.0) -> None: - super().__init__() - - self.conv1 = nn.Conv2d(2, 8, 2, 1, bias=False) - self.iaf1 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - self.pool1 = sl.SumPool2d(2,2) - self.pool1a = sl.SumPool2d(4,4) - - self.conv2 = nn.Conv2d(8, 8, 2, 1, bias=False) - self.iaf2 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - self.pool2 = sl.SumPool2d(2,2) - - self.conv3 = nn.Conv2d(8, 8, 2, 1, bias=False) - self.iaf3 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - self.pool3 = sl.SumPool2d(2,2) - self.pool3a = sl.SumPool2d(4,4) - - self.conv4 = nn.Conv2d(8, 8, 2, 1, bias=False) - self.iaf4 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - self.pool4 = sl.SumPool2d(2,2) - - self.flat = nn.Flatten() - - flat_s = SCNN.get_flatten_size(input_size) - - self.fc1 = nn.Linear(flat_s, 100, bias=False) - self.iaf1_fc = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - self.fc2 = nn.Linear(100, 100, bias=False) - self.iaf2_fc = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - self.fc3 = nn.Linear(100, 100, bias=False) - self.iaf3_fc = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - self.fc4 = nn.Linear(100, 100, bias=False) - self.iaf4_fc = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - self.fc5 = nn.Linear(100, nb_classes, bias=False) - self.iaf5_fc = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - # skip - - self.merge1 = sl.Merge() - self.merge2 = sl.Merge() - self.merge3 = sl.Merge() - - @staticmethod - def get_flatten_size(input_size): - conv1_dims = SCNN.conv2d_output_size(input_size, 8, (2, 2)) - pool1_dims = SCNN.pool_output_size(conv1_dims, 8, (2, 2)) - - conv2_dims = SCNN.conv2d_output_size(pool1_dims, 8, (2, 2)) - pool2_dims = SCNN.pool_output_size(conv2_dims, 8, (2, 2)) - - conv3_dims = SCNN.conv2d_output_size(pool2_dims, 8, (2, 2)) - pool3_dims = SCNN.pool_output_size(conv3_dims, 8, (2, 2)) - - conv4_dims = SCNN.conv2d_output_size(pool3_dims, 8, (2, 2)) - pool4_dims = SCNN.pool_output_size(conv4_dims, 8, (2, 2)) - - return pool4_dims[0]*pool4_dims[1]*pool4_dims[2] - - @staticmethod - def conv2d_output_size(input_size, out_channels, kernel_size, stride=1, padding=0, dilation=1): - input_height, input_width, input_channels = input_size - kernel_height, kernel_width = kernel_size - - output_height = ((input_height + 2 * padding - dilation * (kernel_height - 1) - 1) // stride) + 1 - output_width = ((input_width + 2 * padding - dilation * (kernel_width - 1) - 1) // stride) + 1 - - return (output_height, output_width, out_channels) - - @staticmethod - def pool_output_size(input_size, out_channels, kernel_size, stride=None, padding=0): - input_height, input_width, input_channels = input_size - kernel_height, kernel_width = kernel_size - - if stride is None: - stride = kernel_height - - output_height = ((input_height + 2 * padding - kernel_height) // stride) + 1 - output_width = ((input_width + 2 * padding - kernel_width) // stride) + 1 - - return (output_height, output_width, out_channels) - - def detach_neuron_states(self): - for name, layer in self.named_modules(): - if name != '': - if isinstance(layer, sl.StatefulLayer): - for name, buffer in layer.named_buffers(): - buffer.detach_() - - def init_weights(self): - for name, layer in self.named_modules(): - if isinstance(layer, nn.Conv2d) or isinstance(layer, nn.Linear): - nn.init.xavier_normal_(layer.weight.data) - - def rescale_conv_weights(self, rescale_fn, lambda_): - rescale_fn(self.conv2, [(2,2)], lambda_) - rescale_fn(self.conv3, [(4,4), (2,2)], lambda_) - rescale_fn(self.conv4, [(2,2)], lambda_) - - def forward(self, x): - # conv 1 - con1_out = self.conv1(x) - iaf1_out = self.iaf1(con1_out) - pool1_out = self.pool1(iaf1_out) - pool1a_out = self.pool1a(iaf1_out) - # conv 2 - conv2_out = self.conv2(pool1_out) - iaf2_out = self.iaf2(conv2_out) - pool2_out = self.pool2(iaf2_out) - - merge1_out = self.merge1(pool1a_out, pool2_out) - # conv 3 - conv3_out = self.conv3(merge1_out) - iaf3_out = self.iaf3(conv3_out) - pool3_out = self.pool3(iaf3_out) - pool3a_out = self.pool3a(iaf3_out) - # conv 4 - conv4_out = self.conv4(pool3_out) - iaf4_out = self.iaf4(conv4_out) - pool4_out = self.pool4(iaf4_out) - - merge2_out = self.merge2(pool3a_out, pool4_out) - - flat_out = self.flat(merge2_out) - # fc 1 - fc1_out = self.fc1(flat_out) - iaf1_fc_out = self.iaf1_fc(fc1_out) - # fc 2 - fc2_out = self.fc2(iaf1_fc_out) - iaf2_fc_out = self.iaf2_fc(fc2_out) - - merge3_out = self.merge3(iaf1_fc_out, iaf2_fc_out) - # fc 3 - fc3_out = self.fc3(merge3_out) - iaf3_fc_out = self.iaf3_fc(fc3_out) - # fc 4 - fc4_out = self.fc4(iaf3_fc_out) - iaf4_fc_out = self.iaf4_fc(fc4_out) - # fc 5 - fc5_out = self.fc5(iaf4_fc_out) - iaf5_fc_out = self.iaf5_fc(fc5_out) - - return iaf5_fc_out \ No newline at end of file diff --git a/tests/test_nonsequential/using_SumPool2d/models/ResSCNN_4.py b/tests/test_nonsequential/using_SumPool2d/models/ResSCNN_4.py deleted file mode 100644 index 4d07ff37..00000000 --- a/tests/test_nonsequential/using_SumPool2d/models/ResSCNN_4.py +++ /dev/null @@ -1,154 +0,0 @@ -import torch.nn as nn -import sinabs.layers as sl -from sinabs.exodus.layers import IAFSqueeze - -class SCNN(nn.Module): - def __init__(self, input_size, nb_classes, batch_size, surrogate_fn, min_v_mem=-0.313, spk_thr=2.0) -> None: - super().__init__() - - self.conv1 = nn.Conv2d(2, 8, 2, 1, bias=False) - self.iaf1 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - self.pool1 = sl.SumPool2d(2,2) - self.pool1a = sl.SumPool2d(4,4) - - self.conv2 = nn.Conv2d(8, 8, 2, 1, bias=False) - self.iaf2 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - self.pool2 = sl.SumPool2d(2,2) - - self.conv3 = nn.Conv2d(8, 8, 2, 1, bias=False) - self.iaf3 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - self.pool3 = sl.SumPool2d(2,2) - self.pool3a = sl.SumPool2d(4,4) - - self.conv4 = nn.Conv2d(8, 8, 2, 1, bias=False) - self.iaf4 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - self.pool4 = sl.SumPool2d(2,2) - - self.flat = nn.Flatten() - - flat_s = SCNN.get_flatten_size(input_size) - - self.fc1 = nn.Linear(flat_s, 100, bias=False) - self.iaf1_fc = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - self.fc2 = nn.Linear(100, 100, bias=False) - self.iaf2_fc = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - self.fc3 = nn.Linear(100, 100, bias=False) - self.iaf3_fc = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - self.fc4 = nn.Linear(100, 100, bias=False) - self.iaf4_fc = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - self.fc5 = nn.Linear(100, nb_classes, bias=False) - self.iaf5_fc = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - # skip - - self.merge1 = sl.Merge() - self.merge2 = sl.Merge() - self.merge3 = sl.Merge() - self.merge4 = sl.Merge() - - @staticmethod - def get_flatten_size(input_size): - conv1_dims = SCNN.conv2d_output_size(input_size, 8, (2, 2)) - pool1_dims = SCNN.pool_output_size(conv1_dims, 8, (2, 2)) - - conv2_dims = SCNN.conv2d_output_size(pool1_dims, 8, (2, 2)) - pool2_dims = SCNN.pool_output_size(conv2_dims, 8, (2, 2)) - - conv3_dims = SCNN.conv2d_output_size(pool2_dims, 8, (2, 2)) - pool3_dims = SCNN.pool_output_size(conv3_dims, 8, (2, 2)) - - conv4_dims = SCNN.conv2d_output_size(pool3_dims, 8, (2, 2)) - pool4_dims = SCNN.pool_output_size(conv4_dims, 8, (2, 2)) - - return pool4_dims[0]*pool4_dims[1]*pool4_dims[2] - - @staticmethod - def conv2d_output_size(input_size, out_channels, kernel_size, stride=1, padding=0, dilation=1): - input_height, input_width, input_channels = input_size - kernel_height, kernel_width = kernel_size - - output_height = ((input_height + 2 * padding - dilation * (kernel_height - 1) - 1) // stride) + 1 - output_width = ((input_width + 2 * padding - dilation * (kernel_width - 1) - 1) // stride) + 1 - - return (output_height, output_width, out_channels) - - @staticmethod - def pool_output_size(input_size, out_channels, kernel_size, stride=None, padding=0): - input_height, input_width, input_channels = input_size - kernel_height, kernel_width = kernel_size - - if stride is None: - stride = kernel_height - - output_height = ((input_height + 2 * padding - kernel_height) // stride) + 1 - output_width = ((input_width + 2 * padding - kernel_width) // stride) + 1 - - return (output_height, output_width, out_channels) - - def detach_neuron_states(self): - for name, layer in self.named_modules(): - if name != '': - if isinstance(layer, sl.StatefulLayer): - for name, buffer in layer.named_buffers(): - buffer.detach_() - - def init_weights(self): - for name, layer in self.named_modules(): - if isinstance(layer, nn.Conv2d) or isinstance(layer, nn.Linear): - nn.init.xavier_normal_(layer.weight.data) - - def rescale_conv_weights(self, rescale_fn, lambda_): - rescale_fn(self.conv2, [(2,2)], lambda_) - rescale_fn(self.conv3, [(4,4), (2,2)], lambda_) - rescale_fn(self.conv4, [(2,2)], lambda_) - - def forward(self, x): - # conv 1 - con1_out = self.conv1(x) - iaf1_out = self.iaf1(con1_out) - pool1_out = self.pool1(iaf1_out) - pool1a_out = self.pool1a(iaf1_out) - # conv 2 - conv2_out = self.conv2(pool1_out) - iaf2_out = self.iaf2(conv2_out) - pool2_out = self.pool2(iaf2_out) - - merge1_out = self.merge1(pool1a_out, pool2_out) - # conv 3 - conv3_out = self.conv3(merge1_out) - iaf3_out = self.iaf3(conv3_out) - pool3_out = self.pool3(iaf3_out) - pool3a_out = self.pool3a(iaf3_out) - # conv 4 - conv4_out = self.conv4(pool3_out) - iaf4_out = self.iaf4(conv4_out) - pool4_out = self.pool4(iaf4_out) - - merge2_out = self.merge2(pool3a_out, pool4_out) - - flat_out = self.flat(merge2_out) - # fc 1 - fc1_out = self.fc1(flat_out) - iaf1_fc_out = self.iaf1_fc(fc1_out) - # fc 2 - fc2_out = self.fc2(iaf1_fc_out) - iaf2_fc_out = self.iaf2_fc(fc2_out) - - merge3_out = self.merge3(iaf1_fc_out, iaf2_fc_out) - # fc 3 - fc3_out = self.fc3(merge3_out) - iaf3_fc_out = self.iaf3_fc(fc3_out) - # fc 4 - fc4_out = self.fc4(iaf3_fc_out) - iaf4_fc_out = self.iaf4_fc(fc4_out) - - merge4_out = self.merge4(iaf3_fc_out, iaf4_fc_out) - # fc 5 - fc5_out = self.fc5(merge4_out) - iaf5_fc_out = self.iaf5_fc(fc5_out) - - return iaf5_fc_out \ No newline at end of file diff --git a/tests/test_nonsequential/using_SumPool2d/models/ResSCNN_5.py b/tests/test_nonsequential/using_SumPool2d/models/ResSCNN_5.py deleted file mode 100644 index 8ba45649..00000000 --- a/tests/test_nonsequential/using_SumPool2d/models/ResSCNN_5.py +++ /dev/null @@ -1,143 +0,0 @@ -import torch.nn as nn -import sinabs.layers as sl -from sinabs.exodus.layers import IAFSqueeze - -class SCNN(nn.Module): - def __init__(self, input_size, nb_classes, batch_size, surrogate_fn, min_v_mem=-0.313, spk_thr=2.0) -> None: - super().__init__() - - self.conv1 = nn.Conv2d(2, 8, 2, 1, bias=False) - self.iaf1 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - self.pool1 = sl.SumPool2d(2,2) - self.pool1a = sl.SumPool2d(8,8) - - self.conv2 = nn.Conv2d(8, 8, 2, 1, bias=False) - self.iaf2 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - self.pool2 = sl.SumPool2d(2,2) - - self.conv3 = nn.Conv2d(8, 8, 2, 1, bias=False) - self.iaf3 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - self.pool3 = sl.SumPool2d(2,2) - - self.conv4 = nn.Conv2d(8, 8, 2, 1, bias=False) - self.iaf4 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - self.pool4 = sl.SumPool2d(2,2) - - self.flat = nn.Flatten() - - flat_s = SCNN.get_flatten_size(input_size) - - self.fc1 = nn.Linear(flat_s, 100, bias=False) - self.iaf1_fc = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - self.fc2 = nn.Linear(100, 100, bias=False) - self.iaf2_fc = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - self.fc3 = nn.Linear(100, 100, bias=False) - self.iaf3_fc = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - self.fc4 = nn.Linear(100, 100, bias=False) - self.iaf4_fc = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - self.fc5 = nn.Linear(100, nb_classes, bias=False) - self.iaf5_fc = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - # skip - - self.merge1 = sl.Merge() - - @staticmethod - def get_flatten_size(input_size): - conv1_dims = SCNN.conv2d_output_size(input_size, 8, (2, 2)) - pool1_dims = SCNN.pool_output_size(conv1_dims, 8, (2, 2)) - - conv2_dims = SCNN.conv2d_output_size(pool1_dims, 8, (2, 2)) - pool2_dims = SCNN.pool_output_size(conv2_dims, 8, (2, 2)) - - conv3_dims = SCNN.conv2d_output_size(pool2_dims, 8, (2, 2)) - pool3_dims = SCNN.pool_output_size(conv3_dims, 8, (2, 2)) - - conv4_dims = SCNN.conv2d_output_size(pool3_dims, 8, (2, 2)) - pool4_dims = SCNN.pool_output_size(conv4_dims, 8, (2, 2)) - - return pool4_dims[0]*pool4_dims[1]*pool4_dims[2] - - @staticmethod - def conv2d_output_size(input_size, out_channels, kernel_size, stride=1, padding=0, dilation=1): - input_height, input_width, input_channels = input_size - kernel_height, kernel_width = kernel_size - - output_height = ((input_height + 2 * padding - dilation * (kernel_height - 1) - 1) // stride) + 1 - output_width = ((input_width + 2 * padding - dilation * (kernel_width - 1) - 1) // stride) + 1 - - return (output_height, output_width, out_channels) - - @staticmethod - def pool_output_size(input_size, out_channels, kernel_size, stride=None, padding=0): - input_height, input_width, input_channels = input_size - kernel_height, kernel_width = kernel_size - - if stride is None: - stride = kernel_height - - output_height = ((input_height + 2 * padding - kernel_height) // stride) + 1 - output_width = ((input_width + 2 * padding - kernel_width) // stride) + 1 - - return (output_height, output_width, out_channels) - - def detach_neuron_states(self): - for name, layer in self.named_modules(): - if name != '': - if isinstance(layer, sl.StatefulLayer): - for name, buffer in layer.named_buffers(): - buffer.detach_() - - def init_weights(self): - for name, layer in self.named_modules(): - if isinstance(layer, nn.Conv2d) or isinstance(layer, nn.Linear): - nn.init.xavier_normal_(layer.weight.data) - - def rescale_conv_weights(self, rescale_fn, lambda_): - rescale_fn(self.conv2, [(2,2)], lambda_) - rescale_fn(self.conv3, [(2,2)], lambda_) - rescale_fn(self.conv4, [(8,8), (2,2)], lambda_) - - def forward(self, x): - # conv 1 - con1_out = self.conv1(x) - iaf1_out = self.iaf1(con1_out) - pool1_out = self.pool1(iaf1_out) - pool1a_out = self.pool1a(iaf1_out) - # conv 2 - conv2_out = self.conv2(pool1_out) - iaf2_out = self.iaf2(conv2_out) - pool2_out = self.pool2(iaf2_out) - # conv 3 - conv3_out = self.conv3(pool2_out) - iaf3_out = self.iaf3(conv3_out) - pool3_out = self.pool3(iaf3_out) - - merge1_out = self.merge1(pool1a_out, pool3_out) - # conv 4 - conv4_out = self.conv4(merge1_out) - iaf4_out = self.iaf4(conv4_out) - pool4_out = self.pool4(iaf4_out) - - flat_out = self.flat(pool4_out) - # fc 1 - fc1_out = self.fc1(flat_out) - iaf1_fc_out = self.iaf1_fc(fc1_out) - # fc 2 - fc2_out = self.fc2(iaf1_fc_out) - iaf2_fc_out = self.iaf2_fc(fc2_out) - # fc 3 - fc3_out = self.fc3(iaf2_fc_out) - iaf3_fc_out = self.iaf3_fc(fc3_out) - # fc 4 - fc4_out = self.fc4(iaf3_fc_out) - iaf4_fc_out = self.iaf4_fc(fc4_out) - # fc 5 - fc5_out = self.fc5(iaf4_fc_out) - iaf5_fc_out = self.iaf5_fc(fc5_out) - - return iaf5_fc_out \ No newline at end of file diff --git a/tests/test_nonsequential/using_SumPool2d/models/ResSCNN_6.py b/tests/test_nonsequential/using_SumPool2d/models/ResSCNN_6.py deleted file mode 100644 index 5f761619..00000000 --- a/tests/test_nonsequential/using_SumPool2d/models/ResSCNN_6.py +++ /dev/null @@ -1,146 +0,0 @@ -import torch.nn as nn -import sinabs.layers as sl -from sinabs.exodus.layers import IAFSqueeze - -class SCNN(nn.Module): - def __init__(self, input_size, nb_classes, batch_size, surrogate_fn, min_v_mem=-0.313, spk_thr=2.0) -> None: - super().__init__() - - self.conv1 = nn.Conv2d(2, 8, 2, 1, bias=False) - self.iaf1 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - self.pool1 = sl.SumPool2d(2,2) - self.pool1a = sl.SumPool2d(8,8) - - self.conv2 = nn.Conv2d(8, 8, 2, 1, bias=False) - self.iaf2 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - self.pool2 = sl.SumPool2d(2,2) - - self.conv3 = nn.Conv2d(8, 8, 2, 1, bias=False) - self.iaf3 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - self.pool3 = sl.SumPool2d(2,2) - - self.conv4 = nn.Conv2d(8, 8, 2, 1, bias=False) - self.iaf4 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - self.pool4 = sl.SumPool2d(2,2) - - self.flat = nn.Flatten() - - flat_s = SCNN.get_flatten_size(input_size) - - self.fc1 = nn.Linear(flat_s, 100, bias=False) - self.iaf1_fc = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - self.fc2 = nn.Linear(100, 100, bias=False) - self.iaf2_fc = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - self.fc3 = nn.Linear(100, 100, bias=False) - self.iaf3_fc = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - self.fc4 = nn.Linear(100, 100, bias=False) - self.iaf4_fc = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - self.fc5 = nn.Linear(100, nb_classes, bias=False) - self.iaf5_fc = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - # skip - - self.merge1 = sl.Merge() - self.merge2 = sl.Merge() - - @staticmethod - def get_flatten_size(input_size): - conv1_dims = SCNN.conv2d_output_size(input_size, 8, (2, 2)) - pool1_dims = SCNN.pool_output_size(conv1_dims, 8, (2, 2)) - - conv2_dims = SCNN.conv2d_output_size(pool1_dims, 8, (2, 2)) - pool2_dims = SCNN.pool_output_size(conv2_dims, 8, (2, 2)) - - conv3_dims = SCNN.conv2d_output_size(pool2_dims, 8, (2, 2)) - pool3_dims = SCNN.pool_output_size(conv3_dims, 8, (2, 2)) - - conv4_dims = SCNN.conv2d_output_size(pool3_dims, 8, (2, 2)) - pool4_dims = SCNN.pool_output_size(conv4_dims, 8, (2, 2)) - - return pool4_dims[0]*pool4_dims[1]*pool4_dims[2] - - @staticmethod - def conv2d_output_size(input_size, out_channels, kernel_size, stride=1, padding=0, dilation=1): - input_height, input_width, input_channels = input_size - kernel_height, kernel_width = kernel_size - - output_height = ((input_height + 2 * padding - dilation * (kernel_height - 1) - 1) // stride) + 1 - output_width = ((input_width + 2 * padding - dilation * (kernel_width - 1) - 1) // stride) + 1 - - return (output_height, output_width, out_channels) - - @staticmethod - def pool_output_size(input_size, out_channels, kernel_size, stride=None, padding=0): - input_height, input_width, input_channels = input_size - kernel_height, kernel_width = kernel_size - - if stride is None: - stride = kernel_height - - output_height = ((input_height + 2 * padding - kernel_height) // stride) + 1 - output_width = ((input_width + 2 * padding - kernel_width) // stride) + 1 - - return (output_height, output_width, out_channels) - - def detach_neuron_states(self): - for name, layer in self.named_modules(): - if name != '': - if isinstance(layer, sl.StatefulLayer): - for name, buffer in layer.named_buffers(): - buffer.detach_() - - def init_weights(self): - for name, layer in self.named_modules(): - if isinstance(layer, nn.Conv2d) or isinstance(layer, nn.Linear): - nn.init.xavier_normal_(layer.weight.data) - - def rescale_conv_weights(self, rescale_fn, lambda_): - rescale_fn(self.conv2, [(2,2)], lambda_) - rescale_fn(self.conv3, [(2,2)], lambda_) - rescale_fn(self.conv4, [(8,8), (2,2)], lambda_) - - def forward(self, x): - # conv 1 - con1_out = self.conv1(x) - iaf1_out = self.iaf1(con1_out) - pool1_out = self.pool1(iaf1_out) - pool1a_out = self.pool1a(iaf1_out) - # conv 2 - conv2_out = self.conv2(pool1_out) - iaf2_out = self.iaf2(conv2_out) - pool2_out = self.pool2(iaf2_out) - # conv 3 - conv3_out = self.conv3(pool2_out) - iaf3_out = self.iaf3(conv3_out) - pool3_out = self.pool3(iaf3_out) - - merge1_out = self.merge1(pool1a_out, pool3_out) - # conv 4 - conv4_out = self.conv4(merge1_out) - iaf4_out = self.iaf4(conv4_out) - pool4_out = self.pool4(iaf4_out) - - flat_out = self.flat(pool4_out) - # fc 1 - fc1_out = self.fc1(flat_out) - iaf1_fc_out = self.iaf1_fc(fc1_out) - # fc 2 - fc2_out = self.fc2(iaf1_fc_out) - iaf2_fc_out = self.iaf2_fc(fc2_out) - # fc 3 - fc3_out = self.fc3(iaf2_fc_out) - iaf3_fc_out = self.iaf3_fc(fc3_out) - - merge2_out = self.merge2(iaf1_fc_out, iaf3_fc_out) - # fc 4 - fc4_out = self.fc4(merge2_out) - iaf4_fc_out = self.iaf4_fc(fc4_out) - # fc 5 - fc5_out = self.fc5(iaf4_fc_out) - iaf5_fc_out = self.iaf5_fc(fc5_out) - - return iaf5_fc_out \ No newline at end of file diff --git a/tests/test_nonsequential/using_SumPool2d/models/ResSCNN_7.py b/tests/test_nonsequential/using_SumPool2d/models/ResSCNN_7.py deleted file mode 100644 index 21039b28..00000000 --- a/tests/test_nonsequential/using_SumPool2d/models/ResSCNN_7.py +++ /dev/null @@ -1,146 +0,0 @@ -import torch.nn as nn -import sinabs.layers as sl -from sinabs.exodus.layers import IAFSqueeze - -class SCNN(nn.Module): - def __init__(self, input_size, nb_classes, batch_size, surrogate_fn, min_v_mem=-0.313, spk_thr=2.0) -> None: - super().__init__() - - self.conv1 = nn.Conv2d(2, 8, 2, 1, bias=False) - self.iaf1 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - self.pool1 = sl.SumPool2d(2,2) - self.pool1a = sl.SumPool2d(4,4) - self.pool1b = sl.SumPool2d(8,8) - - self.conv2 = nn.Conv2d(8, 8, 2, 1, bias=False) - self.iaf2 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - self.pool2 = sl.SumPool2d(2,2) - - self.conv3 = nn.Conv2d(8, 8, 2, 1, bias=False) - self.iaf3 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - self.pool3 = sl.SumPool2d(2,2) - - self.conv4 = nn.Conv2d(8, 8, 2, 1, bias=False) - self.iaf4 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - self.pool4 = sl.SumPool2d(2,2) - - self.flat = nn.Flatten() - - flat_s = SCNN.get_flatten_size(input_size) - - self.fc1 = nn.Linear(flat_s, 100, bias=False) - self.iaf1_fc = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - self.fc2 = nn.Linear(100, 100, bias=False) - self.iaf2_fc = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - self.fc3 = nn.Linear(100, 100, bias=False) - self.iaf3_fc = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - self.fc4 = nn.Linear(100, 100, bias=False) - self.iaf4_fc = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - self.fc5 = nn.Linear(100, nb_classes, bias=False) - self.iaf5_fc = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - # skip - - self.merge1a = sl.Merge() - self.merge1b = sl.Merge() - - @staticmethod - def get_flatten_size(input_size): - conv1_dims = SCNN.conv2d_output_size(input_size, 8, (2, 2)) - pool1_dims = SCNN.pool_output_size(conv1_dims, 8, (2, 2)) - - conv2_dims = SCNN.conv2d_output_size(pool1_dims, 8, (2, 2)) - pool2_dims = SCNN.pool_output_size(conv2_dims, 8, (2, 2)) - - conv3_dims = SCNN.conv2d_output_size(pool2_dims, 8, (2, 2)) - pool3_dims = SCNN.pool_output_size(conv3_dims, 8, (2, 2)) - - conv4_dims = SCNN.conv2d_output_size(pool3_dims, 8, (2, 2)) - pool4_dims = SCNN.pool_output_size(conv4_dims, 8, (2, 2)) - - return pool4_dims[0]*pool4_dims[1]*pool4_dims[2] - - @staticmethod - def conv2d_output_size(input_size, out_channels, kernel_size, stride=1, padding=0, dilation=1): - input_height, input_width, input_channels = input_size - kernel_height, kernel_width = kernel_size - - output_height = ((input_height + 2 * padding - dilation * (kernel_height - 1) - 1) // stride) + 1 - output_width = ((input_width + 2 * padding - dilation * (kernel_width - 1) - 1) // stride) + 1 - - return (output_height, output_width, out_channels) - - @staticmethod - def pool_output_size(input_size, out_channels, kernel_size, stride=None, padding=0): - input_height, input_width, input_channels = input_size - kernel_height, kernel_width = kernel_size - - if stride is None: - stride = kernel_height - - output_height = ((input_height + 2 * padding - kernel_height) // stride) + 1 - output_width = ((input_width + 2 * padding - kernel_width) // stride) + 1 - - return (output_height, output_width, out_channels) - - def detach_neuron_states(self): - for name, layer in self.named_modules(): - if name != '': - if isinstance(layer, sl.StatefulLayer): - for name, buffer in layer.named_buffers(): - buffer.detach_() - - def init_weights(self): - for name, layer in self.named_modules(): - if isinstance(layer, nn.Conv2d) or isinstance(layer, nn.Linear): - nn.init.xavier_normal_(layer.weight.data) - - def rescale_conv_weights(self, rescale_fn, lambda_): - rescale_fn(self.conv2, [(2,2)], lambda_) - rescale_fn(self.conv3, [(4,4), (2,2)], lambda_) - rescale_fn(self.conv4, [(8,8), (2,2)], lambda_) - - def forward(self, x): - # conv 1 - con1_out = self.conv1(x) - iaf1_out = self.iaf1(con1_out) - pool1_out = self.pool1(iaf1_out) - pool1a_out = self.pool1a(iaf1_out) - pool1b_out = self.pool1b(iaf1_out) - # conv 2 - conv2_out = self.conv2(pool1_out) - iaf2_out = self.iaf2(conv2_out) - pool2_out = self.pool2(iaf2_out) - # conv 3 - merge_1a_out = self.merge1a(pool1a_out, pool2_out) - conv3_out = self.conv3(merge_1a_out) - iaf3_out = self.iaf3(conv3_out) - pool3_out = self.pool3(iaf3_out) - # conv 4 - merge_1b_out = self.merge1b(pool1b_out, pool3_out) - conv4_out = self.conv4(merge_1b_out) - iaf4_out = self.iaf4(conv4_out) - pool4_out = self.pool4(iaf4_out) - - flat_out = self.flat(pool4_out) - # fc 1 - fc1_out = self.fc1(flat_out) - iaf1_fc_out = self.iaf1_fc(fc1_out) - # fc 2 - fc2_out = self.fc2(iaf1_fc_out) - iaf2_fc_out = self.iaf2_fc(fc2_out) - # fc 3 - fc3_out = self.fc3(iaf2_fc_out) - iaf3_fc_out = self.iaf3_fc(fc3_out) - # fc 4 - fc4_out = self.fc4(iaf3_fc_out) - iaf4_fc_out = self.iaf4_fc(fc4_out) - # fc 5 - fc5_out = self.fc5(iaf4_fc_out) - iaf5_fc_out = self.iaf5_fc(fc5_out) - - return iaf5_fc_out \ No newline at end of file diff --git a/tests/test_nonsequential/using_SumPool2d/models/ResSCNN_8.py b/tests/test_nonsequential/using_SumPool2d/models/ResSCNN_8.py deleted file mode 100644 index 9086a3e3..00000000 --- a/tests/test_nonsequential/using_SumPool2d/models/ResSCNN_8.py +++ /dev/null @@ -1,151 +0,0 @@ -import torch.nn as nn -import sinabs.layers as sl -from sinabs.exodus.layers import IAFSqueeze - -class SCNN(nn.Module): - def __init__(self, input_size, nb_classes, batch_size, surrogate_fn, min_v_mem=-0.313, spk_thr=2.0) -> None: - super().__init__() - - self.conv1 = nn.Conv2d(2, 8, 2, 1, bias=False) - self.iaf1 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - self.pool1 = sl.SumPool2d(2,2) - self.pool1a = sl.SumPool2d(4,4) - self.pool1b = sl.SumPool2d(8,8) - - self.conv2 = nn.Conv2d(8, 8, 2, 1, bias=False) - self.iaf2 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - self.pool2 = sl.SumPool2d(2,2) - - self.conv3 = nn.Conv2d(8, 8, 2, 1, bias=False) - self.iaf3 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - self.pool3 = sl.SumPool2d(2,2) - - self.conv4 = nn.Conv2d(8, 8, 2, 1, bias=False) - self.iaf4 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - self.pool4 = sl.SumPool2d(2,2) - - self.flat = nn.Flatten() - - flat_s = SCNN.get_flatten_size(input_size) - - self.fc1 = nn.Linear(flat_s, 100, bias=False) - self.iaf1_fc = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - self.fc2 = nn.Linear(100, 100, bias=False) - self.iaf2_fc = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - self.fc3 = nn.Linear(100, 100, bias=False) - self.iaf3_fc = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - self.fc4 = nn.Linear(100, 100, bias=False) - self.iaf4_fc = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - self.fc5 = nn.Linear(100, nb_classes, bias=False) - self.iaf5_fc = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - # skip - - self.merge1a = sl.Merge() - self.merge1b = sl.Merge() - - self.merge_fc1a = sl.Merge() - self.merge_fc1b = sl.Merge() - - @staticmethod - def get_flatten_size(input_size): - conv1_dims = SCNN.conv2d_output_size(input_size, 8, (2, 2)) - pool1_dims = SCNN.pool_output_size(conv1_dims, 8, (2, 2)) - - conv2_dims = SCNN.conv2d_output_size(pool1_dims, 8, (2, 2)) - pool2_dims = SCNN.pool_output_size(conv2_dims, 8, (2, 2)) - - conv3_dims = SCNN.conv2d_output_size(pool2_dims, 8, (2, 2)) - pool3_dims = SCNN.pool_output_size(conv3_dims, 8, (2, 2)) - - conv4_dims = SCNN.conv2d_output_size(pool3_dims, 8, (2, 2)) - pool4_dims = SCNN.pool_output_size(conv4_dims, 8, (2, 2)) - - return pool4_dims[0]*pool4_dims[1]*pool4_dims[2] - - @staticmethod - def conv2d_output_size(input_size, out_channels, kernel_size, stride=1, padding=0, dilation=1): - input_height, input_width, input_channels = input_size - kernel_height, kernel_width = kernel_size - - output_height = ((input_height + 2 * padding - dilation * (kernel_height - 1) - 1) // stride) + 1 - output_width = ((input_width + 2 * padding - dilation * (kernel_width - 1) - 1) // stride) + 1 - - return (output_height, output_width, out_channels) - - @staticmethod - def pool_output_size(input_size, out_channels, kernel_size, stride=None, padding=0): - input_height, input_width, input_channels = input_size - kernel_height, kernel_width = kernel_size - - if stride is None: - stride = kernel_height - - output_height = ((input_height + 2 * padding - kernel_height) // stride) + 1 - output_width = ((input_width + 2 * padding - kernel_width) // stride) + 1 - - return (output_height, output_width, out_channels) - - def detach_neuron_states(self): - for name, layer in self.named_modules(): - if name != '': - if isinstance(layer, sl.StatefulLayer): - for name, buffer in layer.named_buffers(): - buffer.detach_() - - def init_weights(self): - for name, layer in self.named_modules(): - if isinstance(layer, nn.Conv2d) or isinstance(layer, nn.Linear): - nn.init.xavier_normal_(layer.weight.data) - - def rescale_conv_weights(self, rescale_fn, lambda_): - rescale_fn(self.conv2, [(2,2)], lambda_) - rescale_fn(self.conv3, [(4,4), (2,2)], lambda_) - rescale_fn(self.conv4, [(8,8), (2,2)], lambda_) - - def forward(self, x): - # conv 1 - con1_out = self.conv1(x) - iaf1_out = self.iaf1(con1_out) - pool1_out = self.pool1(iaf1_out) - pool1a_out = self.pool1a(iaf1_out) - pool1b_out = self.pool1b(iaf1_out) - # conv 2 - conv2_out = self.conv2(pool1_out) - iaf2_out = self.iaf2(conv2_out) - pool2_out = self.pool2(iaf2_out) - # conv 3 - merge_1a_out = self.merge1a(pool1a_out, pool2_out) - conv3_out = self.conv3(merge_1a_out) - iaf3_out = self.iaf3(conv3_out) - pool3_out = self.pool3(iaf3_out) - # conv 4 - merge_1b_out = self.merge1b(pool1b_out, pool3_out) - conv4_out = self.conv4(merge_1b_out) - iaf4_out = self.iaf4(conv4_out) - pool4_out = self.pool4(iaf4_out) - - flat_out = self.flat(pool4_out) - # fc 1 - fc1_out = self.fc1(flat_out) - iaf1_fc_out = self.iaf1_fc(fc1_out) - # fc 2 - fc2_out = self.fc2(iaf1_fc_out) - iaf2_fc_out = self.iaf2_fc(fc2_out) - # fc 3 - merge_fc1a_out = self.merge_fc1a(iaf1_fc_out, iaf2_fc_out) - fc3_out = self.fc3(merge_fc1a_out) - iaf3_fc_out = self.iaf3_fc(fc3_out) - # fc 4 - merge_fc1b_out = self.merge_fc1b(iaf1_fc_out, iaf3_fc_out) - fc4_out = self.fc4(merge_fc1b_out) - iaf4_fc_out = self.iaf4_fc(fc4_out) - # fc 5 - fc5_out = self.fc5(iaf4_fc_out) - iaf5_fc_out = self.iaf5_fc(fc5_out) - - return iaf5_fc_out \ No newline at end of file diff --git a/tests/test_nonsequential/using_SumPool2d/models/ResSCNN_9.py b/tests/test_nonsequential/using_SumPool2d/models/ResSCNN_9.py deleted file mode 100644 index 7ed5ca4d..00000000 --- a/tests/test_nonsequential/using_SumPool2d/models/ResSCNN_9.py +++ /dev/null @@ -1,124 +0,0 @@ -import torch.nn as nn -import sinabs.layers as sl -from sinabs.exodus.layers import IAFSqueeze - -class SCNN(nn.Module): - def __init__(self, input_size, nb_classes, batch_size, surrogate_fn, min_v_mem=-0.313, spk_thr=2.0): - super().__init__() - - self.conv1 = nn.Conv2d(2, 8, 2, 1, bias=False) - self.iaf1 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - self.conv2 = nn.Conv2d(8, 8, 3, 1, 1, bias=False) - self.iaf2 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - self.conv3 = nn.Conv2d(8, 8, 3, 1, 1, bias=False) - self.iaf3 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - self.pool3a = sl.SumPool2d(2,2) - - self.conv4 = nn.Conv2d(8, 8, 2, 1, bias=False) - self.iaf4 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - self.pool4 = sl.SumPool2d(2,2) - self.pool4a = sl.SumPool2d(4,4) - - self.conv5 = nn.Conv2d(8, 8, 2, 1, bias=False) - self.iaf5 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - self.pool5 = sl.SumPool2d(2,2) - self.pool5a = sl.SumPool2d(2,2) - - self.conv6 = nn.Conv2d(8, 8, 3, 1, 1, bias=False) - self.iaf6 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - self.pool6a = sl.SumPool2d(2,2) - - self.conv7 = nn.Conv2d(8, 8, 2, 1, bias=False) - self.iaf7 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - self.pool7 = sl.SumPool2d(2,2) - - self.conv8 = nn.Conv2d(8, 8, 2, 1, bias=False) - self.iaf8 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - self.pool8 = sl.SumPool2d(2,2) - - self.flat = nn.Flatten() - - self.fc_out = nn.Linear(392, nb_classes, bias=False) - self.iaf_fc_out = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - # skip - - self.merge1 = sl.Merge() - self.merge2 = sl.Merge() - self.merge3 = sl.Merge() - self.merge4 = sl.Merge() - self.merge5 = sl.Merge() - self.merge6 = sl.Merge() - - def detach_neuron_states(self): - for name, layer in self.named_modules(): - if name != '': - if isinstance(layer, sl.StatefulLayer): - for name, buffer in layer.named_buffers(): - buffer.detach_() - - def init_weights(self): - for name, layer in self.named_modules(): - if isinstance(layer, nn.Conv2d) or isinstance(layer, nn.Linear): - nn.init.xavier_normal_(layer.weight.data) - - def rescale_conv_weights(self, rescale_fn, lambda_): - rescale_fn(self.conv5, [(2,2), (2,2)], lambda_) - rescale_fn(self.conv6, [(4,4), (2,2)], lambda_) - rescale_fn(self.conv7, [(2,2)], lambda_) - rescale_fn(self.conv8, [(2,2), (2,2)], lambda_) - - def forward(self, x): - # -- conv block 1 --- - con1_out = self.conv1(x) - iaf1_out = self.iaf1(con1_out) - # -- conv block 2 --- - conv2_out = self.conv2(iaf1_out) - iaf2_out = self.iaf2(conv2_out) # to CONV 4 - # -- conv block 3 --- - #print(iaf1_out.shape, iaf2_out.shape) - merge1_out = self.merge1(iaf1_out, iaf2_out) - conv3_out = self.conv3(merge1_out) - iaf3_out = self.iaf3(conv3_out) - pool3a_out = self.pool3a(iaf3_out) # to CONV 5 - # -- conv block 4 --- - #print(iaf2_out.shape, iaf3_out.shape) - merge2_out = self.merge2(iaf2_out, iaf3_out) - conv4_out = self.conv4(merge2_out) - iaf4_out = self.iaf4(conv4_out) - pool4_out = self.pool4(iaf4_out) - pool4a_out = self.pool4a(iaf4_out) # to CONV 6 - # -- conv block 5 --- - #print(pool3a_out.shape, pool4_out.shape) - merge3_out = self.merge3(pool3a_out, pool4_out) - conv5_out = self.conv5(merge3_out) - iaf5_out = self.iaf5(conv5_out) - pool5_out = self.pool5(iaf5_out) - pool5a_out = self.pool5a(iaf5_out) # to CONV 7 - # -- conv block 6 --- - #print(pool4a_out.shape, pool5_out.shape) - merge4_out = self.merge4(pool4a_out, pool5_out) - conv6_out = self.conv6(merge4_out) - iaf6_out = self.iaf6(conv6_out) - pool6a_out = self.pool6a(iaf6_out) # to CONV 8 - # -- conv block 7 --- - #print(pool5a_out.shape, iaf6_out.shape) - merge5_out = self.merge5(pool5a_out, iaf6_out) - conv7_out = self.conv7(merge5_out) - iaf7_out = self.iaf7(conv7_out) - pool7_out = self.pool7(iaf7_out) - # -- conv block 8 --- - #print(pool6a_out.shape, pool7_out.shape) - merge6_out = self.merge6(pool6a_out, pool7_out) - conv8_out = self.conv8(merge6_out) - iaf8_out = self.iaf8(conv8_out) - pool8_out = self.pool8(iaf8_out) - # -- output -- - flat = self.flat(pool8_out) - #print(flat.shape) - fc_out = self.fc_out(flat) - iaf_fc_out = self.iaf_fc_out(fc_out) - - return iaf_fc_out \ No newline at end of file diff --git a/tests/test_nonsequential/using_SumPool2d/models/SCNN.py b/tests/test_nonsequential/using_SumPool2d/models/SCNN.py deleted file mode 100644 index 5e3d689a..00000000 --- a/tests/test_nonsequential/using_SumPool2d/models/SCNN.py +++ /dev/null @@ -1,130 +0,0 @@ -import torch.nn as nn -import sinabs.layers as sl -from sinabs.exodus.layers import IAFSqueeze - -class SCNN(nn.Module): - def __init__(self, input_size, nb_classes, batch_size, surrogate_fn, min_v_mem=-1.0, spk_thr=1.0) -> None: - super().__init__() - - self.conv1 = nn.Conv2d(2, 1, 2, 1, bias=False) - self.iaf1 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - self.pool1 = sl.SumPool2d(2,2) - - self.conv2 = nn.Conv2d(1, 8, 2, 1, bias=False) - self.iaf2 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - self.pool2 = sl.SumPool2d(2,2) - - self.conv3 = nn.Conv2d(8, 16, 2, 1, bias=False) - self.iaf3 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - self.pool3 = sl.SumPool2d(2,2) - - self.conv4 = nn.Conv2d(16, 16, 2, 1, bias=False) - self.iaf4 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - self.pool4 = sl.SumPool2d(2,2) - - self.flat = nn.Flatten() - - flat_s = SCNN.get_flatten_size(input_size) - - self.fc1 = nn.Linear(flat_s, 1024, bias=False) - self.iaf4 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - self.fc2 = nn.Linear(1024, 256, bias=False) - self.iaf5 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - self.fc3 = nn.Linear(256, 128, bias=False) - self.iaf6 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - self.fc4 = nn.Linear(128, 64, bias=False) - self.iaf7 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - self.fc5 = nn.Linear(64, nb_classes, bias=False) - self.iaf8 = IAFSqueeze(batch_size=batch_size, min_v_mem=min_v_mem, surrogate_grad_fn=surrogate_fn, spike_threshold=spk_thr) - - @staticmethod - def get_flatten_size(input_size): - conv1_dims = SCNN.conv2d_output_size(input_size, 1, (2, 2)) - pool1_dims = SCNN.pool_output_size(conv1_dims, 1, (2, 2)) - - conv2_dims = SCNN.conv2d_output_size(pool1_dims, 8, (2, 2)) - pool2_dims = SCNN.pool_output_size(conv2_dims, 8, (2, 2)) - - conv3_dims = SCNN.conv2d_output_size(pool2_dims, 16, (2, 2)) - pool3_dims = SCNN.pool_output_size(conv3_dims, 16, (2, 2)) - - conv4_dims = SCNN.conv2d_output_size(pool3_dims, 16, (2, 2)) - pool4_dims = SCNN.pool_output_size(conv4_dims, 16, (2, 2)) - - return pool4_dims[0]*pool4_dims[1]*pool4_dims[2] - - @staticmethod - def conv2d_output_size(input_size, out_channels, kernel_size, stride=1, padding=0, dilation=1): - input_height, input_width, input_channels = input_size - kernel_height, kernel_width = kernel_size - - output_height = ((input_height + 2 * padding - dilation * (kernel_height - 1) - 1) // stride) + 1 - output_width = ((input_width + 2 * padding - dilation * (kernel_width - 1) - 1) // stride) + 1 - - return (output_height, output_width, out_channels) - - @staticmethod - def pool_output_size(input_size, out_channels, kernel_size, stride=None, padding=0): - input_height, input_width, input_channels = input_size - kernel_height, kernel_width = kernel_size - - if stride is None: - stride = kernel_height - - output_height = ((input_height + 2 * padding - kernel_height) // stride) + 1 - output_width = ((input_width + 2 * padding - kernel_width) // stride) + 1 - - return (output_height, output_width, out_channels) - - def detach_neuron_states(self): - for name, layer in self.named_modules(): - if name != '': - if isinstance(layer, sl.StatefulLayer): - for name, buffer in layer.named_buffers(): - buffer.detach_() - - def init_weights(self): - for name, layer in self.named_modules(): - if isinstance(layer, nn.Conv2d) or isinstance(layer, nn.Linear): - nn.init.xavier_normal_(layer.weight.data) - - def forward(self, x): - - con1_out = self.conv1(x) - iaf1_out = self.iaf1(con1_out) - pool1_out = self.pool1(iaf1_out) - - conv2_out = self.conv2(pool1_out) - iaf2_out = self.iaf2(conv2_out) - pool2_out = self.pool2(iaf2_out) - - conv3_out = self.conv3(pool2_out) - iaf3_out = self.iaf3(conv3_out) - pool3_out = self.pool3(iaf3_out) - - conv4_out = self.conv4(pool3_out) - iaf4_out = self.iaf4(conv4_out) - pool4_out = self.pool4(iaf4_out) - - flat_out = self.flat(pool4_out) - - fc1_out = self.fc1(flat_out) - iaf4_out = self.iaf4(fc1_out) - - fc2_out = self.fc2(iaf4_out) - iaf5_out = self.iaf5(fc2_out) - - fc3_out = self.fc3(iaf5_out) - iaf6_out = self.iaf6(fc3_out) - - fc4_out = self.fc4(iaf6_out) - iaf7_out = self.iaf7(fc4_out) - - fc5_out = self.fc5(iaf7_out) - iaf8_out = self.iaf8(fc5_out) - - return iaf8_out \ No newline at end of file diff --git a/tests/test_nonsequential/utils/train_test_fn.py b/tests/test_nonsequential/utils/train_test_fn.py deleted file mode 100644 index d166fdff..00000000 --- a/tests/test_nonsequential/utils/train_test_fn.py +++ /dev/null @@ -1,274 +0,0 @@ -from tqdm.notebook import tqdm -import torch -from tonic.datasets.dvsgesture import DVSGesture -from tonic.datasets.nmnist import NMNIST -from tonic.transforms import ToFrame -import numpy as np -from torch.utils.data import Subset - -def training_loop(device, nb_time_steps, batch_size, feature_map_size, dataloader_train, model, loss_fn, optimizer, epochs, dataloader_test): - epochs_y = [] - epochs_x = [] - epochs_acc = [] - model.train() - - for e in range(epochs): - losses = [] - batches = [] - batch_count = 0 - train_p_bar = tqdm(dataloader_train) - - for X, y in train_p_bar: - # reshape the input from [Batch, Time, Channel, Height, Width] into [Batch*Time, Channel, Height, Width] - X = X.reshape(-1, feature_map_size[2], feature_map_size[0], feature_map_size[1]).to(dtype=torch.float, device=device) - y = y.to(dtype=torch.long, device=device) - - # forward - pred = model(X) - - # reshape the output from [Batch*Time,num_classes] into [Batch, Time, num_classes] - pred = pred.reshape(batch_size, nb_time_steps, -1) - - # accumulate all time-steps output for final prediction - pred = pred.sum(dim = 1) - loss = loss_fn(pred, y) - - # gradient update - optimizer.zero_grad() - loss.backward() - optimizer.step() - - # detach the neuron states and activations from current computation graph(necessary) - model.detach_neuron_states() - - train_p_bar.set_description(f"Epoch {e} - BPTT Training Loss: {round(loss.item(), 4)}") - - batch_count += 1 - losses.append(loss.item()) - batches.append(batch_count) - - epochs_y.append(losses) - epochs_x.append(batches) - - acc = test(device, nb_time_steps, batch_size, feature_map_size, dataloader_test, model) - print(f'Epoch {e} accuracy: {acc}') - epochs_acc.append(acc) - - return epochs_x, epochs_y, epochs_acc - -def training_loop_no_tqdm(device, nb_time_steps, batch_size, feature_map_size, dataloader_train, model, loss_fn, optimizer, epochs, dataloader_test, record_data = False): - epochs_y = [] - epochs_x = [] - epochs_acc = [] - - model.train() - - for e in range(epochs): - losses = [] - batches = [] - batch_count = 0 - - for X, y in dataloader_train: - # reshape the input from [Batch, Time, Channel, Height, Width] into [Batch*Time, Channel, Height, Width] - X = X.reshape(-1, feature_map_size[2], feature_map_size[0], feature_map_size[1]).to(dtype=torch.float, device=device) - y = y.to(dtype=torch.long, device=device) - - # forward - pred = model(X) - - # reshape the output from [Batch*Time,num_classes] into [Batch, Time, num_classes] - pred = pred.reshape(batch_size, nb_time_steps, -1) - - # accumulate all time-steps output for final prediction - pred = pred.sum(dim = 1) - loss = loss_fn(pred, y) - - # gradient update - optimizer.zero_grad() - loss.backward() - optimizer.step() - - # detach the neuron states and activations from current computation graph(necessary) - model.detach_neuron_states() - - if record_data: - batch_count += 1 - losses.append(loss.item()) - batches.append(batch_count) - - if record_data: - epochs_y.append(losses) - epochs_x.append(batches) - - acc = test_no_tqdm(device, nb_time_steps, batch_size, feature_map_size, dataloader_test, model) - if record_data: - epochs_acc.append(acc) - - if record_data: - return epochs_x, epochs_y, epochs_acc - else: - return acc - -def test_no_tqdm(device, nb_time_steps, batch_size, feature_map_size, dataloader_test, model): - correct_predictions = [] - - with torch.no_grad(): - for X, y in dataloader_test: - # reshape the input from [Batch, Time, Channel, Height, Width] into [Batch*Time, Channel, Height, Width] - X = X.reshape(-1, feature_map_size[2], feature_map_size[0], feature_map_size[1]).to(dtype=torch.float, device=device) - y = y.to(dtype=torch.long, device=device) - - # forward - output = model(X) - - # reshape the output from [Batch*Time,num_classes] into [Batch, Time, num_classes] - output = output.reshape(batch_size, nb_time_steps, -1) - - # accumulate all time-steps output for final prediction - output = output.sum(dim=1) - - # calculate accuracy - pred = output.argmax(dim=1, keepdim=True) - - # compute the total correct predictions - correct_predictions.append(pred.eq(y.view_as(pred))) - - correct_predictions = torch.cat(correct_predictions) - return correct_predictions.sum().item()/(len(correct_predictions))*100 - -def test(device, nb_time_steps, batch_size, feature_map_size, dataloader_test, model): - correct_predictions = [] - with torch.no_grad(): - test_p_bar = tqdm(dataloader_test) - for X, y in test_p_bar: - # reshape the input from [Batch, Time, Channel, Height, Width] into [Batch*Time, Channel, Height, Width] - X = X.reshape(-1, feature_map_size[2], feature_map_size[0], feature_map_size[1]).to(dtype=torch.float, device=device) - y = y.to(dtype=torch.long, device=device) - - # forward - output = model(X) - - # reshape the output from [Batch*Time,num_classes] into [Batch, Time, num_classes] - output = output.reshape(batch_size, nb_time_steps, -1) - - # accumulate all time-steps output for final prediction - output = output.sum(dim=1) - - # calculate accuracy - pred = output.argmax(dim=1, keepdim=True) - - # compute the total correct predictions - correct_predictions.append(pred.eq(y.view_as(pred))) - - test_p_bar.set_description(f"Testing Model...") - - correct_predictions = torch.cat(correct_predictions) - return correct_predictions.sum().item()/(len(correct_predictions))*100 - -def load_dataset(dataset, n_time_steps): - if dataset == 'DVSGESTURE': - root_dir = "../../DVSGESTURE" - _ = DVSGesture(save_to=root_dir, train=True) - _ = DVSGesture(save_to=root_dir, train=False) - - to_raster = ToFrame(sensor_size=DVSGesture.sensor_size, n_time_bins=n_time_steps) - - snn_train_dataset = DVSGesture(save_to=root_dir, train=True, transform=to_raster) - snn_test_dataset = DVSGesture(save_to=root_dir, train=False, transform=to_raster) - - return snn_train_dataset, snn_test_dataset, DVSGesture.sensor_size - - elif dataset == 'NMNIST': - root_dir = "../../NMNIST" - _ = NMNIST(save_to=root_dir, train=True) - _ = NMNIST(save_to=root_dir, train=False) - - to_raster = ToFrame(sensor_size=NMNIST.sensor_size, n_time_bins=n_time_steps) - - snn_train_dataset = NMNIST(save_to=root_dir, train=True, transform=to_raster) - snn_test_dataset = NMNIST(save_to=root_dir, train=False, transform=to_raster) - - return snn_train_dataset, snn_test_dataset, NMNIST.sensor_size - - else: - - raise ValueError('no valid dataset') - -def split_train_validation(validation_ratio, snn_train_dataset, rand_seed): - num_samples = len(snn_train_dataset) - num_validation_samples = int(validation_ratio * num_samples) - - np.random.seed(rand_seed) - - validation_indices = np.random.choice(np.arange(num_samples), size=num_validation_samples, replace=False) - training_indices = np.array(list(filter(lambda x: x not in validation_indices, np.arange(num_samples)))) - - train_dataset = Subset(snn_train_dataset, training_indices) - validation_dataset = Subset(snn_train_dataset, validation_indices) - - return train_dataset, validation_dataset - -def split_train_validation_used_seed(validation_ratio, snn_train_dataset, used_seed): - """ Will generate a validation dataset in which the random indices do not overlap - with the ones that are generated using the random seed `used_seed`. - """ - num_samples = len(snn_train_dataset) - num_validation_samples = int(validation_ratio * num_samples) - - np.random.seed(used_seed) - - used_validation_indices = np.random.choice(np.arange(num_samples), size=num_validation_samples, replace=False) - - validation_indices = np.random.choice(np.setdiff1d(np.arange(num_samples), used_validation_indices), size=len(used_validation_indices), replace=False) - - training_indices = np.array(list(filter(lambda x: x not in validation_indices, np.arange(num_samples)))) - - if len(np.intersect1d(used_validation_indices, validation_indices)) != 0: - raise ValueError(f'data leakage: generated validation set overlaps with previously generated indices') - - train_dataset = Subset(snn_train_dataset, training_indices) - validation_dataset = Subset(snn_train_dataset, validation_indices) - - return train_dataset, validation_dataset - -def load_architecture( - architecture, input_size, nb_classes, batch_size, surrogate_fn, - min_v_mem=-0.313, spk_thr=2.0, hetero_init = False, hetero_seed = 1): - import sys - sys.path.append('../models') - - if architecture == 'ResSCNN_1': - from ResSCNN_1 import SCNN - return SCNN(input_size, nb_classes, batch_size, surrogate_fn, min_v_mem, spk_thr) - elif architecture == 'ResSCNN_2': - from ResSCNN_2 import SCNN - return SCNN(input_size, nb_classes, batch_size, surrogate_fn, min_v_mem, spk_thr) - elif architecture == 'ResSCNN_3': - from ResSCNN_3 import SCNN - return SCNN(input_size, nb_classes, batch_size, surrogate_fn, min_v_mem, spk_thr) - elif architecture == 'ResSCNN_4': - from ResSCNN_4 import SCNN - return SCNN(input_size, nb_classes, batch_size, surrogate_fn, min_v_mem, spk_thr) - elif architecture == 'ResSCNN_5': - from ResSCNN_5 import SCNN - return SCNN(input_size, nb_classes, batch_size, surrogate_fn, min_v_mem, spk_thr) - elif architecture == 'ResSCNN_6': - from ResSCNN_6 import SCNN - return SCNN(input_size, nb_classes, batch_size, surrogate_fn, min_v_mem, spk_thr) - elif architecture == 'ResSCNN_7': - from ResSCNN_7 import SCNN - return SCNN(input_size, nb_classes, batch_size, surrogate_fn, min_v_mem, spk_thr) - elif architecture == 'ResSCNN_8': - from ResSCNN_8 import SCNN - return SCNN(input_size, nb_classes, batch_size, surrogate_fn, min_v_mem, spk_thr) - elif architecture == 'ResSCNN_9': - from ResSCNN_9 import SCNN - return SCNN(input_size, nb_classes, batch_size, surrogate_fn, min_v_mem, spk_thr, hetero_init, hetero_seed) - elif architecture == 'ResSCNN_10': - from ResSCNN_10 import SCNN - return SCNN(input_size, nb_classes, batch_size, surrogate_fn, min_v_mem, spk_thr) - elif architecture == 'ResSCNN_11': - from ResSCNN_11 import SCNN - return SCNN(input_size, nb_classes, batch_size, surrogate_fn, min_v_mem, spk_thr) - else: - return None \ No newline at end of file diff --git a/tests/test_nonsequential/utils/weight_initialization.py b/tests/test_nonsequential/utils/weight_initialization.py deleted file mode 100644 index 53d2ddb6..00000000 --- a/tests/test_nonsequential/utils/weight_initialization.py +++ /dev/null @@ -1,49 +0,0 @@ -import torch.nn as nn -import numpy as np -import statistics - -def rescale_method_1(conv_layer: nn.Conv2d, input_pool_kernel: list, lambda_: float = 1): - """ - The `method 1` will use the average of the computed rescaling factor for each pooling layer - feeding into `conv_layer` (if there are more than one) to rescale its weights. - - Arguments - --------- - input_pool_kernel (list): the kernels of all pooling layers feeding input to `conv_layer`. - lambda_ (float): scales the computed re-scaling factor. If the outputs of the pooling are too small - the rescaling might lead to vanishing gradients, so we can try to control that by scaling it by - lambda. - """ - rescaling_factors = [] - - for kernel in input_pool_kernel: - rescaling_factors.append(kernel[0]*kernel[1]) - - rescaling_factor = np.mean(rescaling_factors)*lambda_ - - # print(f'method 1 - recaling factor: {rescaling_factor} (computed using {len(input_pool_kernel)} kernels and lambda {lambda_})') - - conv_layer.weight.data /= rescaling_factor - -def rescale_method_2(conv_layer: nn.Conv2d, input_pool_kernel: list, lambda_: float = 1): - """ - The `method 2` will use the harmonic mean of the computed rescaling factor for each pooling layer - feeding into `conv_layer` (if there are more than one) to rescale its weights. - - Arguments - --------- - input_pool_kernel (list): the kernels of all pooling layers feeding input to `conv_layer`. - lambda_ (float): scales the computed re-scaling factor. If the outputs of the pooling are too small - the rescaling might lead to vanishing gradients, so we can try to control that by scaling it by - lambda. - """ - rescaling_factors = [] - - for kernel in input_pool_kernel: - rescaling_factors.append(kernel[0]*kernel[1]) - - rescaling_factor = statistics.harmonic_mean(rescaling_factors)*lambda_ - - # print(f'method 2 - recaling factor: {rescaling_factor} (computed using {len(input_pool_kernel)} kernels and lambda {lambda_})') - - conv_layer.weight.data /= rescaling_factor \ No newline at end of file