Important: Read this before posting to this forum

  1. This forum is for questions related to the use of Apollo. We will answer some general choice modelling questions too, where appropriate, and time permitting. We cannot answer questions about how to estimate choice models with other software packages.
  2. There is a very detailed manual for Apollo available at http://www.ApolloChoiceModelling.com/manual.html. This contains detailed descriptions of the various Apollo functions, and numerous examples are available at http://www.ApolloChoiceModelling.com/examples.html. In addition, help files are available for all functions, using e.g. ?apollo_mnl
  3. Before asking a question on the forum, users are kindly requested to follow these steps:
    1. Check that the same issue has not already been addressed in the forum - there is a search tool.
    2. Ensure that the correct syntax has been used. For any function, detailed instructions are available directly in Apollo, e.g. by using ?apollo_mnl for apollo_mnl
    3. Check the frequently asked questions section on the Apollo website, which discusses some common issues/failures. Please see http://www.apollochoicemodelling.com/faq.html
    4. Make sure that R is using the latest official release of Apollo.
  4. If the above steps do not resolve the issue, then users should follow these steps when posting a question:
    1. provide full details on the issue, including the entire code and output, including any error messages
    2. posts will not immediately appear on the forum, but will be checked by a moderator first. We check the forum at least twice a week. It may thus take a couple of days for your post to appear and before we reply. There is no need to submit the post multiple times.

Latent Class model estimation ( Failed to converge properly)

Ask questions about how to estimate models and how to change your settings for estimation.
Post Reply
jackhan1208
Posts: 4
Joined: 28 Apr 2025, 21:12

Latent Class model estimation ( Failed to converge properly)

Post by jackhan1208 »

Dear Professor Hess and Apollo team, :)
I'm currently conducting a LC MMNL model for a unlabelled design dataset.
Here is the code for three classes estimation, there are five attributes associated with alternatives, where I defined price with negative values, and the rest positive, because those attributes are expected to be more preferrable than without.

Code: Select all

# ---------------------------------------------------- #
#### CLEAN WORKSPACE AND LOAD LIBRARY ####
# ---------------------------------------------------- #
rm(list = ls())
gc()
library(apollo)
apollo_initialise()

# ---------------------------------------------------- #
#### CORE SETTINGS ####
# ---------------------------------------------------- #
apollo_control = list(
  modelName       = "LCMIXL_DriedApple_3Class",
  modelDescr      = "3-class LC Mixed Logit model for dried apple",
  indivID         = "respID",
  nCores          = 16,
  outputDirectory = "output",
  mixing          = TRUE
)

# ---------------------------------------------------- #
#### LOAD DATA ####
# ---------------------------------------------------- #
database <- read.csv("dataset_apple_wide.csv")

# ---------------------------------------------------- #
#### DEFINE MODEL PARAMETERS ####
# ---------------------------------------------------- #
apollo_beta = c(
  # Means
  asc_opt_1       = 0,
  mu_b_price_1    = -1,
  mu_b_process_1  = 0.2,
  mu_b_carbon_1   = 0.2,
  mu_b_fibre_1    = 0.2,
  mu_b_crispy_1   = 0.2,
  
  asc_opt_2       = 0,
  mu_b_price_2    = -1.1,
  mu_b_process_2  = 0.4,
  mu_b_carbon_2   = 0.1,
  mu_b_fibre_2    = 0.1,
  mu_b_crispy_2   = 0.3,
  
  asc_opt_3       = 0,
  mu_b_price_3    = -0.9,
  mu_b_process_3  = 0.1,
  mu_b_carbon_3   = 0.3,
  mu_b_fibre_3    = 0.2,
  mu_b_crispy_3   = 0.2,
  
  # Standard deviations
  sigma_price_1   = 0.3,
  sigma_process_1 = 0.3,
  sigma_carbon_1  = 0.3,
  sigma_fibre_1   = 0.3,
  sigma_crispy_1  = 0.3,
  
  sigma_price_2   = 0.2,
  sigma_process_2 = 0.2,
  sigma_carbon_2  = 0.2,
  sigma_fibre_2   = 0.2,
  sigma_crispy_2  = 0.2,
  
  sigma_price_3   = 0.1,
  sigma_process_3 = 0.1,
  sigma_carbon_3  = 0.1,
  sigma_fibre_3   = 0.1,
  sigma_crispy_3  = 0.1,
  
  # Class allocation
  theta1 = 0,
  theta2 = 0
)

apollo_fixed = c("asc_opt_1", "asc_opt_2", "asc_opt_3")

# ---------------------------------------------------- #
#### DRAW SETTINGS ####
# ---------------------------------------------------- #
apollo_draws = list(
  interDrawsType = "halton",
  interNDraws    = 500,
  interNormDraws = c("draws_price", "draws_process", "draws_carbon", "draws_fibre", "draws_crispy")
)

