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.

Hardware requirements for complex hybrid latent class models in Apollo

Ask questions about how to estimate models and how to change your settings for estimation.
Post Reply
Peter_C
Posts: 21
Joined: 03 May 2020, 13:52

Hardware requirements for complex hybrid latent class models in Apollo

Post by Peter_C »

Dear Apollo Team,

I am currently working with Apollo in the context of hybrid choice modelling, and I have encountered computational limitations when estimating a relatively complex model.

The model is based on a best-worst scaling / maxdiff choice experiment with approximately 6,400 respondents. The specification I would like to estimate includes a latent class structure, two latent variables in the class allocation component, and more than 150 parameters to be estimated. When running the model with parallel processing, I receive the following error message:

Error in checkForRemoteErrors(lapply(cl, recvResult)) :
6 nodes produced errors; first error: cannot allocate vector of size 28.5 Mb

I understand that this is most likely related to memory limitations, especially because the model objects and data may be copied across workers when using multiple cores.

We are now considering purchasing a new computer specifically for estimating such complex Apollo models. Could you please advise what kind of hardware specifications you would recommend, especially in terms of:

- RAM capacity,
- processor type / number of cores,
- whether fewer but more powerful cores or more cores are preferable,
- and whether you would recommend a workstation/server-type machine for models of this complexity?

More generally, I would be grateful for any practical guidance regarding the hardware requirements for estimating large-scale hybrid choice models with latent variables and latent classes in Apollo.

Thank you very much in advance for your help.

Kind regards,
Peter
stephanehess
Site Admin
Posts: 1366
Joined: 24 Apr 2020, 16:29

Re: Hardware requirements for complex hybrid latent class models in Apollo

Post by stephanehess »

Peter

how many draws are you using? And what were the runtimes like for simpler specifications of the model, e.g. just latent class? That would tell us whether there are some issues specific to your implementation, as your model per se is not beyond models we have successfully run on standard laptops

Stephane
--------------------------------
Stephane Hess
www.stephanehess.me.uk
Peter_C
Posts: 21
Joined: 03 May 2020, 13:52

Re: Hardware requirements for complex hybrid latent class models in Apollo

Post by Peter_C »

Hi Stephane!

Thank you very much for your quick reply.

I am trying to run the model with 500 MLHS draws. With this setting, I already receive the error message I mentioned earlier.

The 5-class latent class model on which this hybrid choice specification is based ran without any problems. Its main outputs were as follows:

Code: Select all

Model name                                  : Apollo_BWS_maxdiff_5_class
Model description                           : Latent class maxdiff model_5_class
Model run at                                : 2026-05-22 20:47:58.448209
Estimation method                           : bfgs
Model diagnosis                             : successful convergence
Optimisation diagnosis                      : Maximum found
     hessian properties                     : Negative definite
     maximum eigenvalue                     : -13.907161
     reciprocal of condition number         : 0.00437654
Number of individuals                       : 6404
Number of rows in database                  : 44828
Number of modelled outcomes                 : 44828

Number of cores used                        : 6
Model without mixing

LL(start)                                   : -80321
LL (whole model) at equal shares, LL(0)     : -80321
LL (whole model) at observed shares, LL(C)  : -75169
LL(final, whole model)                      : -67339
Rho-squared vs equal shares                 : 0.1616
Adj.Rho-squared vs equal shares             : 0.1612
Rho-squared vs observed shares              : 0.1042
Adj.Rho-squared vs observed shares          : 0.104
AIC                                         : 134746
BIC                                         : 135042

Estimated parameters                        : 34
Time taken (hh:mm:ss)                       : 00:03:05.47
     pre-estimation                         : 00:00:27.39
     estimation                             : 00:00:44.24
     post-estimation                        : 00:01:53.85
Iterations                                  : 72

I used the parameter estimates from this model as starting values for the 5-class hybrid choice model.

The sample includes 6,404 respondents from 8 countries, with approximately 800 respondents per country. I also tried reducing the sample and running the model with only 4 countries, but this was still unsuccessful. With a single country, the model did start running, but it was rather slow.

This is why I thought that the issue might be related to the computer specifications. I am currently trying to run the model on a 64-bit operating system with 16 GB RAM and an Intel(R) Core(TM) i7-9700K CPU @ 3.60 GHz. I also tried running it on a stronger laptop, but I was not successful there either.

I paste below the full code of the problematic specification in case it helps to identify whether there is an implementation issue.

Kind regards,
Peter

Code: Select all


library(support.BWS)
library(crossdes)
library(apollo)
library(dplyr)

