{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"execution": {},
"id": "view-in-github"
},
"source": [
""
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"# Using RL to Model Cognitive Tasks\n",
"\n",
"**By Neurmatch Academy**\n",
"\n",
"__Content creators:__ Morteza Ansarinia, Yamil Vidal\n",
"\n",
"__Production editor:__ Spiros Chavlis\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"---\n",
"# Objective\n",
"\n",
"- This project aims to use behavioral data to train an agent and then use the agent to investigate data produced by human subjects. Having a computational agent that mimics humans in such tests, we will be able to compare its mechanics with human data.\n",
"\n",
"- In another conception, we could fit an agent that learns many cognitive tasks that require abstract-level constructs such as executive functions. This is a multi-task control problem.\n",
"\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"---\n",
"# Setup"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Install dependencies\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"hide-input"
]
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m A new release of pip is available: \u001b[0m\u001b[31;49m24.0\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m24.1.2\u001b[0m\n",
"\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m To update, run: \u001b[0m\u001b[32;49mpip install --upgrade pip\u001b[0m\n",
"\u001b[33mWARNING: Skipping seaborn as it is not installed.\u001b[0m\u001b[33m\n",
"\u001b[0m"
]
}
],
"source": [
"# @title Install dependencies\n",
"!pip install jedi --quiet --root-user-action=ignore\n",
"!pip install --upgrade pip setuptools wheel --quiet --root-user-action=ignore\n",
"!pip install 'dm-acme[jax]' --quiet --root-user-action=ignore\n",
"!pip install dm-sonnet --quiet --root-user-action=ignore\n",
"!pip install trfl --quiet --root-user-action=ignore\n",
"!pip install numpy==1.24.1 --quiet --ignore-installed --root-user-action=ignore\n",
"!pip uninstall seaborn -y --quiet --root-user-action=ignore\n",
"!pip install seaborn --quiet --root-user-action=ignore"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {}
},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"2024-07-16 14:41:51.924400: W tensorflow/stream_executor/platform/default/dso_loader.cc:64] Could not load dynamic library 'libcudart.so.11.0'; dlerror: libcudart.so.11.0: cannot open shared object file: No such file or directory; LD_LIBRARY_PATH: :/usr/local/cuda-11.0/lib64/:/usr/local/cuda-11.0/lib64/:/usr/local/cuda-11.0/lib64/\n",
"2024-07-16 14:41:51.924418: I tensorflow/stream_executor/cuda/cudart_stub.cc:29] Ignore above cudart dlerror if you do not have a GPU set up on your machine.\n"
]
}
],
"source": [
"# Imports\n",
"import time\n",
"import numpy as np\n",
"import pandas as pd\n",
"import sonnet as snt\n",
"import seaborn as sns\n",
"import matplotlib.pyplot as plt\n",
"\n",
"import dm_env\n",
"\n",
"import acme\n",
"from acme import specs\n",
"from acme import wrappers\n",
"from acme import EnvironmentLoop\n",
"from acme.agents.tf import dqn\n",
"from acme.utils import loggers"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Figure settings\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"hide-input"
]
},
"outputs": [],
"source": [
"# @title Figure settings\n",
"from IPython.display import clear_output, display, HTML\n",
"%matplotlib inline\n",
"sns.set()"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"---\n",
"# Background\n",
"\n",
"- Cognitive scientists use standard lab tests to tap into specific processes in the brain and behavior. Some examples of those tests are Stroop, N-back, Digit Span, TMT (Trail making tests), and WCST (Wisconsin Card Sorting Tests).\n",
"\n",
"- Despite an extensive body of research that explains human performance using descriptive what-models, we still need a more sophisticated approach to gain a better understanding of the underlying processes (i.e., a how-model).\n",
"\n",
"- Interestingly, many of such tests can be thought of as a continuous stream of stimuli and corresponding actions, that is in consonant with the RL formulation. In fact, RL itself is in part motivated by how the brain enables goal-directed behaviors using reward systems, making it a good choice to explain human performance.\n",
"\n",
"- One behavioral test example would be the N-back task.\n",
"\n",
" - In the N-back, participants view a sequence of stimuli, one by one, and are asked to categorize each stimulus as being either match or non-match. Stimuli are usually numbers, and feedback is given at both timestep and trajectory levels.\n",
"\n",
" - The agent is rewarded when its response matches the stimulus that was shown N steps back in the episode. A simpler version of the N-back uses two-choice action schema, that is match vs non-match. Once the present stimulus matches the one presented N step back, then the agent is expected to respond to it as being a `match`.\n",
"\n",
"\n",
"- Given a trained RL agent, we then find correlates of its fitted parameters with the brain mechanisms. The most straightforward composition could be the correlation of model parameters with the brain activities."
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"## Datasets\n",
"\n",
"- HCP WM task ([NMA-CN HCP notebooks](https://github.com/NeuromatchAcademy/course-content/tree/master/projects/fMRI))\n",
"\n",
"Any dataset that used cognitive tests would work.\n",
"Question: limit to behavioral data vs fMRI?\n",
"Question: Which stimuli and actions to use?\n",
"classic tests can be modeled using 1) bounded symbolic stimuli/actions (e.g., A, B, C), but more sophisticated one would require texts or images (e.g., face vs neutral images in social stroop dataset)\n",
"The HCP dataset from NMA-CN contains behavioral and imaging data for 7 cognitive tests including various versions of N-back."
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"## N-back task\n",
"\n",
"In the N-back task, participants view a sequence of stimuli, one per time, and are asked to categorize each stimulus as being either match or non-match. Stimuli are usually numbers, and feedbacks are given at both timestep and trajectory levels.\n",
"\n",
"In a typical neuro setup, both accuracy and response time are measured, but here, for the sake of brevity, we focus only on accuracy of responses."
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"---\n",
"# Cognitive Tests Environment\n",
"\n",
"First we develop an environment in that agents perform a cognitive test, here the N-back."
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"## Human dataset\n",
"\n",
"We need a dataset of human perfoming a N-back test, with the following features:\n",
"\n",
"- `participant_id`: following the BIDS format, it contains a unique identifier for each participant.\n",
"- `trial_index`: same as `time_step`.\n",
"- `stimulus`: same as `observation`.\n",
"- `response`: same as `action`, recorded response by the human subject.\n",
"- `expected_response`: correct response.\n",
"- `is_correct`: same as `reward`, whether the human subject responded correctly.\n",
"- `response_time`: won't be used here.\n",
"\n",
"Here we generate a mock dataset with those features, but remember to **replace this with real human data.**"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {}
},
"outputs": [
{
"data": {
"image/png": "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yIkTJ1BWVobWrVvD1tYWgYGB+Pnnn/XapKSkwN3dvVoDjImIiKhyvERlhujoaHh5ecHDwwMNGzbEuXPn8PXXX8PDwwN9+vQBAEyZMgWjR4/Ge++9h/DwcBw6dAjJycn47LPPrFw9ERGR+DHgmMHHxwcpKSlYunQpBEFAq1atEBkZiQkTJsDW1hYA0LVrV8TFxeHzzz/HDz/8gJYtW2L+/PkIDw+3cvVERETix4BjhkmTJmHSpEmVtuvduzd69+5dCxURERFReRyDQ0RERKLDgENERESiw4BDREREosOAQ0RERKLDgENERESiw4BDREREosOAQ0RERKLDgENERESiw4BDREREosOAQ0RERKLDgENERESiw4BDREREosOAQ0RERKLDgENERESiw4BDREREosOAQ0RERKIjt3YBRNUllUqq1F4QBAiChYohIqKHAgMO1VmNGsih1ghwcbGr0nIqtQY52QUMOUREIsaAQ3WWrY0MMqkESzYcR05+iUnLONs3wNRIX0gkEghMOEREosWAQ3VeTn4JspXF1i6DiIgeIhxkTERERKLDgENERESiw4BDREREosOAQ0RERKLDgENERESiw4BDREREosOAQ0RERKLDgENERESiw4BDREREosOAQ0RERKLDgENERESiw4BDREREosOAQ0RERKLDgENERESiw4BDREREosOAQ0RERKLDgENERESiw4Bjhm3btmHKlCno2bMnfH19MXDgQPzwww8QBEGv3YYNGxAWFgZvb28MGDAAO3futFLFRERE9QsDjhm+/fZbNGrUCLNmzUJiYiJ69uyJ2NhYJCQk6Nps3boVsbGxCA8PR1JSEnx9fREdHY3jx49br3AiIqJ6Qm7tAuqixMRENGnSRPd7cHAwcnJysHz5ckydOhVSqRSLFy9GREQEpk+fDgAICgrC+fPnkZCQgKSkJCtVTkREVD/wDI4ZyocbLU9PT+Tn56OwsBCZmZm4fPkywsPD9dr07dsXBw4cQGlpaW2VSkREVC/xDE4NSU9PR/PmzWFvb4/09HQAgJubm14bd3d3lJWVITMzE+7u7mZvSy6vfi6VSv9dhwSQSCSVttc2kUgkJrU3ZxlLt9e2Be71oUYjVNK66mQyqd5PqhnsV8th31oG+9X6GHBqwO+//46UlBS89dZbAIDc3FwAgKOjo1477e/a+eaQSiVwcbEz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7t69q9f21KlTmDBhAgIDA+Hj44PQ0FDMnj1br41Go8G3336LiIgIeHt748knn8ScOXOQm5tbpX78+OOPAQC9e/eGh4cHPDw8cO3aNQCGY3C0r+H333/H/PnzERQUhK5du2LOnDkoLS2FUqnEm2++iYCAAAQEBODjjz/G/X8LuSbqJqoveImKqJ567bXX8PjjjyMmJgaCICAxMRFffPEFwsPDMWzYMNy9exerVq3CCy+8gP/+979wdHREaWkpJkyYgNLSUrz44ot45JFHcOvWLezatQtKpRIODg669R85cgQpKSmIioqCra0t1qxZg4kTJ2LDhg1QKBQAgAsXLuCFF16AnZ0dJk6cCLlcjnXr1iEqKgqrVq1C586d9WqeP38+HB0dER0djaysLKxYsQLz5s3D559/DgC4c+cOJkyYABcXF0yaNAmOjo64du0atm/frreeOXPmYNOmTRgyZAiioqJw7do1rF69GmfOnMGaNWtMOvPyzDPP4PLly0hOTsbs2bPh4uICAGjSpMkDl5s/fz4eeeQRTJs2DSdOnMC6devg4OCAY8eO4bHHHkNMTAx2796Nr7/+GgqFAoMGDarRuonqDYGI6pXFixcLCoVCeP3113XTrl27Jnh6egqJiYl6bf/880+hY8eOuulnzpwRFAqFsG3btgduQ6FQCAqFQjh16pRuWlZWluDt7S288sorumlTp04VOnXqJFy9elU37datW4Kfn5/wwgsv6Kb9+OOPgkKhEMaOHStoNBrd9A8++EDw9PQUlEqlIAiCsH37dkGhUAgnT56ssLYjR44ICoVC2LJli9703bt3G53+IMuWLRMUCoWQmZlpMK9Xr17CW2+9ZfAaxo8fr/cann/+ecHDw0OYM2eObppKpRJ69uwpvPjiixapm6g+4CUqonpqxIgRuv/fvn07NBoNwsPDcffuXd1/jzzyCB5//HEcOnQIAGBvbw8A2Lt3L4qKih64fj8/P3h5eel+b9myJXr37o29e/dCrVZDrVZj37596NOnD1xdXXXtHn30UfTr1w/p6enIz8/XW+fw4cP1Bu527doVarUaWVlZAKA7g7Rr1y6UlZUZrSs1NRUODg4ICQnRe62dOnVC48aNda/VUoYNG6b3Gnx8fCAIAoYNG6abJpPJ4OXlhczMzIembqK6hpeoiOqp1q1b6/7/8uXLEAQBzz77rNG2cvm9jwpXV1eMGzcOy5cvx08//YSuXbsiNDQUAwYM0Ls8BQCPP/64wXratm2LoqIi3biZoqIiuLm5GbRzd3eHRqPBjRs38MQTT+imt2zZUq+d9s4l7W3a3bp1Q1hYGOLj4/Htt9+iW7du6NOnD/r37w9bW1sAwJUrV5CXl4fg4GCjr/XOnTtGp9eU+1+Dtt8ee+wxg+nlx9ZYu26iuoYBh6ieatCgge7/NRoNJBIJkpKSIJPJDNo2btxY9/+zZs3C4MGDkZaWhn379mH+/Pn46quvsH79erRo0cKiNUulxk86C/8OxpVIJFi8eDGOHz+OnTt3Ys+ePXj77bexfPlyrFu3DnZ2dtBoNGjatCk+/fRTo+uqbAxNdVX0GiqarmXtuonqGgYcIkKbNm0gCAJat25t9IzK/bR3DE2dOhVHjx7FyJEjsWbNGsTExOjaXLlyxWC5y5cvo1GjRrp/jBs1aoS//vrLoF1GRgakUqnBWQ1T+fr6wtfXFzExMfjpp58wc+ZMpKSkIDIyEm3atMGBAwfg7++Phg0bmrV+rdp8zk1N1k1UH3AMDhHh2WefhUwmQ3x8vMGtyYIgIDs7GwCQn58PlUqlN1+hUEAqlaK0tFRv+rFjx3D69Gnd7zdu3EBaWhpCQkIgk8kgk8kQEhKCtLQ03a3VAPDPP/8gOTkZXbp00Y35MVVubq5B/Z6engCgqy88PBxqtRpLliwxWF6lUlXpqcSNGjUCAL1b5C2lJusmqg94BoeI0KZNG0yfPh0LFy5EVlYW+vTpAzs7O1y7dg2//vorhg8fjgkTJuDgwYOYN28ennvuObRt2xZqtRqbN2+GTCZDWFiY3joVCgUmTJigd5s4AEybNk3XZvr06di/fz9GjRqFUaNGQSaTYd26dSgtLcUbb7xR5dexadMmrFmzBn369EGbNm1QUFCA9evXw97eHj179gRwb5zO888/j6+++gpnz55FSEgIbGxscPnyZaSmpuKdd97Bc889Z9L2OnXqBAD47LPP0LdvX9jY2KBXr156l/RqSk3WTVQfMOAQEQBg0qRJaNu2Lb799lskJCQAAFq0aIGQkBCEhoYCuHdpqnv37ti5cydu3bqFRo0awcPDA0lJSfD19dVbX0BAAHx9fZGQkIDr16+jffv2WLBgATp06KBr88QTT2D16tVYuHAhvvrqKwiCAB8fH3zyyScGz8AxRbdu3XDq1CmkpKTgn3/+gYODA3x8fPDpp5/q3ak1b948eHl5Ye3atfjss88gk8nQqlUrDBgwAP7+/iZvz8fHB6+99hrWrl2LPXv2QKPRIC0tzSIBpybrJqoPJML953OJiKrJw8MDL7zwAubMmWPtUoionuIYHCIiIhIdXqIiIrpPQUFBpX+AtEmTJkZvqSeihwMDDhHRfb755hvEx8c/sE1aWprewxKJ6OHCMThERPfJzMzU+zMJxnTp0kXvYYlE9HBhwCEiIiLR4SBjIiIiEh0GHCIiIhIdBhwiIiISHQYcIiIiEh0GHCIiIhIdBhwiIiISHQYcIiIiEp3/BzaJAvNZB1iAAAAAAElFTkSuQmCC",
"text/plain": [
"
"
],
"text/plain": [
" participant_id trial_index stimulus response response_time \\\n",
"0 sub-1 1 A None NaN \n",
"1 sub-1 2 C None NaN \n",
"2 sub-1 3 C non-match 0.317768 \n",
"3 sub-1 4 C non-match 1.096391 \n",
"4 sub-1 5 F non-match 0.843995 \n",
"\n",
" expected_response is_correct \n",
"0 None 1 \n",
"1 None 1 \n",
"2 non-match 1 \n",
"3 match 0 \n",
"4 non-match 1 "
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def generate_mock_nback_dataset(N=2,\n",
" n_participants=10,\n",
" n_trials=32,\n",
" stimulus_choices=list('ABCDEF'),\n",
" response_choices=['match', 'non-match']):\n",
" \"\"\"Generate a mock dataset for the N-back task.\"\"\"\n",
"\n",
" n_rows = n_participants * n_trials\n",
"\n",
" participant_ids = sorted([f'sub-{pid}' for pid in range(1, n_participants + 1)] * n_trials)\n",
" trial_indices = list(range(1, n_trials + 1)) * n_participants\n",
" stimulus_sequence = np.random.choice(stimulus_choices, n_rows)\n",
"\n",
" responses = np.random.choice(response_choices, n_rows)\n",
" response_times = np.random.exponential(size=n_rows)\n",
"\n",
" df = pd.DataFrame({\n",
" 'participant_id': participant_ids,\n",
" 'trial_index': trial_indices,\n",
" 'stimulus': stimulus_sequence,\n",
" 'response': responses,\n",
" 'response_time': response_times\n",
" })\n",
"\n",
" # mark matchig stimuli\n",
" _nback_stim = df['stimulus'].shift(N)\n",
" df['expected_response'] = (df['stimulus'] == _nback_stim).map({True: 'match', False: 'non-match'})\n",
"\n",
" df['is_correct'] = (df['response'] == df['expected_response'])\n",
"\n",
" # we don't care about burn-in trials (trial < N)\n",
" df.loc[df['trial_index'] <= N, 'is_correct'] = True\n",
" df.loc[df['trial_index'] <= N, ['response', 'response_time', 'expected_response']] = None\n",
"\n",
" return df\n",
"\n",
"\n",
"# ========\n",
"# now generate the actual data with the provided function and plot some of its features\n",
"mock_nback_data = generate_mock_nback_dataset()\n",
"mock_nback_data['is_correct'] = mock_nback_data['is_correct'].astype(int)\n",
"\n",
"sns.displot(data=mock_nback_data, x='response_time')\n",
"plt.suptitle('response time distribution of the mock N-back dataset', y=1.01)\n",
"plt.show()\n",
"\n",
"sns.displot(data=mock_nback_data, x='is_correct')\n",
"plt.suptitle('Accuracy distribution of the mock N-back dataset', y=1.06)\n",
"plt.show()\n",
"\n",
"sns.barplot(data=mock_nback_data, y='is_correct', x='participant_id')\n",
"plt.suptitle('Accuracy distribution of the mock N-back dataset', y=1.06)\n",
"plt.show()\n",
"\n",
"mock_nback_data.head()"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"## Implementation scheme\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"### Environment\n",
"\n",
"The following cell implments N-back envinronment, that we later use to train a RL agent on human data. It is capable of performing two kinds of simulation:\n",
"- rewards the agent once the action was correct (i.e., a normative model of the environment).\n",
"- receives human data (or mock data if you prefer), and returns what participants performed as the observation. This is more useful for preference-based RL."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {}
},
"outputs": [],
"source": [
"class NBack(dm_env.Environment):\n",
"\n",
" ACTIONS = ['match', 'non-match']\n",
"\n",
" def __init__(self,\n",
" N=2,\n",
" episode_steps=32,\n",
" stimuli_choices=list('ABCDEF'),\n",
" human_data=None,\n",
" seed=1,\n",
" ):\n",
" \"\"\"\n",
" Args:\n",
" N: Number of steps to look back for the matched stimuli. Defaults to 2 (as in 2-back).\n",
" episode_steps\n",
" stimuli_choices\n",
" human_data\n",
" seed\n",
"\n",
" \"\"\"\n",
" self.N = N\n",
" self.episode_steps = episode_steps\n",
" self.stimuli_choices = stimuli_choices\n",
" self.stimuli = np.empty(shape=episode_steps) # will be filled in the `reset()`\n",
"\n",
" self._reset_next_step = True\n",
"\n",
" # whether mimic humans or reward the agent once it responds optimally.\n",
" if human_data is None:\n",
" self._imitate_human = False\n",
" self.human_data = None\n",
" self.human_subject_data = None\n",
" else:\n",
" self._imitate_human = True\n",
" self.human_data = human_data\n",
" self.human_subject_data = None\n",
"\n",
" self._action_history = []\n",
"\n",
" def reset(self):\n",
" self._reset_next_step = False\n",
" self._current_step = 0\n",
" self._action_history.clear()\n",
"\n",
" # generate a random sequence instead of relying on human data\n",
" if self.human_data is None:\n",
" # self.stimuli = np.random.choice(self.stimuli_choices, self.episode_steps)\n",
" # FIXME This is a fix for acme & reverb issue with string observation. Agent should be able to handle strings\n",
" self.stimuli = np.random.choice(len(self.stimuli_choices), self.episode_steps).astype(np.float32)\n",
" else:\n",
" # randomly choose a subject from the human data and follow her trials and responses.\n",
" # FIXME should we always use one specific human subject or randomly select one in each episode?\n",
" self.human_subject_data = self.human_data.query('participant_id == participant_id.sample().iloc[0]',\n",
" engine='python').sort_values('trial_index')\n",
" self.stimuli = self.human_subject_data['stimulus'].to_list()\n",
" self.stimuli = np.array([ord(s) - ord('A') + 1 for s in self.stimuli]).astype(np.float32)\n",
"\n",
" return dm_env.restart(self._observation())\n",
"\n",
"\n",
" def _episode_return(self):\n",
" if self._imitate_human:\n",
" return np.mean(self.human_subject_data['response'] == self._action_history)\n",
" else:\n",
" return 0.0\n",
"\n",
" def step(self, action: int):\n",
" if self._reset_next_step:\n",
" return self.reset()\n",
"\n",
" agent_action = NBack.ACTIONS[action]\n",
"\n",
" if self._imitate_human:\n",
" # if it was the same action as the human subject, then reward the agent\n",
" human_action = self.human_subject_data['response'].iloc[self._current_step]\n",
" step_reward = 0. if (agent_action == human_action) else -1.\n",
" else:\n",
" # assume the agent is rationale and doesn't want to reproduce human, reward once the response it correct\n",
" expected_action = 'match' if (self.stimuli[self._current_step] == self.stimuli[self._current_step - self.N]) else 'non-match'\n",
" step_reward = 0. if (agent_action == expected_action) else -1.\n",
"\n",
" self._action_history.append(agent_action)\n",
"\n",
" self._current_step += 1\n",
"\n",
" # Check for termination.\n",
" if self._current_step == self.stimuli.shape[0]:\n",
" self._reset_next_step = True\n",
" # we are using the mean of total time step rewards as the episode return\n",
" return dm_env.termination(reward=self._episode_return(),\n",
" observation=self._observation())\n",
" else:\n",
" return dm_env.transition(reward=step_reward,\n",
" observation=self._observation())\n",
"\n",
" def observation_spec(self):\n",
" return dm_env.specs.BoundedArray(\n",
" shape=self.stimuli.shape,\n",
" dtype=self.stimuli.dtype,\n",
" name='nback_stimuli', minimum=0, maximum=len(self.stimuli_choices) + 1)\n",
"\n",
" def action_spec(self):\n",
" return dm_env.specs.DiscreteArray(\n",
" num_values=len(NBack.ACTIONS),\n",
" dtype=np.int32,\n",
" name='action')\n",
"\n",
" def _observation(self):\n",
"\n",
" # agent observes only the current trial\n",
" # obs = self.stimuli[self._current_step - 1]\n",
"\n",
" # agents observe stimuli up to the current trial\n",
" obs = self.stimuli[:self._current_step+1].copy()\n",
" obs = np.pad(obs,(0, len(self.stimuli) - len(obs)))\n",
"\n",
" return obs\n",
"\n",
" def plot_state(self):\n",
" \"\"\"Display current state of the environment.\n",
"\n",
" Note: `M` mean `match`, and `.` is a `non-match`.\n",
" \"\"\"\n",
" stimuli = self.stimuli[:self._current_step - 1]\n",
" actions = ['M' if a=='match' else '.' for a in self._action_history[:self._current_step - 1]]\n",
" return HTML(\n",
" f'Environment ({self.N}-back): '\n",
" f'
Stimuli: {\"\".join(map(str,map(int,stimuli)))}
'\n",
" f'
Actions: {\"\".join(actions)}
'\n",
" )\n",
"\n",
" @staticmethod\n",
" def create_environment():\n",
" \"\"\"Utility function to create a N-back environment and its spec.\"\"\"\n",
"\n",
" # Make sure the environment outputs single-precision floats.\n",
" environment = wrappers.SinglePrecisionWrapper(NBack())\n",
"\n",
" # Grab the spec of the environment.\n",
" environment_spec = specs.make_environment_spec(environment)\n",
"\n",
" return environment, environment_spec"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"### Define a random agent\n",
"\n",
"For more information you can refer to NMA-DL W3D2 Basic Reinforcement learning."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {}
},
"outputs": [],
"source": [
"class RandomAgent(acme.Actor):\n",
"\n",
" def __init__(self, environment_spec):\n",
" \"\"\"Gets the number of available actions from the environment spec.\"\"\"\n",
" self._num_actions = environment_spec.actions.num_values\n",
"\n",
" def select_action(self, observation):\n",
" \"\"\"Selects an action uniformly at random.\"\"\"\n",
" action = np.random.randint(self._num_actions)\n",
" return action\n",
"\n",
" def observe_first(self, timestep):\n",
" \"\"\"Does not record as the RandomAgent has no use for data.\"\"\"\n",
" pass\n",
"\n",
" def observe(self, action, next_timestep):\n",
" \"\"\"Does not record as the RandomAgent has no use for data.\"\"\"\n",
" pass\n",
"\n",
" def update(self):\n",
" \"\"\"Does not update as the RandomAgent does not learn from data.\"\"\"\n",
" pass"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"### Initialize the environment and the agent"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"actions:\n",
" DiscreteArray(shape=(), dtype=int32, name=action, minimum=0, maximum=1, num_values=2)\n",
"observations:\n",
" BoundedArray(shape=(32,), dtype=dtype('float32'), name='nback_stimuli', minimum=0.0, maximum=7.0)\n",
"rewards:\n",
" Array(shape=(), dtype=dtype('float32'), name='reward')\n"
]
}
],
"source": [
"env, env_spec = NBack.create_environment()\n",
"agent = RandomAgent(env_spec)\n",
"\n",
"print('actions:\\n', env_spec.actions)\n",
"print('observations:\\n', env_spec.observations)\n",
"print('rewards:\\n', env_spec.rewards)"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"### Run the loop"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {}
},
"outputs": [
{
"data": {
"image/png": "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nog6BocHIKIOMXLkSAwaNAhr1qyBwWBASEgIkpKS8Omnn6KwsLDB+qWlpbb/r7s7rLECIzIyEocPH663bMOGDU22KHWkxlqp1q5d2yA2k8mEjIyMenno0aMHlEolDh06VG/dTz75pME+9Xo9MjIyeDmPyAnYokREHWbOnDn47W9/i40bN+KRRx7BG2+8gUcffRR33XUXHnroIURGRqK4uBjHjx9Hfn4+vvzySwBAfHw8lEolVqxYAb1eD5VKhVGjRiEkJAQPPvgg3njjDTz77LO45ZZbcO7cOezZswdBQUESH631rrfNmzfDz88PsbGxOH78OPbt24fAwMB66xUUFGDatGm47777sHDhQgCAv78/pkyZgv/+978QBAGRkZH4/vvvUVJS0uB5du/ejVdeeQV/+9vfcP/993fEoRG5DRZKRNRhbr/9dvTs2ROrVq3CQw89hNjYWHz++edYunQpvvjiC5SXlyM4OBj9+/dHWlqabbuwsDDMnz8fy5cvxx//+EeYzWZ89NFHCAkJwUMPPYScnBx89tln+PHHHzFs2DB8+OGHDe66k8If//hHKBQKbNmyBQaDAUOHDsWHH36IJ598slXbv/baa6itrcX69euhUqkwZcoU/O53v8Odd97p5MiJqI4gttSjkIiImpSTk4OJEyfi9ddfx7Rp0+Dn51fv7j6pGI1GVFRUYNu2bViwYAE+++wzW+d6Imo99lEiInKABQsWIDk5Gd9++63UoQAA0tPTkZycjAULFkgdCpFLY4sSEZEdDAYDjhw5Yvs7Li4OISEhEkZkVVpainPnztn+HjRoEPz8/CSMiMg1sVAiIiIiagIvvRERERE1gYUSERERURNYKBERERE1gYUSERERURNYKBERERE1gYUSERERURNYKBERERE1gYUSERERURNYKBERERE14f8DLsoYpl91TpAAAAAASUVORK5CYII=",
"text/plain": [
"
"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# fitting parameters\n",
"n_episodes = 1_000\n",
"n_total_steps = 0\n",
"log_loss = False\n",
"n_steps = n_episodes * 32\n",
"all_returns = []\n",
"\n",
"# main loop\n",
"for episode in range(n_episodes):\n",
" episode_steps = 0\n",
" episode_return = 0\n",
" episode_loss = 0\n",
"\n",
" start_time = time.time()\n",
"\n",
" timestep = env.reset()\n",
"\n",
" # Make the first observation.\n",
" agent.observe_first(timestep)\n",
"\n",
" # Run an episode\n",
" while not timestep.last():\n",
"\n",
" # DEBUG\n",
" # print(timestep)\n",
"\n",
" # Generate an action from the agent's policy and step the environment.\n",
" action = agent.select_action(timestep.observation)\n",
" timestep = env.step(action)\n",
"\n",
" # Have the agent observe the timestep and let the agent update itself.\n",
" agent.observe(action, next_timestep=timestep)\n",
" agent.update()\n",
"\n",
" # Book-keeping.\n",
" episode_steps += 1\n",
" n_total_steps += 1\n",
" episode_return += timestep.reward\n",
"\n",
" if log_loss:\n",
" episode_loss += agent.last_loss\n",
"\n",
" if n_steps is not None and n_total_steps >= n_steps:\n",
" break\n",
"\n",
" # Collect the results and combine with counts.\n",
" steps_per_second = episode_steps / (time.time() - start_time)\n",
" result = {\n",
" 'episode': episode,\n",
" 'episode_length': episode_steps,\n",
" 'episode_return': episode_return,\n",
" }\n",
" if log_loss:\n",
" result['loss_avg'] = episode_loss/episode_steps\n",
"\n",
" all_returns.append(episode_return)\n",
"\n",
" display(env.plot_state())\n",
" # Log the given results.\n",
" print(result)\n",
"\n",
" if n_steps is not None and n_total_steps >= n_steps:\n",
" break\n",
"\n",
"clear_output()\n",
"\n",
"# Histogram of all returns\n",
"plt.figure()\n",
"sns.histplot(all_returns, stat=\"density\", kde=True, bins=12)\n",
"plt.xlabel('Return [a.u.]')\n",
"plt.ylabel('Density')\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"**Note:** You can simplify the environment loop using [DeepMind Acme](https://github.com/deepmind/acme)."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {}
},
"outputs": [],
"source": [
"# init a new N-back environment\n",
"env, env_spec = NBack.create_environment()\n",
"\n",
"# DEBUG fake testing environment.\n",
"# Uncomment this to debug your agent without using the N-back environment.\n",
"# env = fakes.DiscreteEnvironment(\n",
"# num_actions=2,\n",
"# num_observations=1000,\n",
"# obs_dtype=np.float32,\n",
"# episode_length=32)\n",
"# env_spec = specs.make_environment_spec(env)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {}
},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"[reverb/cc/platform/tfrecord_checkpointer.cc:150] Initializing TFRecordCheckpointer in /tmp/tmp7sxxomp9.\n",
"[reverb/cc/platform/tfrecord_checkpointer.cc:386] Loading latest checkpoint from /tmp/tmp7sxxomp9\n",
"[reverb/cc/platform/default/server.cc:71] Started replay server on port 42739\n",
"2024-07-16 14:42:04.610076: E tensorflow/stream_executor/cuda/cuda_driver.cc:271] failed call to cuInit: CUDA_ERROR_NO_DEVICE: no CUDA-capable device is detected\n",
"2024-07-16 14:42:04.610155: I tensorflow/stream_executor/cuda/cuda_diagnostics.cc:156] kernel driver does not appear to be running on this host (TinasMacBookPro): /proc/driver/nvidia/version does not exist\n",
"2024-07-16 14:42:04.611714: I tensorflow/core/platform/cpu_feature_guard.cc:151] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations: AVX2 AVX512F FMA\n",
"To enable them in other operations, rebuild TensorFlow with the appropriate compiler flags.\n",
"2024-07-16 14:42:05.261603: W tensorflow/compiler/jit/mark_for_compilation_pass.cc:1658] (One-time warning): Not using XLA:CPU for cluster.\n",
"\n",
"If you want XLA:CPU, do one of the following:\n",
"\n",
" - set the TF_XLA_FLAGS to include \"--tf_xla_cpu_global_jit\", or\n",
" - set cpu_global_jit to true on this session's OptimizerOptions, or\n",
" - use experimental_jit_scope, or\n",
" - use tf.function(jit_compile=True).\n",
"\n",
"To confirm that XLA is active, pass --vmodule=xla_compilation_cache=1 (as a\n",
"proper command-line flag, not via TF_XLA_FLAGS).\n",
"2024-07-16 14:42:05.267531: W tensorflow/python/util/util.cc:368] Sets are not currently considered sequences, but this may change in the future, so consider avoiding using them.\n"
]
}
],
"source": [
"def dqn_make_network(action_spec: specs.DiscreteArray) -> snt.Module:\n",
" return snt.Sequential([\n",
" snt.Flatten(),\n",
" snt.nets.MLP([50, 50, action_spec.num_values]),\n",
" ])\n",
"\n",
"# construct a DQN agent\n",
"agent = dqn.DQN(\n",
" environment_spec=env_spec,\n",
" network=dqn_make_network(env_spec.actions),\n",
" epsilon=[0.5],\n",
" logger=loggers.InMemoryLogger(),\n",
" checkpoint=False,\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"Now, we run the environment loop with the DQN agent and print the training log."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {}
},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"[reverb/cc/client.cc:165] Sampler and server are owned by the same process (248687) so Table priority_table is accessed directly without gRPC.\n",
"[reverb/cc/client.cc:165] Sampler and server are owned by the same process (248687) so Table priority_table is accessed directly without gRPC.\n",
"[reverb/cc/client.cc:165] Sampler and server are owned by the same process (248687) so Table priority_table is accessed directly without gRPC.\n",
"[reverb/cc/client.cc:165] Sampler and server are owned by the same process (248687) so Table priority_table is accessed directly without gRPC.\n"
]
},
{
"data": {
"text/html": [
"