Page 1 of 1

MNL for Case 1 BWS: saddle point convergence

Posted: 22 Mar 2024, 10:59
by jayb
Hi,

I'm specifying an MNL model for case 1 BWS. The experiment presented respondents with 8 choice sets, each with 4 attributes per choice set, and 16 attributes in total. I captured the order of choice, so the availability of alternatives is observed not assumed. I have copied the data structure and code below.

The model throws a warning (WARNING: Some eigenvalues of the Hessian are positive, indicating convergence to a saddle point!), leaving NaNs in the output. However, if I fix the first position-specific constant of the worst choices, the model converges. To me, it makes more sense that the position-specific constants for the worst choices are relative to the first position-specific constant of the best choices, but I also see it may be reasonable to assume the position-specific effects are independent between best and worst choices. In any case, I don't expect the model not to converge properly. Can you advise?

Thanks,

Jay

Code: Select all

Rows: 7,408
Columns: 77
$ uuid         <chr> "01nemkz0cju…
$ panel        <dbl> 13, 13, 13, …
$ setno        <dbl> 1, 2, 3, 4, …
$ choice_best  <dbl> 4, 2, 3, 3, …
$ choice_worst <dbl> 3, 1, 1, 4, …
$ T1_1         <dbl> 0, 0, 0, 0, …
$ T1_2         <dbl> 0, 0, 0, 0, …
$ T1_3         <dbl> 1, 0, 0, 0, …
$ T1_4         <dbl> 0, 0, 0, 0, …
$ T2_1         <dbl> 0, 0, 0, 0, …
$ T2_2         <dbl> 0, 0, 0, 0, …
$ T2_3         <dbl> 0, 0, 0, 0, …
$ T2_4         <dbl> 0, 1, 0, 0, …
$ T3_1         <dbl> 0, 0, 0, 0, …
$ T3_2         <dbl> 0, 0, 0, 0, …
$ T3_3         <dbl> 0, 1, 0, 0, …
$ T3_4         <dbl> 0, 0, 0, 0, …
$ T4_1         <dbl> 1, 0, 0, 0, …
$ T4_2         <dbl> 0, 0, 0, 0, …
$ T4_3         <dbl> 0, 0, 0, 0, …
$ T4_4         <dbl> 0, 0, 0, 0, …
$ T5_1         <dbl> 0, 0, 0, 0, …
$ T5_2         <dbl> 0, 0, 0, 0, …
$ T5_3         <dbl> 0, 0, 0, 0, …
$ T5_4         <dbl> 0, 0, 0, 1, …
$ T6_1         <dbl> 0, 0, 0, 0, …
$ T6_2         <dbl> 0, 0, 0, 0, …
$ T6_3         <dbl> 0, 0, 0, 0, …
$ T6_4         <dbl> 0, 0, 1, 0, …
$ T7_1         <dbl> 0, 0, 0, 0, …
$ T7_2         <dbl> 0, 0, 1, 0, …
$ T7_3         <dbl> 0, 0, 0, 0, …
$ T7_4         <dbl> 0, 0, 0, 0, …
$ T8_1         <dbl> 0, 0, 0, 0, …
$ T8_2         <dbl> 0, 0, 0, 1, …
$ T8_3         <dbl> 0, 0, 0, 0, …
$ T8_4         <dbl> 0, 0, 0, 0, …
$ T9_1         <dbl> 0, 0, 0, 0, …
$ T9_2         <dbl> 0, 0, 0, 0, …
$ T9_3         <dbl> 0, 0, 1, 0, …
$ T9_4         <dbl> 0, 0, 0, 0, …
$ T10_1        <dbl> 0, 0, 0, 1, …
$ T10_2        <dbl> 0, 0, 0, 0, …
$ T10_3        <dbl> 0, 0, 0, 0, …
$ T10_4        <dbl> 0, 0, 0, 0, …
$ T11_1        <dbl> 0, 0, 0, 0, …
$ T11_2        <dbl> 0, 0, 0, 0, …
$ T11_3        <dbl> 0, 0, 0, 1, …
$ T11_4        <dbl> 0, 0, 0, 0, …
$ T12_1        <dbl> 0, 0, 1, 0, …
$ T12_2        <dbl> 0, 0, 0, 0, …
$ T12_3        <dbl> 0, 0, 0, 0, …
$ T12_4        <dbl> 0, 0, 0, 0, …
$ T13_1        <dbl> 0, 0, 0, 0, …
$ T13_2        <dbl> 0, 1, 0, 0, …
$ T13_3        <dbl> 0, 0, 0, 0, …
$ T13_4        <dbl> 0, 0, 0, 0, …
$ T14_1        <dbl> 0, 0, 0, 0, …
$ T14_2        <dbl> 0, 0, 0, 0, …
$ T14_3        <dbl> 0, 0, 0, 0, …
$ T14_4        <dbl> 1, 0, 0, 0, …
$ T15_1        <dbl> 0, 0, 0, 0, …
$ T15_2        <dbl> 1, 0, 0, 0, …
$ T15_3        <dbl> 0, 0, 0, 0, …
$ T15_4        <dbl> 0, 0, 0, 0, …
$ T16_1        <dbl> 0, 1, 0, 0, …
$ T16_2        <dbl> 0, 0, 0, 0, …
$ T16_3        <dbl> 0, 0, 0, 0, …
$ T16_4        <dbl> 0, 0, 0, 0, …
$ avail1B      <dbl> 1, 1, 1, 1, …
$ avail1W      <dbl> 1, 1, 1, 1, …
$ avail2B      <dbl> 1, 1, 1, 1, …
$ avail2W      <dbl> 1, 0, 1, 1, …
$ avail3B      <dbl> 0, 1, 1, 1, …
$ avail3W      <dbl> 1, 1, 0, 0, …
$ avail4B      <dbl> 1, 1, 1, 1, …
$ avail4W      <dbl> 1, 1, 1, 1, …