items <- c("A_hús_frissessége", "A_hús_külső_megjelenése_a_hús_látványa", "A_hús_őshonos_fajtájú_nem_hibrid_vagy_modern_fajta_állatból_származik", "A_hús_szaga", "A_hús_íze", "A_hús_állaga", "Egészségre_gyakorolt_hatás_a_hagyományosan_előállított_húsokhoz_képest")

values<-c(1,1,5,4,1,4,5,2,4,6,6,6,2,7,3,5,2,3,7,7,3)
design<-matrix(data=values,nrow = 7,ncol = 3)

dmd <- bws.dataset(data = bws_data, choice.sets = design,
                   design.type = 2, item.names = items, model = "maxdiff")

### Convert dataset format
dmd.apollo <- bws.apollo(dmd)

### Conduct modeling approach: maxdiff model
apollo_initialise()
apollo_control = list(
  modelName = "Apollo_BWS_maxdiff_5_class_HLC",
  modelDescr = "Latent class maxdiff model_5_class_HLC",
  indivID = "id",
  noValidation = TRUE,
  nCores          = 6,
  outputDirectory = "LC_results_5_class_HLC"
)
database = dmd.apollo
apollo_beta = c(b_kulso_a = 0, b_oshonos_a = 0, b_szag_a = 0, b_iz_a = 0, b_allag_a = 0, b_egeszseg_a = 0,
                b_kulso_b = 0, b_oshonos_b = 0, b_szag_b = 0, b_iz_b = 0, b_allag_b = 0, b_egeszseg_b = 0,
                b_kulso_c = 0, b_oshonos_c = 0, b_szag_c = 0, b_iz_c = 0, b_allag_c = 0, b_egeszseg_c = 0,
                b_kulso_d = 0, b_oshonos_d = 0, b_szag_d = 0, b_iz_d = 0, b_allag_d = 0, b_egeszseg_d = 0,
                b_kulso_e = 0, b_oshonos_e = 0, b_szag_e = 0, b_iz_e = 0, b_allag_e = 0, b_egeszseg_e = 0,
                delta_a = 0, delta_c = 0, delta_d = 0, delta_e = 0,
                lambda_elun_a = 0, lambda_elun_c = 0, lambda_elun_d = 0, lambda_elun_e = 0,
                lambda_eltech_a = 0, lambda_eltech_c = 0, lambda_eltech_d = 0, lambda_eltech_e = 0,
                gamma_austria_elun = 0, gamma_czech_elun = 0, gamma_germany_elun = 0, gamma_hungary_elun = 0, gamma_italy_elun = 0, gamma_poland_elun = 0, gamma_slovak_elun = 0,
                gamma_austria_eltech = 0, gamma_czech_eltech = 0, gamma_germany_eltech = 0, gamma_hungary_eltech = 0, gamma_italy_eltech = 0, gamma_poland_eltech = 0, gamma_slovak_eltech = 0,
                zeta_elun_1 = 1, zeta_elun_2 = 1, zeta_elun_3 = 1, zeta_elun_4 = 1, zeta_elun_5 = 1, zeta_elun_6 = 1, zeta_elun_7 = 1, zeta_elun_8 = 1,
                tau_elun1_1 = -2, tau_elun1_2 = -1, tau_elun1_3 = 1, tau_elun1_4 = 2,
                tau_elun2_1 = -2, tau_elun2_2 = -1, tau_elun2_3 = 1, tau_elun2_4 = 2,
                tau_elun3_1 = -2, tau_elun3_2 = -1, tau_elun3_3 = 1, tau_elun3_4 = 2,
                tau_elun4_1 = -2, tau_elun4_2 = -1, tau_elun4_3 = 1, tau_elun4_4 = 2,
                tau_elun5_1 = -2, tau_elun5_2 = -1, tau_elun5_3 = 1, tau_elun5_4 = 2,
                tau_elun6_1 = -2, tau_elun6_2 = -1, tau_elun6_3 = 1, tau_elun6_4 = 2,
                tau_elun7_1 = -2, tau_elun7_2 = -1, tau_elun7_3 = 1, tau_elun7_4 = 2,
                tau_elun8_1 = -2, tau_elun8_2 = -1, tau_elun8_3 = 1, tau_elun8_4 = 2,
                zeta_eltech_1 = 1, zeta_eltech_2 = 1, zeta_eltech_3 = 1, zeta_eltech_4 = 1, zeta_eltech_5 = 1, zeta_eltech_6 = 1, zeta_eltech_7 = 1, zeta_eltech_8 = 1, zeta_eltech_9 = 1, zeta_eltech_10 = -1, zeta_eltech_11 = -1, zeta_eltech_12 = -1, zeta_eltech_13 = -1,
                tau_eltech1_1 = -3, tau_eltech1_2 = -2, tau_eltech1_3 = -1, tau_eltech1_4 = 1, tau_eltech1_5 = 2, tau_eltech1_6 = 3,
                tau_eltech2_1 = -3, tau_eltech2_2 = -2, tau_eltech2_3 = -1, tau_eltech2_4 = 1, tau_eltech2_5 = 2, tau_eltech2_6 = 3,
                tau_eltech3_1 = -3, tau_eltech3_2 = -2, tau_eltech3_3 = -1, tau_eltech3_4 = 1, tau_eltech3_5 = 2, tau_eltech3_6 = 3,
                tau_eltech4_1 = -3, tau_eltech4_2 = -2, tau_eltech4_3 = -1, tau_eltech4_4 = 1, tau_eltech4_5 = 2, tau_eltech4_6 = 3,
                tau_eltech5_1 = -3, tau_eltech5_2 = -2, tau_eltech5_3 = -1, tau_eltech5_4 = 1, tau_eltech5_5 = 2, tau_eltech5_6 = 3,
                tau_eltech6_1 = -3, tau_eltech6_2 = -2, tau_eltech6_3 = -1, tau_eltech6_4 = 1, tau_eltech6_5 = 2, tau_eltech6_6 = 3,
                tau_eltech7_1 = -3, tau_eltech7_2 = -2, tau_eltech7_3 = -1, tau_eltech7_4 = 1, tau_eltech7_5 = 2, tau_eltech7_6 = 3,
                tau_eltech8_1 = -3, tau_eltech8_2 = -2, tau_eltech8_3 = -1, tau_eltech8_4 = 1, tau_eltech8_5 = 2, tau_eltech8_6 = 3,
                tau_eltech9_1 = -3, tau_eltech9_2 = -2, tau_eltech9_3 = -1, tau_eltech9_4 = 1, tau_eltech9_5 = 2, tau_eltech9_6 = 3,
                tau_eltech10_1 = -3, tau_eltech10_2 = -2, tau_eltech10_3 = -1, tau_eltech10_4 = 1, tau_eltech10_5 = 2, tau_eltech10_6 = 3,
                tau_eltech11_1 = -3, tau_eltech11_2 = -2, tau_eltech11_3 = -1, tau_eltech11_4 = 1, tau_eltech11_5 = 2, tau_eltech11_6 = 3,
                tau_eltech12_1 = -3, tau_eltech12_2 = -2, tau_eltech12_3 = -1, tau_eltech12_4 = 1, tau_eltech12_5 = 2, tau_eltech12_6 = 3,
                tau_eltech13_1 = -3, tau_eltech13_2 = -2, tau_eltech13_3 = -1, tau_eltech13_4 = 1, tau_eltech13_5 = 2, tau_eltech13_6 = 3)
