# Help with performance drop when adjusting a Bradley-Terry model

**URL:** <https://discourse.mc-stan.org/t/help-with-performance-drop-when-adjusting-a-bradley-terry-model/21054>\
**Category:** Modeling\
**Tags:** performance, rstan\
**Created:** [March 2, 2021, 12:21pm UTC](https://discourse.mc-stan.org/t/help-with-performance-drop-when-adjusting-a-bradley-terry-model/21054 "2021-03-02T12:21:02Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![C\_G](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.mc-stan.org/c_g/32/5806_2.png) [@C\_G](https://discourse.mc-stan.org/u/C_G)\
**Post date:** [March 2, 2021, 12:21pm UTC](https://discourse.mc-stan.org/t/help-with-performance-drop-when-adjusting-a-bradley-terry-model/21054/1 "2021-03-02T12:21:02Z")

</div>

Hi,

I am trying to fit a [Bradley-Terry](https://en.wikipedia.org/wiki/Bradley%E2%80%93Terry_model) model using Stan to model team performance data.

I started off using an example [here](https://github.com/stan-dev/example-models/blob/master/knitr/bradley-terry/individual-uniform.stan) created by Bob Carpenter which worked perfectly.

However I am now in the process of trying to adapt this example to allow for additional covariates other than just the team index and so far my attempts result in a doubling of run time when using the exact same number of covariates as the original example. Am I doing something obviously wrong or is there a way to improve the run time ?

Here is my Stan model so far:

```

data {
  int<lower = 0> K; // # of Variables
  int<lower = 0> N; // # of Matches
  matrix[N,K] M; // Matrix of covariate differences
  int<lower = 0, upper = 1> y[N]; // Result from Team A
}

parameters {
    vector[K] alpha; // Coeficents
}

model {
    y ~ bernoulli_logit(M * alpha);
}

```

And for reference here is my R calling code:

```
team_a_mat <- model.matrix(~ team_a + covar_a, data = adat)[,-1]
team_b_mat <- model.matrix(~ team_b + covar_b, data = adat)[,-1]

stopifnot(
    nrow(team_a_mat) == nrow(team_b_mat),
    ncol(team_a_mat) == ncol(team_b_mat)
)

diff_mat <- team_a_mat - team_b_mat

fit <- sampling(
    mod,
    data = list(
        K = ncol(diff_mat),
        N = nrow(diff_mat),
        M = diff_mat,
        y = adat$team_a_result
    )
)

```

EDIT: Made a couple of tweaks to remove the second matrix multiplication which sped things up a bit but am still seeing a 2x worsening in performance :( - have updated the numbers in the main thread accordingly

---

<div class="post-metadata">

**Author:** ![Max\_Mantei](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.mc-stan.org/max_mantei/32/7912_2.png) [@Max\_Mantei](https://discourse.mc-stan.org/u/Max_Mantei)\
**Post date:** [March 5, 2021, 10:42am UTC](https://discourse.mc-stan.org/t/help-with-performance-drop-when-adjusting-a-bradley-terry-model/21054/2 "2021-03-05T10:42:35Z")

</div>

Hey there, welcome back!

Your model looks like logistic regression. sometimes inference can be unstable when you have perfect separation induced by the predictors/variables.

I think adding weakly informative priors for `alpha` will help greatly. Since the predictor is on the log-odds scale, something like `alpha ~ normal(0, 2.5);` will probably stabilize estimation, while still being pretty wide in terms of plausible values.

Cheers,  
Max

---

<div class="post-metadata">

**Author:** ![Max\_Mantei](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.mc-stan.org/max_mantei/32/7912_2.png) [@Max\_Mantei](https://discourse.mc-stan.org/u/Max_Mantei)\
**Post date:** [March 10, 2021, 9:07am UTC](https://discourse.mc-stan.org/t/help-with-performance-drop-when-adjusting-a-bradley-terry-model/21054/3 "2021-03-10T09:07:07Z")

</div>

Hey @C_G !

Just wanted to ask if you got your model to work? Did using (informative) priors help?

Cheers,  
Max

---

<div class="post-metadata">

**Author:** ![C\_G](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.mc-stan.org/c_g/32/5806_2.png) [@C\_G](https://discourse.mc-stan.org/u/C_G)\
**Post date:** [March 14, 2021, 1:23pm UTC](https://discourse.mc-stan.org/t/help-with-performance-drop-when-adjusting-a-bradley-terry-model/21054/4 "2021-03-14T13:23:47Z")

</div>

Hi Max,

Apologies for the delay in replying. Indeed you are right at this point the model is just a different specification of logistic regression. Also specifying some weakly informative priors did speed up the sampling by a marginal amount. I think in general its fair to say that the original model specification used by Bob Carpenter is a superior implementation but is obviously much more limited in its formulation.

Thank you for your help !

---

<div class="post-metadata">

**Author:** ![andrjohns](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.mc-stan.org/andrjohns/32/15297_2.png) [@andrjohns](https://discourse.mc-stan.org/u/andrjohns)\
**Post date:** [March 14, 2021, 2:01pm UTC](https://discourse.mc-stan.org/t/help-with-performance-drop-when-adjusting-a-bradley-terry-model/21054/5 "2021-03-14T14:01:51Z")

</div>

Something else to try is the `bernoulli_logit_glm` likelihood ([more info in the manual](https://mc-stan.org/docs/2_26/functions-reference/bernoulli-logit-glm.html)), which is a more efficient implementation.

So you would change your likelihood:

```
    y ~ bernoulli_logit(M * alpha);

```

to:

```
    y ~ bernoulli_logit_glm(M, 0, alpha);

```

(The 0 is because you don’t have an intercept, just coefficients and covariates). The `_glm` distributions will (generally) sample faster and better than the matrix multiplication. Also, if you have a discrete GPU and a large dataset, then you can GPU-accelerate the model