# ---------------------------------------------------- #
#### DEFINE RANDOM COEFFICIENTS ####
# ---------------------------------------------------- #
apollo_randCoeff = function(apollo_beta, apollo_inputs){
  randcoeff = list()
  
  for (i in 1:3) {
    randcoeff[[paste0("b_price_", i)]]   = get(paste0("mu_b_price_", i)) + get(paste0("sigma_price_", i)) * draws_price
    randcoeff[[paste0("b_process_", i)]] = get(paste0("mu_b_process_", i)) + get(paste0("sigma_process_", i)) * draws_process
    randcoeff[[paste0("b_carbon_", i)]]  = get(paste0("mu_b_carbon_", i)) + get(paste0("sigma_carbon_", i)) * draws_carbon
    randcoeff[[paste0("b_fibre_", i)]]   = get(paste0("mu_b_fibre_", i)) + get(paste0("sigma_fibre_", i)) * draws_fibre
    randcoeff[[paste0("b_crispy_", i)]]  = get(paste0("mu_b_crispy_", i)) + get(paste0("sigma_crispy_", i)) * draws_crispy
  }
  
  return(randcoeff)
}

# ---------------------------------------------------- #
#### CLASS ALLOCATION ####
# ---------------------------------------------------- #
apollo_lcPars = function(apollo_beta, apollo_inputs){
  lcpars = list()
  
  for (i in 1:3) {
    lcpars[["b_price"]][[i]]   = get(paste0("b_price_", i))
    lcpars[["b_process"]][[i]] = get(paste0("b_process_", i))
    lcpars[["b_carbon"]][[i]]  = get(paste0("b_carbon_", i))
    lcpars[["b_fibre"]][[i]]   = get(paste0("b_fibre_", i))
    lcpars[["b_crispy"]][[i]]  = get(paste0("b_crispy_", i))
    lcpars[["asc_opt"]][[i]]   = get(paste0("asc_opt_", i))
  }
  
  V = list(class1 = 0, class2 = theta1, class3 = theta2)
  lcpars[["pi_values"]] = apollo_classAlloc(list(classes = c(class1=1, class2=2, class3=3), utilities = V))
  
  return(lcpars)
}

# ---------------------------------------------------- #
#### VALIDATE INPUTS ####
# ---------------------------------------------------- #
apollo_inputs = apollo_validateInputs()

# ---------------------------------------------------- #
#### DEFINE PROBABILITIES ####
# ---------------------------------------------------- #
apollo_probabilities = function(apollo_beta, apollo_inputs, functionality = "estimate") {
  apollo_attach(apollo_beta, apollo_inputs)
  on.exit(apollo_detach(apollo_beta, apollo_inputs))
  
  P = list()
  for (s in 1:3) {
    V = list()
    V[["alt1"]] = b_price[[s]] * price_1 + b_process[[s]] * process_1 + b_carbon[[s]] * carbon_1 + b_fibre[[s]] * fibre_1 + b_crispy[[s]] * crispy_1
    V[["alt2"]] = b_price[[s]] * price_2 + b_process[[s]] * process_2 + b_carbon[[s]] * carbon_2 + b_fibre[[s]] * fibre_2 + b_crispy[[s]] * crispy_2
    V[["alt3"]] = asc_opt[[s]] + b_price[[s]] * price_3 + b_process[[s]] * process_3 + b_carbon[[s]] * carbon_3 + b_fibre[[s]] * fibre_3 + b_crispy[[s]] * crispy_3
    
    mnl_settings = list(
      alternatives = c(alt1=1, alt2=2, alt3=3),
      choiceVar = choice_new,
      V = V
    )
    
    P[[paste0("class", s)]] = apollo_mnl(mnl_settings, functionality)
    P[[paste0("class", s)]] = apollo_panelProd(P[[paste0("class", s)]], apollo_inputs, functionality)
    P[[paste0("class", s)]] = apollo_avgInterDraws(P[[paste0("class", s)]], apollo_inputs, functionality)
  }
  
  lc_settings = list(inClassProb = P, classProb = pi_values)
  P[["model"]] = apollo_lc(lc_settings, apollo_inputs, functionality)
  P = apollo_prepareProb(P, apollo_inputs, functionality)
  return(P)
}

# ---------------------------------------------------- #
#### ESTIMATE MODEL ####
# ---------------------------------------------------- #
model = apollo_estimate(apollo_beta, apollo_fixed, apollo_probabilities, apollo_inputs)
apollo_modelOutput(model)
apollo_saveOutput(model)


# Create an empty list to store WTPs
mWTP = list()