Code: Select all

### Initialise code
apollo_initialise()

### Set core controls
apollo_control = list(
  modelName       = "TEST_BW_MNL_no_covariates",
  modelDescr      = "MNL model on BW choice data, no covariates",
  indivID         = "uuid",
  nCores          = 4,
  outputDirectory = "output",
  seed = 1234
)

# ################################################################# #
#### LOAD DATA AND APPLY ANY TRANSFORMATIONS                     ####
# ################################################################# #
database

# ################################################################# #
#### DEFINE MODEL PARAMETERS                                     ####
# ################################################################# #

### Vector of parameters, including any that are kept fixed in estimation
apollo_beta = c(set_names(rep(0, 24),
                          c(paste0("asc_alt", 1:4, "_",  "B"),
                            paste0("asc_alt", 1:4, "_",  "W"),
                            paste0("beta_T", 1:16))),
                mu_worst = 1)

### Vector with names (in quotes) of parameters to be kept fixed at their starting value in apollo_beta, use apollo_beta_fixed = c() if none
apollo_fixed = c("asc_alt1_B", "beta_T2")


# ################################################################# #
#### GROUP AND VALIDATE INPUTS                                   ####
# ################################################################# #

apollo_inputs = apollo_validateInputs()

# ################################################################# #
#### DEFINE MODEL AND LIKELIHOOD FUNCTION                        ####
# ################################################################# #

