---
title: "Response Models"
description: "Ordered and multinomial response models in EMC2"
author: "Niek Stevenson"
output: rmarkdown::html_document
bibliography: refs.bib
vignette: >
  %\VignetteIndexEntry{"Response Models"}
  %\VignetteEncoding{UTF-8}
  %\VignetteEngine{knitr::rmarkdown}
editor_options: 
  markdown: 
    wrap: 72
---

```{r, echo = FALSE}
rm(list = ls())
library(EMC2)
set.seed(21)
```

## Introduction

This vignette shows how to use the response-only models currently
implemented in *EMC2*. These models fall into two different response
geometries:

1.  Ordered response models: `ordered_probit()` and `ordered_logit()`
2.  Multinomial choice models: `multinomial_logit()` and
    `multinomial_probit()`

Ordered response models assume a single latent evidence variable and one
or more cutpoints. In the binary case this is the same general setup as
signal detection theory: a latent evidence value is compared against a
criterion. With more than two ordered responses, the single criterion
becomes a set of ordered criteria, as in rating or confidence versions
of Signal Detection Theory (SDT). `ordered_probit()` uses a Gaussian
latent noise distribution, which makes it the closest match to classical
Gaussian SDT. `ordered_logit()` uses the same threshold geometry but
with logistic noise.

Multinomial response models are different. They are not threshold models
on one evidence axis, but random-utility models over a set of
alternatives. `multinomial_logit()` is the standard multinomial-logit or
softmax model: each response has a latent utility and the response
probabilities are a softmax over those utilities. `multinomial_probit()`
uses the same utility geometry but with Gaussian noise instead of the
softmax/logit noise assumption.

The worked examples below use `ordered_probit()` and
`multinomial_logit()`. The other two models follow the same design
logic, but swap the latent noise distribution within the same geometry.

The workflow is the same as for the DDM and race models:

1.  Specify the design
2.  Inspect sampled parameters and their mapping to design cells
3.  Simulate data
4.  Define priors and create an `emc` object
5.  Fit the model
6.  Summarize posterior estimates and compare observed and posterior
    predictive choice proportions

```{r}
choice_summary <- function(data) {
  out <- as.data.frame(prop.table(table(data$S, data$R), 1))
  names(out) <- c("S", "R", "prob")
  out
}
```

## 1. Ordered Response Models

Ordered response models place responses on a single latent evidence axis
and use cutpoints to divide that axis into response categories. Here we
use a 3-category task with `low`, `mid`, and `high` stimuli and
responses. `location` depends on stimulus identity, `scale` is fixed to
1, and `cut ~ 1` estimates the standard `K - 1` thresholds.

Conceptually, this is the SDT-like response family in *EMC2*. In a
binary yes/no task there is one criterion. In a 3-category task there
are two ordered criteria. `location` shifts the latent evidence
distribution, and `cut` determines where the response boundaries lie.

```{r}
matchfun <- function(d) d$S == d$lR

design_ord <- design(
  Rlevels = c("low", "mid", "high"),
  factors = list(subjects = 1, S = c("low", "mid", "high")),
  formula = list(location ~ 0 + S, scale ~ 1, cut ~ 1),
  matchfun = matchfun,
  constants = c(scale = log(1)),
  model = ordered_probit
)
```

`sampled_pars()` shows the free parameters, and `mapped_pars()` shows
how they map to the latent design cells.

```{r}
sampled_pars(design_ord)
```

```{r}
p_vector_ord <- sampled_pars(design_ord)
p_vector_ord[] <- c(-1, 0, 1.2, -0.4, log(1.3))

mapped_pars(design_ord, p_vector_ord)
```

Now we simulate data from these parameters:

```{r, results = "hide"}
dat_ord <- make_data(parameters = p_vector_ord, design = design_ord, n_trials = 80)
```

For choice-only models it is often most useful to inspect response
proportions directly:

```{r}
choice_summary(dat_ord)
```

Next we define a prior and create the `emc` object.

```{r, results = "hide"}
prior_ord <- prior(
  design = design_ord,
  type = "single",
  pmean = c(
    location_Slow = -0.5,
    location_Smid = 0,
    location_Shigh = 0.5,
    cut_lRlow = -0.2,
    cut_lRmid = log(1.1)
  ),
  psd = c(
    location_Slow = 0.8,
    location_Smid = 0.8,
    location_Shigh = 0.8,
    cut_lRlow = 0.5,
    cut_lRmid = 0.3
  )
)

emc_ord <- make_emc(dat_ord, design_ord, prior_list = prior_ord, type = "single", n_chains = 2)
```

## 2. Fit the Ordered Model

The following call fits the model and saves the result:

```{r, eval = FALSE}
emc_ord <- fit(emc_ord, fileName = "data/response-models-ordered.RData")
```

```{r, include = FALSE}
load("data/response-models-ordered.RData")
emc_ord <- emc
rm(emc)
```

`summary()` reports posterior quantiles, `Rhat`, and ESS:

```{r}
summary(emc_ord)
```

`plot_pars()` compares the posterior to the generating values:

```{r, fig.alt = "Posterior parameter densities against true values for the ordered probit example"}
plot_pars(emc_ord, true_pars = p_vector_ord, use_prior_lim = FALSE)
```

Finally, `plot_fit_choice()` compares observed response probabilities to
posterior predictive intervals:

```{r}
plot_fit_choice(emc_ord, factors = "S", style = "prob", n_post = 20)
```

For ordered responses, cumulative fits can also be useful because they
reflect the threshold structure directly:

```{r}
plot_fit_choice(emc_ord, factors = "S", style = "cumulative", n_post = 20)
```

To switch from ordered probit to ordered logit, the design is identical
except for the model choice. That is, the latent threshold structure
stays the same, but the Gaussian link is replaced by a logistic one:

```{r, eval = FALSE}
design_ord_logit <- design(
  Rlevels = c("low", "mid", "high"),
  factors = list(subjects = 1, S = c("low", "mid", "high")),
  formula = list(location ~ 0 + S, scale ~ 1, cut ~ 1),
  matchfun = matchfun,
  constants = c(scale = log(1)),
  model = ordered_logit
)
```

EMC2 also supports multinomial probit and logit response models, they
have documentation, but they mostly exist to be paired with trend
models, more on that later!