# Attributes for each class
attributes1 = c("mu_b_process_1", "mu_b_carbon_1", "mu_b_fibre_1", "mu_b_crispy_1")
attributes2 = c("mu_b_process_2", "mu_b_carbon_2", "mu_b_fibre_2", "mu_b_crispy_2")
attributes3 = c("mu_b_process_3", "mu_b_carbon_3", "mu_b_fibre_3", "mu_b_crispy_3")

# Loop for Class 1
for (attr in attributes1) {
  deltaMethod_settings = list(
    operation = "ratio",
    parName1  = attr,
    parName2  = "mu_b_price_1",
    multPar1  = -1
  )
  mWTP[[attr]] <- apollo_deltaMethod(model, deltaMethod_settings)
}

# Loop for Class 2
for (attr in attributes2) {
  deltaMethod_settings = list(
    operation = "ratio",
    parName1  = attr,
    parName2  = "mu_b_price_2",
    multPar1  = -1
  )
  mWTP[[attr]] <- apollo_deltaMethod(model, deltaMethod_settings)
}

# Loop for Class 3
for (attr in attributes3) {
  deltaMethod_settings = list(
    operation = "ratio",
    parName1  = attr,
    parName2  = "mu_b_price_3",
    multPar1  = -1
  )
  mWTP[[attr]] <- apollo_deltaMethod(model, deltaMethod_settings)
}

# Output results
cat("\nEstimated Willingness-to-Pay (WTP) values for all classes:\n")
print(mWTP)
This provided me with a converged results based on 500 halton draws, overall results seems reasonable

Code: Select all

Model name                                  : LCMIXL_DriedApple_3Class
Model description                           : 3-class LC Mixed Logit model for dried apple
Model run at                                : 2025-04-30 18:57:27.926488
Estimation method                           : bgw
Model diagnosis                             : Relative function convergence
Optimisation diagnosis                      : Maximum found
     hessian properties                     : Negative definite
     maximum eigenvalue                     : -0.270401
     reciprocal of condition number         : 0.000221373
Number of individuals                       : 337
Number of rows in database                  : 3370
Number of modelled outcomes                 : 3370

Number of cores used                        :  4 
Number of inter-individual draws            : 500 (halton)

LL(start)                                   : -3952.55
LL (whole model) at equal shares, LL(0)     : -3702.32
LL (whole model) at observed shares, LL(C)  : -3578.9
LL(final, whole model)                      : -2584.83
Rho-squared vs equal shares                  :  0.3018 
Adj.Rho-squared vs equal shares              :  0.2932 
Rho-squared vs observed shares               :  0.2778 
Adj.Rho-squared vs observed shares           :  0.2705 
AIC                                         :  5233.66 
BIC                                         :  5429.58 

LL(0,class1)                     : -3702.32
LL(final,class1)                 : -3697.5
LL(0,class2)                     : -3702.32
LL(final,class2)                 : -3579.05
LL(0,class3)                     : -3702.32
LL(final,class3)                 : -3057.11

Estimated parameters                        : 32
Time taken (hh:mm:ss)                       :  00:09:9.83 
     pre-estimation                         :  00:00:26.14 
     estimation                             :  00:01:33.19 
     post-estimation                        :  00:07:10.5 
Iterations                                  :  34  

Unconstrained optimisation.

Estimates:
                   Estimate        s.e.   t.rat.(0)    Rob.s.e.
asc_opt_1          0.000000          NA          NA          NA
mu_b_price_1      -1.152593     0.09724  -11.852845    0.154686
mu_b_process_1     1.014236     0.11802    8.593455    0.103312
mu_b_carbon_1      1.504771     0.13841   10.871456    0.150597
mu_b_fibre_1       1.368967     0.13027   10.508684    0.129252
mu_b_crispy_1      1.989127     0.23652    8.409805    0.391446
asc_opt_2          0.000000          NA          NA          NA
mu_b_price_2      -0.739687     0.24919   -2.968360    0.539437
mu_b_process_2    -4.428926     1.42061   -3.117631    3.120268
mu_b_carbon_2      0.206159     0.51374    0.401292    0.479176
mu_b_fibre_2       0.646197     0.34237    1.887444    0.360466
mu_b_crispy_2      0.560655     0.32649    1.717219    0.329188
asc_opt_3          0.000000          NA          NA          NA
mu_b_price_3      -0.113794     0.04716   -2.412901    0.052260
mu_b_process_3     0.796775     0.34539    2.306877    0.863318
mu_b_carbon_3      0.215023     0.13752    1.563532    0.170829
mu_b_fibre_3       0.862340     0.12090    7.132776    0.137223
mu_b_crispy_3      0.081946     0.16591    0.493914    0.243494
sigma_price_1      0.216065     0.05026    4.299239    0.050293
sigma_process_1   -0.006563     0.20727   -0.031667    0.012554
sigma_carbon_1    -0.020148     0.22079   -0.091252    0.022279
sigma_fibre_1   -8.0485e-04     0.14449   -0.005570    0.005112
sigma_crispy_1     0.966497     0.20697    4.669792    0.317935
sigma_price_2      0.783916     0.24381    3.215227    0.567616
sigma_process_2   -2.232379     0.83008   -2.689355    1.758403
sigma_carbon_2    -3.473860     1.03235   -3.365017    2.332288
sigma_fibre_2     -1.035261     0.53145   -1.947993    0.841735
sigma_crispy_2    -0.749543     0.46979   -1.595486    0.506811
sigma_price_3     -0.183003     0.05999   -3.050390    0.114276
sigma_process_3    1.197187     0.40343    2.967534    1.013020
sigma_carbon_3    -0.367009     0.26000   -1.411564    0.454346
sigma_fibre_3     -0.530327     0.15573   -3.405380    0.215532
sigma_crispy_3     0.960287     0.18554    5.175685    0.270616
theta1            -0.810224     0.27787   -2.915821    0.631373
theta2            -0.392524     0.21241   -1.847924    0.297783
                Rob.t.rat.(0)