apollo_fixed = c()


apollo_beta = apollo_readBeta(apollo_beta, apollo_fixed, "Apollo_BWS_maxdiff_5_class", overwriteFixed=FALSE)

# ################################################################# #
#### DEFINE RANDOM COMPONENTS                                    ####
# ################################################################# #

### Set parameters for generating draws
apollo_draws = list(
  interDrawsType = "mlhs", 
  interNDraws    = 500,
  interNormDraws = c("eta_elun", "eta_eltech")
)

### Create random parameters
apollo_randCoeff=function(apollo_beta, apollo_inputs){
  randcoeff = list()
  randcoeff[["LV_elun"]] = eta_elun + gamma_austria_elun * austria + gamma_czech_elun * czech + gamma_germany_elun * germany + gamma_hungary_elun * hungary + gamma_italy_elun * italy + gamma_poland_elun * poland + gamma_slovak_elun * slovak
  randcoeff[["LV_eltech"]] = eta_eltech + gamma_austria_eltech * austria + gamma_czech_eltech * czech + gamma_germany_eltech * germany + gamma_hungary_eltech * hungary + gamma_italy_eltech * italy + gamma_poland_eltech * poland + gamma_slovak_eltech * slovak
  return(randcoeff)
}

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

apollo_lcPars=function(apollo_beta, apollo_inputs){
  lcpars = list()
  
  lcpars[["b_kulso"]] = list(b_kulso_a, b_kulso_b, b_kulso_c, b_kulso_d, b_kulso_e)
  lcpars[["b_oshonos"]] = list(b_oshonos_a, b_oshonos_b, b_oshonos_c, b_oshonos_d, b_oshonos_e)
  lcpars[["b_szag"]] = list(b_szag_a, b_szag_b, b_szag_c, b_szag_d, b_szag_e)
  lcpars[["b_iz"]] = list(b_iz_a, b_iz_b, b_iz_c, b_iz_d, b_iz_e)
  lcpars[["b_allag"]] = list(b_allag_a, b_allag_b, b_allag_c, b_allag_d, b_allag_e)
  lcpars[["b_egeszseg"]] = list(b_egeszseg_a, b_egeszseg_b, b_egeszseg_c, b_egeszseg_d, b_egeszseg_e)
  
  
  V=list()
  V[["class_a"]] = delta_a + lambda_elun_a * LV_elun + lambda_eltech_a * LV_eltech
  V[["class_b"]] = 0
  V[["class_c"]] = delta_c + lambda_elun_c * LV_elun + lambda_eltech_c * LV_eltech
  V[["class_d"]] = delta_d + lambda_elun_d * LV_elun + lambda_eltech_d * LV_eltech
  V[["class_e"]] = delta_e + lambda_elun_e * LV_elun + lambda_eltech_e * LV_eltech
  
  
  classAlloc_settings = list(
    classes      = c(class_a=1, class_b=2, class_c=3, class_d=4, class_e=5), 
    utilities    = V
  )
  
  lcpars[["pi_values"]] = apollo_classAlloc(classAlloc_settings)
  
  return(lcpars)
}


