Page 1 of 1

Latent class model not progressing after "pre-processing likelihood function"

Posted: 14 Sep 2021, 16:51
by Laure K
Hello,
I am trying to run a latent class model with 3 classes, but when estimating the model, R keeps sunning for hours at the stage "Pre-processing likelihood function...". Everything went well when I estimated the model with 2 classes, I then adjusted the code for 3 classes but do not manage to go passed this "Pre-processing likelihood function..." stage. I wonder if I should wait much longer or if there is an issue in my code. I would be very grateful for any advice!

My code is the following:
# ################################################################# #
#### LOAD LIBRARY AND DEFINE CORE SETTINGS ####
# ################################################################# #

### Clear memory
rm(list = ls())

### Load Apollo library
library(apollo)

### Initialise code
apollo_initialise()

apollo_control = list(
modelName ="Latent_Class_3classes_noclusters_forum",
modelDescr ="LC model with class allocation model; 3 classes; only constant to explain class membership, as starting point",
indivID ="ID",
nCores = 4
)

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

database = read.csv("Data_FinalSept_EffectPract.csv",header=TRUE)

#View(database)

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

### Vector of parameters, including any that are kept fixed in estimation
apollo_beta = c(asc_pract_a = 0,
asc_pract_b = 0,
asc_pract_c = 0,
asc_hybrid_a = 0,
asc_hybrid_b = 0,
asc_hybrid_c = 0,
asc_result_a = 0,
asc_result_b = 0,
asc_result_c = 0,
b_practices2_a = 0,
b_practices2_b = 0,
b_practices2_c = 0,
b_practices3_a = 0,
b_practices3_b = 0,
b_practices3_c = 0,
b_water1_a = 0,
b_water1_b = 0,
b_water1_c = 0,
b_water2_a = 0,
b_water2_b = 0,
b_water2_c = 0,
b_cc1_a = 0,
b_cc1_b = 0,
b_cc1_c = 0,
b_cc2_a = 0,
b_cc2_b = 0,
b_cc2_c = 0,
b_biodiv1_a = 0,
b_biodiv1_b = 0,
b_biodiv1_c = 0,
b_biodiv2_a = 0,
b_biodiv2_b = 0,
b_biodiv2_c = 0,
b_share_a = 0,
b_share_b = 0,
b_share_c = 0,
b_payment_a = 0,
b_payment_b = 0,
b_payment_c = 0,
delta_a = 0,
delta_b = 0,
delta_c = 0)

### 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

# parameters of class membership normalised to 0 for reference class (class a), hence added below as "kept fixed" at value = 0.
apollo_fixed = c("delta_a")

# ################################################################# #
#### DEFINE LATENT CLASS COMPONENTS ####
# ################################################################# #

apollo_lcPars=function(apollo_beta, apollo_inputs){
lcpars = list()
lcpars[["asc_pract"]] = list(asc_pract_a, asc_pract_b, asc_pract_c)
lcpars[["asc_hybrid"]] = list(asc_hybrid_a, asc_hybrid_b, asc_hybrid_c)
lcpars[["asc_result"]] = list(asc_result_a, asc_result_b, asc_result_c)
lcpars[["b_practices2"]] = list(b_practices2_a, b_practices2_b, b_practices2_c)
lcpars[["b_practices3"]] = list(b_practices3_a, b_practices3_b, b_practices3_c)
lcpars[["b_water1"]] = list(b_water1_a, b_water1_b, b_water1_c)
lcpars[["b_water2"]] = list(b_water2_a, b_water2_b, b_water2_c)
lcpars[["b_biodiv1"]] = list(b_biodiv1_a, b_biodiv1_b, b_biodiv1_c)
lcpars[["b_biodiv2"]] = list(b_biodiv2_a, b_biodiv2_b, b_biodiv2_c)
lcpars[["b_cc1"]] = list(b_cc1_a, b_cc1_b, b_cc1_c)
lcpars[["b_cc2"]] = list(b_cc2_a, b_cc2_b, b_cc2_c)
lcpars[["b_share"]] = list(b_share_a, b_share_b, b_share_c)
lcpars[["b_payment"]] = list(b_payment_a, b_payment_b, b_payment_c)

V=list()
V[["class_a"]] = delta_a

V[["class_b"]] = delta_b

V[["class_c"]] = delta_c

mnl_settings = list(
alternatives = c(class_a=1, class_b=2, class_c=3),
avail = 1,
choiceVar = NA,
V = V
)

lcpars[["pi_values"]] = apollo_mnl(mnl_settings, functionality="raw")

lcpars[["pi_values"]] = apollo_firstRow(lcpars[["pi_values"]], apollo_inputs)

return(lcpars)
}

# ################################################################# #
#### 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()

### Define settings for MNL model component that are generic across classes
mnl_settings = list(
alternatives = c(pract=1, hybrid=2, result=3, none=4),
avail = list(pract=1, hybrid=1, result=1,none=1),
choiceVar = choice
)