asc_opt_1                  NA
mu_b_price_1          -7.4512
mu_b_process_1         9.8172
mu_b_carbon_1          9.9920
mu_b_fibre_1          10.5915
mu_b_crispy_1          5.0815
asc_opt_2                  NA
mu_b_price_2          -1.3712
mu_b_process_2        -1.4194
mu_b_carbon_2          0.4302
mu_b_fibre_2           1.7927
mu_b_crispy_2          1.7031
asc_opt_3                  NA
mu_b_price_3          -2.1774
mu_b_process_3         0.9229
mu_b_carbon_3          1.2587
mu_b_fibre_3           6.2842
mu_b_crispy_3          0.3365
sigma_price_1          4.2961
sigma_process_1       -0.5228
sigma_carbon_1        -0.9043
sigma_fibre_1         -0.1574
sigma_crispy_1         3.0399
sigma_price_2          1.3811
sigma_process_2       -1.2695
sigma_carbon_2        -1.4895
sigma_fibre_2         -1.2299
sigma_crispy_2        -1.4789
sigma_price_3         -1.6014
sigma_process_3        1.1818
sigma_carbon_3        -0.8078
sigma_fibre_3         -2.4605
sigma_crispy_3         3.5485
theta1                -1.2833
theta2                -1.3182


Summary of class allocation for model component :
        Mean prob.
class1      0.4717
class2      0.2098
class3      0.3185
despite some discrepancies in parameter value

Code: Select all

Changes in parameter estimates from starting values:
                    Initial    Estimate  Difference
asc_opt_1            0.0000    0.000000     0.00000
mu_b_price_1        -1.0000   -1.152593    -0.15259
mu_b_process_1       0.2000    1.014236     0.81424
mu_b_carbon_1        0.2000    1.504771     1.30477
mu_b_fibre_1         0.2000    1.368967     1.16897
mu_b_crispy_1        0.2000    1.989127     1.78913
asc_opt_2            0.0000    0.000000     0.00000
mu_b_price_2        -1.1000   -0.739687     0.36031
mu_b_process_2       0.4000   -4.428926    -4.82893
mu_b_carbon_2        0.1000    0.206159     0.10616
mu_b_fibre_2         0.1000    0.646197     0.54620
mu_b_crispy_2        0.3000    0.560655     0.26065
asc_opt_3            0.0000    0.000000     0.00000
mu_b_price_3        -0.9000   -0.113794     0.78621
mu_b_process_3       0.1000    0.796775     0.69677
mu_b_carbon_3        0.3000    0.215023    -0.08498
mu_b_fibre_3         0.2000    0.862340     0.66234
mu_b_crispy_3        0.2000    0.081946    -0.11805
sigma_price_1        0.3000    0.216065    -0.08393
sigma_process_1      0.3000   -0.006563    -0.30656
sigma_carbon_1       0.3000   -0.020148    -0.32015
sigma_fibre_1        0.3000 -8.0485e-04    -0.30080
sigma_crispy_1       0.3000    0.966497     0.66650
sigma_price_2        0.2000    0.783916     0.58392
sigma_process_2      0.2000   -2.232379    -2.43238
sigma_carbon_2       0.2000   -3.473860    -3.67386
sigma_fibre_2        0.2000   -1.035261    -1.23526
sigma_crispy_2       0.2000   -0.749543    -0.94954
sigma_price_3        0.1000   -0.183003    -0.28300
sigma_process_3      0.1000    1.197187     1.09719
sigma_carbon_3       0.1000   -0.367009    -0.46701
sigma_fibre_3        0.1000   -0.530327    -0.63033
sigma_crispy_3       0.1000    0.960287     0.86029
theta1               0.0000   -0.810224    -0.81022
theta2               0.0000   -0.392524    -0.39252
Then I tries to use this as baseline to estimate four classes models