apollo_probabilities=function(apollo_beta, apollo_inputs, functionality = "estimate"){

  ### Attach inputs and detach after function exit
  apollo_attach(apollo_beta, apollo_inputs)
  on.exit(apollo_detach(apollo_beta, apollo_inputs))

  ### Create list of probabilities P
  P = list()
  P_bw = list()

  ### List of utilities for the "best" choice
  V_best=list()
  V_best[["alt1B"]] = asc_alt1_B + beta_T1*T1_1 + beta_T2*T2_1 + beta_T3*T3_1 + beta_T4*T4_1 +
    beta_T5*T5_1 + beta_T6*T6_1 + beta_T7*T7_1 +
    beta_T8*T8_1 + beta_T9*T9_1 + beta_T10*T10_1 +
    beta_T11*T11_1 + beta_T12*T12_1 + beta_T13*T13_1 +
    beta_T14*T14_1 + beta_T15*T15_1 + beta_T16*T16_1
  V_best[["alt2B"]] = asc_alt2_B + beta_T1*T1_2 + beta_T2*T2_2 + beta_T3*T3_2 + beta_T4*T4_2 +
    beta_T5*T5_2 + beta_T6*T6_2 + beta_T7*T7_2 +
    beta_T8*T8_2 + beta_T9*T9_2 + beta_T10*T10_2 +
    beta_T11*T11_2 + beta_T12*T12_2 + beta_T13*T13_2 +
    beta_T14*T14_2 + beta_T15*T15_2 + beta_T16*T16_2
  V_best[["alt3B"]] = asc_alt3_B + beta_T1*T1_3 + beta_T2*T2_3 + beta_T3*T3_3 + beta_T4*T4_3 +
    beta_T5*T5_3 + beta_T6*T6_3 + beta_T7*T7_3 +
    beta_T8*T8_3 + beta_T9*T9_3 + beta_T10*T10_3 +
    beta_T11*T11_3 + beta_T12*T12_3 + beta_T13*T13_3 +
    beta_T14*T14_3 + beta_T15*T15_3 + beta_T16*T16_3
  V_best[["alt4B"]] = asc_alt4_B + beta_T1*T1_4 + beta_T2*T2_4 + beta_T3*T3_4 + beta_T4*T4_4 +
    beta_T5*T5_4 + beta_T6*T6_4 + beta_T7*T7_4 +
    beta_T8*T8_4 + beta_T9*T9_4 + beta_T10*T10_4 +
    beta_T11*T11_4 + beta_T12*T12_4 + beta_T13*T13_4 +
    beta_T14*T14_4 + beta_T15*T15_4 + beta_T16*T16_4

  ### Compute probabilities for "best" choice using MNL model
  mnl_settings_best = list(
    alternatives  = c(alt1B=1, alt2B=2, alt3B=3, alt4B=4),
    avail         = list(alt1B=avail1B, alt2B=avail2B, alt3B=avail3B, alt4B=avail4B),
    choiceVar     = choice_best,
    utilities     = V_best,
    componentName = "best"
  )
  P_bw[["choice_best"]] = apollo_mnl(mnl_settings_best, functionality)

  ### List of utilities for the "worst" choice
  V_worst = list()
  V_worst[["alt1W"]] = -mu_worst * (asc_alt1_W + beta_T1*T1_1 + beta_T2*T2_1 + beta_T3*T3_1 + beta_T4*T4_1 +
                                      beta_T5*T5_1 + beta_T6*T6_1 + beta_T7*T7_1 +
                                      beta_T8*T8_1 + beta_T9*T9_1 + beta_T10*T10_1 +
                                      beta_T11*T11_1 + beta_T12*T12_1 + beta_T13*T13_1 )+
    beta_T14*T14_1 + beta_T15*T15_1 + beta_T16*T16_1
  V_worst[["alt2W"]] = -mu_worst * (asc_alt2_W + beta_T1*T1_2 + beta_T2*T2_2 + beta_T3*T3_2 + beta_T4*T4_2 +
                                      beta_T5*T5_2 + beta_T6*T6_2 + beta_T7*T7_2 +
                                      beta_T8*T8_2 + beta_T9*T9_2 + beta_T10*T10_2 +
                                      beta_T11*T11_2 + beta_T12*T12_2 + beta_T13*T13_2 +
                                      beta_T14*T14_2 + beta_T15*T15_2 + beta_T16*T16_2)
  V_worst[["alt3W"]] = -mu_worst * (asc_alt3_W + beta_T1*T1_3 + beta_T2*T2_3 + beta_T3*T3_3 + beta_T4*T4_3 +
                                      beta_T5*T5_3 + beta_T6*T6_3 + beta_T7*T7_3 +
                                      beta_T8*T8_3 + beta_T9*T9_3 + beta_T10*T10_3 +
                                      beta_T11*T11_3 + beta_T12*T12_3 + beta_T13*T13_3 +
                                      beta_T14*T14_3 + beta_T15*T15_3 + beta_T16*T16_3)
  V_worst[["alt4W"]] = -mu_worst * (asc_alt4_W + beta_T1*T1_4 + beta_T2*T2_4 + beta_T3*T3_4 + beta_T4*T4_4 +
                                      beta_T5*T5_4 + beta_T6*T6_4 + beta_T7*T7_4 +
                                      beta_T8*T8_4 + beta_T9*T9_4 + beta_T10*T10_4 +
                                      beta_T11*T11_4 + beta_T12*T12_4 + beta_T13*T13_4 +
                                      beta_T14*T14_4 + beta_T15*T15_4 + beta_T16*T16_4)

  ### Compute probabilities for "worst" choice using MNL model
  mnl_settings_worst = list(
    alternatives  = c(alt1W=1, alt2W=2, alt3W=3, alt4W=4),
    avail         = list(alt1W=avail1W, alt2W=avail2W, alt3W=avail3W, alt4W=avail4W),
    choiceVar     = choice_worst,
    utilities     = V_worst,
    componentName = "worst"
  )

  P_bw[["choice_worst"]] = apollo_mnl(mnl_settings_worst, functionality)

  ### Combined model
  P_bw = apollo_combineModels(P_bw, apollo_inputs, functionality)

  ### Take product across observation for same individual
  P = apollo_panelProd(P_bw, apollo_inputs, functionality)

  ### Prepare and return outputs of function
  P = apollo_prepareProb(P, apollo_inputs, functionality)
  return(P)
}

# ################################################################# #
#### MODEL ESTIMATION                                            ####
# ################################################################# #

### Optional starting values search

model = apollo_estimate(apollo_beta, apollo_fixed, apollo_probabilities, apollo_inputs)

# ################################################################# #
#### MODEL OUTPUTS                                               ####
# ################################################################# #

# ----------------------------------------------------------------- #
#---- FORMATTED OUTPUT (TO SCREEN)                               ----
# ----------------------------------------------------------------- #

apollo_modelOutput(model, modelOutput_settings = list(printPVal=1))

# ----------------------------------------------------------------- #
#---- FORMATTED OUTPUT (TO FILE, using model name)               ----
# ----------------------------------------------------------------- #

apollo_saveOutput(model)


Re: MNL for Case 1 BWS: saddle point convergence

Posted: 01 May 2024, 11:39
by stephanehess
Jay

can you show us the output, please?

Thanks

Stephane