Page 1 of 1

Latent Class model estimation ( Failed to converge properly)

Posted: 30 Apr 2025, 19:47
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 ?

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

Posted: 19 May 2025, 18:32
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

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

Posted: 28 May 2025, 15:01
by jackhan1208
Thank you Professor Hess for helping me diagnose the issue !
I will go ahead to modify this !
Jia