Code: Select all

# ---------------------------------------------------- #
#### CLEAN WORKSPACE AND LOAD LIBRARY ####
# ---------------------------------------------------- #
rm(list = ls())
gc()
library(apollo)
apollo_initialise()

# ---------------------------------------------------- #
#### CORE SETTINGS ####
# ---------------------------------------------------- #
apollo_control = list(
  modelName       = "LCMIXL_DriedApple_3Class",
  modelDescr      = "4-class LC Mixed Logit model for dried apple",
  indivID         = "respID",
  nCores          = 16,
  outputDirectory = "output",
  mixing          = TRUE
)

# ---------------------------------------------------- #
#### LOAD DATA ####
# ---------------------------------------------------- #
database <- read.csv("dataset_apple_wide.csv")

# ---------------------------------------------------- #
#### DEFINE MODEL PARAMETERS ####
# ---------------------------------------------------- #
apollo_beta = c(
  # Means
  asc_opt_1       = 0,
  mu_b_price_1    = -1,
  mu_b_process_1  = 0.2,
  mu_b_carbon_1   = 0.2,
  mu_b_fibre_1    = 0.2,
  mu_b_crispy_1   = 0.2,
  
  asc_opt_2       = 0,
  mu_b_price_2    = -1.1,
  mu_b_process_2  = 0.4,
  mu_b_carbon_2   = 0.1,
  mu_b_fibre_2    = 0.1,
  mu_b_crispy_2   = 0.3,
  
  asc_opt_3       = 0,
  mu_b_price_3    = -0.9,
  mu_b_process_3  = 0.1,
  mu_b_carbon_3   = 0.3,
  mu_b_fibre_3    = 0.2,
  mu_b_crispy_3   = 0.2,
  
  asc_opt_4       = 0,
  mu_b_price_4    = -1.2,
  mu_b_process_4  = 0.3,
  mu_b_carbon_4   = 0.3,
  mu_b_fibre_4    = 0.3,
  mu_b_crispy_4   = 0.3,
  
  # Standard deviations
  sigma_price_1   = 0.3,
  sigma_process_1 = 0.3,
  sigma_carbon_1  = 0.3,
  sigma_fibre_1   = 0.3,
  sigma_crispy_1  = 0.3,
  
  sigma_price_2   = 0.2,
  sigma_process_2 = 0.2,
  sigma_carbon_2  = 0.2,
  sigma_fibre_2   = 0.2,
  sigma_crispy_2  = 0.2,
  
  sigma_price_3   = 0.1,
  sigma_process_3 = 0.1,
  sigma_carbon_3  = 0.1,
  sigma_fibre_3   = 0.1,
  sigma_crispy_3  = 0.1,
  
  sigma_price_4   = 0.2,
  sigma_process_4 = 0.2,
  sigma_carbon_4  = 0.2,
  sigma_fibre_4   = 0.2,
  sigma_crispy_4  = 0.2,
  # Class allocation
  theta1 = 0,
  theta2 = 0,
  theta3 = 0
)

apollo_fixed = c("asc_opt_1", "asc_opt_2", "asc_opt_3","asc_opt_4")

# ---------------------------------------------------- #
#### DRAW SETTINGS ####
# ---------------------------------------------------- #
apollo_draws = list(
  interDrawsType = "halton",
  interNDraws    = 500,
  interNormDraws = c("draws_price", "draws_process", "draws_carbon", "draws_fibre", "draws_crispy")
)

# ---------------------------------------------------- #
#### DEFINE RANDOM COEFFICIENTS ####
# ---------------------------------------------------- #
apollo_randCoeff = function(apollo_beta, apollo_inputs){
  randcoeff = list()
  
  for (i in 1:4) {
    randcoeff[[paste0("b_price_", i)]]   = get(paste0("mu_b_price_", i)) + get(paste0("sigma_price_", i)) * draws_price
    randcoeff[[paste0("b_process_", i)]] = get(paste0("mu_b_process_", i)) + get(paste0("sigma_process_", i)) * draws_process
    randcoeff[[paste0("b_carbon_", i)]]  = get(paste0("mu_b_carbon_", i)) + get(paste0("sigma_carbon_", i)) * draws_carbon
    randcoeff[[paste0("b_fibre_", i)]]   = get(paste0("mu_b_fibre_", i)) + get(paste0("sigma_fibre_", i)) * draws_fibre
    randcoeff[[paste0("b_crispy_", i)]]  = get(paste0("mu_b_crispy_", i)) + get(paste0("sigma_crispy_", i)) * draws_crispy
  }
  
  return(randcoeff)
}

