{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "25d9cf74",
   "metadata": {},
   "source": [
    "# How to add a trainable readout\n",
    "\n",
    "**Task.** Decode a continuous output from a spiking network with a\n",
    "`LeakyRateReadout` head, and train it end to end.\n",
    "\n",
    "**Audience.** Training. Assumes {doc}`../tutorials/04-train-an-snn`.\n",
    "\n",
    "A spiking hidden layer emits 0/1 events; to produce a smooth, trainable output\n",
    "you read it out through a leaky rate unit. `brainpy.state.LeakyRateReadout`\n",
    "applies a trainable weight and low-pass filters the result with time constant\n",
    "`tau`, giving a differentiable `[batch, out]` signal you can attach a loss to."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "e518120b",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-06-17T09:08:56.189680Z",
     "iopub.status.busy": "2026-06-17T09:08:56.189440Z",
     "iopub.status.idle": "2026-06-17T09:09:00.314689Z",
     "shell.execute_reply": "2026-06-17T09:09:00.313500Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "An NVIDIA GPU may be present on this machine, but a CUDA-enabled jaxlib is not installed. Falling back to cpu.\n"
     ]
    }
   ],
   "source": [
    "import brainpy\n",
    "import brainstate\n",
    "import braintools\n",
    "import brainunit as u\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a8dbb637",
   "metadata": {},
   "source": [
    "## A recurrent SNN with a rate readout\n",
    "\n",
    "The hidden layer is a surrogate-gradient LIF; the readout maps its spikes to the\n",
    "output classes."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "4dbdf8d2",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-06-17T09:09:00.316899Z",
     "iopub.status.busy": "2026-06-17T09:09:00.316580Z",
     "iopub.status.idle": "2026-06-17T09:09:00.321652Z",
     "shell.execute_reply": "2026-06-17T09:09:00.320543Z"
    }
   },
   "outputs": [],
   "source": [
    "class ReadoutSNN(brainstate.nn.Module):\n",
    "    def __init__(self, n_in, n_rec, n_out):\n",
    "        super().__init__()\n",
    "        self.i2r = brainstate.nn.Sequential(\n",
    "            brainstate.nn.Linear(\n",
    "                n_in, n_rec,\n",
    "                w_init=braintools.init.KaimingNormal(unit=u.mA),\n",
    "                b_init=braintools.init.ZeroInit(unit=u.mA)),\n",
    "            brainpy.state.Expon(n_rec, tau=5. * u.ms,\n",
    "                                g_initializer=braintools.init.Constant(0. * u.mA)))\n",
    "        self.r = brainpy.state.LIF(\n",
    "            n_rec, tau=20. * u.ms, V_rest=0. * u.mV, V_reset=0. * u.mV,\n",
    "            V_th=1. * u.mV, spk_fun=braintools.surrogate.ReluGrad())\n",
    "        # trainable, low-pass readout head\n",
    "        self.readout = brainpy.state.LeakyRateReadout(n_rec, n_out, tau=10. * u.ms)\n",
    "\n",
    "    def update(self, spike):\n",
    "        return self.readout(self.r(self.i2r(spike)))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3985b203",
   "metadata": {},
   "source": [
    "## Train it\n",
    "\n",
    "The loss averages the readout over time and applies a cross-entropy, exactly as\n",
    "before; only the output head has changed."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "25059b23",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-06-17T09:09:00.324189Z",
     "iopub.status.busy": "2026-06-17T09:09:00.323908Z",
     "iopub.status.idle": "2026-06-17T09:09:05.935739Z",
     "shell.execute_reply": "2026-06-17T09:09:05.934796Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "first 1.0986  last 0.8690\n"
     ]
    }
   ],
   "source": [
    "with brainstate.environ.context(dt=1.0 * u.ms):\n",
    "    n_in, n_rec, n_out = 100, 8, 3\n",
    "    num_step, num_sample = 150, 128\n",
    "    net = ReadoutSNN(n_in, n_rec, n_out)\n",
    "\n",
    "    x_data = (brainstate.random.rand(num_step, num_sample, n_in)\n",
    "              < 6. * u.Hz * brainstate.environ.get_dt()).astype(float)\n",
    "    y_data = u.math.asarray(brainstate.random.randint(0, n_out, (num_sample,)), dtype=int)\n",
    "\n",
    "    optimizer = braintools.optim.Adam(lr=2e-3)\n",
    "    optimizer.register_trainable_weights(net.states(brainstate.ParamState))\n",
    "\n",
    "    def loss_fn():\n",
    "        preds = brainstate.transform.for_loop(net.update, x_data)   # [T, B, C]\n",
    "        preds = u.math.mean(preds, axis=0)\n",
    "        return braintools.metric.softmax_cross_entropy_with_integer_labels(\n",
    "            preds, y_data).mean()\n",
    "\n",
    "    @brainstate.transform.jit\n",
    "    def train_step():\n",
    "        brainstate.nn.init_all_states(net, batch_size=num_sample)\n",
    "        grads, l = brainstate.transform.grad(\n",
    "            loss_fn, net.states(brainstate.ParamState), return_value=True)()\n",
    "        optimizer.update(grads)\n",
    "        return l\n",
    "\n",
    "    losses = [float(train_step()) for _ in range(200)]\n",
    "\n",
    "print('first %.4f  last %.4f' % (losses[0], losses[-1]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "1658ad28",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-06-17T09:09:05.938563Z",
     "iopub.status.busy": "2026-06-17T09:09:05.937864Z",
     "iopub.status.idle": "2026-06-17T09:09:06.011486Z",
     "shell.execute_reply": "2026-06-17T09:09:06.010667Z"
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "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TPxsdevWLbBOkiRh3LhxAKrGNjpy5Ai6d+8OZ2dnSJKEbdu26U0XQmDWrFlwcnKCsbExAgICEBERodfn4cOHGDRoECwsLGBlZYXhw4cjPT29AtdC39PWKS8vDzNmzECzZs1gamoKZ2dnDB48GDExMXrLKGzbfvrppxW8Jv/zrO00dOjQAnm7dOmi16cqbScAhb63JEnCwoULdX0q23Yqzmd3cT7roqOjERQUBBMTE9jb22PatGnIz88vk4wsQirAhg0bMHnyZMyePRvnz5+Hj48PAgMDkZCQIHe0Yvnrr78wbtw4nDx5Evv27UNeXh46d+6MjIwMvX4jR45EbGys7vH555/LlLh4mjZtqpf32LFjummTJk3Czp07sWnTJvz111+IiYlB7969ZUz7bGfOnNFbn3379gEA+vXrp+tT2bdRRkYGfHx8sHz58kKnf/755/j666+xcuVKnDp1CqampggMDER2drauz6BBg3DlyhXs27cPv//+O44cOYJRo0ZV1CoU8LR1yszMxPnz5/HRRx/h/Pnz2LJlC65fv44ePXoU6Dtv3jy9bffuu+9WRPxCPWs7AUCXLl308v7yyy9606vSdgKgty6xsbH48ccfIUkS+vTpo9evMm2n4nx2P+uzTqPRICgoCLm5uThx4gTWrFmDkJAQzJo1q2xCCip3L774ohg3bpzud41GI5ydncWCBQtkTPX8EhISBADx119/6drat28v3nvvPflCldDs2bOFj49PodOSk5OFoaGh2LRpk67t2rVrAoAIDQ2toISl99577wkPDw+h1WqFEFVvGwEQW7du1f2u1WqFo6OjWLhwoa4tOTlZqFQq8csvvwghhLh69aoAIM6cOaPr88cffwhJksT9+/crLHtR/r1OhTl9+rQAIO7cuaNrc3NzE4sXLy7fcM+psHUaMmSI6NmzZ5HzVIft1LNnT/HKK6/otVXm7SREwc/u4nzW7d69WygUChEXF6frs2LFCmFhYSFycnJKnYl7QspZbm4uzp07h4CAAF2bQqFAQEAAQkNDZUz2/FJSUgAA1tbWeu0///wzbG1t4eXlheDgYGRmZsoRr9giIiLg7OwMd3d3DBo0CNHR0QCAc+fOIS8vT2+beXp6ok6dOlVmm+Xm5mLdunV4++239W7CWNW20T9FRkYiLi5Ob7tYWlrCz89Pt11CQ0NhZWWFli1b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",
      "text/plain": [
       "<Figure size 600x300 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.figure(figsize=(6, 3))\n",
    "plt.plot(np.asarray(losses))\n",
    "plt.xlabel('Epoch'); plt.ylabel('Training loss')\n",
    "plt.title('Training a LeakyRateReadout head')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "63ce52ac",
   "metadata": {},
   "source": [
    "## See also\n",
    "\n",
    "- {doc}`/apis/brainpy-readouts` — `LeakyRateReadout` reference.\n",
    "- {doc}`train-surrogate-gradients` — the surrogate on the hidden layer.\n",
    "- {doc}`train-long-rollouts-checkpoint` — long-sequence training."
   ]
  }
 ],
 "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.13.11"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