apollo_inputs = apollo_validateInputs()
apollo_probabilities = function(apollo_beta, apollo_inputs, functionality = "estimate"){
  apollo_attach(apollo_beta, apollo_inputs)
  on.exit(apollo_detach(apollo_beta, apollo_inputs))
  
  
  ### Create list of probabilities P
  P = list()
  
  ### Likelihood of indicators
  ol_settings1_elun = list(
    outcomeOrdered = el_un1, 
    utility        = zeta_elun_1 * LV_elun, 
    tau            = list(tau_elun1_1, tau_elun1_2, tau_elun1_3, tau_elun1_4),
    rows           = (Q == 1 & el_un1 != 0), 
    componentName  = "indic_elun1"
  )
  
  ol_settings2_elun = list(
    outcomeOrdered = el_un2, 
    utility        = zeta_elun_2 * LV_elun, 
    tau            = list(tau_elun2_1, tau_elun2_2, tau_elun2_3, tau_elun2_4),
    rows           = (Q == 1 & el_un2 != 0), 
    componentName  = "indic_elun2"
  )
  
  ol_settings3_elun = list(
    outcomeOrdered = el_un3, 
    utility        = zeta_elun_3 * LV_elun, 
    tau            = list(tau_elun3_1, tau_elun3_2, tau_elun3_3, tau_elun3_4),
    rows           = (Q == 1 & el_un3 != 0), 
    componentName  = "indic_elun3"
  )
  
  ol_settings4_elun = list(
    outcomeOrdered = el_un4, 
    utility        = zeta_elun_4 * LV_elun, 
    tau            = list(tau_elun4_1, tau_elun4_2, tau_elun4_3, tau_elun4_4),
    rows           = (Q == 1 & el_un4 != 0), 
    componentName  = "indic_elun4"
  )
  
  ol_settings5_elun = list(
    outcomeOrdered = el_un5, 
    utility        = zeta_elun_5 * LV_elun, 
    tau            = list(tau_elun5_1, tau_elun5_2, tau_elun5_3, tau_elun5_4),
    rows           = (Q == 1 & el_un5 != 0), 
    componentName  = "indic_elun5"
  )
  
  ol_settings6_elun = list(
    outcomeOrdered = el_un6, 
    utility        = zeta_elun_6 * LV_elun, 
    tau            = list(tau_elun6_1, tau_elun6_2, tau_elun6_3, tau_elun6_4),
    rows           = (Q == 1 & el_un6 != 0), 
    componentName  = "indic_elun6"
  )
  
  ol_settings7_elun = list(
    outcomeOrdered = el_un7, 
    utility        = zeta_elun_7 * LV_elun, 
    tau            = list(tau_elun7_1, tau_elun7_2, tau_elun7_3, tau_elun7_4),
    rows           = (Q == 1 & el_un7 != 0), 
    componentName  = "indic_elun7"
  )
  
  ol_settings8_elun = list(
    outcomeOrdered = el_un8, 
    utility        = zeta_elun_8 * LV_elun, 
    tau            = list(tau_elun8_1, tau_elun8_2, tau_elun8_3, tau_elun8_4),
    rows           = (Q == 1 & el_un8 != 0), 
    componentName  = "indic_elun8"
  )
  
  ol_settings1_eltech = list(
    outcomeOrdered = el_tech1, 
    utility        = zeta_eltech_1 * LV_eltech, 
    tau            = list(tau_eltech1_1, tau_eltech1_2, tau_eltech1_3, tau_eltech1_4, tau_eltech1_5, tau_eltech1_6),
    rows           = (Q == 1 & el_tech1 != 0), 
    componentName  = "indic_eltech1"
  )
  
  ol_settings2_eltech = list(
    outcomeOrdered = el_tech2, 
    utility        = zeta_eltech_2 * LV_eltech, 
    tau            = list(tau_eltech2_1, tau_eltech2_2, tau_eltech2_3, tau_eltech2_4, tau_eltech2_5, tau_eltech2_6),
    rows           = (Q == 1 & el_tech2 != 0), 
    componentName  = "indic_eltech2"
  )
  
  ol_settings3_eltech = list(
    outcomeOrdered = el_tech3, 
    utility        = zeta_eltech_3 * LV_eltech, 
    tau            = list(tau_eltech3_1, tau_eltech3_2, tau_eltech3_3, tau_eltech3_4, tau_eltech3_5, tau_eltech3_6),
    rows           = (Q == 1 & el_tech3 != 0), 
    componentName  = "indic_eltech3"
  )
  
  ol_settings4_eltech = list(
    outcomeOrdered = el_tech4, 
    utility        = zeta_eltech_4 * LV_eltech, 
    tau            = list(tau_eltech4_1, tau_eltech4_2, tau_eltech4_3, tau_eltech4_4, tau_eltech4_5, tau_eltech4_6),
    rows           = (Q == 1 & el_tech4 != 0), 
    componentName  = "indic_eltech4"
  )
  
  ol_settings5_eltech = list(
    outcomeOrdered = el_tech5, 
    utility        = zeta_eltech_5 * LV_eltech, 
    tau            = list(tau_eltech5_1, tau_eltech5_2, tau_eltech5_3, tau_eltech5_4, tau_eltech5_5, tau_eltech5_6),
    rows           = (Q == 1 & el_tech5 != 0), 
    componentName  = "indic_eltech5"
  )
  
  ol_settings6_eltech = list(
    outcomeOrdered = el_tech6, 
    utility        = zeta_eltech_6 * LV_eltech, 
    tau            = list(tau_eltech6_1, tau_eltech6_2, tau_eltech6_3, tau_eltech6_4, tau_eltech6_5, tau_eltech6_6),
    rows           = (Q == 1 & el_tech6 != 0), 
    componentName  = "indic_eltech6"
  )
  
  ol_settings7_eltech = list(
    outcomeOrdered = el_tech7, 
    utility        = zeta_eltech_7 * LV_eltech, 
    tau            = list(tau_eltech7_1, tau_eltech7_2, tau_eltech7_3, tau_eltech7_4, tau_eltech7_5, tau_eltech7_6),
    rows           = (Q == 1 & el_tech7 != 0), 
    componentName  = "indic_eltech7"
  )
  
  ol_settings8_eltech = list(
    outcomeOrdered = el_tech8, 
    utility        = zeta_eltech_8 * LV_eltech, 
    tau            = list(tau_eltech8_1, tau_eltech8_2, tau_eltech8_3, tau_eltech8_4, tau_eltech8_5, tau_eltech8_6),
    rows           = (Q == 1 & el_tech8 != 0), 
    componentName  = "indic_eltech8"
  )
  
  ol_settings9_eltech = list(
    outcomeOrdered = el_tech9, 
    utility        = zeta_eltech_9 * LV_eltech, 
    tau            = list(tau_eltech9_1, tau_eltech9_2, tau_eltech9_3, tau_eltech9_4, tau_eltech9_5, tau_eltech9_6),
    rows           = (Q == 1 & el_tech9 != 0), 
    componentName  = "indic_eltech9"
  )
  
  ol_settings10_eltech = list(
    outcomeOrdered = el_tech10, 
    utility        = zeta_eltech_10 * LV_eltech, 
    tau            = list(tau_eltech10_1, tau_eltech10_2, tau_eltech10_3, tau_eltech10_4, tau_eltech10_5, tau_eltech10_6),
    rows           = (Q == 1 & el_tech10 != 0), 
    componentName  = "indic_eltech10"
  )
  
  ol_settings11_eltech = list(
    outcomeOrdered = el_tech11, 
    utility        = zeta_eltech_11 * LV_eltech, 
    tau            = list(tau_eltech11_1, tau_eltech11_2, tau_eltech11_3, tau_eltech11_4, tau_eltech11_5, tau_eltech11_6),
    rows           = (Q == 1 & el_tech11 != 0), 
    componentName  = "indic_eltech11"
  )
  
  ol_settings12_eltech = list(
    outcomeOrdered = el_tech12, 
    utility        = zeta_eltech_12 * LV_eltech, 
    tau            = list(tau_eltech12_1, tau_eltech12_2, tau_eltech12_3, tau_eltech12_4, tau_eltech12_5, tau_eltech12_6),
    rows           = (Q == 1 & el_tech12 != 0), 
    componentName  = "indic_eltech12"
  )
  
  ol_settings13_eltech = list(
    outcomeOrdered = el_tech13, 
    utility        = zeta_eltech_13 * LV_eltech, 
    tau            = list(tau_eltech13_1, tau_eltech13_2, tau_eltech13_3, tau_eltech13_4, tau_eltech13_5, tau_eltech13_6),
    rows           = (Q == 1 & el_tech13 != 0), 
    componentName  = "indic_eltech13"
  )
  
  P[["indic_elun1"]] = apollo_ol(ol_settings1_elun, functionality) 
  P[["indic_elun1"]] = apollo_panelProd(P[["indic_elun1"]], apollo_inputs, functionality)
  
  P[["indic_elun2"]] = apollo_ol(ol_settings2_elun, functionality) 
  P[["indic_elun2"]] = apollo_panelProd(P[["indic_elun2"]], apollo_inputs, functionality)
  
  P[["indic_elun3"]] = apollo_ol(ol_settings3_elun, functionality) 
  P[["indic_elun3"]] = apollo_panelProd(P[["indic_elun3"]], apollo_inputs, functionality)
  
  P[["indic_elun4"]] = apollo_ol(ol_settings4_elun, functionality) 
  P[["indic_elun4"]] = apollo_panelProd(P[["indic_elun4"]], apollo_inputs, functionality)
  
  P[["indic_elun5"]] = apollo_ol(ol_settings5_elun, functionality) 
  P[["indic_elun5"]] = apollo_panelProd(P[["indic_elun5"]], apollo_inputs, functionality)
  
  P[["indic_elun6"]] = apollo_ol(ol_settings6_elun, functionality) 
  P[["indic_elun6"]] = apollo_panelProd(P[["indic_elun6"]], apollo_inputs, functionality)
  
  P[["indic_elun7"]] = apollo_ol(ol_settings7_elun, functionality) 
  P[["indic_elun7"]] = apollo_panelProd(P[["indic_elun7"]], apollo_inputs, functionality)
  
  P[["indic_elun8"]] = apollo_ol(ol_settings8_elun, functionality) 
  P[["indic_elun8"]] = apollo_panelProd(P[["indic_elun8"]], apollo_inputs, functionality)  
  
  P[["indic_eltech1"]] = apollo_ol(ol_settings1_eltech, functionality) 
  P[["indic_eltech1"]] = apollo_panelProd(P[["indic_eltech1"]], apollo_inputs, functionality)
  
  P[["indic_eltech2"]] = apollo_ol(ol_settings2_eltech, functionality) 
  P[["indic_eltech2"]] = apollo_panelProd(P[["indic_eltech2"]], apollo_inputs, functionality)
  
  P[["indic_eltech3"]] = apollo_ol(ol_settings3_eltech, functionality) 
  P[["indic_eltech3"]] = apollo_panelProd(P[["indic_eltech3"]], apollo_inputs, functionality)
  
  P[["indic_eltech4"]] = apollo_ol(ol_settings4_eltech, functionality) 
  P[["indic_eltech4"]] = apollo_panelProd(P[["indic_eltech4"]], apollo_inputs, functionality)
  
  P[["indic_eltech5"]] = apollo_ol(ol_settings5_eltech, functionality) 
  P[["indic_eltech5"]] = apollo_panelProd(P[["indic_eltech5"]], apollo_inputs, functionality)
  
  P[["indic_eltech6"]] = apollo_ol(ol_settings6_eltech, functionality) 
  P[["indic_eltech6"]] = apollo_panelProd(P[["indic_eltech6"]], apollo_inputs, functionality)
  
  P[["indic_eltech7"]] = apollo_ol(ol_settings7_eltech, functionality) 
  P[["indic_eltech7"]] = apollo_panelProd(P[["indic_eltech7"]], apollo_inputs, functionality)
  
  P[["indic_eltech8"]] = apollo_ol(ol_settings8_eltech, functionality) 
  P[["indic_eltech8"]] = apollo_panelProd(P[["indic_eltech8"]], apollo_inputs, functionality)
  
  P[["indic_eltech9"]] = apollo_ol(ol_settings9_eltech, functionality) 
  P[["indic_eltech9"]] = apollo_panelProd(P[["indic_eltech9"]], apollo_inputs, functionality)
  
  P[["indic_eltech10"]] = apollo_ol(ol_settings10_eltech, functionality) 
  P[["indic_eltech10"]] = apollo_panelProd(P[["indic_eltech10"]], apollo_inputs, functionality)
  
  P[["indic_eltech11"]] = apollo_ol(ol_settings11_eltech, functionality) 
  P[["indic_eltech11"]] = apollo_panelProd(P[["indic_eltech11"]], apollo_inputs, functionality)
  
  P[["indic_eltech12"]] = apollo_ol(ol_settings12_eltech, functionality) 
  P[["indic_eltech12"]] = apollo_panelProd(P[["indic_eltech12"]], apollo_inputs, functionality)
  
  P[["indic_eltech13"]] = apollo_ol(ol_settings13_eltech, functionality) 
  P[["indic_eltech13"]] = apollo_panelProd(P[["indic_eltech13"]], apollo_inputs, functionality)
  
  ### Loop over classes
  S = 5
  for(s in 1:S){
    
    
    V = list()
    V[['alt1']]  = b_kulso[[s]] * A_hús_külső_megjelenése_a_hús_látványa.1    + b_oshonos[[s]] * A_hús_őshonos_fajtájú_nem_hibrid_vagy_modern_fajta_állatból_származik.1  + b_szag[[s]] * A_hús_szaga.1  + 
      b_iz[[s]] * A_hús_íze.1  + b_allag[[s]] * A_hús_állaga.1    + b_egeszseg[[s]] * Egészségre_gyakorolt_hatás_a_hagyományosan_előállított_húsokhoz_képest.1
    V[['alt2']]  = b_kulso[[s]] * A_hús_külső_megjelenése_a_hús_látványa.2    + b_oshonos[[s]] * A_hús_őshonos_fajtájú_nem_hibrid_vagy_modern_fajta_állatból_származik.2  + b_szag[[s]] * A_hús_szaga.2  + 
      b_iz[[s]] * A_hús_íze.2  + b_allag[[s]] * A_hús_állaga.2    + b_egeszseg[[s]] * Egészségre_gyakorolt_hatás_a_hagyományosan_előállított_húsokhoz_képest.2
    V[['alt3']]  = b_kulso[[s]] * A_hús_külső_megjelenése_a_hús_látványa.3    + b_oshonos[[s]] * A_hús_őshonos_fajtájú_nem_hibrid_vagy_modern_fajta_állatból_származik.3  + b_szag[[s]] * A_hús_szaga.3  + 
      b_iz[[s]] * A_hús_íze.3  + b_allag[[s]] * A_hús_állaga.3    + b_egeszseg[[s]] * Egészségre_gyakorolt_hatás_a_hagyományosan_előállított_húsokhoz_képest.3
    V[['alt4']]  = b_kulso[[s]] * A_hús_külső_megjelenése_a_hús_látványa.4    + b_oshonos[[s]] * A_hús_őshonos_fajtájú_nem_hibrid_vagy_modern_fajta_állatból_származik.4  + b_szag[[s]] * A_hús_szaga.4  + 
      b_iz[[s]] * A_hús_íze.4  + b_allag[[s]] * A_hús_állaga.4    + b_egeszseg[[s]] * Egészségre_gyakorolt_hatás_a_hagyományosan_előállított_húsokhoz_képest.4
    V[['alt5']]  = b_kulso[[s]] * A_hús_külső_megjelenése_a_hús_látványa.5    + b_oshonos[[s]] * A_hús_őshonos_fajtájú_nem_hibrid_vagy_modern_fajta_állatból_származik.5  + b_szag[[s]] * A_hús_szaga.5  + 
      b_iz[[s]] * A_hús_íze.5  + b_allag[[s]] * A_hús_állaga.5    + b_egeszseg[[s]] * Egészségre_gyakorolt_hatás_a_hagyományosan_előállított_húsokhoz_képest.5
    V[['alt6']]  = b_kulso[[s]] * A_hús_külső_megjelenése_a_hús_látványa.6    + b_oshonos[[s]] * A_hús_őshonos_fajtájú_nem_hibrid_vagy_modern_fajta_állatból_származik.6  + b_szag[[s]] * A_hús_szaga.6  + 
      b_iz[[s]] * A_hús_íze.6  + b_allag[[s]] * A_hús_állaga.6    + b_egeszseg[[s]] * Egészségre_gyakorolt_hatás_a_hagyományosan_előállított_húsokhoz_képest.6
    
    
    ### Define settings for MNL model component that are generic across classes
    mnl_settings = list(
      alternatives = c(alt1 = 1, alt2 = 2, alt3 = 3, alt4 = 4, alt5 = 5, alt6 = 6),
      choiceVar    = RES,
      utilities    = V
    )
    
    ### 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)
  }
  
  ### Compute latent class model probabilities
  lc_settings   = list(inClassProb = P[paste0("Class_", 1:S)], classProb=pi_values)
  P[["choice"]] = apollo_lc(lc_settings, apollo_inputs, functionality)
  
  
  ### Comment out as necessary
  P = apollo_combineModels(P, apollo_inputs, functionality, components=c("indic_elun1",                                                                          
                                                                         "indic_elun2",
                                                                         "indic_elun3",
                                                                         "indic_elun4",
                                                                         "indic_elun5",
                                                                         "indic_elun6",
                                                                         "indic_elun7",
                                                                         "indic_elun8",
                                                                         "indic_eltech1",
                                                                         "indic_eltech2",
                                                                         "indic_eltech3",
                                                                         "indic_eltech4",
                                                                         "indic_eltech5",
                                                                         "indic_eltech6",
                                                                         "indic_eltech7",
                                                                         "indic_eltech8",
                                                                         "indic_eltech9",
                                                                         "indic_eltech10",
                                                                         "indic_eltech11",
                                                                         "indic_eltech12",
                                                                         "indic_eltech13",
                                                                         "choice"))
  P = apollo_avgInterDraws(P, apollo_inputs, functionality)
  P = apollo_prepareProb(P, apollo_inputs, functionality)
  return(P)
}