# ---------------------------------------------------- #
#### CLASS ALLOCATION ####
# ---------------------------------------------------- #
apollo_lcPars = function(apollo_beta, apollo_inputs){
  lcpars = list()
  
  for (i in 1:4) {
    lcpars[["b_price"]][[i]]   = get(paste0("b_price_", i))
    lcpars[["b_process"]][[i]] = get(paste0("b_process_", i))
    lcpars[["b_carbon"]][[i]]  = get(paste0("b_carbon_", i))
    lcpars[["b_fibre"]][[i]]   = get(paste0("b_fibre_", i))
    lcpars[["b_crispy"]][[i]]  = get(paste0("b_crispy_", i))
    lcpars[["asc_opt"]][[i]]   = get(paste0("asc_opt_", i))
  }
  
  V = list(class1 = 0, class2 = theta1, class3 = theta2, class4 = theta3)
  lcpars[["pi_values"]] = apollo_classAlloc(list(classes = c(class1=1, class2=2, class3=3, class4=4), utilities = V))
  
  return(lcpars)
}

# ---------------------------------------------------- #
#### VALIDATE INPUTS ####
# ---------------------------------------------------- #
apollo_inputs = apollo_validateInputs()

# ---------------------------------------------------- #
#### DEFINE PROBABILITIES ####
# ---------------------------------------------------- #
apollo_probabilities = function(apollo_beta, apollo_inputs, functionality = "estimate") {
  apollo_attach(apollo_beta, apollo_inputs)
  on.exit(apollo_detach(apollo_beta, apollo_inputs))
  
  P = list()
  for (s in 1:4) {
    V = list()
    V[["alt1"]] = b_price[[s]] * price_1 + b_process[[s]] * process_1 + b_carbon[[s]] * carbon_1 + b_fibre[[s]] * fibre_1 + b_crispy[[s]] * crispy_1
    V[["alt2"]] = b_price[[s]] * price_2 + b_process[[s]] * process_2 + b_carbon[[s]] * carbon_2 + b_fibre[[s]] * fibre_2 + b_crispy[[s]] * crispy_2
    V[["alt3"]] = asc_opt[[s]] + b_price[[s]] * price_3 + b_process[[s]] * process_3 + b_carbon[[s]] * carbon_3 + b_fibre[[s]] * fibre_3 + b_crispy[[s]] * crispy_3
    
    mnl_settings = list(
      alternatives = c(alt1=1, alt2=2, alt3=3),
      choiceVar = choice_new,
      V = V
    )
    
    P[[paste0("class", s)]] = apollo_mnl(mnl_settings, functionality)
    P[[paste0("class", s)]] = apollo_panelProd(P[[paste0("class", s)]], apollo_inputs, functionality)
    P[[paste0("class", s)]] = apollo_avgInterDraws(P[[paste0("class", s)]], apollo_inputs, functionality)
  }
  
  lc_settings = list(inClassProb = P, classProb = pi_values)
  P[["model"]] = apollo_lc(lc_settings, apollo_inputs, functionality)
  P = apollo_prepareProb(P, apollo_inputs, functionality)
  
  return(P)
}

# ---------------------------------------------------- #
#### ESTIMATE MODEL ####
# ---------------------------------------------------- #
model = apollo_estimate(apollo_beta, apollo_fixed, apollo_probabilities, apollo_inputs)
apollo_modelOutput(model)
apollo_saveOutput(model)
, the apollo warned that the data did not converged properly , the results is as follow

Code: Select all

Model name                                  : LCMIXL_DriedApple_3Class
Model description                           : 4-class LC Mixed Logit model for dried apple
Model run at                                : 2025-04-30 19:18:07.58613
Estimation method                           : bgw
Model diagnosis                             : Function evaluation limit
Number of individuals                       : 337
Number of rows in database                  : 3370
Number of modelled outcomes                 : 3370

Number of cores used                        :  16 
Number of inter-individual draws            : 500 (halton)

LL(start)                                   : -4006.56
LL (whole model) at equal shares, LL(0)     : -3702.32
LL (whole model) at observed shares, LL(C)  : -3578.9
LL(final, whole model)                      : -2583.95
Rho-squared vs equal shares                  :  0.3021 
Adj.Rho-squared vs equal shares              :  0.2905 
Rho-squared vs observed shares               :  0.278 
Adj.Rho-squared vs observed shares           :  0.2682 
AIC                                         :  5253.9 
BIC                                         :  5517.17 

LL(0,class1)                     : -3702.32
LL(final,class1)                 : -2921.61
LL(0,class2)                     : -3702.32
LL(final,class2)                 : -66614.52
LL(0,class3)                     : -3702.32
LL(final,class3)                 : -Inf Likelihood equal to zero for at least
                                        one individual in this component.
LL(0,class4)                     : -3702.32
LL(final,class4)                 : -3634.59