### Loop over classes
s=1
while(s<=3){

### Compute class-specific utilities
V=list()
V[['pract']] = asc_pract[[s]] + b_practices2[[s]]*practices2_pract + b_practices3[[s]]*practices3_pract + b_share[[s]]*(share_pract==0)+ b_payment[[s]]*payment_pract

V[['hybrid']] = asc_hybrid[[s]] + b_practices2[[s]]*practices2_hybrid + b_practices3[[s]]*practices3_hybrid + b_water1[[s]]*water1_hybrid + b_water2[[s]]*water2_hybrid + b_cc1[[s]] * cc1_hybrid + b_cc2[[s]]*cc2_hybrid + b_biodiv1[[s]]*biodiv1_hybrid +b_biodiv2[[s]] * biodiv2_hybrid + b_share[[s]]*share_hybrid + b_payment[[s]]*payment_hybrid

V[['result']] = asc_result[[s]] + b_water1[[s]]*water1_result + b_water2[[s]]*water2_result + b_cc1[[s]] * cc1_result + b_cc2[[s]] * cc2_result + b_biodiv1[[s]]*biodiv1_result +b_biodiv2[[s]] * biodiv2_result + b_share[[s]]*(share_result==6) + b_payment[[s]]*payment_result

V[['none']] = 0

mnl_settings$V = V
mnl_settings$componentName = paste0("Class_",s)

### Compute within-class choice probabilities using MNL model
P[[paste0("Class_",s)]] = apollo_mnl(mnl_settings, functionality)

### Take product across observation for same individual
P[[paste0("Class_",s)]] = apollo_panelProd(P[[paste0("Class_",s)]], apollo_inputs,functionality)

s=s+1}

### Compute latent class model probabilities
lc_settings = list(inClassProb = P,
classProb=pi_values)

P[["model"]] = apollo_lc(lc_settings,
apollo_inputs,
functionality)

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


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

#apollo_beta=apollo_searchStart(apollo_beta, apollo_fixed,apollo_probabilities, apollo_inputs)
#apollo_outOfSample(apollo_beta, apollo_fixed,apollo_probabilities, apollo_inputs)

### Estimate model
model = apollo_estimate(apollo_beta, apollo_fixed,
apollo_probabilities, apollo_inputs,
estimate_settings=list(writeIter=FALSE))

### Show output in screen
apollo_modelOutput(model, list(printPVal = 2))

### Save output to file(s)
apollo_saveOutput(model, list(printPVal = 2))

# ################################################################# #
##### POST-PROCESSING ####
# ################################################################# #

### Print outputs of additional diagnostics to new output file (remember to close file writing when complete)
sink(paste(model$apollo_control$modelName,"_additional_output.txt",sep=""),split=TRUE)


# ----------------------------------------------------------------- #
#---- switch off writing to file ----
# ----------------------------------------------------------------- #

if(sink.number()>0) sink()



and the outcome I have so far is:

Apollo ignition sequence completed
Several observations per individual detected based on the value of ID. Setting panelData in
apollo_control set to TRUE.
All checks on apollo_control completed.
All checks on database completed.

Testing likelihood function...

Overview of choices for MNL model component Class_1:
pract hybrid result none
Times available 4386.00 4386.00 4386.00 4386.00
Times chosen 1181.00 903.00 719.00 1583.00
Percentage chosen overall 26.93 20.59 16.39 36.09
Percentage chosen when available 26.93 20.59 16.39 36.09

Overview of choices for MNL model component Class_2:
pract hybrid result none
Times available 4386.00 4386.00 4386.00 4386.00
Times chosen 1181.00 903.00 719.00 1583.00
Percentage chosen overall 26.93 20.59 16.39 36.09
Percentage chosen when available 26.93 20.59 16.39 36.09

Overview of choices for MNL model component Class_3:
pract hybrid result none
Times available 4386.00 4386.00 4386.00 4386.00
Times chosen 1181.00 903.00 719.00 1583.00
Percentage chosen overall 26.93 20.59 16.39 36.09
Percentage chosen when available 26.93 20.59 16.39 36.09

Summary of class allocation for LC model component :
Mean prob.
Class_1 0.3333
Class_2 0.3333
Class_3 0.3333

Pre-processing likelihood function...



With thanks,
Best wishes,
Laure

Re: Latent class model not progressing after "pre-processing likelihood function"

Posted: 17 Sep 2021, 14:56
by dpalma
Hi Laure,

I looked at your code and didn't see anything wrong with it. Nevertheless, below is a set of recommendations that sometimes help in these cases.
  • Make sure you are using the latest version of Apollo (currently v0.2.5)
  • Try adding the setting analytic gradients to false, as follows:

Code: Select all

apollo_control = list(
modelName ="Latent_Class_3classes_noclusters_forum",
modelDescr ="LC model with class allocation model; 3 classes; only constant to explain class membership, as starting point",
indivID ="ID",
nCores = 4, 
analyticGrad = FALSE
)
If the second alternative works, or if none of them work, please send us a copy of your script and data, so we can look at the issue in more detail. You can email it to D.Palma [at] leeds.ac.uk if you prefer.

Cheers
David

Re: Latent class model not progressing after "pre-processing likelihood function"

Posted: 17 Sep 2021, 16:28
by Laure K
Hi David,

I already had the latest version of Apollo, but adding the setting analytic gradients to false solved the issue, thank you very much.
I will send you the script and data by email if this can be useful.

Thanks again,
Best
Laure