#model outputs
modelOutput_settings = list()
modelOutput_settings$printPVal=TRUE
apollo_modelOutput(model,modelOutput_settings)

saveOutput_settings = list()
saveOutput_settings$printPVal=TRUE
apollo_saveOutput(model,modelOutput_settings)
dpalma
Posts: 233
Joined: 24 Apr 2020, 17:54

Re: Hardware requirements for complex hybrid latent class models in Apollo

Post by dpalma »

Hi Peter,

The R language can be quite memory hungry. In the particular case of Apollo, this usually manifest in hybrid models, where the multiple components (measuring + choice) end up consuming significant amounts of memory.

Here are a few tips to reduce memory consumption (at the cost of slower estimation or lower precision):
  • Reduce the number of draws. Of course, you should never go too low on the draws, as it may invalidate your estimation results.
  • In the case of hybrid models, you can try using linear measurement equations instead of ordered logit models. This may reduce memory usage.
  • Use fewer cores. The more cores you use, the faster estimation will be (with decreasing gains), but memory usag will also go up. Try running your model with a single core.
  • Turn analytic gradients off. You can set apollo_control$analyticGrad = FALSE. This should decrease memory usage dramatically, but increase estimation time a lot too.
I hope this helps.

Best wishes,
David
Peter_C
Posts: 21
Joined: 03 May 2020, 13:52