Estimated parameters                        : 43
Time taken (hh:mm:ss)                       :  00:06:15.46 
     pre-estimation                         :  00:00:51.66 
     estimation                             :  00:05:20.05 
     post-estimation                        :  00:00:3.74 
Iterations                                  :  88 (Function evaluation limit) 

Unconstrained optimisation.

Estimates:
                    Estimate        s.e.   t.rat.(0)    Rob.s.e.
asc_opt_1           0.000000          NA          NA          NA
mu_b_price_1       -0.171451          NA          NA          NA
mu_b_process_1     -0.255591          NA          NA          NA
mu_b_carbon_1       0.321396          NA          NA          NA
mu_b_fibre_1        0.875223          NA          NA          NA
mu_b_crispy_1       0.208823          NA          NA          NA
asc_opt_2           0.000000          NA          NA          NA
mu_b_price_2      -22.751562          NA          NA          NA
mu_b_process_2    -36.295984          NA          NA          NA
mu_b_carbon_2    -811.346441          NA          NA          NA
mu_b_fibre_2      -18.064016          NA          NA          NA
mu_b_crispy_2     -17.006011          NA          NA          NA
asc_opt_3           0.000000          NA          NA          NA
mu_b_price_3       1.156e+04          NA          NA          NA
mu_b_process_3     3.179e+04          NA          NA          NA
mu_b_carbon_3    1773.110131          NA          NA          NA
mu_b_fibre_3    -2564.768215          NA          NA          NA
mu_b_crispy_3      3.722e+04          NA          NA          NA
asc_opt_4           0.000000          NA          NA          NA
mu_b_price_4       -1.110255          NA          NA          NA
mu_b_process_4      1.040486          NA          NA          NA
mu_b_carbon_4       1.471342          NA          NA          NA
mu_b_fibre_4        1.337368          NA          NA          NA
mu_b_crispy_4       1.904001          NA          NA          NA
sigma_price_1       0.303276          NA          NA          NA
sigma_process_1     2.124713          NA          NA          NA
sigma_carbon_1     -0.734768          NA          NA          NA
sigma_fibre_1       0.612134          NA          NA          NA
sigma_crispy_1      0.993179          NA          NA          NA
sigma_price_2      10.959878          NA          NA          NA
sigma_process_2    25.858891          NA          NA          NA
sigma_carbon_2  -1278.895842          NA          NA          NA
sigma_fibre_2      19.404407          NA          NA          NA
sigma_crispy_2      8.465367          NA          NA          NA
sigma_price_3     658.012072          NA          NA          NA
sigma_process_3  4028.540016          NA          NA          NA
sigma_carbon_3   -558.139016          NA          NA          NA
sigma_fibre_3     917.603379          NA          NA          NA
sigma_crispy_3     1.085e+04          NA          NA          NA
sigma_price_4       0.224516          NA          NA          NA
sigma_process_4     0.002376          NA          NA          NA
sigma_carbon_4     -0.011173          NA          NA          NA
sigma_fibre_4      -0.002029          NA          NA          NA
sigma_crispy_4     -0.881905          NA          NA          NA
theta1             -1.945271          NA          NA          NA
theta2           -667.495140          NA          NA          NA
theta3              0.034525          NA          NA          NA
                Rob.t.rat.(0)
asc_opt_1                  NA
mu_b_price_1               NA
mu_b_process_1             NA
mu_b_carbon_1              NA
mu_b_fibre_1               NA
mu_b_crispy_1              NA
asc_opt_2                  NA
mu_b_price_2               NA
mu_b_process_2             NA
mu_b_carbon_2              NA
mu_b_fibre_2               NA
mu_b_crispy_2              NA
asc_opt_3                  NA
mu_b_price_3               NA
mu_b_process_3             NA
mu_b_carbon_3              NA
mu_b_fibre_3               NA
mu_b_crispy_3              NA
asc_opt_4                  NA
mu_b_price_4               NA
mu_b_process_4             NA
mu_b_carbon_4              NA
mu_b_fibre_4               NA
mu_b_crispy_4              NA
sigma_price_1              NA
sigma_process_1            NA
sigma_carbon_1             NA
sigma_fibre_1              NA
sigma_crispy_1             NA
sigma_price_2              NA
sigma_process_2            NA
sigma_carbon_2             NA
sigma_fibre_2              NA
sigma_crispy_2             NA
sigma_price_3              NA
sigma_process_3            NA
sigma_carbon_3             NA
sigma_fibre_3              NA
sigma_crispy_3             NA
sigma_price_4              NA
sigma_process_4            NA
sigma_carbon_4             NA
sigma_fibre_4              NA
sigma_crispy_4             NA
theta1                     NA
theta2                     NA
theta3                     NA

