Latent Class Joint Model
Posted: 26 Feb 2021, 13:02
Hello everyone,
I have a new data set with dual response, i.e. the data set contains forced choices on the one hand, but also free choices where the alternative selected first is compared to a none option. Now I have learned that the scale parameter may differ for these two data sets. Therefore, I estimated a MNL and MIXL model with a parameter "mu_CBC" and "mu_DR", respectively, to capture these differences. In fact, in these joint models mu_CBC is significantly greater than one, meaning that scale differs.
Now I wanted to estimate a Latent Class model (using HB or classical estimation). The problem I encountered is that unlike the models covered in the manual, the submodels can no longer simply be written into a list (namely "P"), but I have submodels in the classes (or do I actually have classes in the submodels? I hope my assumption is correct - otherwise please correct me).
I solved the problem by creating a second list “P.componentName” in the while loop, that is while iterating over the classes. This list in then used for apollo_combineModels().
My apollo_probabilities() function for HB looks like this:
For classical model estimation using MSL, it looks like this:
I just wanted to make sure I did not make a mistake in my model specification.
In particular, I wanted to ask if the multiplication by mu_CBC and mu_DR is still correct for taking into account differences in scale?
I am looking forward to your answers.
Best
Nico
I have a new data set with dual response, i.e. the data set contains forced choices on the one hand, but also free choices where the alternative selected first is compared to a none option. Now I have learned that the scale parameter may differ for these two data sets. Therefore, I estimated a MNL and MIXL model with a parameter "mu_CBC" and "mu_DR", respectively, to capture these differences. In fact, in these joint models mu_CBC is significantly greater than one, meaning that scale differs.
Now I wanted to estimate a Latent Class model (using HB or classical estimation). The problem I encountered is that unlike the models covered in the manual, the submodels can no longer simply be written into a list (namely "P"), but I have submodels in the classes (or do I actually have classes in the submodels? I hope my assumption is correct - otherwise please correct me).
I solved the problem by creating a second list “P.componentName” in the while loop, that is while iterating over the classes. This list in then used for apollo_combineModels().
My apollo_probabilities() function for HB looks like this:
Code: Select all
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()
### Loop over classes
s=1
while(s<=2){
### Create list of probabilities P.componentName
P.componentName <- list()
### Compute class-specific utilities
V = list()
### CBC (Forced Choices)
V[['alt1']] = b_asc_1 +
b_Quota_Count_15[[s]] * Quota_Count2.1 + b_Quota_Count_25[[s]] * Quota_Count3.1 + b_Quota_Count_35[[s]] * Quota_Count4.1 +
b_Quota_Max_Duration_1h[[s]] * Quota_Max_Duration2.1 + b_Quota_Max_Duration_2h[[s]] * Quota_Max_Duration3.1 + b_Quota_Max_Duration_3h[[s]] * Quota_Max_Duration4.1 +
b_Quota_Period_midmorning[[s]] * Quota_Period2.1 + b_Quota_Period_afternoon[[s]] * Quota_Period3.1 + b_Quota_Period_evening[[s]] * Quota_Period4.1 + b_Quota_Period_night[[s]] * Quota_Period5.1 +
b_Quota_Compensation[[s]] * Quota_Compensation.1
V[['alt2']] = b_asc_2 +
b_Quota_Count_15[[s]] * Quota_Count2.2 + b_Quota_Count_25[[s]] * Quota_Count3.2 + b_Quota_Count_35[[s]] * Quota_Count4.2 +
b_Quota_Max_Duration_1h[[s]] * Quota_Max_Duration2.2 + b_Quota_Max_Duration_2h[[s]] * Quota_Max_Duration3.2 + b_Quota_Max_Duration_3h[[s]] * Quota_Max_Duration4.2 +
b_Quota_Period_midmorning[[s]] * Quota_Period2.2 + b_Quota_Period_afternoon[[s]] * Quota_Period3.2 + b_Quota_Period_evening[[s]] * Quota_Period4.2 + b_Quota_Period_night[[s]] * Quota_Period5.2 +
b_Quota_Compensation[[s]] * Quota_Compensation.2
V[['alt3']] = b_asc_3 +
b_Quota_Count_15[[s]] * Quota_Count2.3 + b_Quota_Count_25[[s]] * Quota_Count3.3 + b_Quota_Count_35[[s]] * Quota_Count4.3 +
b_Quota_Max_Duration_1h[[s]] * Quota_Max_Duration2.3 + b_Quota_Max_Duration_2h[[s]] * Quota_Max_Duration3.3 + b_Quota_Max_Duration_3h[[s]] * Quota_Max_Duration4.3 +
b_Quota_Period_midmorning[[s]] * Quota_Period2.3 + b_Quota_Period_afternoon[[s]] * Quota_Period3.3 + b_Quota_Period_evening[[s]] * Quota_Period4.3 + b_Quota_Period_night[[s]] * Quota_Period5.3 +
b_Quota_Compensation[[s]] * Quota_Compensation.3
curr.componentName = paste("CBC_", toString(s), sep="")
mnl_settings = list(
alternatives = c(alt1=1, alt2=2, alt3=3),
avail = list(alt1=1, alt2=1, alt3=1),
choiceVar = Choice,
V = lapply(V, "*", mu_CBC),
rows = (CBC_type=="R"),
componentName = curr.componentName
)
### Compute within-class choice probabilities using MNL model
P.componentName[[curr.componentName]] = apollo_mnl(mnl_settings, functionality)
# ### Take product across observation for same individual
# P.componentName[[curr.componentName]] = apollo_panelProd(P[[s]], apollo_inputs ,functionality)
#
# ### Average across inter-individual draws within classes
# P.componentName[[curr.componentName]] = apollo_avgInterDraws(P[[s]], apollo_inputs, functionality)
### DR (Free Choices)
V[['alt0']] = 0
V[['alt1']] = b_DR_asc_1[[s]] +
b_Quota_Count_15[[s]] * Quota_Count2.1 + b_Quota_Count_25[[s]] * Quota_Count3.1 + b_Quota_Count_35[[s]] * Quota_Count4.1 +
b_Quota_Max_Duration_1h[[s]] * Quota_Max_Duration2.1 + b_Quota_Max_Duration_2h[[s]] * Quota_Max_Duration3.1 + b_Quota_Max_Duration_3h[[s]] * Quota_Max_Duration4.1 +
b_Quota_Period_midmorning[[s]] * Quota_Period2.1 + b_Quota_Period_afternoon[[s]] * Quota_Period3.1 + b_Quota_Period_evening[[s]] * Quota_Period4.1 + b_Quota_Period_night[[s]] * Quota_Period5.1 +
b_Quota_Compensation[[s]] * Quota_Compensation.1
curr.componentName = paste("CBC_DR_", toString(s), sep="")
mnl_settings = list(
alternatives = c(alt0=0, alt1=1),
avail = list(alt0=1, alt1=1),
choiceVar = Choice,
V = lapply(V, "*", mu_DR),
rows = (CBC_type=="RD"),
componentName = curr.componentName
)
### Compute within-class choice probabilities using MNL model
P.componentName[[curr.componentName]] = apollo_mnl(mnl_settings, functionality)
# ### Take product across observation for same individual
# P.componentName[[curr.componentName]] = apollo_panelProd(P[[s]], apollo_inputs ,functionality)
#
# ### Average across inter-individual draws within classes
# P.componentName[[curr.componentName]] = apollo_avgInterDraws(P[[s]], apollo_inputs, functionality)
### Combined model
P[[s]] = apollo_combineModels(P.componentName, 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)
}
Code: Select all
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()
### Loop over classes
s=1
while(s<=2){
### Create list of probabilities P.componentName
P.componentName <- list()
### Compute class-specific utilities
V = list()
### CBC (Forced Choices)
V[['alt1']] = b_asc_1 +
b_Quota_Count_15[[s]] * Quota_Count2.1 + b_Quota_Count_25[[s]] * Quota_Count3.1 + b_Quota_Count_35[[s]] * Quota_Count4.1 +
b_Quota_Max_Duration_1h[[s]] * Quota_Max_Duration2.1 + b_Quota_Max_Duration_2h[[s]] * Quota_Max_Duration3.1 + b_Quota_Max_Duration_3h[[s]] * Quota_Max_Duration4.1 +
b_Quota_Period_midmorning[[s]] * Quota_Period2.1 + b_Quota_Period_afternoon[[s]] * Quota_Period3.1 + b_Quota_Period_evening[[s]] * Quota_Period4.1 + b_Quota_Period_night[[s]] * Quota_Period5.1 +
b_Quota_Compensation[[s]] * Quota_Compensation.1
V[['alt2']] = b_asc_2 +
b_Quota_Count_15[[s]] * Quota_Count2.2 + b_Quota_Count_25[[s]] * Quota_Count3.2 + b_Quota_Count_35[[s]] * Quota_Count4.2 +
b_Quota_Max_Duration_1h[[s]] * Quota_Max_Duration2.2 + b_Quota_Max_Duration_2h[[s]] * Quota_Max_Duration3.2 + b_Quota_Max_Duration_3h[[s]] * Quota_Max_Duration4.2 +
b_Quota_Period_midmorning[[s]] * Quota_Period2.2 + b_Quota_Period_afternoon[[s]] * Quota_Period3.2 + b_Quota_Period_evening[[s]] * Quota_Period4.2 + b_Quota_Period_night[[s]] * Quota_Period5.2 +
b_Quota_Compensation[[s]] * Quota_Compensation.2
V[['alt3']] = b_asc_3 +
b_Quota_Count_15[[s]] * Quota_Count2.3 + b_Quota_Count_25[[s]] * Quota_Count3.3 + b_Quota_Count_35[[s]] * Quota_Count4.3 +
b_Quota_Max_Duration_1h[[s]] * Quota_Max_Duration2.3 + b_Quota_Max_Duration_2h[[s]] * Quota_Max_Duration3.3 + b_Quota_Max_Duration_3h[[s]] * Quota_Max_Duration4.3 +
b_Quota_Period_midmorning[[s]] * Quota_Period2.3 + b_Quota_Period_afternoon[[s]] * Quota_Period3.3 + b_Quota_Period_evening[[s]] * Quota_Period4.3 + b_Quota_Period_night[[s]] * Quota_Period5.3 +
b_Quota_Compensation[[s]] * Quota_Compensation.3
curr.componentName = paste("CBC_", toString(s), sep="")
mnl_settings = list(
alternatives = c(alt1=1, alt2=2, alt3=3),
avail = list(alt1=1, alt2=1, alt3=1),
choiceVar = Choice,
V = lapply(V, "*", mu_CBC),
rows = (CBC_type=="R"),
componentName = curr.componentName
)
### Compute within-class choice probabilities using MNL model
P.componentName[[curr.componentName]] = apollo_mnl(mnl_settings, functionality)
### Take product across observation for same individual
P.componentName[[curr.componentName]] = apollo_panelProd(P.componentName[[curr.componentName]], apollo_inputs ,functionality)
### Average across inter-individual draws within classes
P.componentName[[curr.componentName]] = apollo_avgInterDraws(P.componentName[[curr.componentName]], apollo_inputs, functionality)
### DR (Free Choices)
V[['alt0']] = 0
V[['alt1']] = b_DR_asc_1[[s]] +
b_Quota_Count_15[[s]] * Quota_Count2.1 + b_Quota_Count_25[[s]] * Quota_Count3.1 + b_Quota_Count_35[[s]] * Quota_Count4.1 +
b_Quota_Max_Duration_1h[[s]] * Quota_Max_Duration2.1 + b_Quota_Max_Duration_2h[[s]] * Quota_Max_Duration3.1 + b_Quota_Max_Duration_3h[[s]] * Quota_Max_Duration4.1 +
b_Quota_Period_midmorning[[s]] * Quota_Period2.1 + b_Quota_Period_afternoon[[s]] * Quota_Period3.1 + b_Quota_Period_evening[[s]] * Quota_Period4.1 + b_Quota_Period_night[[s]] * Quota_Period5.1 +
b_Quota_Compensation[[s]] * Quota_Compensation.1
curr.componentName = paste("CBC_DR_", toString(s), sep="")
mnl_settings = list(
alternatives = c(alt0=0, alt1=1),
avail = list(alt0=1, alt1=1),
choiceVar = Choice,
V = lapply(V, "*", mu_DR),
rows = (CBC_type=="RD"),
componentName = curr.componentName
)
### Compute within-class choice probabilities using MNL model
P.componentName[[curr.componentName]] = apollo_mnl(mnl_settings, functionality)
### Take product across observation for same individual
P.componentName[[curr.componentName]] = apollo_panelProd(P.componentName[[curr.componentName]], apollo_inputs ,functionality)
### Average across inter-individual draws within classes
P.componentName[[curr.componentName]] = apollo_avgInterDraws(P.componentName[[curr.componentName]], apollo_inputs, functionality)
### Combined model
P[[s]] = apollo_combineModels(P.componentName, 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)
}
In particular, I wanted to ask if the multiplication by mu_CBC and mu_DR is still correct for taking into account differences in scale?
I am looking forward to your answers.
Best
Nico
