diff --git a/.gitignore b/.gitignore index 5a050af5..df02ef97 100644 --- a/.gitignore +++ b/.gitignore @@ -117,3 +117,5 @@ notebooks/*.html .vscode .DS_Store + +.idea/ diff --git a/notebooks/2c-Input-Driven-Transitions-and-Observations-GLM-HMM.ipynb b/notebooks/2c-Input-Driven-Transitions-and-Observations-GLM-HMM.ipynb new file mode 100644 index 00000000..245bc99d --- /dev/null +++ b/notebooks/2c-Input-Driven-Transitions-and-Observations-GLM-HMM.ipynb @@ -0,0 +1,938 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "321343a2", + "metadata": {}, + "source": [ + "# Input Driven Observations and Transitions (GLM-HMM)" + ] + }, + { + "cell_type": "markdown", + "id": "3244b244", + "metadata": {}, + "source": [ + "This notebook is written by Zeinab Mohammadi. Here, a class called \"HMM_TO\" is defined which contains GLM-HMM with Input-Driven Observations and Transitions. We used an HMM enriched with two sets of per-state GLM. These GLMs consist of a Bernoulli GLM, which models observations (mice choices), and a multinomial GLM, which handles transitions between different states. This sophisticated framework effectively captures the dynamic interplay between covariates, mouse choices, and state transitions. As a result, it offers a more refined description of behavioral activity when compared to classical models. " + ] + }, + { + "cell_type": "markdown", + "id": "b6d71ee3", + "metadata": {}, + "source": [ + "Therefore, within the context of our model, we define two sets of covariates: $\\mathbf{U}^{ob}={u}^{ob}_{1}, ..., {u}^{ob}_{T}$ represents the observation covariates, and $\\mathbf{U}^{tr}={u}^{tr}_{1}, ..., {u}^{tr}_{T}$ represents the transition covariates where $T$ is the number of considered trials. Here, the input at each trial has a size of ${M}_{obs}$ for the observation model and ${M}_{tran}$ for the transition model. Additionally, we have a set of latent states denoted as $\\mathbf{Z}={z}_{1}, ..., {z}_{T} $, and corresponding observations for these states denoted as $\\mathbf{Y}={y}_{1}, ..., {y}_{T}$. For more detailed information about the model, please refer to our paper: [Identifying the factors governing internal state switches during nonstationary sensory decision-making](https://www.biorxiv.org/content/10.1101/2024.02.02.578482v2) " + ] + }, + { + "cell_type": "markdown", + "id": "95cffc78", + "metadata": {}, + "source": [ + "If you have any questions, please do not hesitate to contact me at zm6112 at princeton dot edu. Your engagement and feedback are highly appreciated for the improvement of this work." + ] + }, + { + "cell_type": "markdown", + "id": "7db06eb3", + "metadata": {}, + "source": [ + "## Bernoulli GLM for observation" + ] + }, + { + "cell_type": "markdown", + "id": "3de2de69", + "metadata": {}, + "source": [ + "We employed a Bernoulli GLM to map the binary values of the animal's decision to a set of covariates. These weights serve to depict how the inputs of the model (e.g., stimulus features) influence the output (i.e., the animal's choice on each trial). The logit link function stands as the most widely adopted link function for a 2AFC choice GLM, and it can be expressed as $log(p/(1-p)) = F * \\beta$, where $F$ corresponds to a design matrix, and $\\beta$ represents a vector of coefficients. \n", + "\n", + "Consequently, we can describe an observational GLM using the following equation, where the animal choice at trial $t$, denoted by $y_{t}$, can take a value of 1 or 0, indicating the mouse turning the wheel to the right-side or left-side, respectively:" + ] + }, + { + "cell_type": "markdown", + "id": "f95d31fd", + "metadata": {}, + "source": [ + "$$\n", + "\\begin{align}\n", + "\\Pr(y_t \\mid z_{t} = k, u_{t}^{ob}) = \n", + "\\frac{\\exp\\{(w_{kt}^{ob})^\\mathsf{T} u_{t}^{ob} \\}}\n", + "{1+\\exp\\{(w_{kt}^{ob})^\\mathsf{T} u_{t}^{ob} \\}}\n", + "\\end{align}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "id": "59aa0211", + "metadata": {}, + "source": [ + "In this equation, the presented GLM is associated with the observation covariates, $u_{t}^{ob} \\in \\mathbb{R}^{{M}_{obs}}$, and observation weights $w_{kt}^{ob}$ at trial $t$ and state $z_{t} = k$." + ] + }, + { + "cell_type": "markdown", + "id": "cddddbbb", + "metadata": {}, + "source": [ + "## Multinomial GLM for transition" + ] + }, + { + "cell_type": "markdown", + "id": "845ea356", + "metadata": {}, + "source": [ + "The multinomial GLM is an extension of the Generalized Linear Model, specifically designed to handle data with multiple categories. It's also known as softmax regression or the maximum entropy classifier. Unlike logistic regression, which deals with binary outcomes, multinomial GLMs can simultaneously analyze data from multiple categories. They establish relationships between independent variables and categorical dependent variables, enabling the determination of the likelihood associated with each category.\n", + "\n", + "We explore the GLM-HMM with multinomial GLM outputs, a method for estimating the likelihood of the next state. In this framework, each state is equipped with a multinomial GLM, allowing it to model the complex relationship between transition covariates $u_{t}^{tr} \\in \\mathbb{R}^{{M}_{tran}}$, such as previous choice and reward, and the corresponding transition probabilities. This can be written as:" + ] + }, + { + "cell_type": "markdown", + "id": "3a5e6c2a", + "metadata": {}, + "source": [ + "$$\n", + "\\begin{align}\n", + "\\Pr(z_t=k \\mid u_{t}^{tr}) = \n", + "\\frac{\\exp\\{(w_{kt}^{tr})^\\mathsf{T} u_{t}^{tr} \\}}\n", + "{\\sum_{j=1}^{K} \\exp\\{(w_{jt}^{tr})^\\mathsf{T} u_{t}^{tr} \\}}\n", + "\\end{align}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "id": "c0cf811c", + "metadata": {}, + "source": [ + "where $w_{jt}^{tr}$ corresponds to the transition weights associated with j-th state at trial $t$ and $K$ represents the total number of states. " + ] + }, + { + "cell_type": "markdown", + "id": "59eaccf2", + "metadata": {}, + "source": [ + "## 1. Setup\n", + "The line `import ssm` imports the package for use. Here, we have also imported a few other packages for plotting. " + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "d285dbf4", + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import numpy.random as npr\n", + "import matplotlib.pyplot as plt\n", + "import ssm\n", + "import random\n", + "import pandas as pd\n", + "import seaborn as sns\n", + "from ssm.util import find_permutation\n", + "\n", + "%matplotlib inline\n", + "npr.seed(0)" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "7556a945", + "metadata": {}, + "outputs": [], + "source": [ + "# Set the parameters of the GLM-HMM framework\n", + "time_bins = 5000 # number of data points\n", + "num_states = 3 # number of discrete states\n", + "obs_dim = 1 # number of observed dimensions\n", + "num_categories = 2 # number of categories for output\n", + "input_dim_T = 2 # Transition input dimensions\n", + "input_dim_O = 2 # Observation input dimensions" + ] + }, + { + "cell_type": "markdown", + "id": "7f7077f9", + "metadata": {}, + "source": [ + "# 2. Defining matrices of regressors for the model\n", + "\n", + "Here, we generate two design matrices, one for observation and one for transition regressors. Within each matrix, a column represents a covariate. These covariates may include elements such as past choices or past stimuli, which are deemed important in influencing the animal's decision-making process." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "a91b420d", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "inpt_pc= [-1 -1 1 ... -1 -1 1]\n", + "inpt_wsls= [-1 -1 1 ... 1 1 1]\n" + ] + } + ], + "source": [ + "# Specifying the regressors (past choice, past stimuli, etc.)\n", + "inpt_pc = np.array(random.choices([-1, 1], k=time_bins)) \n", + "inpt_wsls = np.array(random.choices([-1, 1], k=time_bins)) \n", + "print('inpt_pc=', inpt_pc)\n", + "print('inpt_wsls=', inpt_wsls)" + ] + }, + { + "cell_type": "markdown", + "id": "a1b8a3f7", + "metadata": {}, + "source": [ + "# 2a. Designing input matrix for Transition \n", + "In this section, we define the inputs for the transition matrix. While we're illustrating a simple case here, these specific regressors play a significant role in the transitions between different states within the GLM-HMM. To exemplify the inclusion of time and history in the regressors, we have applied an exponential filter to the transition regressors." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "2ab033bc", + "metadata": {}, + "outputs": [], + "source": [ + "design_mat_T = np.zeros((time_bins, input_dim_T)) # transition design matrix" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "e465e5e7", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "design_mat_T= [[-1. -1. ]\n", + " [-1. -1. ]\n", + " [-0.05263158 -0.05263158]\n", + " ...\n", + " [-0.23778504 -0.00444354]\n", + " [-0.4918567 0.33037098]\n", + " [ 0.00542887 0.55358065]]\n" + ] + } + ], + "source": [ + "# Creating an exponential filter for the transition regressors\n", + "def ewma_time_series(values, period): \n", + " df_ewma = pd.DataFrame(data=np.array(values))\n", + " ewma_data = df_ewma.ewm(span=period)\n", + " ewma_data_mean = ewma_data.mean()\n", + " return ewma_data_mean\n", + "\n", + "Taus = [5] # time constant for the exponential filter\n", + "add = np.array(Taus).shape[0]\n", + "\n", + "for i, tau in enumerate(Taus):\n", + " design_mat_T[:, i] = ewma_time_series(inpt_pc, tau)[0] \n", + " \n", + "for i, tau in enumerate(Taus):\n", + " design_mat_T[:, i+add] = ewma_time_series(inpt_wsls, tau)[0] \n", + "\n", + "transition_input = design_mat_T\n", + "print('design_mat_T=', design_mat_T)" + ] + }, + { + "cell_type": "markdown", + "id": "bce5725f", + "metadata": {}, + "source": [ + "# 2b. Designing input matrix for Observation " + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "3a887a05", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "design_mat_Obs= [[-1. -1.]\n", + " [-1. -1.]\n", + " [ 1. 1.]\n", + " ...\n", + " [-1. 1.]\n", + " [-1. 1.]\n", + " [ 1. 1.]]\n" + ] + } + ], + "source": [ + "design_mat_Obs = np.zeros((time_bins, input_dim_O)) # observation design matrix\n", + "design_mat_Obs[:, 0] = inpt_pc \n", + "design_mat_Obs[:, 1] = inpt_wsls \n", + "observation_input = design_mat_Obs\n", + "print('design_mat_Obs=', design_mat_Obs)" + ] + }, + { + "cell_type": "markdown", + "id": "ce9ffee4", + "metadata": {}, + "source": [ + "# 3. Creating a GLM-HMM\n", + "In this section, we make a GLM-HMM with the following transition and observation components:\n", + "\n", + "\n", + "```python\n", + "true_glmhmm = ssm.HMM_TO(num_states, obs_dim, M_trans, M_obs, observations=\"input_driven_obs_diff_inputs\", observation_kwargs=dict(C=num_categories), transitions=\"inputdrivenalt\")\n", + "```\n", + "\n", + "This function has two sections:\n", + "\n", + "**a) Observation model:**\n", + "The observation model is a categorical class indicated by `observations=\"input_driven_obs_diff_inputs\"`. Within this model, the animal's choices are influenced by a range of inputs into the system. This observation class is particularly suited for scenarios where transitions are driven by external inputs. Also, `M_obs` represents the number of covariates utilized in the observation model.\n", + "\n", + "We can determine the number of response categories with `observation_kwargs=dict(C=num_categories)`. Here, `C = 2` since there are only two possible choices for the animal, making the observations binary. \n", + "\n", + "\n", + "**b) Transition model:**\n", + "The transition model, specified as `transitions=\"inputdrivenalt\"` is a multiclass logistic regression in which `M_trans` is the number of covariates influencing the transitions between states. In this model, multiple regressors play a key role in determining the transitions between states.\n", + "\n", + "The model's number of states is determined by `num_states`, which represents the number of hypothesized strategies in this task." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "a055856e", + "metadata": {}, + "outputs": [], + "source": [ + "# Make a GLM-HMM\n", + "true_glmhmm = ssm.HMM_TO(num_states, obs_dim, M_trans=input_dim_T, M_obs=input_dim_O,\n", + " observations=\"input_driven_obs_diff_inputs\", observation_kwargs=dict(C=num_categories),\n", + " transitions=\"inputdrivenalt\")" + ] + }, + { + "cell_type": "markdown", + "id": "8777a51c", + "metadata": {}, + "source": [ + "# 3a. Initializing the model\n", + "To ensure that the model accurately reflects the mouse behavior, we must bring the GLM-HMM into an appropriate parameter regime (see Mohammadi et al. (2024)), and provide a good initialization for the observation and transition weights.\n", + "\n", + "By carefully adjusting these parameters and initializing the model accurately, we aim to create a model that closely mirrors the behavioral patterns observed in mice. This fine-tuning process will contribute to a better representation of real-world scenarios, enhancing the model's reliability in studying mice behavior." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "bca3525a", + "metadata": {}, + "outputs": [], + "source": [ + "gen_weights = np.array([[[5, 2]], [[2, -4]], [[-3, 4]]])\n", + "gen_log_trans_mat = np.log(np.array([[[0.94, 0.03, 0.03], [0.05, 0.90, 0.05], [0.04, 0.04, 0.92]]]))\n", + "Ws_transition = np.array([[[3, 1], [2, .6]]])\n", + "\n", + "true_glmhmm.observations.params = gen_weights\n", + "true_glmhmm.transitions.params[0][:] = gen_log_trans_mat\n", + "true_glmhmm.transitions.params[1][None] = Ws_transition" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "53fff4d5", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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zUXLli0RGBho8jh7ffGJqHoYA2pm4cKFmDp1KrZv346vv/4avXv3xjfffINFixYBAGJjY/Hss88iLCwM06dPR2JiIgCUu0rZ1bs/EDkiV3j/O1SEj4qKwqefforx48dDpVJhxowZCA0NhVKpRFFREWbPno2goCBERkbaeqpEVAcYA2qmS5cuWL16tdQf8tlnnwUArFq1CoBxC+ABAwZAJpPh888/x9ixY7Fx40a0a9fOZnMmIutwhfe/QyWzgHEf9tzcXDz//PNISEhAdHQ0/P39cfDgQWRkZODgwYOQyWTlGgETkXNgDKi+fv36AShtch4REYFnn30WMpnM5BdaXFwctFotoqKi0Lp1a1tOmYisxBXe/w67A9hff/2FJUuW4OTJkwgPD0dkZCT+9a9/SfVxrv6xIpGzYwyovQsXLmDp0qX47bff8PTTT+Pvf/+7yXHukEbkvJzp/e+wyWxFHOnFJyLrYwyongsXLuCzzz7D6tWr8d577+GJJ56w9ZSIqJ44y/vf6ZJZIiKqnnPnzuGXX37B5MmT+YcAkYtxhvc/k1kiIpJwZZvIdTnq+5/JLBERERE5LF7qS0REREQOi8ksERERETksJrNERERE5LCYzBIRERGRw2IyS0REREQOi8ksERERETksJrNERERE5LCYzBIRERGRw2IyS0REREQOi8ksERERETms/wdNNeov/wrwRQAAAABJRU5ErkJggg==\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Plot generative parameters:\n", + "fig = plt.figure(figsize=(10, 3), dpi=80, facecolor='w', edgecolor='k')\n", + "cols = ['darkviolet', 'gold', 'chocolate']\n", + "\n", + "# 1) Observation\n", + "gen_weights_obs = gen_weights\n", + "\n", + "plt.subplot(1, 2, 1)\n", + "for k in range(num_states):\n", + " if k ==0:\n", + " plt.plot(range(input_dim_O), gen_weights_obs[k][0], marker='D',\n", + " color=cols[k], linestyle='-', lw=1.5)\n", + " else:\n", + " plt.plot(range(input_dim_O), gen_weights_obs[k][0], marker='D',\n", + " color=cols[k], linestyle='-', lw=1.5)\n", + "\n", + "plt.yticks(fontsize=10)\n", + "plt.ylabel(\"Weight value\", fontsize=15)\n", + "plt.xticks([0, 1], ['Obs_in1', 'Obs_in2'], fontsize=12, rotation=45)\n", + "plt.axhline(y=0, color=\"k\", alpha=0.5, ls=\"--\")\n", + "plt.title(\"Observation GLM\")\n", + "\n", + "# 2) transition \n", + "gen_log_trans_mat = true_glmhmm.transitions.params[0]\n", + "gen_weights_Trans = true_glmhmm.transitions.params[1]\n", + "generative_weights_Trans = true_glmhmm.trans_weights_K(true_glmhmm.params, num_states)\n", + "\n", + "plt.subplot(1, 2, 2)\n", + "for k in range(num_states):\n", + " if k ==0:\n", + " plt.plot(range(input_dim_T), generative_weights_Trans[k], marker='D',\n", + " color=cols[k], linestyle='-', lw=1.5)\n", + " else:\n", + " plt.plot(range(input_dim_T), generative_weights_Trans[k], marker='D',\n", + " color=cols[k], linestyle='-', lw=1.5)\n", + "\n", + "plt.yticks(fontsize=10)\n", + "plt.axhline(y=0, color=\"k\", alpha=0.5, ls=\"--\")\n", + "plt.xticks([0, 1], ['Tran_in1', 'Tran_in2'], fontsize=12, rotation=45)\n", + "plt.title(\"Transition GLM\")\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "id": "6d6d1729", + "metadata": {}, + "source": [ + "# 3b. Sample data from the GLM-HMM" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "d3048b9f", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/var/folders/5r/j_22d45j5wn_6j9p3016x8p00000gw/T/ipykernel_56319/3193879353.py:20: MatplotlibDeprecationWarning: The 'b' parameter of grid() has been renamed 'visible' since Matplotlib 3.5; support for the old name will be dropped two minor releases later.\n", + " plt.grid(b=None)\n" + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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OKhR/95x6bxGbe/1u2mK/XNdP69Y1lEre2RLki763yn+etf37+2zuinknXylfiT13HyNdvR8TvfGbKs77g36948/26kFVw7TrW+95e/fnh0FAdv9Q8Ea3XXhSHn37tXTu1dqSo9MLfj4HcU6IwL69/CkPnqzYJVGJV2kJbvW6YqE3v4aNqx5fb0b1d3h0NtFG3RFuzR/Hy/3VenqlEF6cXuOrus6VO9uX6UiT7lu6TlCczct0W29R+v3+W/plxeN1tKNdR///kGV9NuOqXJ27qh3VmTrjYpIPdk5RUGp3TR2cY5emTRUl83P07s/aiHfwF76x+L5kqTpX/XWJ2keSdLh0X2V98Rf/E0bvi1TZkjda3/fLRdp48wnJUnd1044Zv9ueD73RPkUdDhIn094Uom9K1VUVHTM1+aJ4FYFAACwRnAAAADWCA4AAMAawQEAAFgjOAAAAGsEBwAAYI3gAAAArBEcAACANYIDAACwRnAAAADWCA4AAMAawQEAAFgjOAAAAGsEBwAAYI3gAAAArBEcAACANYIDAACwRnAAAADWCA4AAMAawQEAAFgjOAAAAGsEBwAAYI3gAAAArBEcAACANYIDAACwRnAAAADWCA4AAMAawQEAAFgjOAAAAGsEBwAAYI3gAAAArBEcAACANYIDAACwRnAAAADWCA4AAMAawQEAAFgjOAAAAGsEBwAAYI3gAAAArBEcAACANYIDAACwRnAAAADWCA4AAMAawQEAAFgjOAAAAGsEBwAAYI3gAAAArBEcAACANYIDAACwRnAAAADWCA4AAMAawQEAAFgjOAAAAGsEBwAAYI3gAAAArBEcAACANYIDAACwRnAAAADWCA4AAMAawQEAAFgjOAAAAGsEBwAAYI3gAAAArBEcAACANYIDAACwRnAAAADWCA4AAMAawQEAAFgjOAAAAGsEBwAAYI3gAAAArBEcAACANYIDAACwRnAAAADWCA4AAMAawQEAAFgjOAAAAGsEBwAAYI3gAAAArBEcAACANYIDAACwRnAAAADWCA4AAMAawQEAAFgjOAAAAGsEBwAAYI3gAAAArBEcAACANYIDAACwRnAAAADWCA4AAMAawQEAAFgjOAAAAGsEBwAAYI3gAAAArBEcAACANYIDAACwRnAAAADWCA4AAMAawQEAAFgjOAAAAGsEBwAAYI3gAAAArBEcAACA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\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Sample some data from the GLM-HMM\n", + "true_states, obs = true_glmhmm.sample(time_bins, transition_input=transition_input, observation_input=observation_input)\n", + "\n", + "# Plot the data\n", + "T= 500\n", + "fig = plt.figure(figsize=(8, 2), dpi=80, facecolor='w', edgecolor='k')\n", + "plt.imshow(true_states[None, :], aspect=\"auto\")\n", + "plt.xticks([])\n", + "plt.xlim(0, T)\n", + "plt.yticks([])\n", + "plt.title(\"States\", fontsize=15)\n", + "\n", + "# For visualizing categorical observations, we create a Cmap. \n", + "obs_flat = np.array([x[0] for x in obs]) # SSM initially provides categorical observations as a list of lists, and we transform them into a 1D array to facilitate plotting.\n", + "fig = plt.figure(figsize=(8, 2), dpi=80, facecolor='w', edgecolor='k')\n", + "plt.imshow(obs_flat[None,:], aspect=\"auto\")\n", + "plt.xlim(0, T)\n", + "plt.xlabel(\"trial #\", fontsize=12)\n", + "plt.yticks([])\n", + "plt.grid(b=None)\n", + "plt.title(\"Observations\", fontsize=15)\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "b3e6b0df", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "true_lp = -2030.8011892459606\n" + ] + } + ], + "source": [ + "# Calculate the actual log likelihood by summing over discrete states\n", + "true_lp = true_glmhmm.log_probability(obs, transition_input=transition_input, observation_input=observation_input)\n", + "print(\"true_lp = \" + str(true_lp))" + ] + }, + { + "cell_type": "markdown", + "id": "0f99279f", + "metadata": {}, + "source": [ + "# 4. Make a new HMM for fitting purpose\n", + "\n", + "In this section, we instantiate a new GLM-HMM and assess its ability to recover generative parameters using Maximum Likelihood Estimation (MLE) on simulated data. MLE enables us to optimize model parameters to match the underlying data generation process, providing insights into the model's performance in emulating various scenarios." + ] + }, + { + "cell_type": "markdown", + "id": "944eafb0", + "metadata": {}, + "source": [ + "## EM for fitting" + ] + }, + { + "cell_type": "markdown", + "id": "ff4c3e26", + "metadata": {}, + "source": [ + "We employ the Expectation-Maximization (EM) method to fit the data. The EM algorithm consists of two main steps: the E-step and the M-step. The algorithm starts with an initial guess for the model parameters and iterates until the log marginal likelihood converges. During the E-step, the algorithm computes the expected value of the complete-data log-likelihood based on the model parameters estimate and the observed data (animal choices). Next, the M-Step tries to find the parameters that maximize the expected log-likelihood." + ] + }, + { + "cell_type": "markdown", + "id": "2b7e7566", + "metadata": {}, + "source": [ + "To elaborate further, during each trial and based on the specified GLM-HMM parameters, we compute the joint probability distribution encompassing both the states and the animals' decisions (left or right). Subsequently, the log-likelihood of the model is evaluated using this joint probability distribution. This relationship can be expressed in the following manner:\n", + "\n", + "$$\n", + "\\begin{align}\n", + "\\log \\left[ p(\\mathbf{Y}|\\theta, \\mathbf{X}^{ob}, \\mathbf{X}^{tr})\\right]= \\log \\left[ \\sum_{z} \n", + "p(\\mathbf{Y}, \\mathbf{Z}|\\theta, \\mathbf{X}^{ob}, \\mathbf{X}^{tr})\\right]\n", + "\\end{align}\n", + "$$\n", + "\n", + "In this model, as mentioned, we have defined two sets of covariates, $\\mathbf{X}^{ob}={x}^{ob}_{1}, ..., {x}^{ob}_{T}$ and $\\mathbf{X}^{tr}={x}^{tr}_{1}, ..., {x}^{tr}_{T}$ which correspond to the observation and transition covariates respectively and a set of latent states as $\\mathbf{Z}={z}_{1}, ..., {z}_{T} $.\n", + "The model parameters, represented as $\\theta=\\{ \\mathbf{w}^{tr}, \\mathbf{w}^{ob}, \\pi\\}$, encompass the initial state distribution, transition weights, and observation weights for all states." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "7589af90", + "metadata": {}, + "outputs": [], + "source": [ + "glmhmm = ssm.HMM_TO(num_states, obs_dim, input_dim_T, input_dim_O, observations=\"input_driven_obs_diff_inputs\", \n", + " observation_kwargs=dict(C=num_categories), transitions=\"inputdrivenalt\")" + ] + }, + { + "cell_type": "markdown", + "id": "259f87b9", + "metadata": {}, + "source": [ + "# 4a. Fit the new HMM\n", + "Here, we'll fit the model to simulated data. Through this fitting process, our model tries to capture the underlying dependencies that characterize the behavior of interest. This allows us to gain valuable insights into how well our model aligns with the data and its potential to generalize its findings to other cases." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "70103025", + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "2d9b0344720444a0b5fe8c4fd5c50196", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/200 [00:00" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Visualize the Learned Parameters\n", + "# Plot the log probabilities of the true and fit models\n", + "fig = plt.figure(figsize=(4, 3), dpi=80, facecolor='w', edgecolor='k')\n", + "plt.plot(hmm_lps, label=\"EM\")\n", + "plt.plot([0, N_iters], true_lp * np.ones(2), ':k', label=\"True\")\n", + "plt.legend(loc=\"lower right\")\n", + "plt.xlabel(\"EM Iteration\")\n", + "plt.xlim(0, len(hmm_lps))\n", + "plt.ylabel(\"Log Probability\")\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "c990ef26", + "metadata": {}, + "outputs": [], + "source": [ + "glmhmm.permute(find_permutation(true_states, glmhmm.most_likely_states(obs, transition_input=transition_input, observation_input=observation_input)))" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "a3794b24", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAArkAAAELCAYAAADdtJ5XAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/YYfK9AAAACXBIWXMAAAxOAAAMTgF/d4wjAACh+ElEQVR4nOydd3hUVfrHP3f6JJNk0gMJAVIh9N67YEERG2IHFWR1Xde1r+u6umtf+bmurogFUESlKIqICkhTQIr0QAg11PSe6XN/f9xkkiEBQkiZJOfzPPdh5t5z75wzQ858573v+b6SLMsyAoFAIBAIBAJBC0LV1B0QCAQCgUAgEAjqGyFyBQKBQCAQCAQtDiFyBQKBQCAQCAQtDiFyBQKBQCAQCAQtDiFyBQKBQCAQCAQtDiFyBQKBQCAQCAQtDiFyBQKBQCAQCAQtDiFyBZfN2rVrkSQJp9PZ1F25bEaOHMnf/va3pu6GQCAQNAlz584lJibmstsIBL6AELmCC5KWlsakSZMICwvDYDDQrVs3/vvf/9Lca4g4nU4kSWLt2rVe+7/66iuefvrpBn/97777jjFjxmA2m/H396dLly78+c9/5tixY542FxLcc+fORZIkhg8fXu3Y/fffjyRJQqwLBM0ASZIuuJ07RzU0t956Kzt27PA8v/POO5kyZcoF2zQUGRkZTJs2jdjYWPR6PbGxsVx33XX88MMPnjYXE9wV7+Phw4e99v/yyy9IkiTEegtHiFzBedm3bx8DBgzA7Xbzww8/kJaWxhNPPMELL7zAgw8+2GT9stlsDXbtkJAQTCZTg10f4N///jc33ngj/fv35/vvv2fPnj28/fbbaDQa3nzzzVpfJzg4mB07dngJY4vFwuLFi8XELRA0E86cOePZ/vznPzNo0CCvfYMHD/a0bci5rwKj0Uh4ePhlt7lc0tLS6N27NwcPHmTWrFmkpqayZMkSrr32Wv7yl79c0rViYmKYP3++175PPvlEzJOtAVkgOA+jRo2SBwwYILvdbq/9y5cvlwF5w4YNsizL8po1a2RAXr58uZyYmCgbDAb5hhtukPPz8z3nLFiwQE5OTpb1er0cGRkpT5s2zXOstLRUfvDBB+WwsDA5KChIHj9+vHz06FHP8XvuuUe+/fbb5aeeekoODQ2Vr732WnnChAnyH/7wB69+bd26VVar1fLZs2dlq9Uq33XXXXJMTIzs5+cn9+7dW169erWnbfv27WXAs91zzz2yLMvyiBEj5GeffdbT7uDBg/LYsWNlg8Egh4eHy48//rjscDi8rvPvf/9bvvnmm2U/Pz+5U6dOXq9zLkeOHJHVarX8v//9r8bjVd/rc/tSlTlz5sjR0dHyHXfcIb/44ote7/PAgQMveK5AIPBNnn32WXnEiBGe588//7w8ZMgQeebMmXLbtm3lrl27yrIsyy+//LLcqVMn2Wg0ygkJCfJ//vMfr+uMGDFCfuKJJ+Tp06fLJpNJbt++vfz55597jufk5Mg333yzHBwcLPv5+cndu3eXN27cKMty5dxS8fpV58kKyVC1jSzLssPhkJ944gk5PDxcNhgM8hVXXCEfPHiw2jj++9//ylFRUXJoaKj8xBNPVPtuqcro0aPlgQMH1tim6r5z+3IugPzUU0/J8fHxnn0Wi0U2m83y008/fcFzBc0fEckV1EhOTg5r1qzhz3/+M5IkeR275pprSE5OZuHChV77n3/+eebNm8eaNWs4cOAAf/7znwElUjF16lReeOEF0tLS+O677+jTp4/nvBkzZpCens6KFSv47bffiIiI4LrrrsPlcnnafPPNN1gsFn799VdmzpzJ5MmTWbx4sVebhQsXMnLkSCIjI3E6nSQlJbFs2TJ27drFhAkTuP7668nKygJg8+bNACxZsoQzZ87wn//8p9p74HK5uP7669Hr9WzZsoV58+bxySef8Prrr3u1e/3117nuuuvYuXMnw4YN484778Rut9f4vn711Vf4+fkxbdq0Go+f+15fjLvvvptPP/3U8/yTTz7h7rvvvqRrCAQC32Xnzp389ttv/PTTT545V6/X88EHH7Bv3z5eeukl/vrXv/L99997nff+++/TqVMnduzYwZQpU5g6dapn/nvuuecoLi5m/fr17N69m+effx6dTlfttR9//HFuuukmJk2a5Iks18Trr7/OvHnzmDNnDlu3bsVoNDJhwgSv+Xn37t1s3bqVn3/+mQ8//JC33nqL7777rsbrVXz/PProozXOiZc6T44ePRqbzcbGjRsB5fskKSmJ5OTkS7qOoBnS1Cpb4Jts3rxZBuQdO3bUeHzChAny1VdfLctyZSR3xYoVnuMrV66UNRqNnJ+fL2/btk0ODAyUi4uLq13n6NGjsk6nk/Py8jz77Ha77Ofn54kU33PP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\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Plot generative parameters \n", + "# 1) Observation \n", + "gen_weights_obs = gen_weights\n", + "recovered_weights = glmhmm.observations.params\n", + "\n", + "fig = plt.figure(figsize=(10, 3), dpi=80, facecolor='w', edgecolor='k')\n", + "plt.subplot(1, 2, 1)\n", + "for k in range(num_states):\n", + " if k == 0:\n", + " plt.plot(range(input_dim_O), gen_weights_obs[k][0], marker='D', color=cols[k], linestyle='-',\n", + " lw=1.5, label=\"generative\")\n", + " else:\n", + " plt.plot(range(input_dim_O), gen_weights_obs[k][0], marker='D', color=cols[k], linestyle='-',\n", + " lw=1.5, label=\"\")\n", + "\n", + "plt.yticks(fontsize=10)\n", + "plt.ylabel(\"Weight value\", fontsize=12)\n", + "plt.xticks([0, 1], ['Obs_inp1', 'Obs_inp2'], fontsize=12, rotation=30)\n", + "plt.axhline(y=0, color=\"k\", alpha=0.5, ls=\"--\")\n", + "plt.title(\"Observation GLM\", fontsize=12)\n", + "\n", + "for k in range(num_states):\n", + " if k == 0:\n", + " plt.plot(range(input_dim_O), recovered_weights[k][0], color=cols[k],\n", + " lw=1.5, label = \"recovered\", linestyle = '--')\n", + " else:\n", + " plt.plot(range(input_dim_O), recovered_weights[k][0], color=cols[k],\n", + " lw=1.5, label = '', linestyle = '--')\n", + "plt.yticks(fontsize=10)\n", + "plt.axhline(y=0, color=\"k\", alpha=0.5, ls=\"--\")\n", + "plt.legend()\n", + "\n", + "# 2) transition \n", + "gen_log_trans_mat = true_glmhmm.transitions.params[0]\n", + "gen_weights_Trans = true_glmhmm.transitions.params[1]\n", + "recovered_trans_mat = np.exp(glmhmm.transitions.params[0])\n", + "\n", + "plt.subplot(1, 2, 2)\n", + "recovered_weights_Trans = glmhmm.trans_weights_K(glmhmm.params, num_states)\n", + "generative_weights_Trans = true_glmhmm.trans_weights_K(true_glmhmm.params, num_states)\n", + "\n", + "for k in range(num_states): \n", + " if k == 0:\n", + " plt.plot(range(input_dim_T), generative_weights_Trans[k], marker='D', color=cols[k], linestyle='-',\n", + " lw=1.5, label=\"generative\")\n", + " plt.plot(range(input_dim_T), recovered_weights_Trans[k], color=cols[k],\n", + " lw=1.5, label = \"recovered\", linestyle = '--')\n", + " else:\n", + " plt.plot(range(input_dim_T), generative_weights_Trans[k], marker='D',\n", + " color=cols[k], linestyle='-', lw=1.5, label=\"\")\n", + " plt.plot(range(input_dim_T), recovered_weights_Trans[k], color=cols[k],\n", + " lw=1.5, label = '', linestyle = '--')\n", + " \n", + "plt.yticks(fontsize=10)\n", + "plt.title(\"Transition GLM\", fontsize=12)\n", + "plt.axhline(y=0, color=\"k\", alpha=0.5, ls=\"--\")\n", + "plt.xticks([0, 1], ['Tran_inp1', 'Tran_inp2'], fontsize=12, rotation=30)\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "cfb67801", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# transition matrix\n", + "recovered_matrix = glmhmm.Ps_matrix(data=obs, transition_input=transition_input, observation_input=observation_input) # , train_mask=train_mask)[0]\n", + "gen_trans_mat = np.exp(gen_log_trans_mat)\n", + "\n", + "fig = plt.figure(figsize=(6, 3), dpi=80, facecolor='w', edgecolor='k')\n", + "plt.subplot(1, 2, 1)\n", + "plt.imshow(gen_trans_mat, vmin=-0.8, vmax=1, cmap='bone')\n", + "for i in range(gen_trans_mat.shape[0]):\n", + " for j in range(gen_trans_mat.shape[1]):\n", + " text = plt.text(j, i, str(np.around(gen_trans_mat[i, j], decimals=2)), ha=\"center\", va=\"center\",\n", + " color=\"k\", fontsize=12)\n", + "plt.xlim(-0.5, num_states - 0.5)\n", + "plt.ylim(num_states - 0.5, -0.5)\n", + "plt.xticks(range(0, num_states), ('1', '2', '3'), fontsize=10)\n", + "plt.yticks(range(0, num_states), ('1', '2', '3'), fontsize=10)\n", + "plt.ylabel(\"state t\", fontsize=15)\n", + "plt.xlabel(\"state t+1\", fontsize=15)\n", + "plt.title(\"generative\", fontsize=15)\n", + "\n", + "plt.subplot(1, 2, 2)\n", + "plt.imshow(np.mean(recovered_matrix, axis=0), vmin=-0.8, vmax=1, cmap='bone')\n", + "for i in range(np.mean(recovered_matrix, axis=0).shape[0]):\n", + " for j in range(np.mean(recovered_matrix, axis=0).shape[1]):\n", + " text = plt.text(j, i, str(np.around(np.mean(recovered_matrix, axis=0)[i, j], decimals=2)), ha=\"center\", va=\"center\",\n", + " color=\"k\", fontsize=12)\n", + "plt.xlim(-0.5, num_states - 0.5)\n", + "plt.ylim(num_states - 0.5, -0.5)\n", + "plt.xticks(range(0, num_states), ('1', '2', '3'), fontsize=10)\n", + "plt.yticks(range(0, num_states), ('1', '2', '3'), fontsize=10)\n", + "plt.title(\"recovered\", fontsize=15)\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "id": "0741dcef", + "metadata": {}, + "source": [ + "# 4c. Analysis of the acquired states\n" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "d0350e34", + "metadata": {}, + "outputs": [], + "source": [ + "# Get expected states\n", + "posterior_probs = [glmhmm.expected_states(data = obs, transition_input = transition_input, observation_input=observation_input)[0]]\n", + "\n", + "# Determine the state with the highest posterior probability\n", + "posterior_max = np.argmax(posterior_probs[0], axis = 1)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "e65b35c8", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# calculate state fractional occupancies\n", + "_, occur_for_state = np.unique(posterior_max, return_counts=True)\n", + "sum_all = np.sum(occur_for_state)\n", + "occur_for_state = occur_for_state/sum_all\n", + "\n", + "fig = plt.figure(figsize=(2.5, 2.5), dpi=80, facecolor='w', edgecolor='k')\n", + "\n", + "for state, occur in enumerate(occur_for_state):\n", + " occur_perc = occur * 100\n", + " plt.bar(state, occur_perc, width = 0.7, color = cols[state])\n", + " \n", + "plt.ylim((0, .6))\n", + "plt.xticks([0, 1, 2], ['1', '2', '3'], fontsize=12)\n", + "plt.yticks([0, 25, 50], ['0', '25', '50'], fontsize=12)\n", + "plt.xlabel('state', fontsize=15)\n", + "plt.ylabel('Occupancy (%)', fontsize=15)\n", + "plt.gca().spines['right'].set_visible(False)\n", + "plt.gca().spines['top'].set_visible(False)\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "66269f94", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "fig = plt.figure(figsize=(12, 2.5), dpi=80, facecolor='w', edgecolor='k')\n", + "for k in range(num_states):\n", + " plt.plot(posterior_probs[0][0:200, k], label=\"State \" + str(k + 1), lw=1, marker='*',\n", + " color=cols[k]) \n", + "\n", + "plt.ylim((-0.01, 1.01))\n", + "plt.yticks([0, 0.5, 1], fontsize=10)\n", + "plt.xticks(fontsize=12)\n", + "plt.xlabel(\"trial number\", fontsize=15)\n", + "plt.ylabel(\"Posterior prob.\", fontsize=15)\n", + "plt.gca().spines['right'].set_visible(False)\n", + "plt.gca().spines['top'].set_visible(False)\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "610c21a7", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "# plot choices and latents:\n", + "plt.figure(figsize=(8, 3.5))\n", + "time_bin= 500\n", + "\n", + "plt.subplot(211)\n", + "plt.imshow(true_states[None, :], aspect=\"auto\")\n", + "plt.xticks([])\n", + "plt.xlim(0, time_bin)\n", + "plt.ylabel(\"true\\nstate\", fontsize=14)\n", + "plt.yticks([])\n", + "\n", + "plt.subplot(212)\n", + "inferred_states = glmhmm.most_likely_states(obs, transition_input=transition_input, observation_input=observation_input)\n", + "plt.imshow(inferred_states[None, :], aspect=\"auto\")\n", + "plt.xlim(0, time_bin)\n", + "plt.ylabel(\"inferred\\nstate\", fontsize=14)\n", + "plt.yticks([])\n", + "plt.xlabel(\"trial #\", fontsize=12)\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "14b48101", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "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.8.8" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/notebooks/2c-Input-Driven-Transitions-and-Observations-GLM-HMM.py b/notebooks/2c-Input-Driven-Transitions-and-Observations-GLM-HMM.py new file mode 100644 index 00000000..27a97969 --- /dev/null +++ b/notebooks/2c-Input-Driven-Transitions-and-Observations-GLM-HMM.py @@ -0,0 +1,454 @@ +# --- +# jupyter: +# jupytext: +# text_representation: +# extension: .py +# format_name: light +# format_version: '1.5' +# jupytext_version: 1.16.0 +# kernelspec: +# display_name: Python 3 (ipykernel) +# language: python +# name: python3 +# --- + +""" +Input Driven Observations and Transitions (GLM-HMM) +=================================================== +""" + +# # Input Driven Observations and Transitions (GLM-HMM) + +# This notebook is written by Zeinab Mohammadi. Here, a class called "HMM_TO" is defined which contains GLM-HMM with Input-Driven Observations and Transitions. We used an HMM enriched with two sets of per-state GLM. These GLMs consist of a Bernoulli GLM, which models observations (mice choices), and a multinomial GLM, which handles transitions between different states. This sophisticated framework effectively captures the dynamic interplay between covariates, mouse choices, and state transitions. As a result, it offers a more refined description of behavioral activity when compared to classical models. + +# Therefore, within the context of our model, we define two sets of covariates: $\mathbf{U}^{ob}={u}^{ob}_{1}, ..., {u}^{ob}_{T}$ represents the observation covariates, and $\mathbf{U}^{tr}={u}^{tr}_{1}, ..., {u}^{tr}_{T}$ represents the transition covariates where $T$ is the number of considered trials. Here, the input at each trial has a size of ${M}_{obs}$ for the observation model and ${M}_{tran}$ for the transition model. Additionally, we have a set of latent states denoted as $\mathbf{Z}={z}_{1}, ..., {z}_{T} $, and corresponding observations for these states denoted as $\mathbf{Y}={y}_{1}, ..., {y}_{T}$. For more detailed information about the model, please refer to our paper: [Identifying the factors governing internal state switches during nonstationary sensory decision-making](https://www.biorxiv.org/content/10.1101/2024.02.02.578482v2) + +# If you have any questions, please do not hesitate to contact me at zm6112 at princeton dot edu. Your engagement and feedback are highly appreciated for the improvement of this work. + +# ## Bernoulli GLM for observation + +# We employed a Bernoulli GLM to map the binary values of the animal's decision to a set of covariates. These weights serve to depict how the inputs of the model (e.g., stimulus features) influence the output (i.e., the animal's choice on each trial). The logit link function stands as the most widely adopted link function for a 2AFC choice GLM, and it can be expressed as $log(p/(1-p)) = F * \beta$, where $F$ corresponds to a design matrix, and $\beta$ represents a vector of coefficients. +# +# Consequently, we can describe an observational GLM using the following equation, where the animal choice at trial $t$, denoted by $y_{t}$, can take a value of 1 or 0, indicating the mouse turning the wheel to the right-side or left-side, respectively: + +# $$ +# \begin{align} +# \Pr(y_t \mid z_{t} = k, u_{t}^{ob}) = +# \frac{\exp\{(w_{kt}^{ob})^\mathsf{T} u_{t}^{ob} \}} +# {1+\exp\{(w_{kt}^{ob})^\mathsf{T} u_{t}^{ob} \}} +# \end{align} +# $$ + +# In this equation, the presented GLM is associated with the observation covariates, $u_{t}^{ob} \in \mathbb{R}^{{M}_{obs}}$, and observation weights $w_{kt}^{ob}$ at trial $t$ and state $z_{t} = k$. + +# ## Multinomial GLM for transition + +# The multinomial GLM is an extension of the Generalized Linear Model, specifically designed to handle data with multiple categories. It's also known as softmax regression or the maximum entropy classifier. Unlike logistic regression, which deals with binary outcomes, multinomial GLMs can simultaneously analyze data from multiple categories. They establish relationships between independent variables and categorical dependent variables, enabling the determination of the likelihood associated with each category. +# +# We explore the GLM-HMM with multinomial GLM outputs, a method for estimating the likelihood of the next state. In this framework, each state is equipped with a multinomial GLM, allowing it to model the complex relationship between transition covariates $u_{t}^{tr} \in \mathbb{R}^{{M}_{tran}}$, such as previous choice and reward, and the corresponding transition probabilities. This can be written as: + +# $$ +# \begin{align} +# \Pr(z_t=k \mid u_{t}^{tr}) = +# \frac{\exp\{(w_{kt}^{tr})^\mathsf{T} u_{t}^{tr} \}} +# {\sum_{j=1}^{K} \exp\{(w_{jt}^{tr})^\mathsf{T} u_{t}^{tr} \}} +# \end{align} +# $$ + +# where $w_{jt}^{tr}$ corresponds to the transition weights associated with j-th state at trial $t$ and $K$ represents the total number of states. + +# ## 1. Setup +# The line `import ssm` imports the package for use. Here, we have also imported a few other packages for plotting. + +# + +import numpy as np +import numpy.random as npr +import matplotlib.pyplot as plt +import ssm +import random +import pandas as pd +import seaborn as sns +from ssm.util import find_permutation + +# %matplotlib inline +npr.seed(0) +# - + +# Set the parameters of the GLM-HMM framework +time_bins = 5000 # number of data points +num_states = 3 # number of discrete states +obs_dim = 1 # number of observed dimensions +num_categories = 2 # number of categories for output +input_dim_T = 2 # Transition input dimensions +input_dim_O = 2 # Observation input dimensions + +# # 2. Defining matrices of regressors for the model +# +# Here, we generate two design matrices, one for observation and one for transition regressors. Within each matrix, a column represents a covariate. These covariates may include elements such as past choices or past stimuli, which are deemed pivotal in influencing the animal's decision-making process. + +# Specifying the regressors (past choice, past stimuli, etc.) +inpt_pc = np.array(random.choices([-1, 1], k=time_bins)) +inpt_wsls = np.array(random.choices([-1, 1], k=time_bins)) +print('inpt_pc=', inpt_pc) +print('inpt_wsls=', inpt_wsls) + +# # 2a. Designing input matrix for Transition +# In this section, we define the inputs for the transition matrix. While we're illustrating a simple case here, these specific regressors play a pivotal role in the transitions between different states within the GLM-HMM. To exemplify the inclusion of time and history in the regressors, we have applied an exponential filter to the transition regressors. + +design_mat_T = np.zeros((time_bins, input_dim_T)) # transition design matrix + + +# + +# Creating an exponential filter for the transition regressors +def ewma_time_series(values, period): + df_ewma = pd.DataFrame(data=np.array(values)) + ewma_data = df_ewma.ewm(span=period) + ewma_data_mean = ewma_data.mean() + return ewma_data_mean + +Taus = [5] # time constant for the exponential filter +add = np.array(Taus).shape[0] + +for i, tau in enumerate(Taus): + design_mat_T[:, i] = ewma_time_series(inpt_pc, tau)[0] + +for i, tau in enumerate(Taus): + design_mat_T[:, i+add] = ewma_time_series(inpt_wsls, tau)[0] + +transition_input = design_mat_T +print('design_mat_T=', design_mat_T) +# - + +# # 2b. Designing input matrix for Observation + +design_mat_Obs = np.zeros((time_bins, input_dim_O)) # observation design matrix +design_mat_Obs[:, 0] = inpt_pc +design_mat_Obs[:, 1] = inpt_wsls +observation_input = design_mat_Obs +print('design_mat_Obs=', design_mat_Obs) + +# # 3. Creating a GLM-HMM +# In this section, we make a GLM-HMM with the following transition and observation components: +# +# +# ```python +# true_glmhmm = ssm.HMM_TO(num_states, obs_dim, M_trans, M_obs, observations="input_driven_obs_diff_inputs", observation_kwargs=dict(C=num_categories), transitions="inputdrivenalt") +# ``` +# +# This function has two sections: +# +# **a) Observation model:** +# The observation model is a categorical class indicated by `observations="input_driven_obs_diff_inputs"`. Within this model, the animal's choices are influenced by a range of inputs into the system. This observation class is particularly suited for scenarios where transitions are driven by external inputs. Also, `M_obs` represents the number of covariates utilized in the observation model. +# +# We can determine the number of response categories with `observation_kwargs=dict(C=num_categories)`. Here, `C = 2` since there are only two possible choices for the animal, making the observations binary. +# +# +# **b) Transition model:** +# The transition model, specified as `transitions="inputdrivenalt"` is a multiclass logistic regression in which `M_trans` is the number of covariates influencing the transitions between states. In this model, multiple regressors play a key role in determining the transitions between states. +# +# The model's number of states is determined by `num_states`, which represents the number of hypothesized strategies in this task. + +# Make a GLM-HMM +true_glmhmm = ssm.HMM_TO(num_states, obs_dim, M_trans=input_dim_T, M_obs=input_dim_O, + observations="input_driven_obs_diff_inputs", observation_kwargs=dict(C=num_categories), + transitions="inputdrivenalt") + +# # 3a. Initializing the model +# To ensure that the model accurately reflects the mouse behavior, we must bring the GLM-HMM into an appropriate parameter regime (see Mohammadi et al. (2024)), and provide a good initialization for the observation and transition weights. +# +# By carefully adjusting these parameters and initializing the model accurately, we aim to create a model that closely mirrors the behavioral patterns observed in mice. This fine-tuning process will contribute to a better representation of real-world scenarios, enhancing the model's reliability in studying mice behavior. + +# + +gen_weights = np.array([[[5, 2]], [[2, -4]], [[-3, 4]]]) +gen_log_trans_mat = np.log(np.array([[[0.94, 0.03, 0.03], [0.05, 0.90, 0.05], [0.04, 0.04, 0.92]]])) +Ws_transition = np.array([[[3, 1], [2, .6]]]) + +true_glmhmm.observations.params = gen_weights +true_glmhmm.transitions.params[0][:] = gen_log_trans_mat +true_glmhmm.transitions.params[1][None] = Ws_transition + +# + +# Plot generative parameters: +fig = plt.figure(figsize=(10, 3), dpi=80, facecolor='w', edgecolor='k') +cols = ['darkviolet', 'gold', 'chocolate'] + +# 1) Observation +gen_weights_obs = gen_weights + +plt.subplot(1, 2, 1) +for k in range(num_states): + if k ==0: + plt.plot(range(input_dim_O), gen_weights_obs[k][0], marker='D', + color=cols[k], linestyle='-', lw=1.5) + else: + plt.plot(range(input_dim_O), gen_weights_obs[k][0], marker='D', + color=cols[k], linestyle='-', lw=1.5) + +plt.yticks(fontsize=10) +plt.ylabel("Weight value", fontsize=15) +plt.xticks([0, 1], ['Obs_in1', 'Obs_in2'], fontsize=12, rotation=45) +plt.axhline(y=0, color="k", alpha=0.5, ls="--") +plt.title("Observation GLM") + +# 2) transition +gen_log_trans_mat = true_glmhmm.transitions.params[0] +gen_weights_Trans = true_glmhmm.transitions.params[1] +generative_weights_Trans = true_glmhmm.trans_weights_K(true_glmhmm.params, num_states) + +plt.subplot(1, 2, 2) +for k in range(num_states): + if k ==0: + plt.plot(range(input_dim_T), generative_weights_Trans[k], marker='D', + color=cols[k], linestyle='-', lw=1.5) + else: + plt.plot(range(input_dim_T), generative_weights_Trans[k], marker='D', + color=cols[k], linestyle='-', lw=1.5) + +plt.yticks(fontsize=10) +plt.axhline(y=0, color="k", alpha=0.5, ls="--") +plt.xticks([0, 1], ['Tran_in1', 'Tran_in2'], fontsize=12, rotation=45) +plt.title("Transition GLM") +plt.show() +# - + +# # 3b. Sample data from the GLM-HMM + +# + +# Sample some data from the GLM-HMM +true_states, obs = true_glmhmm.sample(time_bins, transition_input=transition_input, observation_input=observation_input) + +# Plot the data +T= 500 +fig = plt.figure(figsize=(8, 2), dpi=80, facecolor='w', edgecolor='k') +plt.imshow(true_states[None, :], aspect="auto") +plt.xticks([]) +plt.xlim(0, T) +plt.yticks([]) +plt.title("States", fontsize=15) + +# For visualizing categorical observations, we create a Cmap. +obs_flat = np.array([x[0] for x in obs]) #SSM initially provides categorical observations as a list of lists, and we transform them into a 1D array to facilitate plotting. +fig = plt.figure(figsize=(8, 2), dpi=80, facecolor='w', edgecolor='k') +plt.imshow(obs_flat[None,:], aspect="auto") +plt.xlim(0, T) +plt.xlabel("trial #", fontsize=12) +plt.yticks([]) +plt.grid(b=None) +plt.title("Observations", fontsize=15) +plt.show() +# - + +# Calculate the actual log likelihood by summing over discrete states +true_lp = true_glmhmm.log_probability(obs, transition_input=transition_input, observation_input=observation_input) +print("true_lp = " + str(true_lp)) + +# # 4. Make a new HMM for fitting purpose +# +# In this section, we instantiate a new GLM-HMM and assess its ability to recover generative parameters using Maximum Likelihood Estimation (MLE) on simulated data. MLE enables us to optimize model parameters to match the underlying data generation process, providing insights into the model's performance in emulating various scenarios. + +# ## EM for fitting + +# We employ the Expectation-Maximization (EM) method to fit the data. The EM algorithm consists of two main steps: the E-step and the M-step. The algorithm starts with an initial guess for the model parameters and iterates until the log marginal likelihood converges. During the E-step, the algorithm computes the expected value of the complete-data log-likelihood based on the model parameters estimate and the observed data (animal choices). Next, the M-Step tries to find the parameters that maximize the expected log-likelihood. + +# To elaborate further, during each trial and based on the specified GLM-HMM parameters, we compute the joint probability distribution encompassing both the states and the animals' decisions (left or right). Subsequently, the log-likelihood of the model is evaluated using this joint probability distribution. This relationship can be expressed in the following manner: +# +# $$ +# \begin{align} +# \log \left[ p(\mathbf{Y}|\theta, \mathbf{X}^{ob}, \mathbf{X}^{tr})\right]= \log \left[ \sum_{z} +# p(\mathbf{Y}, \mathbf{Z}|\theta, \mathbf{X}^{ob}, \mathbf{X}^{tr})\right] +# \end{align} +# $$ +# +# In this model, as mentioned, we have defined two sets of covariates, $\mathbf{X}^{ob}={x}^{ob}_{1}, ..., {x}^{ob}_{T}$ and $\mathbf{X}^{tr}={x}^{tr}_{1}, ..., {x}^{tr}_{T}$ which correspond to the observation and transition covariates respectively and a set of latent states as $\mathbf{Z}={z}_{1}, ..., {z}_{T} $. +# The model parameters, represented as $\theta=\{ \mathbf{w}^{tr}, \mathbf{w}^{ob}, \pi\}$, encompass the initial state distribution, transition weights, and observation weights for all states. + +glmhmm = ssm.HMM_TO(num_states, obs_dim, input_dim_T, input_dim_O, observations="input_driven_obs_diff_inputs", + observation_kwargs=dict(C=num_categories), transitions="inputdrivenalt") + +# # 4a. Fit the new HMM +# Here, we'll fit the model to simulated data. Through this fitting process, our model tries to capture the underlying dependencies that characterize the behavior of interest. This allows us to gain valuable insights into how well our model aligns with the data and its potential to generalize its findings to other cases. + +# Fitting the model +N_iters = 200 +hmm_lps = glmhmm.fit(obs, transition_input=transition_input, observation_input=observation_input, method="em", num_iters=N_iters, tolerance=10**-4) + +# # 4b. Graphically represent the acquired parameters +# + +# Visualize the Learned Parameters +# Plot the log probabilities of the true and fit models +fig = plt.figure(figsize=(4, 3), dpi=80, facecolor='w', edgecolor='k') +plt.plot(hmm_lps, label="EM") +plt.plot([0, N_iters], true_lp * np.ones(2), ':k', label="True") +plt.legend(loc="lower right") +plt.xlabel("EM Iteration") +plt.xlim(0, len(hmm_lps)) +plt.ylabel("Log Probability") +plt.show() + +glmhmm.permute(find_permutation(true_states, glmhmm.most_likely_states(obs, transition_input=transition_input, observation_input=observation_input))) + +# + +# Plot generative parameters +# 1) Observation +gen_weights_obs = gen_weights +recovered_weights = glmhmm.observations.params + +fig = plt.figure(figsize=(10, 3), dpi=80, facecolor='w', edgecolor='k') +plt.subplot(1, 2, 1) +for k in range(num_states): + if k == 0: + plt.plot(range(input_dim_O), gen_weights_obs[k][0], marker='D', color=cols[k], linestyle='-', + lw=1.5, label="generative") + else: + plt.plot(range(input_dim_O), gen_weights_obs[k][0], marker='D', color=cols[k], linestyle='-', + lw=1.5, label="") + +plt.yticks(fontsize=10) +plt.ylabel("Weight value", fontsize=12) +plt.xticks([0, 1], ['Obs_inp1', 'Obs_inp2'], fontsize=12, rotation=30) +plt.axhline(y=0, color="k", alpha=0.5, ls="--") +plt.title("Observation GLM", fontsize=12) + +for k in range(num_states): + if k == 0: + plt.plot(range(input_dim_O), recovered_weights[k][0], color=cols[k], + lw=1.5, label = "recovered", linestyle = '--') + else: + plt.plot(range(input_dim_O), recovered_weights[k][0], color=cols[k], + lw=1.5, label = '', linestyle = '--') +plt.yticks(fontsize=10) +plt.axhline(y=0, color="k", alpha=0.5, ls="--") +plt.legend() + +# 2) transition +gen_log_trans_mat = true_glmhmm.transitions.params[0] +gen_weights_Trans = true_glmhmm.transitions.params[1] +recovered_trans_mat = np.exp(glmhmm.transitions.params[0]) + +plt.subplot(1, 2, 2) +recovered_weights_Trans = glmhmm.trans_weights_K(glmhmm.params, num_states) +generative_weights_Trans = true_glmhmm.trans_weights_K(true_glmhmm.params, num_states) + +for k in range(num_states): + if k == 0: + plt.plot(range(input_dim_T), generative_weights_Trans[k], marker='D', color=cols[k], linestyle='-', + lw=1.5, label="generative") + plt.plot(range(input_dim_T), recovered_weights_Trans[k], color=cols[k], + lw=1.5, label = "recovered", linestyle = '--') + else: + plt.plot(range(input_dim_T), generative_weights_Trans[k], marker='D', + color=cols[k], linestyle='-', lw=1.5, label="") + plt.plot(range(input_dim_T), recovered_weights_Trans[k], color=cols[k], + lw=1.5, label = '', linestyle = '--') + +plt.yticks(fontsize=10) +plt.title("Transition GLM", fontsize=12) +plt.axhline(y=0, color="k", alpha=0.5, ls="--") +plt.xticks([0, 1], ['Tran_inp1', 'Tran_inp2'], fontsize=12, rotation=30) +plt.show() + +# + +# transition matrix +recovered_matrix = glmhmm.Ps_matrix(data=obs, transition_input=transition_input, observation_input=observation_input) # , train_mask=train_mask)[0] +gen_trans_mat = np.exp(gen_log_trans_mat) + +fig = plt.figure(figsize=(6, 3), dpi=80, facecolor='w', edgecolor='k') +plt.subplot(1, 2, 1) +plt.imshow(gen_trans_mat, vmin=-0.8, vmax=1, cmap='bone') +for i in range(gen_trans_mat.shape[0]): + for j in range(gen_trans_mat.shape[1]): + text = plt.text(j, i, str(np.around(gen_trans_mat[i, j], decimals=2)), ha="center", va="center", + color="k", fontsize=12) +plt.xlim(-0.5, num_states - 0.5) +plt.ylim(num_states - 0.5, -0.5) +plt.xticks(range(0, num_states), ('1', '2', '3'), fontsize=10) +plt.yticks(range(0, num_states), ('1', '2', '3'), fontsize=10) +plt.ylabel("state t", fontsize=15) +plt.xlabel("state t+1", fontsize=15) +plt.title("generative", fontsize=15) + +plt.subplot(1, 2, 2) +plt.imshow(np.mean(recovered_matrix, axis=0), vmin=-0.8, vmax=1, cmap='bone') +for i in range(np.mean(recovered_matrix, axis=0).shape[0]): + for j in range(np.mean(recovered_matrix, axis=0).shape[1]): + text = plt.text(j, i, str(np.around(np.mean(recovered_matrix, axis=0)[i, j], decimals=2)), ha="center", va="center", + color="k", fontsize=12) +plt.xlim(-0.5, num_states - 0.5) +plt.ylim(num_states - 0.5, -0.5) +plt.xticks(range(0, num_states), ('1', '2', '3'), fontsize=10) +plt.yticks(range(0, num_states), ('1', '2', '3'), fontsize=10) +plt.title("recovered", fontsize=15) +plt.show() +# - + +# # 4c. Analysis of the acquired states +# + +# + +# Get expected states +posterior_probs = [glmhmm.expected_states(data = obs, transition_input = transition_input, observation_input=observation_input)[0]] + +# Determine the state with the highest posterior probability +posterior_max = np.argmax(posterior_probs[0], axis = 1) + + +# + +# calculate state fractional occupancies +_, occur_for_state = np.unique(posterior_max, return_counts=True) +sum_all = np.sum(occur_for_state) +occur_for_state = occur_for_state/sum_all + +fig = plt.figure(figsize=(2.5, 2.5), dpi=80, facecolor='w', edgecolor='k') + +for state, occur in enumerate(occur_for_state): + occur_perc = occur * 100 + plt.bar(state, occur_perc, width = 0.7, color = cols[state]) + +plt.ylim((0, .6)) +plt.xticks([0, 1, 2], ['1', '2', '3'], fontsize=12) +plt.yticks([0, 25, 50], ['0', '25', '50'], fontsize=12) +plt.xlabel('state', fontsize=15) +plt.ylabel('Occupancy (%)', fontsize=15) +plt.gca().spines['right'].set_visible(False) +plt.gca().spines['top'].set_visible(False) +plt.show() + +# + +fig = plt.figure(figsize=(12, 2.5), dpi=80, facecolor='w', edgecolor='k') +for k in range(num_states): + plt.plot(posterior_probs[0][0:200, k], label="State " + str(k + 1), lw=1, marker='*', + color=cols[k]) + +plt.ylim((-0.01, 1.01)) +plt.yticks([0, 0.5, 1], fontsize=10) +plt.xticks(fontsize=12) +plt.xlabel("trial number", fontsize=15) +plt.ylabel("Posterior prob.", fontsize=15) +plt.gca().spines['right'].set_visible(False) +plt.gca().spines['top'].set_visible(False) +plt.show() + +# + +# plot choices and latents: +plt.figure(figsize=(8, 3.5)) +time_bin= 500 + +plt.subplot(211) +plt.imshow(true_states[None, :], aspect="auto") +plt.xticks([]) +plt.xlim(0, time_bin) +plt.ylabel("true\nstate", fontsize=14) +plt.yticks([]) + +plt.subplot(212) +inferred_states = glmhmm.most_likely_states(obs, transition_input=transition_input, observation_input=observation_input) +plt.imshow(inferred_states[None, :], aspect="auto") +plt.xlim(0, time_bin) +plt.ylabel("inferred\nstate", fontsize=14) +plt.yticks([]) +plt.xlabel("trial #", fontsize=12) +plt.show() +# - + + diff --git a/setup.cfg b/setup.cfg index c6be352f..98d4a402 100644 --- a/setup.cfg +++ b/setup.cfg @@ -27,7 +27,7 @@ doc = memory_profiler # measuring memory during docs building mkl jupytext - myst-nb + myst-nb myst-parser numpydoc sphinx diff --git a/ssm/__init__.py b/ssm/__init__.py index eb52d12d..e694ed9b 100644 --- a/ssm/__init__.py +++ b/ssm/__init__.py @@ -1,4 +1,4 @@ # Default imports for SSM - +from .hmm_TO import * from .hmm import * from .lds import * \ No newline at end of file diff --git a/ssm/hmm_TO.py b/ssm/hmm_TO.py new file mode 100644 index 00000000..20d04bb0 --- /dev/null +++ b/ssm/hmm_TO.py @@ -0,0 +1,551 @@ +from functools import partial +from tqdm.auto import trange + +import autograd.numpy as np +import autograd.numpy.random as npr +from autograd import value_and_grad + +from ssm.optimizers import adam_step, rmsprop_step, sgd_step, convex_combination +from ssm.primitives import hmm_normalizer +from ssm.messages import hmm_expected_states, hmm_filter, hmm_sample, viterbi +from ssm.util import ensure_args_are_lists, ensure_args_not_none_modified, ensure_args_not_none, \ + ensure_slds_args_not_none, ensure_variational_args_are_lists, \ + replicate, collapse, ssm_pbar, ensure_args_are_lists_modified + +import ssm.observations as obs +import ssm.transitions as trans +import ssm.init_state_distns as isd +import ssm.hierarchical as hier +import ssm.emissions as emssn + +__all__ = ['HMM_TO'] + + +class HMM_TO(object): + """ + Base class for hidden Markov models with observation and transition inputs. + + Notation: + K: number of discrete latent states + D: dimensionality of observations + M_obs: dimensionality of observation inputs + M_trans: dimensionality of transition inputs + + In the code we will sometimes refer to the discrete + latent state sequence as z and the data as x. + """ + + def __init__(self, K, D, M_trans=0, M_obs=0, init_state_distn=None, + transitions='standard', + transition_kwargs=None, + hierarchical_transition_tags=None, + observations="gaussian", observation_kwargs=None, + hierarchical_observation_tags=None, **kwargs): + + # Make the initial state distribution + if init_state_distn is None: + init_state_distn = isd.InitialStateDistribution(K, D, M=M_trans) + if not isinstance(init_state_distn, isd.InitialStateDistribution): + raise TypeError("'init_state_distn' must be a subclass of" + " ssm.init_state_distns.InitialStateDistribution.") + + # Make the transition model + transition_classes = dict( + standard=trans.StationaryTransitions, + stationary=trans.StationaryTransitions, + constrained=trans.ConstrainedStationaryTransitions, + sticky=trans.StickyTransitions, + inputdriven=trans.InputDrivenTransitions, + inputdrivenalt=trans.InputDrivenTransitionsAlternativeFormulation, + recurrent=trans.RecurrentTransitions, + recurrent_only=trans.RecurrentOnlyTransitions, + rbf_recurrent=trans.RBFRecurrentTransitions, + nn_recurrent=trans.NeuralNetworkRecurrentTransitions + ) + + if isinstance(transitions, str): + if transitions not in transition_classes: + raise Exception("Invalid transition model: {}. Must be one of {}". + format(transitions, list(transition_classes.keys()))) + + transition_kwargs = transition_kwargs or {} + transitions = \ + hier.HierarchicalTransitions(transition_classes[transitions], K, D, M=M_trans, + tags=hierarchical_transition_tags, + **transition_kwargs) \ + if hierarchical_transition_tags is not None \ + else transition_classes[transitions](K, D, M=M_trans, **transition_kwargs) + if not isinstance(transitions, trans.Transitions): + raise TypeError("'transitions' must be a subclass of" + " ssm.transitions.Transitions") + + # This is the master list of observation classes. + # When you create a new observation class, add it here. + observation_classes = dict( + gaussian=obs.GaussianObservations, + diagonal_gaussian=obs.DiagonalGaussianObservations, + studentst=obs.MultivariateStudentsTObservations, + t=obs.MultivariateStudentsTObservations, + diagonal_t=obs.StudentsTObservations, + diagonal_studentst=obs.StudentsTObservations, + exponential=obs.ExponentialObservations, + bernoulli=obs.BernoulliObservations, + categorical=obs.CategoricalObservations, + input_driven_obs=obs.InputDrivenObservations, + input_driven_obs_diff_inputs=obs.InputDrivenObservationsDiffInputs, + poisson=obs.PoissonObservations, + vonmises=obs.VonMisesObservations, + ar=obs.AutoRegressiveObservations, + autoregressive=obs.AutoRegressiveObservations, + no_input_ar=obs.AutoRegressiveObservationsNoInput, + diagonal_ar=obs.AutoRegressiveDiagonalNoiseObservations, + diagonal_autoregressive=obs.AutoRegressiveDiagonalNoiseObservations, + independent_ar=obs.IndependentAutoRegressiveObservations, + robust_ar=obs.RobustAutoRegressiveObservations, + no_input_robust_ar=obs.RobustAutoRegressiveObservationsNoInput, + robust_autoregressive=obs.RobustAutoRegressiveObservations, + diagonal_robust_ar=obs.RobustAutoRegressiveDiagonalNoiseObservations, + diagonal_robust_autoregressive=obs.RobustAutoRegressiveDiagonalNoiseObservations, + ) + + if isinstance(observations, str): + observations = observations.lower() + if observations not in observation_classes: + raise Exception("Invalid observation model: {}. Must be one of {}". + format(observations, list(observation_classes.keys()))) + + observation_kwargs = observation_kwargs or {} + observations = \ + hier.HierarchicalObservations(observation_classes[observations], K, D, M_obs=M_obs, + tags=hierarchical_observation_tags, + **observation_kwargs) \ + if hierarchical_observation_tags is not None \ + else observation_classes[observations](K, D, M_obs=M_obs, **observation_kwargs) + if not isinstance(observations, obs.Observations): + raise TypeError("'observations' must be a subclass of" + " ssm.observations.Observations") + + self.K, self.D, self.M_trans, self.M_obs = K, D, M_trans, M_obs + self.init_state_distn = init_state_distn + self.transitions = transitions + self.observations = observations + + @property + def params(self): + return self.init_state_distn.params, \ + self.transitions.params, \ + self.observations.params + + @params.setter + def params(self, value): + self.init_state_distn.params = value[0] + self.transitions.params = value[1] + self.observations.params = value[2] + + @ensure_args_are_lists_modified + def initialize(self, datas, transition_input=None, observation_input=None, masks=None, tags=None, + init_method="random"): + """ + Initialize parameters given data. + """ + self.init_state_distn.initialize(datas, inputs=observation_input, masks=masks, tags=tags) + self.transitions.initialize(datas, inputs=transition_input, masks=masks, tags=tags) + self.observations.initialize(datas, inputs=observation_input, masks=masks, tags=tags, init_method=init_method) + + def permute(self, perm): + """ + Permute the discrete latent states. + """ + assert np.all(np.sort(perm) == np.arange(self.K)) + self.init_state_distn.permute(perm) + self.transitions.permute(perm) + self.observations.permute(perm) + + def sample(self, T, prefix=None, transition_input=None, observation_input=None, tag=None, with_noise=True): + """ + Sample synthetic data from the model. Optionally, condition on a given + prefix (preceding discrete states and data). + + Parameters + ---------- + T : int + number of time steps to sample + + prefix : (zpre, xpre) + Optional prefix of discrete states (zpre) and continuous states (xpre) + zpre must be an array of integers taking values 0...num_states-1. + xpre must be an array of the same length that has preceding observations. + + transition_input : (T, transition_input_dim) array_like + Optional transition inputs to specify for sampling + + observation_input : (T, observation_input_dim) array_like + Optional observation inputs to specify for sampling + + tag : object + Optional tag indicating which "type" of sampled data + + with_noise : bool + Whether or not to sample data with noise. + + Returns + ------- + z_sample : array_like of type int + Sequence of sampled discrete states + + x_sample : (T x observation_dim) array_like + Array of sampled data + """ + K = self.K + D = (self.D,) if isinstance(self.D, int) else self.D + M_trans = (self.M_trans,) if isinstance(self.M_trans, int) else self.M_trans + M_obs = (self.M_obs,) if isinstance(self.M_obs, int) else self.M_obs + + assert isinstance(D, tuple) + assert isinstance(M_trans, tuple) + assert isinstance(M_obs, tuple) + assert T > 0 + + # Check the transition_input + if transition_input is not None: + assert transition_input.shape == (T,) + M_trans + + # Check the observation_input + if observation_input is not None: + assert observation_input.shape == (T,) + M_obs + + # Get the type of the observations + if isinstance(self.observations, obs.InputDrivenObservationsDiffInputs): + dtype = int + else: + dummy_data = self.observations.sample_x(0, np.empty(0, ) + D) + dtype = dummy_data.dtype + + # Fit the data array + if prefix is None: + # No prefix is given. Sample the initial state as the prefix. + pad = 1 + z = np.zeros(T, dtype=int) + data = np.zeros((T,) + D, dtype=dtype) + transition_input = np.zeros((T,) + M_trans) if transition_input is None else transition_input + observation_input = np.zeros((T,) + M_obs) if observation_input is None else observation_input + + mask = np.ones((T,) + D, dtype=bool) + + # Sample the first state from the initial distribution + pi0 = self.init_state_distn.initial_state_distn + z[0] = npr.choice(self.K, p=pi0) + data[0] = self.observations.sample_x(z[0], data[:0], observation_input=observation_input[0], + with_noise=with_noise) + + # We only need to sample T-1 data points now + T = T - 1 + + else: + # Check that the prefix is of the right type + zpre, xpre = prefix + pad = len(zpre) + assert zpre.dtype == int and zpre.min() >= 0 and zpre.max() < K + assert xpre.shape == (pad,) + D + + # Construct the states, data, transition_input, observation_input and mask arrays + z = np.concatenate((zpre, np.zeros(T, dtype=int))) + data = np.concatenate((xpre, np.zeros((T,) + D, dtype))) + transition_input = np.zeros((T + pad,) + M_trans) if transition_input is None else np.concatenate( + (np.zeros((pad,) + M_trans), transition_input)) + observation_input = np.zeros((T + pad,) + M_obs) if observation_input is None else np.concatenate( + (np.zeros((pad,) + M_obs), observation_input)) + mask = np.ones((T + pad,) + D, dtype=bool) + + # Fill in the rest of the data + for t in range(pad, pad + T): + Pt = self.transitions.transition_matrices(data[t - 1:t + 1], transition_input[t - 1:t + 1], + mask=mask[t - 1:t + 1], tag=tag)[0] + z[t] = npr.choice(self.K, p=Pt[z[t - 1]]) + data[t] = self.observations.sample_x(z[t], data[:t], observation_input=observation_input[t], tag=tag, + with_noise=with_noise) + + # Return the whole data if no prefix is given. + # Otherwise, just return the simulated part. + if prefix is None: + return z, data + else: + return z[pad:], data[pad:] + + @ensure_args_not_none_modified + def expected_states(self, data, transition_input=None, observation_input=None, mask=None, tag=None): + pi0 = self.init_state_distn.initial_state_distn + Ps = self.transitions.transition_matrices(data, transition_input, mask, tag) + log_likes = self.observations.log_likelihoods(data, observation_input, mask, tag) + return hmm_expected_states(pi0, Ps, log_likes) + + def Ps_matrix(self, data, transition_input=None, observation_input=None, mask=None, tag=None): + Ps = self.transitions.transition_matrices(data, transition_input, mask, tag) + return Ps + + @ensure_args_not_none_modified + def most_likely_states(self, data, transition_input=None, observation_input=None, mask=None, tag=None): + pi0 = self.init_state_distn.initial_state_distn + Ps = self.transitions.transition_matrices(data, transition_input, mask, tag) + log_likes = self.observations.log_likelihoods(data, observation_input, mask, tag) + return viterbi(pi0, Ps, log_likes) + + @ensure_args_not_none_modified + def filter(self, data, transition_input=None, observation_input=None, mask=None, tag=None): + pi0 = self.init_state_distn.initial_state_distn + Ps = self.transitions.transition_matrices(data, transition_input, mask, tag) + log_likes = self.observations.log_likelihoods(data, observation_input, mask, tag) + return hmm_filter(pi0, Ps, log_likes) + + @ensure_args_not_none_modified + def smooth(self, data, transition_input=None, observation_input=None, mask=None, tag=None): + """ + Compute the mean observation under the posterior distribution + of latent discrete states. + """ + Ez, _, _ = self.expected_states(data, transition_input, observation_input, mask) + return self.observations.smooth(Ez, data, transition_input, observation_input, tag) + + def log_prior(self): + """ + Compute the log prior probability of the model parameters + """ + return self.init_state_distn.log_prior() + \ + self.transitions.log_prior() + \ + self.observations.log_prior() + + @ensure_args_are_lists_modified + def log_likelihood(self, datas, transition_input=None, observation_input=None, masks=None, tags=None): + """ + Compute the log probability of the data under the current + model parameters. + + :param datas: single array or list of arrays of data. + :return total log probability of the data. + """ + ll = 0 + for data, transition_input, observation_input, mask, tag in zip(datas, transition_input, observation_input, + masks, tags): + pi0 = self.init_state_distn.initial_state_distn + Ps = self.transitions.transition_matrices(data, transition_input, mask, tag) + log_likes = self.observations.log_likelihoods(data, observation_input, mask, tag) + ll += hmm_normalizer(pi0, Ps, log_likes) + assert np.isfinite(ll) + return ll + + @ensure_args_are_lists_modified + def log_probability(self, datas, transition_input=None, observation_input=None, masks=None, tags=None): + return self.log_likelihood(datas, transition_input, observation_input, masks, tags) + self.log_prior() + + def expected_log_likelihood(self, expectations, datas, transition_inputs=None, observation_inputs=None, masks=None, + tags=None): + """ + Compute log-likelihood given current model parameters. + + :param datas: single array or list of arrays of data. + :return total log probability of the data. + """ + ell = 0.0 + for (Ez, Ezzp1, _), data, transition_input, observation_input, mask, tag in \ + zip(expectations, datas, transition_inputs, observation_inputs, masks, tags): + pi0 = self.init_state_distn.initial_state_distn + log_Ps = self.transitions.log_transition_matrices(data, transition_input, mask, tag) + log_likes = self.observations.log_likelihoods(data, observation_input, mask, tag) + + ell += np.sum(Ez[0] * np.log(pi0)) + ell += np.sum(Ezzp1 * log_Ps) + ell += np.sum(Ez * log_likes) + assert np.isfinite(ell) + + return ell + + def expected_log_probability(self, expectations, datas, transition_inputs=None, observation_inputs=None, masks=None, + tags=None): + """ + Compute the log-probability of the data given current + model parameters. + """ + ell = self.expected_log_likelihood(expectations, datas, transition_inputs=transition_inputs, + observation_inputs=observation_inputs, masks=masks, tags=tags) + return ell + self.log_prior() + + def trans_weights_K(self, hmm_params, K): + """ + Standardize the GLM transition weights. + """ + trans_weight_append_zero = np.vstack((hmm_params[1][1], np.zeros((1, hmm_params[1][1].shape[1])))) + permutation = range(K) + trans_weight_append_zero_standard = trans_weight_append_zero + v1 = - np.mean(trans_weight_append_zero, axis=0) + trans_weight_append_zero_standard[-1, :] = v1 + for i in range(K - 1): + trans_weight_append_zero_standard[i, :] = v1 + trans_weight_append_zero[i, :] # vi = v1 + wi + weight_vectors_trans = trans_weight_append_zero_standard[permutation] + return weight_vectors_trans + + # Model fitting + def _fit_sgd(self, optimizer, datas, transition_input, observation_input, masks, tags, verbose=2, num_iters=1000, + **kwargs): + """ + Fit the model with maximum marginal likelihood. + """ + T = sum([data.shape[0] for data in datas]) + + def _objective(params, itr): + self.params = params + obj = self.log_probability(datas, transition_input, observation_input, masks, tags) + return -obj / T + + # Set up the progress bar + lls = [-_objective(self.params, 0) * T] + pbar = ssm_pbar(num_iters, verbose, "Epoch {} Itr {} LP: {:.1f}", [0, 0, lls[-1]]) + + # Run the optimizer + step = dict(sgd=sgd_step, rmsprop=rmsprop_step, adam=adam_step)[optimizer] + state = None + for itr in pbar: + self.params, val, g, state = step(value_and_grad(_objective), self.params, itr, state, **kwargs) + lls.append(-val * T) + if verbose == 2: + pbar.set_description("LP: {:.1f}".format(lls[-1])) + pbar.update(1) + return lls + + def _fit_stochastic_em(self, optimizer, datas, transition_input, observation_input, masks, tags, verbose=2, + num_epochs=100, **kwargs): + """ + Replace the M-step of EM with a stochastic gradient update using the ELBO computed + on a minibatch of data. + """ + M = len(datas) + T = sum([data.shape[0] for data in datas]) + + # A helper to grab a minibatch of data + perm = [np.random.permutation(M) for _ in range(num_epochs)] + + def _get_minibatch(itr): + epoch = itr // M + m = itr % M + i = perm[epoch][m] + return datas[i], transition_input[i], observation_input[i], masks[i], tags[i][i] + + # Define the objective (negative ELBO) + def _objective(params, itr): + # Grab a minibatch of data + data, transition_input, observation_input, mask, tag = _get_minibatch(itr) + Ti = data.shape[0] + + # E step: compute expected latent states with current parameters + Ez, Ezzp1, _ = self.expected_states(data, transition_input, observation_input, mask, tag) + + # M step: set the parameter and compute the (normalized) objective function + self.params = params + pi0 = self.init_state_distn.initial_state_distn + log_Ps = self.transitions.log_transition_matrices(data, transition_input, mask, tag) + log_likes = self.observations.log_likelihoods(data, observation_input, mask, tag) + + # Compute the expected log probability + # (Scale by number of length of this minibatch.) + obj = self.log_prior() + obj += np.sum(Ez[0] * np.log(pi0)) * M + obj += np.sum(Ezzp1 * log_Ps) * (T - M) / (Ti - 1) + obj += np.sum(Ez * log_likes) * T / Ti + assert np.isfinite(obj) + + return -obj / T + + # Set up the progress bar + lls = [-_objective(self.params, 0) * T] + pbar = ssm_pbar(num_epochs * M, verbose, "Epoch {} Itr {} LP: {:.1f}", [0, 0, lls[-1]]) + + # Run the optimizer + step = dict(sgd=sgd_step, rmsprop=rmsprop_step, adam=adam_step)[optimizer] + state = None + for itr in pbar: + self.params, val, _, state = step(value_and_grad(_objective), self.params, itr, state, **kwargs) + epoch = itr // M + m = itr % M + lls.append(-val * T) + if verbose == 2: + pbar.set_description("Epoch {} Itr {} LP: {:.1f}".format(epoch, m, lls[-1])) + pbar.update(1) + return lls + + def _fit_em(self, datas, transition_input, observation_input, masks, tags, verbose=2, num_iters=100, tolerance=0, + init_state_mstep_kwargs={}, + transitions_mstep_kwargs={}, + observations_mstep_kwargs={}, + **kwargs): + """ + Fit the parameters with expectation maximization. + + E step: compute E[z_t] and E[z_t, z_{t+1}] with message passing; + M-step: analytical maximization of E_{p(z | x)} [log p(x, z; theta)]. + """ + lls = [self.log_probability(datas, transition_input, observation_input, masks, tags)] + pbar = ssm_pbar(num_iters, verbose, "LP: {:.1f}", [lls[-1]]) + + for itr in pbar: + # E step: compute expected latent states with current parameters + expectations = [self.expected_states(data, transition_input, observation_input, mask, tag) + for data, transition_input, observation_input, mask, tag, + in zip(datas, transition_input, observation_input, masks, tags)] + + # M step: maximize expected log joint wrt parameters + self.init_state_distn.m_step_modified(expectations, datas, transition_input, observation_input, masks, tags, + **init_state_mstep_kwargs) + self.transitions.m_step(expectations, datas, transition_input, masks, tags, **transitions_mstep_kwargs) + self.observations.m_step(expectations, datas, observation_input, masks, tags, **observations_mstep_kwargs) + + # Store progress + lls.append(self.log_prior() + sum([ll for (_, _, ll) in expectations])) + + if verbose == 2: + pbar.set_description("LP: {:.1f}".format(lls[-1])) + + # Check for convergence + if itr > 0 and abs(lls[-1] - lls[-2]) < tolerance: + if verbose == 2: + pbar.set_description("Converged to LP: {:.1f}".format(lls[-1])) + break + + return lls + + @ensure_args_are_lists_modified + def fit(self, datas, transition_input=None, observation_input=None, masks=None, tags=None, + verbose=2, method="em", + initialize=True, + init_method="random", + **kwargs): + + _fitting_methods = \ + dict(sgd=partial(self._fit_sgd, "sgd"), + adam=partial(self._fit_sgd, "adam"), + em=self._fit_em, + stochastic_em=partial(self._fit_stochastic_em, "adam"), + stochastic_em_sgd=partial(self._fit_stochastic_em, "sgd"), + ) + + if method not in _fitting_methods: + raise Exception("Invalid method: {}. Options are {}". + format(method, _fitting_methods.keys())) + + if initialize: + self.initialize(datas, + transition_input=None, observation_input=None, + masks=masks, + tags=tags, + init_method=init_method) + + if isinstance(self.transitions, + trans.ConstrainedStationaryTransitions): + if method != "em": + raise Exception("Only EM is implemented for constrained transitions.") + + return _fitting_methods[method](datas, + transition_input=transition_input, + observation_input=observation_input, + masks=masks, + tags=tags, + verbose=verbose, + **kwargs) diff --git a/ssm/init_state_distns.py b/ssm/init_state_distns.py index 21c22c25..187cb369 100644 --- a/ssm/init_state_distns.py +++ b/ssm/init_state_distns.py @@ -47,6 +47,9 @@ def m_step(self, expectations, datas, inputs, masks, tags, **kwargs): pi0 = sum([Ez[0] for Ez, _, _ in expectations]) + 1e-8 self.log_pi0 = np.log(pi0 / pi0.sum()) + def m_step_modified(self, expectations, datas, transition_input, observation_input, masks, tags, **kwargs): + pi0 = sum([Ez[0] for Ez, _, _ in expectations]) + 1e-8 + self.log_pi0 = np.log(pi0 / pi0.sum()) class FixedInitialStateDistribution(InitialStateDistribution): def __init__(self, K, D, pi0=None, M=0): diff --git a/ssm/observations.py b/ssm/observations.py index a27824df..7d008984 100644 --- a/ssm/observations.py +++ b/ssm/observations.py @@ -819,6 +819,297 @@ def smooth(self, expectations, data, input, tag): """ raise NotImplementedError +class InputDrivenObservationsDiffInputs(Observations): + + def __init__(self, K, D, M_obs=0, C=2, prior_mean=0, prior_sigma=1000): + """ + @param K: number of states + @param D: dimensionality of output + @param C: number of distinct classes for each dimension of output + @param prior_sigma: parameter governing strength of prior. Prior on GLM weights is multivariate + normal distribution with mean 'prior_mean' and diagonal covariance matrix (prior_sigma is on diagonal) + """ + super(InputDrivenObservationsDiffInputs, self).__init__(K, D, M_obs) + self.C = C + self.M_obs = M_obs + self.D = D + self.K = K + self.prior_mean = prior_mean + self.prior_sigma = prior_sigma + # Parameters linking input to distribution over output classes + self.Wk = npr.randn(K, C - 1, M_obs) + + @property + def params(self): + return self.Wk + + @params.setter + def params(self, value): + self.Wk = value + + def permute(self, perm): + self.Wk = self.Wk[perm] + + def log_prior(self): + lp = 0 + for k in range(self.K): + for c in range(self.C - 1): + weights = self.Wk[k][c] + lp += stats.multivariate_normal_logpdf(weights, mus=np.repeat(self.prior_mean, (self.M_obs)), + Sigmas=((self.prior_sigma) ** 2) * np.identity(self.M_obs)) + return lp + + # Calculate time dependent logits - output is matrix of size TxKxC + # Input is size TxM + def calculate_logits(self, observation_input): + """ + Return array of size TxKxC containing log(pr(yt=C|zt=k)) + :param observation_input: observation_input array of covariates of size TxM_obs + :return: array of size TxKxC containing log(pr(yt=c|zt=k, ut)) for all c in {1, ..., C} and k in {1, ..., K} + """ + # Transpose array dimensions, so that array is now of shape ((C-1)xKx(M+1)) + Wk_tranpose = np.transpose(self.Wk, (1, 0, 2)) + # Stack column of zeros to transform array from size ((C-1)xKx(M_obs+1)) to ((C)xKx(M_obs+1)) and then transform shape back to (KxCx(M_obs+1)) + Wk = np.transpose(np.vstack([Wk_tranpose, np.zeros((1, Wk_tranpose.shape[1], Wk_tranpose.shape[2]))]), + (1, 0, 2)) + # Input effect; transpose so that output has dims TxKxC + time_dependent_logits = np.transpose(np.dot(Wk, observation_input.T), (2, 0, + 1)) # Note: this has an unexpected effect when both input (and thus Wk) are empty arrays and returns an array of zeros + time_dependent_logits = time_dependent_logits - logsumexp(time_dependent_logits, axis=2, keepdims=True) + return time_dependent_logits + + def log_likelihoods(self, data, observation_input, mask, tag): + if observation_input.ndim == 1 and observation_input.shape == ( + self.M_obs,): # if input is vector of size self.M_obs (one time point), expand dims to be (1, M_obs) + observation_input = np.expand_dims(observation_input, axis=0) + time_dependent_logits = self.calculate_logits(observation_input) + assert self.D == 1, "InputDrivenObservationsDiffInputs written for D = 1!" + mask = np.ones_like(data, dtype=bool) if mask is None else mask + return stats.categorical_logpdf(data[:, None, :], time_dependent_logits[:, :, None, :], mask=mask[:, None, :]) + + def sample_x(self, z, xhist, observation_input=None, tag=None, with_noise=True): + assert self.D == 1, "InputDrivenObservationsDiffInputs written for D = 1!" + if observation_input.ndim == 1 and observation_input.shape == (self.M_obs,): + observation_input = np.expand_dims(observation_input, axis=0) + time_dependent_logits = self.calculate_logits(observation_input) # size TxKxC + ps = np.exp(time_dependent_logits) + T = time_dependent_logits.shape[0] + + if T == 1: + sample = np.array([npr.choice(self.C, p=ps[t, z]) for t in range(T)]) + elif T > 1: + sample = np.array([npr.choice(self.C, p=ps[t, z[t]]) for t in range(T)]) + return sample + + def m_step(self, expectations, datas, observation_input, masks, tags, optimizer="bfgs", **kwargs): + + T = sum([data.shape[0] for data in datas]) # total number of data points: time_bins + + def _multisoftplus(X): + ''' + computes f(X) = log(1+sum(exp(X), axis =1)) and its first derivative + :param X: array of size Tx(C-1) + :return f(X) of size T and df of size (Tx(C-1)) + ''' + X_augmented = np.append(X, np.zeros((X.shape[0], 1)), + 1) # append a column of zeros to X for rowmax calculation + rowmax = np.max(X_augmented, axis=1, + keepdims=1) # get max along column for log-sum-exp trick, rowmax is size T + # compute f: + f = np.log(np.exp(-rowmax[:, 0]) + np.sum(np.exp(X - rowmax), axis=1)) + rowmax[:, 0] + # compute df + df = np.exp(X - rowmax) / np.expand_dims((np.exp(-rowmax[:, 0]) + np.sum(np.exp(X - rowmax), axis=1)), + axis=1) + return f, df + + def _objective(params, k): + ''' + computes term in negative expected complete loglikelihood that depends on weights for state k + :param params: vector of size (C-1)xM_obs + :return term in negative expected complete LL that depends on weights for state k; scalar value + ''' + W = np.reshape(params, (self.C - 1, self.M_obs)) + obj = 0 + for data, input, mask, tag, (expected_states, _, _) \ + in zip(datas, observation_input, masks, tags, expectations): + xproj = input @ W.T # projection of input onto weight matrix for particular state, size is Tx(C-1) + f, _ = _multisoftplus(xproj) + assert data.shape[1] == 1, "InputDrivenObservationsDiffInputs written for D = 1!" + data_one_hot = one_hot(data[:, 0], self.C) # convert to one-hot representation of size TxC + temp_obj = (-np.sum(data_one_hot[:, :-1] * xproj, axis=1) + f) @ expected_states[:, k] + obj += temp_obj + + # add contribution of prior: + if self.prior_sigma != 0: + obj += 1 / (2 * self.prior_sigma ** 2) * np.sum(W ** 2) + return obj / T + + def _gradient(params, k): + ''' + Explicit calculation of gradient of _objective w.r.t weight matrix for state k, W_{k} + :param params: vector of size (C-1)xM_obs + :param k: state whose parameters we are currently optimizing + :return gradient of objective with respect to parameters; vector of size (C-1)xM_obs + ''' + W = np.reshape(params, (self.C - 1, self.M_obs)) + grad = np.zeros((self.C - 1, self.M_obs)) + for data, input, mask, tag, (expected_states, _, _) \ + in zip(datas, observation_input, masks, tags, expectations): + xproj = input @ W.T # projection of input onto weight matrix for particular state, size is Tx(C-1) + _, df = _multisoftplus(xproj) + assert data.shape[1] == 1, "InputDrivenObservationsDiffInputs written for D = 1!" + data_one_hot = one_hot(data[:, 0], self.C) # convert to one-hot representation of size TxC + grad += (df - data_one_hot[:, :-1]).T @ ( + expected_states[:, [k]] * input) # gradient is shape (C-1,M_obs) + # Add contribution to gradient from prior: + if self.prior_sigma != 0: + grad += (1 / (self.prior_sigma) ** 2) * W + # Now flatten grad into a vector: + grad = grad.flatten() + return grad / T + + def _hess(params, k): + ''' + Explicit calculation of hessian of _objective w.r.t weight matrix for state k, W_{k} + :param params: vector of size (C-1)xM_obs + :param k: state whose parameters we are currently optimizing + :return hessian of objective with respect to parameters; matrix of size ((C-1)xM_obs) x ((C-1)xM_obs) + ''' + W = np.reshape(params, (self.C - 1, self.M_obs)) + hess = np.zeros(((self.C - 1) * self.M_obs, (self.C - 1) * self.M_obs)) + for data, input, mask, tag, (expected_states, _, _) \ + in zip(datas, observation_input, masks, tags, expectations): + xproj = input @ W.T # projection of input onto weight matrix for particular state + _, df = _multisoftplus(xproj) + # center blocks: + dftensor = np.expand_dims(df, axis=2) # dims are now (T, (C-1), 1) + Xdf = np.expand_dims(input, + axis=1) * dftensor # multiply every input covariate term with every class derivative term for a given time step; dims are now (T, (C-1), M) + # reshape Xdf to (T, (C-1)*M_obs) + Xdf = np.reshape(Xdf, (Xdf.shape[0], -1)) + # weight Xdf by posterior state probabilities + pXdf = expected_states[:, [k]] * Xdf # output is size (T, (C-1)*M_obs) + # outer product with input vector, size (M_obs, (C-1)*M_obs) + XXdf = input.T @ pXdf + # center blocks of hessian: + temp_hess = np.zeros(((self.C - 1) * self.M_obs, (self.C - 1) * self.M_obs)) + for c in range(1, self.C): + inds = range((c - 1) * self.M_obs, c * self.M_obs) + temp_hess[np.ix_(inds, inds)] = XXdf[:, inds] + # off diagonal entries: + hess += temp_hess - Xdf.T @ pXdf + # add contribution of prior to hessian + if self.prior_sigma != 0: + hess += (1 / self.prior_sigma ** 2) + return hess / T + + from scipy.optimize import minimize + # Optimize weights for each state separately: + for k in range(self.K): + def _objective_k(params): + return _objective(params, k) + + def _gradient_k(params): + return _gradient(params, k) + + def _hess_k(params): + return _hess(params, k) + + sol = minimize(_objective_k, self.params[k].reshape(((self.C - 1) * self.M_obs)), hess=_hess_k, + jac=_gradient_k, method="trust-ncg") + self.params[k] = np.reshape(sol.x, (self.C - 1, + self.M_obs)) # for InputDrivenObservationsDiffInputs class: comment out if you want to stop observation weights being updated + + def smooth(self, expectations, data, observation_input, tag): + """ + Compute the mean observation under the posterior distribution + of latent discrete states. + """ + raise NotImplementedError + + +class _AutoRegressiveObservationsBase(Observations): + """ + Base class for autoregressive observations of the form, + + E[x_t | x_{t-1}, z_t=k, u_t] + = \sum_{l=1}^{L} A_k^{(l)} x_{t-l} + b_k + V_k u_t. + + where L is the number of lags and u_t is the input. + """ + + def __init__(self, K, D, M=0, lags=1): + super(_AutoRegressiveObservationsBase, self).__init__(K, D, M) + + # Distribution over initial point + self.mu_init = np.zeros((K, D)) + + # AR parameters + assert lags > 0 + self.lags = lags + self.bs = npr.randn(K, D) + self.Vs = npr.randn(K, D, M) + + # Inheriting classes may treat _As differently + self._As = None + + @property + def As(self): + return self._As + + @As.setter + def As(self, value): + self._As = value + + @property + def params(self): + return self.As, self.bs, self.Vs + + @params.setter + def params(self, value): + self.As, self.bs, self.Vs = value + + def permute(self, perm): + self.mu_init = self.mu_init[perm] + self.As = self.As[perm] + self.bs = self.bs[perm] + self.Vs = self.Vs[perm] + + def _compute_mus(self, data, input, mask, tag): + # assert np.all(mask), "ARHMM cannot handle missing data" + K, M = self.K, self.M + T, D = data.shape + As, bs, Vs, mu0s = self.As, self.bs, self.Vs, self.mu_init + + # Instantaneous inputs + mus = np.empty((K, T, D)) + mus = [] + for k, (A, b, V, mu0) in enumerate(zip(As, bs, Vs, mu0s)): + # Initial condition + mus_k_init = mu0 * np.ones((self.lags, D)) + + # Subsequent means are determined by the AR process + mus_k_ar = np.dot(input[self.lags:, :M], V.T) + for l in range(self.lags): + Al = A[:, l * D:(l + 1) * D] + mus_k_ar = mus_k_ar + np.dot(data[self.lags - l - 1:-l - 1], Al.T) + mus_k_ar = mus_k_ar + b + + # Append concatenated mean + mus.append(np.vstack((mus_k_init, mus_k_ar))) + + return np.array(mus) + + def smooth(self, expectations, data, input, tag): + """ + Compute the mean observation under the posterior distribution + of latent discrete states. + """ + T = expectations.shape[0] + mask = np.ones((T, self.D), dtype=bool) + mus = np.swapaxes(self._compute_mus(data, input, mask, tag), 0, 1) + return (expectations[:, :, None] * mus).sum(1) + class _AutoRegressiveObservationsBase(Observations): """ diff --git a/ssm/transitions.py b/ssm/transitions.py index 79d5e432..23dc3b07 100644 --- a/ssm/transitions.py +++ b/ssm/transitions.py @@ -262,6 +262,99 @@ def neg_hessian_expected_log_trans_prob(self, data, input, mask, tag, expected_j T, D = data.shape return np.zeros((T-1, D, D)) + +class InputDrivenTransitionsAlternativeFormulation(StickyTransitions): + # This class contains K-1 weight vectors so as to cope with degeneracy + """ + Hidden Markov Model whose transition probabilities are + determined by a generalized linear model applied to the + exogenous input. This has K-1 weight vectors so as to cope with degeneracy. + """ + def __init__(self, K, D, M, prior_sigma=1000, alpha=1, kappa=0): + """ + @param K: number of states + @param D: dimensionality of output + @param C: number of distinct classes for each dimension of output + @param prior_sigma: parameter governing strength of prior. Prior on GLM weights is multivariate + normal distribution with mean 'prior_mean' and diagonal covariance matrix (prior_sigma is on diagonal) + """ + + super(InputDrivenTransitionsAlternativeFormulation, self).__init__(K, D, M=M, alpha=alpha, kappa=kappa) + + # Parameters linking input to state distribution + self.Ws = npr.randn(K-1, M) + + # Regularization of Ws + # self.l2_penalty = l2_penalty + self.prior_sigma = prior_sigma + # self.global_fit = global_fit + + @property + def params(self): + return [self.log_Ps, self.Ws] + + @params.setter + def params(self, value): + [self.log_Ps, self.Ws] = value + + def permute(self, perm): + """ + Permute the discrete latent states. + """ + self.log_Ps = self.log_Ps[np.ix_(perm, perm)] + self.Ws = np.vstack([self.Ws, np.zeros((1, self.Ws.shape[1]))]) + self.Ws = self.Ws[perm] + + def log_prior(self): + lp = super(InputDrivenTransitionsAlternativeFormulation, self).log_prior() + lp = lp + np.sum(-0.5 * (1 / (self.prior_sigma ** 2)) * self.Ws**2) + return lp + + def log_transition_matrices(self, data, input, mask, tag): + T = np.array(data).shape[0] + assert np.array(input).shape[0] == T + # Previous state effect + log_Ps = np.tile(self.log_Ps[None, :, :], (T-1, 1, 1)) + # Append column of zeros so that Ws_with_zeros is now KxM + Ws_with_zeros = np.vstack([self.Ws, np.zeros((1, self.Ws.shape[1]))]) + if self.Ws.shape[0] > input[1:].shape[1]: # If it already has a column of zeros + Ws_with_zeros=self.Ws + # Input effect + log_Ps = log_Ps + np.dot(input[1:], Ws_with_zeros.T)[:, None, :] + normalized_Ps = log_Ps - logsumexp(log_Ps, axis=2, keepdims=True) + return normalized_Ps + + def m_step(self, expectations, datas, inputs, masks, tags, + optimizer="lbfgs", num_iters=1000, **kwargs): + optimizer = dict(sgd=sgd, adam=adam, rmsprop=rmsprop, bfgs=bfgs, lbfgs=lbfgs)[optimizer] + # Maximize the expected log joint + def _expected_log_joint(expectations): + elbo = self.log_prior() + for data, input, mask, tag, (expected_states, expected_joints, _) \ + in zip(datas, inputs, masks, tags, expectations): + log_Ps = self.log_transition_matrices(data, input, mask, tag) + K = np.array(log_Ps).shape[1] + elbo += np.sum(expected_joints * log_Ps) + return elbo + + T = sum([data.shape[0] for data in datas]) + + def _objective(params, itr): + self.params = params + obj = _expected_log_joint(expectations) + return -obj / T + + # Call the optimizer. Persist state (e.g. SGD momentum) across calls to m_step + optimizer_state = self.optimizer_state if hasattr(self, "optimizer_state") else None + self.params, self.optimizer_state = \ + optimizer(_objective, self.params, num_iters=num_iters, + state=optimizer_state, full_output=True, **kwargs) + + def neg_hessian_expected_log_trans_prob(self, data, input, mask, tag, expected_joints): + # Return (T-1, D, D) array of blocks for the diagonal of the Hessian + T, D = data.shape + return np.zeros((T-1, D, D)) + class RecurrentTransitions(InputDrivenTransitions): """ Generalization of the input driven HMM in which the observations serve as future inputs diff --git a/ssm/util.py b/ssm/util.py index 093b9cc6..3eb60eae 100644 --- a/ssm/util.py +++ b/ssm/util.py @@ -113,6 +113,42 @@ def wrapper(self, datas, inputs=None, masks=None, tags=None, **kwargs): return wrapper +def ensure_args_are_lists_modified(f): + def wrapper(self, datas, transition_input=None, observation_input=None, masks=None, tags=None, **kwargs): + + datas = [datas] if not isinstance(datas, (list, tuple)) else datas + + M_obs = (self.M_obs,) if isinstance(self.M_obs, int) else self.M_obs + assert isinstance(M_obs, tuple) + + M_trans = (self.M_trans,) if isinstance(self.M_trans, int) else self.M_trans + assert isinstance(M_trans, tuple) + + if transition_input is None: + transition_input = [np.zeros((data.shape[0],) + M_trans) for data in datas] + elif not isinstance(transition_input, (list, tuple)): + transition_input = [transition_input] + + if observation_input is None: + observation_input = [np.zeros((data.shape[0],) + M_obs) for data in datas] + elif not isinstance(observation_input, (list, tuple)): + observation_input = [observation_input] + + if masks is None: + masks = [np.ones_like(data, dtype=bool) for data in datas] + elif not isinstance(masks, (list, tuple)): + masks = [masks] + + if tags is None: + tags = [None] * len(datas) + elif not isinstance(tags, (list, tuple)): + tags = [tags] + + return f(self, datas, transition_input=transition_input, observation_input=observation_input, masks=masks, tags=tags, **kwargs) + + return wrapper + + def ensure_variational_args_are_lists(f): def wrapper(self, arg0, datas, inputs=None, masks=None, tags=None, **kwargs): datas = [datas] if not isinstance(datas, (list, tuple)) else datas @@ -158,6 +194,24 @@ def wrapper(self, data, input=None, mask=None, tag=None, **kwargs): return f(self, data, input=input, mask=mask, tag=tag, **kwargs) return wrapper +def ensure_args_not_none_modified(f): + + def wrapper(self, data, transition_input=None, observation_input=None, mask=None, tag=None, **kwargs): + assert data is not None + + M_obs = (self.M_obs,) if isinstance(self.M_obs, int) else self.M_obs + assert isinstance(M_obs, tuple) + + M_trans = (self.M_trans,) if isinstance(self.M_trans, int) else self.M_trans + assert isinstance(M_trans, tuple) + + transition_input = np.zeros((data.shape[0],) + M) if transition_input is None else transition_input + observation_input = np.zeros((data.shape[0],) + M) if observation_input is None else observation_input + + mask = np.ones_like(data, dtype=bool) if mask is None else mask + + return f(self, data, transition_input=transition_input, observation_input=observation_input, mask=mask, tag=tag, **kwargs) + return wrapper def ensure_slds_args_not_none(f): def wrapper(self, variational_mean, data, input=None, mask=None, tag=None, **kwargs):