Re: Hardware requirements for complex hybrid latent class models in Apollo

Post by Peter_C »

Hi David,

Thank you very much for your reply and for your helpful suggestions.

Do you think that increasing the amount of RAM could solve the problem? If so, do you have any recommendation regarding how much RAM would be needed to run a model of this complexity reliably?

Thank you very much in advance for your help.

Peter
dpalma
Posts: 233
Joined: 24 Apr 2020, 17:54

Re: Hardware requirements for complex hybrid latent class models in Apollo

Post by dpalma »

Hi Peter,

Yes, adding more RAM to your computer should help. But it is quite hard to predict how much it will be used (as I mentioned, R's memory usage is a bit obscure). If you want to add more RAM, I would go to the max you can afford or your computer can take.

Another practical solution is renting a server to run your model. For example, you can rent a big computer from Amazon web services (AWS) with 64, 128, or more GB of RAM and try your model. It takes a bit of time to set up, but you can keep the server's "image" for the next time you need it. That could also give you a hint of how much RAM you would need.

Don't forget to update Apollo to its latest version, as we are constantly trying to improve memory usage.

Finally, I have been working on an experimental fork of Apollo that offloads some memory to disk. It is slower, but it should allow running much larger models. If you are interested, write me to david.palma[at]uab.cat, and I can give you access to it.

Best wishes,
David
Post Reply