Your model did not converge properly, and some of your parameter
  values are tending to +/- infinity. This could point to an
  identification issue. If you want to retain these parameters in
  the model, you may wish to set their value(s) in apollo_beta to
  the estimated value(s), include the parameter name(s) in
  apollo_fixed, and re-estimate the model.


Summary of class allocation for model component :
        Mean prob.
class1     0.45912
class2     0.06563
class3  5.922e-291
class4     0.47525
the results seems to suggests that there does not exists a fourth group, but I cannot fully sure about this, and parameter value report suggests a huge differences

Code: Select all

Changes in parameter estimates from starting values:
                    Initial     Estimate   Difference
asc_opt_1            0.0000     0.000000     0.000000
mu_b_price_1        -1.0000    -0.171451     0.828549
mu_b_process_1       0.2000    -0.255591    -0.455591
mu_b_carbon_1        0.2000     0.321396     0.121396
mu_b_fibre_1         0.2000     0.875223     0.675223
mu_b_crispy_1        0.2000     0.208823     0.008823
asc_opt_2            0.0000     0.000000     0.000000
mu_b_price_2        -1.1000   -22.751562   -21.651562
mu_b_process_2       0.4000   -36.295984   -36.695984
mu_b_carbon_2        0.1000  -811.346441  -811.446441
mu_b_fibre_2         0.1000   -18.064016   -18.164016
mu_b_crispy_2        0.3000   -17.006011   -17.306011
asc_opt_3            0.0000     0.000000     0.000000
mu_b_price_3        -0.9000    1.156e+04    1.156e+04
mu_b_process_3       0.1000    3.179e+04    3.179e+04
mu_b_carbon_3        0.3000  1773.110131  1772.810131
mu_b_fibre_3         0.2000 -2564.768215 -2564.968215
mu_b_crispy_3        0.2000    3.722e+04    3.722e+04
asc_opt_4            0.0000     0.000000     0.000000
mu_b_price_4        -1.2000    -1.110255     0.089745
mu_b_process_4       0.3000     1.040486     0.740486
mu_b_carbon_4        0.3000     1.471342     1.171342
mu_b_fibre_4         0.3000     1.337368     1.037368
mu_b_crispy_4        0.3000     1.904001     1.604001
sigma_price_1        0.3000     0.303276     0.003276
sigma_process_1      0.3000     2.124713     1.824713
sigma_carbon_1       0.3000    -0.734768    -1.034768
sigma_fibre_1        0.3000     0.612134     0.312134
sigma_crispy_1       0.3000     0.993179     0.693179
sigma_price_2        0.2000    10.959878    10.759878
sigma_process_2      0.2000    25.858891    25.658891
sigma_carbon_2       0.2000 -1278.895842 -1279.095842
sigma_fibre_2        0.2000    19.404407    19.204407
sigma_crispy_2       0.2000     8.465367     8.265367
sigma_price_3        0.1000   658.012072   657.912072
sigma_process_3      0.1000  4028.540016  4028.440016
sigma_carbon_3       0.1000  -558.139016  -558.239016
sigma_fibre_3        0.1000   917.603379   917.503379
sigma_crispy_3       0.1000    1.085e+04    1.084e+04
sigma_price_4        0.2000     0.224516     0.024516
sigma_process_4      0.2000     0.002376    -0.197624
sigma_carbon_4       0.2000    -0.011173    -0.211173
sigma_fibre_4        0.2000    -0.002029    -0.202029
sigma_crispy_4       0.2000    -0.881905    -1.081905
theta1               0.0000    -1.945271    -1.945271
theta2               0.0000  -667.495140  -667.495140
theta3               0.0000     0.034525     0.034525
I also tried LC MNL with four classes , which also failed to converge. I tried, LC MNL with 2,3 classes, and same LC MMNL with 2 classes, with LC MMNL 3 classes has the lowest AIC and BIC.
Based on given results and code, would it suggests that there is no fourth latent group in the data, and LC MMNL 3 class is an appropriate model?
What other method would you suggest me to try out to further diagnose this ?
stephanehess
Site Admin
Posts: 1339
Joined: 24 Apr 2020, 16:29

Re: Latent Class model estimation ( Failed to converge properly)

Post by stephanehess »

Hi

apologies for the slow reply.

The section "Changes in parameter estimates from starting values:" is not showing any issues, that just shows how far the estimates have moved from the starting values.

The problem is that you run out of iterations in the 4 class models. Try increasing maxIterations - please have a look at the manual or help file via

Code: Select all

?apollo_estimate
Stephane
--------------------------------
Stephane Hess
www.stephanehess.me.uk
jackhan1208
Posts: 4
Joined: 28 Apr 2025, 21:12

Re: Latent Class model estimation ( Failed to converge properly)

Post by jackhan1208 »

Thank you Professor Hess for helping me diagnose the issue !
I will go ahead to modify this !
Jia
Post Reply