Hi,
I am currently working with latent class models in Apollo and would like to inquire whether it is possible to implement a hierarchical latent class model. That is, a model structure allows for subclasses nested within higher-level latent classes.
If this is supported, could you kindly provide a code example and guidance on how to structure such a model in Apollo?
Thank you very much for your time and assistance!
Best regards,
kiki
Important: Read this before posting to this forum
- 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.
- 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
- Before asking a question on the forum, users are kindly requested to follow these steps:
- Check that the same issue has not already been addressed in the forum - there is a search tool.
- 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
- Check the frequently asked questions section on the Apollo website, which discusses some common issues/failures. Please see http://www.apollochoicemodelling.com/faq.html
- Make sure that R is using the latest official release of Apollo.
- Users can check which version they are running by entering packageVersion("apollo").
- Then check what is the latest full release (not development version) at http://www.ApolloChoiceModelling.com/code.html.
- To update to the latest official version, just enter install.packages("apollo"). To update to a development version, download the appropriate binary file from http://www.ApolloChoiceModelling.com/code.html, and install the package from file
- If the above steps do not resolve the issue, then users should follow these steps when posting a question:
- provide full details on the issue, including the entire code and output, including any error messages
- 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.
Nested Latent Class Model
-
stephanehess
- Site Admin
- Posts: 1330
- Joined: 24 Apr 2020, 16:29
Re: Nested Latent Class Model
Hi
could you provide a mathematical example of what you are after? Then I can advise on how to do this in Apollo
Stephane
could you provide a mathematical example of what you are after? Then I can advise on how to do this in Apollo
Stephane
Re: Nested Latent Class Model
Hi Stephone,
Thank you! The mathematical example can be referred in the paper named "A model for the simultaneous inference of attribute nonattendance and taste heterogeneity", Eq(1)-(9).
The outer latent classes are specified as a conventional latent class model, where each class has its own set of parameters. The inner IANA latent classes have only one set of parameters, which are shared across all inner classes. This parameter structure seems inconsistent with Apollo’s requirements. In the Apollo, all existing specifications of the latent class model have the same parameter structure (same number and naming of parameters) to construct the joint likelihood. When I attempt to include two indices in the utility function to reflect this structure, it triggers errors
Best regards,
kiki
Thank you! The mathematical example can be referred in the paper named "A model for the simultaneous inference of attribute nonattendance and taste heterogeneity", Eq(1)-(9).
The outer latent classes are specified as a conventional latent class model, where each class has its own set of parameters. The inner IANA latent classes have only one set of parameters, which are shared across all inner classes. This parameter structure seems inconsistent with Apollo’s requirements. In the Apollo, all existing specifications of the latent class model have the same parameter structure (same number and naming of parameters) to construct the joint likelihood. When I attempt to include two indices in the utility function to reflect this structure, it triggers errors
Best regards,
kiki
-
stephanehess
- Site Admin
- Posts: 1330
- Joined: 24 Apr 2020, 16:29
Re: Nested Latent Class Model
Hi
you only need the same structure if you write the classes in a loop. Otherwise you can have different structures in different classes. If you share your code, I can have a look
Stephane
you only need the same structure if you write the classes in a loop. Otherwise you can have different structures in different classes. If you share your code, I can have a look
Stephane
Re: Nested Latent Class Model
Hi Stephane,
I have attached the code I tried to implement for a two-layer latent class model. In the code, “k” corresponds to the inner classes (following the IANA structure) and “s” corresponds to the outer classes (following the conventional latent class structure).
When I run the code, I encounter the following error:
The attached code has an error "Error in apollo_estimate(apollo_beta, apollo_fixed, apollo_probabilities, :
SPECIFICATION ISSUE - Parameter asc3_A does not influence the log-likelihood of your model!".
I have removed the random specification for asc3, but the error still remains.
First of all, I would greatly appreciate your help in addressing this error. Additionally, could you review the code to check its overall logic? The mathematical formulation we are using follows the paper “A Model for the Simultaneous Inference of Attribute Nonattendance and Taste Heterogeneity.”
If you need any further information or data sample to test the code, I would be happy to provide it via email. Thank you very much!
#################################################################
# ================================================================= #
# Clean, fixed and runnable Apollo script: 3-class LC + ANA (IANA)
# ================================================================= #
rm(list=ls())
library(apollo)
apollo_initialise()
apollo_control = list(
modelName = "TypeII_ANA_fixed",
modelDescr = "3-class LC with inner ANA (fixed runnable example)",
indivID = "ID",
nCores = 3,
debug = TRUE,
analyticGrad = FALSE,
outputDirectory = "~/TypeII_ANA_output" # 修改为你想要的目录
)
# ---------------------------
# Load data - replace path if needed
# ---------------------------
database = read.csv("xxxx.csv", header=TRUE)
# ---------------------------
# Parameters (starting values)
# ---------------------------
apollo_beta = c(
# RANDOM ASC (for alt3 across classes)
asc3_A=0, asc3_B=0, asc3_C=0,
#mu_asc3_A = 0, sigma_asc3_A = 0,
# mu_asc3_B = 0, sigma_asc3_B = 0,
#mu_asc3_C = 0, sigma_asc3_C = 0,
# class-specific coefficients (A, B, C)
b_passport_A = 0, b_tele_A = 0, b_home_A = 0,
b_size1_A = 0, b_size2_A = 0, b_size3_A = 0,
b_weight1_A = 0, b_weight2_A = 0, b_weight3_A = 0,
b_incentive1_A = 0, b_incentive2_A = 0, b_incentive3_A = 0,
b_extracost_A = 0,
b_passport_B = 0, b_tele_B = 0, b_home_B = 0,
b_size1_B = 0, b_size2_B = 0, b_size3_B = 0,
b_weight1_B = 0, b_weight2_B = 0, b_weight3_B = 0,
b_incentive1_B = 0, b_incentive2_B = 0, b_incentive3_B = 0,
b_extracost_B = 0,
b_passport_C = 0, b_tele_C = 0, b_home_C = 0,
b_size1_C = 0, b_size2_C = 0, b_size3_C = 0,
b_weight1_C = 0, b_weight2_C = 0, b_weight3_C = 0,
b_incentive1_C = 0, b_incentive2_C = 0, b_incentive3_C = 0,
b_extracost_C = 0,
# example socio-demo effects in class allocation (you had many; kept a subset)
mu_agecombine1_A = 0, mu_agecombine6_A = 0,
mu_male_A = 0, mu_hhincombine1_A = 0, mu_hhincombine9_A = 0,
mu_agecombine1_B = 0, mu_agecombine6_B = 0,
mu_male_B = 0, mu_hhincombine1_B = 0, mu_hhincombine9_B = 0,
# class allocation constants
delta_A = 0, delta_B = 0
)
apollo_fixed = c() # none fixed
# Random draws settings (if used)
#apollo_draws = list(interDrawsType="MLHS", interNDraws=475, interNormDraws=c("draw_asc3_A","draw_asc3_B","draw_asc3_C"))
#apollo_randCoeff = function(apollo_beta, apollo_inputs){
# randcoeff = list()
# randcoeff[["asc3_A"]] = mu_asc3_A + sigma_asc3_A * draw_asc3_A
# randcoeff[["asc3_B"]] = mu_asc3_B + sigma_asc3_B * draw_asc3_B
# randcoeff[["asc3_C"]] = mu_asc3_C + sigma_asc3_C * draw_asc3_C
# return(randcoeff)
#}
# ---------------------------
# Build attend_matrix (ANA patterns)
# attribute_count = 3
# Here: columns correspond to [incentive, passport, size] (same order as your code)
# ---------------------------
attribute_count = 3
attend_vector = c(0,1)
attend_matrix = expand.grid(replicate(attribute_count, attend_vector, simplify=FALSE))
colnames(attend_matrix) <- c("attend_incentive","attend_passport","attend_size")
# ---------------------------
# Create apollo_inputs properly (must include database)
# ---------------------------
apollo_inputs = apollo_validateInputs()
apollo_inputs$database = database
apollo_inputs$attend_matrix = attend_matrix
# ---------------------------
# Probability function (we compute per-class-per-attendance, combine inner then outer)
# ---------------------------
apollo_probabilities = function(apollo_beta, apollo_inputs, functionality="estimate"){
### Attach parameters and inputs
apollo_attach(apollo_beta, apollo_inputs)
on.exit(apollo_detach(apollo_beta, apollo_inputs))
# Generate random coefficients
#randcoeff = apollo_randCoeff(apollo_beta, apollo_inputs)
# Get attend patterns and dims
attend = apollo_inputs$attend_matrix
nK = nrow(attend) # number of inner attendance patterns
nS = 3 # number of outer classes (A,B,C)
P = list()
# generic MNL settings
mnl_settings = list(
alternatives = c(alt1=1, alt2=2, alt3=3),
avail = list(alt1=1, alt2=1, alt3=1),
choiceVar = choice
)
# We'll compute P_{s,k} for s in 1..3 and k in 1..nK
# store as P[["s1k1"]], etc.
for(k in 1:nK){
# read attendance indicators for this pattern
att_inc = attend[k,"attend_incentive"]
att_pass = attend[k,"attend_passport"]
att_size = attend[k,"attend_size"]
for(s in 1:nS){
# select class-specific base coefficients and apply attendance modifiers where you intended
# Following the pattern in your original code: for class B some coefficients were multiplied by attendance; others left as is.
# Here I follow your original pattern: passport_B and size_C and incentive_A were multiplied by attend matrix when originally coded.
# Implemented as:
if(s==1){ # class A
asc3_s = asc3_A
# asc3_s = randcoeff[["asc3_A"]]
b_passport_s = b_passport_A
b_tele_s = b_tele_A
b_home_s = b_home_A
b_size1_s = b_size1_A
b_size2_s = b_size2_A
b_size3_s = b_size3_A
b_weight1_s = b_weight1_A
b_weight2_s = b_weight2_A
b_weight3_s = b_weight3_A
b_incent1_s = att_inc * b_incentive1_A # in your earlier code incentive in A was multiplied by attend_matrix[k,1]
b_incent2_s = att_inc * b_incentive2_A
b_incent3_s = att_inc * b_incentive3_A
b_extracost_s= b_extracost_A
} else if(s==2){ # class B
asc3_s = asc3_B
# asc3_s = randcoeff[["asc3_B"]]
b_passport_s = att_pass * b_passport_B # earlier you multiplied passport_B by attendance
b_tele_s = b_tele_B
b_home_s = b_home_B
b_size1_s = b_size1_B
b_size2_s = b_size2_B
b_size3_s = b_size3_B
b_weight1_s = b_weight1_B
b_weight2_s = b_weight2_B
b_weight3_s = b_weight3_B
b_incent1_s = b_incentive1_B
b_incent2_s = b_incentive2_B
b_incent3_s = b_incentive3_B
b_extracost_s= b_extracost_B
} else { # class C
asc3_s = asc3_C
# asc3_s = randcoeff[["asc3_C"]]
b_passport_s = b_passport_C
b_tele_s = b_tele_C
b_home_s = b_home_C
# earlier you multiplied size_C by attendance; reflect that:
b_size1_s = att_size * b_size1_C
b_size2_s = att_size * b_size2_C
b_size3_s = att_size * b_size3_C
b_weight1_s = b_weight1_C
b_weight2_s = b_weight2_C
b_weight3_s = b_weight3_C
b_incent1_s = b_incentive1_C
b_incent2_s = b_incentive2_C
b_incent3_s = b_incentive3_C
b_extracost_s= b_extracost_C
}
# Build utilities for alt1, alt2, alt3 following your original formula (replace variable names to match your data)
V = list()
V[["alt1"]] =
b_tele_s * tele_1 +
b_passport_s * passport_1 +
b_home_s * home_1 +
b_size1_s * dummysize1_1 + b_size2_s * dummysize1_2 + b_size3_s * dummysize1_3 +
b_weight1_s * dummyweight1_1 + b_weight2_s * dummyweight1_2 + b_weight3_s * dummyweight1_3 +
b_incent1_s * dummyincentive1_1 + b_incent2_s * dummyincentive1_2 + b_incent3_s * dummyincentive1_3 +
b_extracost_s * extracost1
V[["alt2"]] =
b_tele_s * tele_1 +
b_passport_s * passport_1 +
b_home_s * home_1 +
b_size1_s * dummysize2_1 + b_size2_s * dummysize2_2 + b_size3_s * dummysize2_3 +
b_weight1_s * dummyweight2_1 + b_weight2_s * dummyweight2_2 + b_weight3_s * dummyweight2_3 +
b_incent1_s * dummyincentive2_1 + b_incent2_s * dummyincentive2_2 + b_incent3_s * dummyincentive2_3 +
b_extracost_s * extracost2
V[["alt3"]] = asc3_s # alt3 only has ASC (as in your code)
mnl_settings$utilities = V
# Unique componentName per (s,k) to avoid duplicate warnings
mnl_settings$componentName = paste0("Class_", s, "_k", k)
# within-class probabilities
P[[paste0("Class_", s, "_k", k)]] = apollo_mnl(mnl_settings, functionality)
P[[paste0("Class_", s, "_k", k)]] = apollo_panelProd(P[[paste0("Class_", s, "_k", k)]], apollo_inputs, functionality)
} # end for s
} # end for k
# ------------------------------------------------------------
# Combine over inner ANA (k) to get class-specific probabilities
# ------------------------------------------------------------
# If you want inner class allocation to be estimated with parameters (delta_attend...), you should:
# - define delta_attend_incentive etc in apollo_beta
# - build a utilities list V_inner and call apollo_classAlloc(V_inner)
# For now we use uniform weights across attendance patterns (1/nK).
pi_k = rep(1/nK, nK)
innerP = list()
for(s in 1:3){
# sum over k: pi_k[k] * P_s_k
tmp = 0
for(k in 1:nK){
tmp = tmp + pi_k[k] * P[[paste0("Class_", s, "_k", k)]]
}
innerP[[paste0("Class_", s)]] = tmp
}
# ------------------------------------------------------------
# Outer class allocation (use soc-demo variables as utilities)
# ------------------------------------------------------------
# Build utilities named to match innerP list names
V_outer = list()
V_outer[["Class_1"]] = delta_A + mu_agecombine1_A * age_combine_1 + mu_agecombine6_A*age_combine_6 + mu_male_A*gender_1 + mu_hhincombine1_A*hh_income_combine_1 + mu_hhincombine9_A*hh_income_combine_9
V_outer[["Class_2"]] = delta_B + mu_agecombine1_B * age_combine_1 + mu_agecombine6_B*age_combine_6 + mu_male_B*gender_1 + mu_hhincombine1_B*hh_income_combine_1 + mu_hhincombine9_B*hh_income_combine_9
V_outer[["Class_3"]] = 0
# classAlloc must have classes names matching innerP names
classAlloc_settings = list(classes = c(Class_1=1, Class_2=2, Class_3=3), utilities = V_outer)
pi_values_s = apollo_classAlloc(classAlloc_settings)
# ------------------------------------------------------------
# Combine innerP (inClassProb) with outer classProb
# ------------------------------------------------------------
lc_settings = list(inClassProb = innerP, classProb = pi_values_s)
P[["choice"]] = apollo_lc(lc_settings, apollo_inputs, functionality)
# combine & prepare
P = apollo_combineModels(P, apollo_inputs, functionality, components = c("choice"))
# P = apollo_avgInterDraws(P, apollo_inputs, functionality)
P = apollo_prepareProb(P, apollo_inputs, functionality)
return(P)
}
# ---------------------------
# Quick check: compute LL at starting values
# ---------------------------
apollo_llCalc(apollo_beta, apollo_probabilities, apollo_inputs)
# ---------------------------
# Estimate model
# ---------------------------
model = apollo_estimate(apollo_beta, apollo_fixed, apollo_probabilities, apollo_inputs,
estimate_settings = list(estimationRoutine = "BFGS", maxIterations = 1000))
# Output
apollo_modelOutput(model)
apollo_saveOutput(model)
##############################################################################
Best regards,
kiki
I have attached the code I tried to implement for a two-layer latent class model. In the code, “k” corresponds to the inner classes (following the IANA structure) and “s” corresponds to the outer classes (following the conventional latent class structure).
When I run the code, I encounter the following error:
The attached code has an error "Error in apollo_estimate(apollo_beta, apollo_fixed, apollo_probabilities, :
SPECIFICATION ISSUE - Parameter asc3_A does not influence the log-likelihood of your model!".
I have removed the random specification for asc3, but the error still remains.
First of all, I would greatly appreciate your help in addressing this error. Additionally, could you review the code to check its overall logic? The mathematical formulation we are using follows the paper “A Model for the Simultaneous Inference of Attribute Nonattendance and Taste Heterogeneity.”
If you need any further information or data sample to test the code, I would be happy to provide it via email. Thank you very much!
#################################################################
# ================================================================= #
# Clean, fixed and runnable Apollo script: 3-class LC + ANA (IANA)
# ================================================================= #
rm(list=ls())
library(apollo)
apollo_initialise()
apollo_control = list(
modelName = "TypeII_ANA_fixed",
modelDescr = "3-class LC with inner ANA (fixed runnable example)",
indivID = "ID",
nCores = 3,
debug = TRUE,
analyticGrad = FALSE,
outputDirectory = "~/TypeII_ANA_output" # 修改为你想要的目录
)
# ---------------------------
# Load data - replace path if needed
# ---------------------------
database = read.csv("xxxx.csv", header=TRUE)
# ---------------------------
# Parameters (starting values)
# ---------------------------
apollo_beta = c(
# RANDOM ASC (for alt3 across classes)
asc3_A=0, asc3_B=0, asc3_C=0,
#mu_asc3_A = 0, sigma_asc3_A = 0,
# mu_asc3_B = 0, sigma_asc3_B = 0,
#mu_asc3_C = 0, sigma_asc3_C = 0,
# class-specific coefficients (A, B, C)
b_passport_A = 0, b_tele_A = 0, b_home_A = 0,
b_size1_A = 0, b_size2_A = 0, b_size3_A = 0,
b_weight1_A = 0, b_weight2_A = 0, b_weight3_A = 0,
b_incentive1_A = 0, b_incentive2_A = 0, b_incentive3_A = 0,
b_extracost_A = 0,
b_passport_B = 0, b_tele_B = 0, b_home_B = 0,
b_size1_B = 0, b_size2_B = 0, b_size3_B = 0,
b_weight1_B = 0, b_weight2_B = 0, b_weight3_B = 0,
b_incentive1_B = 0, b_incentive2_B = 0, b_incentive3_B = 0,
b_extracost_B = 0,
b_passport_C = 0, b_tele_C = 0, b_home_C = 0,
b_size1_C = 0, b_size2_C = 0, b_size3_C = 0,
b_weight1_C = 0, b_weight2_C = 0, b_weight3_C = 0,
b_incentive1_C = 0, b_incentive2_C = 0, b_incentive3_C = 0,
b_extracost_C = 0,
# example socio-demo effects in class allocation (you had many; kept a subset)
mu_agecombine1_A = 0, mu_agecombine6_A = 0,
mu_male_A = 0, mu_hhincombine1_A = 0, mu_hhincombine9_A = 0,
mu_agecombine1_B = 0, mu_agecombine6_B = 0,
mu_male_B = 0, mu_hhincombine1_B = 0, mu_hhincombine9_B = 0,
# class allocation constants
delta_A = 0, delta_B = 0
)
apollo_fixed = c() # none fixed
# Random draws settings (if used)
#apollo_draws = list(interDrawsType="MLHS", interNDraws=475, interNormDraws=c("draw_asc3_A","draw_asc3_B","draw_asc3_C"))
#apollo_randCoeff = function(apollo_beta, apollo_inputs){
# randcoeff = list()
# randcoeff[["asc3_A"]] = mu_asc3_A + sigma_asc3_A * draw_asc3_A
# randcoeff[["asc3_B"]] = mu_asc3_B + sigma_asc3_B * draw_asc3_B
# randcoeff[["asc3_C"]] = mu_asc3_C + sigma_asc3_C * draw_asc3_C
# return(randcoeff)
#}
# ---------------------------
# Build attend_matrix (ANA patterns)
# attribute_count = 3
# Here: columns correspond to [incentive, passport, size] (same order as your code)
# ---------------------------
attribute_count = 3
attend_vector = c(0,1)
attend_matrix = expand.grid(replicate(attribute_count, attend_vector, simplify=FALSE))
colnames(attend_matrix) <- c("attend_incentive","attend_passport","attend_size")
# ---------------------------
# Create apollo_inputs properly (must include database)
# ---------------------------
apollo_inputs = apollo_validateInputs()
apollo_inputs$database = database
apollo_inputs$attend_matrix = attend_matrix
# ---------------------------
# Probability function (we compute per-class-per-attendance, combine inner then outer)
# ---------------------------
apollo_probabilities = function(apollo_beta, apollo_inputs, functionality="estimate"){
### Attach parameters and inputs
apollo_attach(apollo_beta, apollo_inputs)
on.exit(apollo_detach(apollo_beta, apollo_inputs))
# Generate random coefficients
#randcoeff = apollo_randCoeff(apollo_beta, apollo_inputs)
# Get attend patterns and dims
attend = apollo_inputs$attend_matrix
nK = nrow(attend) # number of inner attendance patterns
nS = 3 # number of outer classes (A,B,C)
P = list()
# generic MNL settings
mnl_settings = list(
alternatives = c(alt1=1, alt2=2, alt3=3),
avail = list(alt1=1, alt2=1, alt3=1),
choiceVar = choice
)
# We'll compute P_{s,k} for s in 1..3 and k in 1..nK
# store as P[["s1k1"]], etc.
for(k in 1:nK){
# read attendance indicators for this pattern
att_inc = attend[k,"attend_incentive"]
att_pass = attend[k,"attend_passport"]
att_size = attend[k,"attend_size"]
for(s in 1:nS){
# select class-specific base coefficients and apply attendance modifiers where you intended
# Following the pattern in your original code: for class B some coefficients were multiplied by attendance; others left as is.
# Here I follow your original pattern: passport_B and size_C and incentive_A were multiplied by attend matrix when originally coded.
# Implemented as:
if(s==1){ # class A
asc3_s = asc3_A
# asc3_s = randcoeff[["asc3_A"]]
b_passport_s = b_passport_A
b_tele_s = b_tele_A
b_home_s = b_home_A
b_size1_s = b_size1_A
b_size2_s = b_size2_A
b_size3_s = b_size3_A
b_weight1_s = b_weight1_A
b_weight2_s = b_weight2_A
b_weight3_s = b_weight3_A
b_incent1_s = att_inc * b_incentive1_A # in your earlier code incentive in A was multiplied by attend_matrix[k,1]
b_incent2_s = att_inc * b_incentive2_A
b_incent3_s = att_inc * b_incentive3_A
b_extracost_s= b_extracost_A
} else if(s==2){ # class B
asc3_s = asc3_B
# asc3_s = randcoeff[["asc3_B"]]
b_passport_s = att_pass * b_passport_B # earlier you multiplied passport_B by attendance
b_tele_s = b_tele_B
b_home_s = b_home_B
b_size1_s = b_size1_B
b_size2_s = b_size2_B
b_size3_s = b_size3_B
b_weight1_s = b_weight1_B
b_weight2_s = b_weight2_B
b_weight3_s = b_weight3_B
b_incent1_s = b_incentive1_B
b_incent2_s = b_incentive2_B
b_incent3_s = b_incentive3_B
b_extracost_s= b_extracost_B
} else { # class C
asc3_s = asc3_C
# asc3_s = randcoeff[["asc3_C"]]
b_passport_s = b_passport_C
b_tele_s = b_tele_C
b_home_s = b_home_C
# earlier you multiplied size_C by attendance; reflect that:
b_size1_s = att_size * b_size1_C
b_size2_s = att_size * b_size2_C
b_size3_s = att_size * b_size3_C
b_weight1_s = b_weight1_C
b_weight2_s = b_weight2_C
b_weight3_s = b_weight3_C
b_incent1_s = b_incentive1_C
b_incent2_s = b_incentive2_C
b_incent3_s = b_incentive3_C
b_extracost_s= b_extracost_C
}
# Build utilities for alt1, alt2, alt3 following your original formula (replace variable names to match your data)
V = list()
V[["alt1"]] =
b_tele_s * tele_1 +
b_passport_s * passport_1 +
b_home_s * home_1 +
b_size1_s * dummysize1_1 + b_size2_s * dummysize1_2 + b_size3_s * dummysize1_3 +
b_weight1_s * dummyweight1_1 + b_weight2_s * dummyweight1_2 + b_weight3_s * dummyweight1_3 +
b_incent1_s * dummyincentive1_1 + b_incent2_s * dummyincentive1_2 + b_incent3_s * dummyincentive1_3 +
b_extracost_s * extracost1
V[["alt2"]] =
b_tele_s * tele_1 +
b_passport_s * passport_1 +
b_home_s * home_1 +
b_size1_s * dummysize2_1 + b_size2_s * dummysize2_2 + b_size3_s * dummysize2_3 +
b_weight1_s * dummyweight2_1 + b_weight2_s * dummyweight2_2 + b_weight3_s * dummyweight2_3 +
b_incent1_s * dummyincentive2_1 + b_incent2_s * dummyincentive2_2 + b_incent3_s * dummyincentive2_3 +
b_extracost_s * extracost2
V[["alt3"]] = asc3_s # alt3 only has ASC (as in your code)
mnl_settings$utilities = V
# Unique componentName per (s,k) to avoid duplicate warnings
mnl_settings$componentName = paste0("Class_", s, "_k", k)
# within-class probabilities
P[[paste0("Class_", s, "_k", k)]] = apollo_mnl(mnl_settings, functionality)
P[[paste0("Class_", s, "_k", k)]] = apollo_panelProd(P[[paste0("Class_", s, "_k", k)]], apollo_inputs, functionality)
} # end for s
} # end for k
# ------------------------------------------------------------
# Combine over inner ANA (k) to get class-specific probabilities
# ------------------------------------------------------------
# If you want inner class allocation to be estimated with parameters (delta_attend...), you should:
# - define delta_attend_incentive etc in apollo_beta
# - build a utilities list V_inner and call apollo_classAlloc(V_inner)
# For now we use uniform weights across attendance patterns (1/nK).
pi_k = rep(1/nK, nK)
innerP = list()
for(s in 1:3){
# sum over k: pi_k[k] * P_s_k
tmp = 0
for(k in 1:nK){
tmp = tmp + pi_k[k] * P[[paste0("Class_", s, "_k", k)]]
}
innerP[[paste0("Class_", s)]] = tmp
}
# ------------------------------------------------------------
# Outer class allocation (use soc-demo variables as utilities)
# ------------------------------------------------------------
# Build utilities named to match innerP list names
V_outer = list()
V_outer[["Class_1"]] = delta_A + mu_agecombine1_A * age_combine_1 + mu_agecombine6_A*age_combine_6 + mu_male_A*gender_1 + mu_hhincombine1_A*hh_income_combine_1 + mu_hhincombine9_A*hh_income_combine_9
V_outer[["Class_2"]] = delta_B + mu_agecombine1_B * age_combine_1 + mu_agecombine6_B*age_combine_6 + mu_male_B*gender_1 + mu_hhincombine1_B*hh_income_combine_1 + mu_hhincombine9_B*hh_income_combine_9
V_outer[["Class_3"]] = 0
# classAlloc must have classes names matching innerP names
classAlloc_settings = list(classes = c(Class_1=1, Class_2=2, Class_3=3), utilities = V_outer)
pi_values_s = apollo_classAlloc(classAlloc_settings)
# ------------------------------------------------------------
# Combine innerP (inClassProb) with outer classProb
# ------------------------------------------------------------
lc_settings = list(inClassProb = innerP, classProb = pi_values_s)
P[["choice"]] = apollo_lc(lc_settings, apollo_inputs, functionality)
# combine & prepare
P = apollo_combineModels(P, apollo_inputs, functionality, components = c("choice"))
# P = apollo_avgInterDraws(P, apollo_inputs, functionality)
P = apollo_prepareProb(P, apollo_inputs, functionality)
return(P)
}
# ---------------------------
# Quick check: compute LL at starting values
# ---------------------------
apollo_llCalc(apollo_beta, apollo_probabilities, apollo_inputs)
# ---------------------------
# Estimate model
# ---------------------------
model = apollo_estimate(apollo_beta, apollo_fixed, apollo_probabilities, apollo_inputs,
estimate_settings = list(estimationRoutine = "BFGS", maxIterations = 1000))
# Output
apollo_modelOutput(model)
apollo_saveOutput(model)
##############################################################################
Best regards,
kiki
-
stephanehess
- Site Admin
- Posts: 1330
- Joined: 24 Apr 2020, 16:29
Re: Nested Latent Class Model
Hi
did you look an AI tool for generating this. Tools like chatgpt are not that great at generating Apollo code (yet).
If you share the code and data with me by e-mail, I'll look into it for you
Stephane
did you look an AI tool for generating this. Tools like chatgpt are not that great at generating Apollo code (yet).
If you share the code and data with me by e-mail, I'll look into it for you
Stephane