Adults
Main model
To test the effect of nameability on category learning, we predicted
participants’ trial-by-trial accuracy on training trials from Condition
(centered; Low Nameability = -0.5, High Nameability = 0.5), Block Number
(centered) and Experiment Round (centered), and all interactions between
the three predictors in a logistic mixed-effects model. We fit the model
with the maximal by-subject random effects structure, including a
by-subject intercept and a by-subject random slopes for Block Number,
Experiment Round, and their interaction.
#### training modeling ####
m <- glmer(is_right~condition_c*block_c*round_c+(1+block_c*round_c|subject), data=subset(d, age_group=="adult" & trial_kind=="learn"), family=binomial,glmerControl(optimizer="bobyqa"))
summary(m)
## Generalized linear mixed model fit by maximum likelihood (Laplace
## Approximation) [glmerMod]
## Family: binomial ( logit )
## Formula: is_right ~ condition_c * block_c * round_c + (1 + block_c * round_c |
## subject)
## Data: subset(d, age_group == "adult" & trial_kind == "learn")
## Control: glmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 2108.3 2223.0 -1036.2 2072.3 4302
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -8.2258 0.0710 0.1549 0.3037 1.0864
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## subject (Intercept) 1.6816 1.2968
## block_c 0.3381 0.5815 1.00
## round_c 0.4148 0.6440 0.85 0.85
## block_c:round_c 0.4582 0.6769 0.17 0.17 -0.37
## Number of obs: 4320, groups: subject, 90
##
## Fixed effects:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) 3.5775 0.2253 15.882 < 2e-16 ***
## condition_c 1.6758 0.3634 4.611 4.01e-06 ***
## block_c 1.2632 0.2027 6.233 4.57e-10 ***
## round_c 1.2565 0.3191 3.937 8.24e-05 ***
## condition_c:block_c 0.5556 0.2675 2.077 0.0378 *
## condition_c:round_c 0.3679 0.3990 0.922 0.3565
## block_c:round_c -0.2288 0.3563 -0.642 0.5208
## condition_c:block_c:round_c -0.1765 0.4473 -0.394 0.6932
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) cndtn_ blck_c rond_c cndtn_c:b_ cndtn_c:r_ blc_:_
## condition_c 0.274
## block_c 0.765 0.241
## round_c 0.521 0.137 0.417
## cndtn_c:bl_ 0.274 0.730 0.408 0.110
## cndtn_c:rn_ 0.187 0.466 0.139 0.420 0.302
## blck_c:rnd_ 0.301 0.068 0.502 0.681 0.170 0.282
## cndtn_c:_:_ 0.084 0.119 0.181 0.267 0.299 0.422 0.399
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
#Anova(m, type="III") # chi-squared test yields virtually identical results
confint(m, method="Wald")[11:18,]
## 2.5 % 97.5 %
## (Intercept) 3.13606404 4.0190322
## condition_c 0.96348822 2.3881622
## block_c 0.86602702 1.6604334
## round_c 0.63102772 1.8819361
## condition_c:block_c 0.03132518 1.0798923
## condition_c:round_c -0.41417325 1.1499622
## block_c:round_c -0.92722203 0.4695611
## condition_c:block_c:round_c -1.05315796 0.7002500
coefs <- summary(m)$coef %>%
as_tibble %>%
mutate_at(c("Estimate","Std. Error", "z value", "Pr(>|z|)"),
function (x) signif(x, digits = 3)) %>%
rename(SE = `Std. Error`,
z = `z value`,
p = `Pr(>|z|)`)
rownames(coefs) <- c("Intercept", "Condition", "Block Number", "Round",
"Condition * Block Number","Condition * Round", "Block Number * Round",
"Condition * Block Number * Round")
write.table(coefs, file=here::here(model_output_path,"adult_lme_model_output.csv"),sep=",")
Simplified random effects
While the model with the full random effects had a singular fit,
simplifying the random effects structure did not meaningfully affect the
main pattern of results from the model. Below, we successively prune
random effects until no singular fit is obtained. The simplified model
yields highly similar results to the model with the full random effects
structure.
#remove round random slope
#m <- glmer(is_right~condition_c*block_c*round_c+(1+block_c+block_c:round_c|subject), data=filter(d, age_group=="adult" & trial_kind=="learn"), family=binomial,glmerControl(optimizer="bobyqa"))
#model still yields a singular fit
#remove random slope for block
#m <- glmer(is_right~condition_c*block_c*round_c+(1+round_c+block_c:round_c|subject), data=filter(d, age_group=="adult" & trial_kind=="learn"), family=binomial,glmerControl(optimizer="bobyqa"))
#model still yields a singular fit
#remove both round and block random slopes
m <- glmer(is_right~condition_c*block_c*round_c+(1+block_c:round_c|subject), data=filter(d, age_group=="adult" & trial_kind=="learn"), family=binomial,glmerControl(optimizer="bobyqa"))
summary(m)
## Generalized linear mixed model fit by maximum likelihood (Laplace
## Approximation) [glmerMod]
## Family: binomial ( logit )
## Formula: is_right ~ condition_c * block_c * round_c + (1 + block_c:round_c |
## subject)
## Data: filter(d, age_group == "adult" & trial_kind == "learn")
## Control: glmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 2123.8 2193.9 -1050.9 2101.8 4309
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -9.8287 0.0971 0.1716 0.3055 1.2036
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## subject (Intercept) 0.9409 0.970
## block_c:round_c 0.8705 0.933 -0.50
## Number of obs: 4320, groups: subject, 90
##
## Fixed effects:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) 3.2404 0.1547 20.949 < 2e-16 ***
## condition_c 1.6122 0.2835 5.688 1.29e-08 ***
## block_c 0.8065 0.1034 7.796 6.39e-15 ***
## round_c 0.7487 0.1761 4.251 2.13e-05 ***
## condition_c:block_c 0.5104 0.2065 2.472 0.01343 *
## condition_c:round_c 0.2986 0.3517 0.849 0.39595
## block_c:round_c -0.8532 0.2847 -2.997 0.00272 **
## condition_c:block_c:round_c -0.2263 0.4776 -0.474 0.63560
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) cndtn_ blck_c rond_c cndtn_c:b_ cndtn_c:r_ blc_:_
## condition_c 0.293
## block_c 0.298 0.267
## round_c 0.156 0.128 0.055
## cndtn_c:bl_ 0.233 0.328 0.618 0.069
## cndtn_c:rn_ 0.118 0.164 0.070 0.644 0.053
## blck_c:rnd_ -0.281 -0.011 0.237 0.394 0.169 0.304
## cndtn_c:_:_ -0.012 -0.183 0.195 0.372 0.247 0.450 0.457
#note that the round by block interaction now becomes significant after removing the random slopes - this effect is not of particular theoretical interest in the current study.
Plot
#summarize by block
adult_training_by_block <- d %>%
filter(age_group=="adult" & trial_kind=="learn") %>%
group_by(subject,condition,round,block) %>%
summarize(accuracy=mean(is_right)) %>%
summarySEwithin(measurevar="accuracy",betweenvars=c("condition"),withinvars=c("round","block"),idvar="subject") %>%
mutate(round_factor = case_when(
round=="1" ~ "Round 1",
round=="2" ~ "Round 2"
)) %>%
mutate(
lower_ci = accuracy - ci,
upper_ci = accuracy + ci
)
# show by block learning accuracy as a table
adult_training_by_block %>%
select(condition,N,round,block,accuracy,lower_ci,upper_ci) %>%
kable(digits=3)
| high |
45 |
1 |
1 |
0.856 |
0.814 |
0.897 |
| high |
45 |
1 |
2 |
0.972 |
0.954 |
0.990 |
| high |
45 |
1 |
3 |
0.983 |
0.971 |
0.996 |
| high |
45 |
2 |
1 |
0.961 |
0.937 |
0.985 |
| high |
45 |
2 |
2 |
0.989 |
0.977 |
1.001 |
| high |
45 |
2 |
3 |
0.989 |
0.974 |
1.004 |
| low |
45 |
1 |
1 |
0.739 |
0.701 |
0.777 |
| low |
45 |
1 |
2 |
0.861 |
0.829 |
0.893 |
| low |
45 |
1 |
3 |
0.917 |
0.891 |
0.942 |
| low |
45 |
2 |
1 |
0.881 |
0.845 |
0.916 |
| low |
45 |
2 |
2 |
0.908 |
0.883 |
0.934 |
| low |
45 |
2 |
3 |
0.933 |
0.906 |
0.960 |
#learning phase
ggplot(adult_training_by_block, aes(block,accuracy,color=condition,group=condition))+
geom_line(aes(linetype=condition),position=position_dodge(0.1),size=1.3)+
geom_point(aes(shape=condition),position=position_dodge(0.1),size=2.5)+
geom_errorbar(aes(ymin=accuracy-se,ymax=accuracy+se),width=0,size=0.5,position=position_dodge(.1))+
xlab("Block")+
ylab("Accuracy")+
scale_linetype_discrete(name="Nameability")+
scale_shape_discrete(name="Nameability")+
scale_color_brewer(palette="Set1",name="Nameability")+
#ggtitle("Performance during training")+
geom_hline(yintercept=0.5, linetype="dashed",size=1)+
theme(legend.position=c(0.3,0.3))+
theme(text=element_text(size=18))+
theme(strip.text.x = element_text(size=16), plot.background = element_rect(fill="white",color="white"))+
facet_wrap(~round_factor)+
ylim(0,1)

ggsave(here::here("figures","adults_training_half.png"),width=8, height=5,dpi=600)
Overall Accuracy
adult_training_summarized <- adult_subj %>%
group_by(condition) %>%
summarize(
N=n(),
avg_accuracy = mean(mean_learning_accuracy),
avg_accuracy_ci = qt(0.975, N-1)*sd(mean_learning_accuracy,na.rm=TRUE)/sqrt(N),
avg_accuracy_lower_ci = avg_accuracy - avg_accuracy_ci,
avg_accuracy_upper_ci = avg_accuracy + avg_accuracy_ci,
)
adult_training_summarized %>%
select(-avg_accuracy_ci) %>%
mutate(
ci = str_c("[",round(avg_accuracy_lower_ci,3),", ", round(avg_accuracy_upper_ci,3),"]")) %>%
select(condition,N,avg_accuracy,ci) %>%
kable(col.names=c("Condition", "N", "Average Accuracy","CI"),digits=3)
| high |
45 |
0.958 |
[0.947, 0.97] |
| low |
45 |
0.873 |
[0.841, 0.905] |
#effect size
cohens_d(mean_learning_accuracy ~ condition,data=adult_subj)
## Cohen's d | 95% CI
## ------------------------
## 1.06 | [0.61, 1.50]
##
## - Estimated using pooled SD.
Children
Main model
To test the effect of nameability on category learning, we predicted
participants’ trial-by-trial accuracy on training trials from Condition
(centered; Low Nameability = -0.5, High Nameability = 0.5), Block Number
(centered) and Experiment Round (centered), and all interactions between
the three predictors in a logistic mixed-effects model. We fit the model
with the maximal by-subject random effects structure, including a
by-subject intercept and a by-subject random slopes for Block Number,
Experiment Round, and their interaction.
#### training modeling ####
m <- glmer(
is_right~condition_c*block_c*round_c+(1+block_c*round_c|subject),
data=filter(d, age_group=="kid" & trial_kind=="learn"),
family=binomial,
glmerControl(optimizer="bobyqa"))
summary(m)
## Generalized linear mixed model fit by maximum likelihood (Laplace
## Approximation) [glmerMod]
## Family: binomial ( logit )
## Formula: is_right ~ condition_c * block_c * round_c + (1 + block_c * round_c |
## subject)
## Data: filter(d, age_group == "kid" & trial_kind == "learn")
## Control: glmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 5520.5 5636.5 -2742.3 5484.5 4638
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -4.6099 -1.0710 0.4750 0.7436 1.1249
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## subject (Intercept) 0.64208 0.8013
## block_c 0.03008 0.1734 0.58
## round_c 0.35489 0.5957 0.87 0.91
## block_c:round_c 0.06064 0.2462 -0.82 -0.94 -1.00
## Number of obs: 4656, groups: subject, 97
##
## Fixed effects:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) 0.93598 0.09001 10.399 < 2e-16 ***
## condition_c 0.27810 0.17796 1.563 0.11812
## block_c 0.12478 0.04902 2.545 0.01092 *
## round_c 0.45523 0.09683 4.701 2.58e-06 ***
## condition_c:block_c 0.23083 0.08951 2.579 0.00992 **
## condition_c:round_c 0.06553 0.18327 0.358 0.72065
## block_c:round_c -0.25631 0.09482 -2.703 0.00687 **
## condition_c:block_c:round_c -0.11709 0.17181 -0.681 0.49557
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) cndtn_ blck_c rond_c cndtn_c:b_ cndtn_c:r_ blc_:_
## condition_c 0.005
## block_c 0.212 0.016
## round_c 0.571 0.006 0.181
## cndtn_c:bl_ 0.015 0.230 0.048 -0.002
## cndtn_c:rn_ 0.006 0.575 0.002 0.033 0.229
## blck_c:rnd_ -0.214 0.001 0.094 -0.131 0.020 0.030
## cndtn_c:_:_ 0.000 -0.236 0.019 0.029 -0.039 -0.174 0.051
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
#Anova(m, type="III") # chi-squared test yields virtually identical results
confint(m, method="Wald")[11:18,]
## 2.5 % 97.5 %
## (Intercept) 0.75956687 1.11239528
## condition_c -0.07069404 0.62689610
## block_c 0.02869696 0.22087051
## round_c 0.26544627 0.64500576
## condition_c:block_c 0.05538923 0.40627317
## condition_c:round_c -0.29365852 0.42472752
## block_c:round_c -0.44214751 -0.07047936
## condition_c:block_c:round_c -0.45382935 0.21965776
coefs <- summary(m)$coef %>%
as_tibble %>%
mutate_at(c("Estimate","Std. Error", "z value", "Pr(>|z|)"),
function (x) signif(x, digits = 3)) %>%
rename(SE = `Std. Error`,
z = `z value`,
p = `Pr(>|z|)`)
rownames(coefs) <- c("Intercept", "Condition", "Block Number", "Round",
"Condition * Block Number","Condition * Round", "Block Number * Round",
"Condition * Block Number * Round")
write.table(coefs, file=here::here(model_output_path,"kid_lme_model_output.csv"),sep=",")
Simplified random effects
While the model with the full random effects had a singular fit,
simplifying the random effects structure did not meaningfully affect the
pattern of results from the model. Below, we successively prune random
effects until no singular fit is obtained. The simplified model yields
highly similar results to the model with the full random effects
structure.
#remove block and round random slopes
#m <- glmer(is_right~condition_c*block_c*round_c+(1+block_c:round_c|subject), data=filter(d, age_group=="kid" & trial_kind=="learn"), family=binomial,glmerControl(optimizer="bobyqa"))
#model still yields a singular fit
# remove interaction random effect
#m <- glmer(is_right~condition_c*block_c*round_c+(1+block_c+round_c|subject), data=filter(d, age_group=="kid" & trial_kind=="learn"), family=binomial,glmerControl(optimizer="bobyqa"))
# model still yields a singular fit
# retain only the block random slope
m <- glmer(is_right~condition_c*block_c*round_c+(1+block_c|subject), data=filter(d, age_group=="kid" & trial_kind=="learn"), family=binomial,glmerControl(optimizer="bobyqa"))
summary(m)
## Generalized linear mixed model fit by maximum likelihood (Laplace
## Approximation) [glmerMod]
## Family: binomial ( logit )
## Formula: is_right ~ condition_c * block_c * round_c + (1 + block_c | subject)
## Data: filter(d, age_group == "kid" & trial_kind == "learn")
## Control: glmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 5546.9 5617.8 -2762.5 5524.9 4645
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -4.0321 -1.0877 0.4765 0.7242 1.1829
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## subject (Intercept) 0.53648 0.7324
## block_c 0.02246 0.1499 0.89
## Number of obs: 4656, groups: subject, 97
##
## Fixed effects:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) 0.89129 0.08268 10.779 < 2e-16 ***
## condition_c 0.25865 0.16408 1.576 0.11494
## block_c 0.14694 0.04621 3.180 0.00147 **
## round_c 0.30377 0.06622 4.587 4.49e-06 ***
## condition_c:block_c 0.22574 0.08710 2.592 0.00955 **
## condition_c:round_c 0.02884 0.13236 0.218 0.82753
## block_c:round_c -0.22863 0.08116 -2.817 0.00484 **
## condition_c:block_c:round_c -0.12816 0.16216 -0.790 0.42935
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) cndtn_ blck_c rond_c cndtn_c:b_ cndtn_c:r_ blc_:_
## condition_c 0.001
## block_c 0.311 0.016
## round_c 0.022 0.003 -0.025
## cndtn_c:bl_ 0.014 0.310 0.038 -0.005
## cndtn_c:rn_ 0.003 0.019 -0.007 0.034 -0.021
## blck_c:rnd_ -0.011 -0.003 0.047 0.043 0.004 0.029
## cndtn_c:_:_ -0.004 -0.011 0.004 0.029 0.037 0.044 0.034
Block 3
We tested for a condition difference in block 3 for both round 1 and
round 2 by subsetting the data to the relevant block and predicting
correct responses from condition in a logistic mixed-effects model.
Block 3, Round 1
#block 3, round 1
m=glmer(is_right~condition_c+(1|subject), data=filter(d, age_group=="kid" & trial_kind=="learn"& block==3 & round==1), family=binomial,glmerControl(optimizer="bobyqa"))
summary(m)
## Generalized linear mixed model fit by maximum likelihood (Laplace
## Approximation) [glmerMod]
## Family: binomial ( logit )
## Formula: is_right ~ condition_c + (1 | subject)
## Data: filter(d, age_group == "kid" & trial_kind == "learn" & block ==
## 3 & round == 1)
## Control: glmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 947.4 961.4 -470.7 941.4 773
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -1.9877 -1.0659 0.5031 0.6396 1.0437
##
## Random effects:
## Groups Name Variance Std.Dev.
## subject (Intercept) 0.3712 0.6093
## Number of obs: 776, groups: subject, 97
##
## Fixed effects:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) 0.8694 0.1052 8.261 < 2e-16 ***
## condition_c 0.5517 0.2051 2.690 0.00715 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr)
## condition_c 0.062
confint(m, method="Wald")[2:3,]
## 2.5 % 97.5 %
## (Intercept) 0.6631645 1.0757091
## condition_c 0.1497043 0.9536001
Block 3, Round 2
#block 3, round 2
m=glmer(is_right~condition_c+(1|subject), data=filter(d, age_group=="kid" & trial_kind=="learn" & block==3 & round==2), family=binomial,glmerControl(optimizer="bobyqa"))
summary(m)
## Generalized linear mixed model fit by maximum likelihood (Laplace
## Approximation) [glmerMod]
## Family: binomial ( logit )
## Formula: is_right ~ condition_c + (1 | subject)
## Data: filter(d, age_group == "kid" & trial_kind == "learn" & block ==
## 3 & round == 2)
## Control: glmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 913.0 926.9 -453.5 907.0 773
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.1515 -1.0418 0.4648 0.6399 0.9723
##
## Random effects:
## Groups Name Variance Std.Dev.
## subject (Intercept) 0.5826 0.7633
## Number of obs: 776, groups: subject, 97
##
## Fixed effects:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) 1.0235 0.1199 8.533 <2e-16 ***
## condition_c 0.5268 0.2306 2.285 0.0223 *
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr)
## condition_c 0.063
confint(m, method="Wald")[2:3,]
## 2.5 % 97.5 %
## (Intercept) 0.78840742 1.2585682
## condition_c 0.07488766 0.9787954
Controlling for Age/ Interaction with Age
We also checked if any of these effects interact with children’s age.
We fit the same model structure while including age (centered) as a
fixed effect, as well as the interaction between age and all other fixed
effect terms. Overall, accuracy increased with age, but there was no
interaction between age and any of the other model terms. All of the
lower-order effects observed in the main model remained significant.
#### training modeling ####
m <- glmer(
is_right~condition_c*block_c*round_c*age_c+(1+block_c*round_c|subject),
data=filter(d, age_group=="kid" & trial_kind=="learn"),
family=binomial,
glmerControl(optimizer="bobyqa"))
summary(m)
## Generalized linear mixed model fit by maximum likelihood (Laplace
## Approximation) [glmerMod]
## Family: binomial ( logit )
## Formula: is_right ~ condition_c * block_c * round_c * age_c + (1 + block_c *
## round_c | subject)
## Data: filter(d, age_group == "kid" & trial_kind == "learn")
## Control: glmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 5456.1 5623.5 -2702.1 5404.1 4582
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -4.5009 -1.0636 0.4673 0.7393 1.1258
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## subject (Intercept) 0.56228 0.7499
## block_c 0.02762 0.1662 0.52
## round_c 0.33671 0.5803 0.85 0.89
## block_c:round_c 0.05306 0.2303 -0.80 -0.93 -0.99
## Number of obs: 4608, groups: subject, 96
##
## Fixed effects:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) 0.969383 0.086729 11.177 < 2e-16 ***
## condition_c 0.251116 0.171113 1.468 0.142227
## block_c 0.125883 0.050122 2.512 0.012022 *
## round_c 0.475341 0.098168 4.842 1.28e-06 ***
## age_c 0.040810 0.012193 3.347 0.000816 ***
## condition_c:block_c 0.235856 0.091420 2.580 0.009882 **
## condition_c:round_c 0.052202 0.185587 0.281 0.778497
## block_c:round_c -0.260938 0.097175 -2.685 0.007248 **
## condition_c:age_c 0.004498 0.024327 0.185 0.853300
## block_c:age_c 0.008583 0.006528 1.315 0.188597
## round_c:age_c 0.021706 0.013196 1.645 0.099989 .
## condition_c:block_c:round_c -0.140930 0.175911 -0.801 0.423049
## condition_c:block_c:age_c 0.002529 0.012857 0.197 0.844075
## condition_c:round_c:age_c 0.013985 0.026134 0.535 0.592564
## block_c:round_c:age_c -0.011247 0.012565 -0.895 0.370741
## condition_c:block_c:round_c:age_c -0.022898 0.024704 -0.927 0.353993
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
confint(m, method="Wald")
## 2.5 % 97.5 %
## .sig01 NA NA
## .sig02 NA NA
## .sig03 NA NA
## .sig04 NA NA
## .sig05 NA NA
## .sig06 NA NA
## .sig07 NA NA
## .sig08 NA NA
## .sig09 NA NA
## .sig10 NA NA
## (Intercept) 0.799398299 1.13936841
## condition_c -0.084258904 0.58649146
## block_c 0.027644680 0.22412114
## round_c 0.282935680 0.66774595
## age_c 0.016913490 0.06470726
## condition_c:block_c 0.056677042 0.41503576
## condition_c:round_c -0.311543091 0.41594628
## block_c:round_c -0.451397035 -0.07047837
## condition_c:age_c -0.043181816 0.05217845
## block_c:age_c -0.004212311 0.02137873
## round_c:age_c -0.004157427 0.04756940
## condition_c:block_c:round_c -0.485709760 0.20384966
## condition_c:block_c:age_c -0.022670748 0.02772831
## condition_c:round_c:age_c -0.037236916 0.06520694
## block_c:round_c:age_c -0.035873859 0.01338025
## condition_c:block_c:round_c:age_c -0.071316731 0.02552161
Plot
#summarize by block
kid_training_by_block <- d %>%
filter(age_group=="kid" & trial_kind=="learn") %>%
group_by(subject,condition,round,block) %>%
summarize(accuracy=mean(is_right)) %>%
summarySEwithin(measurevar="accuracy",betweenvars=c("condition"),withinvars=c("round","block"),idvar="subject") %>%
mutate(round_factor = case_when(
round=="1" ~ "Round 1",
round=="2" ~ "Round 2"
)) %>%
mutate(
lower_ci = accuracy - ci,
upper_ci = accuracy + ci
)
# show by block learning accuracy as a table
kid_training_by_block %>%
select(condition,N,round,block,accuracy,lower_ci,upper_ci) %>%
kable(digits=3)
| high |
49 |
1 |
1 |
0.594 |
0.537 |
0.652 |
| high |
49 |
1 |
2 |
0.696 |
0.637 |
0.755 |
| high |
49 |
1 |
3 |
0.742 |
0.699 |
0.786 |
| high |
49 |
2 |
1 |
0.732 |
0.692 |
0.772 |
| high |
49 |
2 |
2 |
0.735 |
0.685 |
0.784 |
| high |
49 |
2 |
3 |
0.758 |
0.712 |
0.803 |
| low |
48 |
1 |
1 |
0.596 |
0.550 |
0.643 |
| low |
48 |
1 |
2 |
0.659 |
0.609 |
0.709 |
| low |
48 |
1 |
3 |
0.633 |
0.586 |
0.679 |
| low |
48 |
2 |
1 |
0.695 |
0.652 |
0.739 |
| low |
48 |
2 |
2 |
0.711 |
0.669 |
0.753 |
| low |
48 |
2 |
3 |
0.661 |
0.620 |
0.703 |
#learning phase plot
ggplot(kid_training_by_block, aes(block,accuracy,color=condition,group=condition))+
geom_line(aes(linetype=condition),position=position_dodge(0.1),size=1.3)+
geom_point(aes(shape=condition),position=position_dodge(0.1),size=2.5)+
geom_errorbar(aes(ymin=accuracy-se,ymax=accuracy+se),width=0,size=0.5,position=position_dodge(.1))+
xlab("Block")+
ylab("Accuracy")+
scale_linetype_discrete(name="Nameability")+
scale_shape_discrete(name="Nameability")+
scale_color_brewer(palette="Set1",name="Nameability")+
#ggtitle("Performance during training")+
geom_hline(yintercept=0.5, linetype="dashed",size=1)+
theme(legend.position=c(0.3,0.3))+
theme(text=element_text(size=18))+
theme(strip.text.x = element_text(size=16), plot.background = element_rect(fill="white",color="white"))+
facet_wrap(~round_factor)+
ylim(0,1)

ggsave(here::here("figures","kids_training_half.png"),width=8, height=5,dpi=600)
Overall Accuracy
kid_training_summarized <- kid_subj %>%
group_by(condition) %>%
summarize(
N=n(),
avg_accuracy = mean(mean_learning_accuracy),
avg_accuracy_ci = qt(0.975, N-1)*sd(mean_learning_accuracy,na.rm=TRUE)/sqrt(N),
avg_accuracy_lower_ci = avg_accuracy - avg_accuracy_ci,
avg_accuracy_upper_ci = avg_accuracy + avg_accuracy_ci,
)
kid_training_summarized %>%
select(-avg_accuracy_ci) %>%
mutate(
ci = str_c("[",round(avg_accuracy_lower_ci,3),", ", round(avg_accuracy_upper_ci,3),"]")) %>%
select(condition,N,avg_accuracy,ci) %>%
kable(col.names=c("Condition", "N", "Average Accuracy","CI"),digits=3)
| high |
49 |
0.710 |
[0.672, 0.748] |
| low |
48 |
0.659 |
[0.616, 0.703] |
#effect size
cohens_d(mean_learning_accuracy ~ condition,data=kid_subj)
## Cohen's d | 95% CI
## -------------------------
## 0.36 | [-0.05, 0.76]
##
## - Estimated using pooled SD.
# effect size, block 3
cohens_d(mean_learning_accuracy_block3 ~ condition,data=kid_subj)
## Cohen's d | 95% CI
## ------------------------
## 0.57 | [0.16, 0.97]
##
## - Estimated using pooled SD.
Children vs. Adults
Main Model
#full model
m <- glmer(
is_right~condition_c*block_c*round_c*age_group_c+(1+block_c*round_c|subject),
data=filter(d, trial_kind=="learn"),
family=binomial,
glmerControl(optimizer="bobyqa"))
summary(m)
## Generalized linear mixed model fit by maximum likelihood (Laplace
## Approximation) [glmerMod]
## Family: binomial ( logit )
## Formula: is_right ~ condition_c * block_c * round_c * age_group_c + (1 +
## block_c * round_c | subject)
## Data: filter(d, trial_kind == "learn")
## Control: glmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 7629.0 7813.7 -3788.5 7577.0 8950
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -9.9494 0.0685 0.2398 0.5665 1.1669
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## subject (Intercept) 0.84916 0.9215
## block_c 0.04853 0.2203 0.93
## round_c 0.36008 0.6001 0.85 0.98
## block_c:round_c 0.08436 0.2905 -0.47 -0.76 -0.87
## Number of obs: 8976, groups: subject, 187
##
## Fixed effects:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) 2.11355 0.09150 23.098 < 2e-16
## condition_c 0.92710 0.17230 5.381 7.42e-08
## block_c 0.54838 0.06976 7.860 3.83e-15
## round_c 0.78755 0.12255 6.426 1.31e-10
## age_group_c 2.32214 0.17614 13.183 < 2e-16
## condition_c:block_c 0.37435 0.11778 3.178 0.001481
## condition_c:round_c 0.17975 0.21457 0.838 0.402193
## block_c:round_c -0.35570 0.13395 -2.655 0.007921
## condition_c:age_group_c 1.28435 0.34374 3.736 0.000187
## block_c:age_group_c 0.78478 0.12318 6.371 1.88e-10
## round_c:age_group_c 0.67643 0.22238 3.042 0.002352
## condition_c:block_c:round_c -0.16717 0.22690 -0.737 0.461267
## condition_c:block_c:age_group_c 0.27926 0.23531 1.187 0.235324
## condition_c:round_c:age_group_c 0.22303 0.42857 0.520 0.602779
## block_c:round_c:age_group_c -0.24931 0.23576 -1.057 0.290290
## condition_c:block_c:round_c:age_group_c -0.08709 0.45320 -0.192 0.847604
##
## (Intercept) ***
## condition_c ***
## block_c ***
## round_c ***
## age_group_c ***
## condition_c:block_c **
## condition_c:round_c
## block_c:round_c **
## condition_c:age_group_c ***
## block_c:age_group_c ***
## round_c:age_group_c **
## condition_c:block_c:round_c
## condition_c:block_c:age_group_c
## condition_c:round_c:age_group_c
## block_c:round_c:age_group_c
## condition_c:block_c:round_c:age_group_c
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## optimizer (bobyqa) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
#Anova(m, type="III") # chi-squared test yields virtually identical results
confint(m, method="Wald")[11:26,]
## 2.5 % 97.5 %
## (Intercept) 1.9342064 2.2928926
## condition_c 0.5893963 1.2647943
## block_c 0.4116436 0.6851146
## round_c 0.5473491 1.0277509
## age_group_c 1.9769002 2.6673756
## condition_c:block_c 0.1435052 0.6051891
## condition_c:round_c -0.2408058 0.6003071
## block_c:round_c -0.6182368 -0.0931577
## condition_c:age_group_c 0.6106202 1.9580755
## block_c:age_group_c 0.5433471 1.0262184
## round_c:age_group_c 0.2405812 1.1122861
## condition_c:block_c:round_c -0.6118915 0.2775464
## condition_c:block_c:age_group_c -0.1819441 0.7404572
## condition_c:round_c:age_group_c -0.6169528 1.0630175
## block_c:round_c:age_group_c -0.7113844 0.2127653
## condition_c:block_c:round_c:age_group_c -0.9753545 0.8011649
coefs <- summary(m)$coef %>%
as_tibble %>%
mutate_at(c("Estimate","Std. Error", "z value", "Pr(>|z|)"),
function (x) signif(x, digits = 3)) %>%
rename(SE = `Std. Error`,
z = `z value`,
p = `Pr(>|z|)`)
rownames(coefs) <- c("Intercept",
"Condition",
"Block Number",
"Round",
"Age Group",
"Condition * Block Number",
"Condition * Round",
"Block Number * Round",
"Condition * Age Group",
"Block Number * Age Group",
"Round * Age Group",
"Condition * Block Number * Round",
"Condition * Block Number * Age Group",
"Condition * Round * Age Group",
"Block * Round * Age Group",
"Condition * Block Number * Round * Age Group")
write.table(coefs, file=here::here(model_output_path,"adult_vs_kid_lme_model_output.csv"),sep=",")
Simplified random effects
While the model with the full random effects had a singular fit,
simplifying the random effects structure did not meaningfully affect the
pattern of results from the model. Below, we successively prune random
effects until no singular fit is obtained. The simplified model yields
highly similar results to the model with the full random effects
structure.
#### pruning random effects structure to achieve convergence
# remove random slope for block
# m <- glmer(
# is_right~condition_c*block_c*round_c*age_group_c+(1+block_c+block_c:round_c|subject),
# data=filter(d, trial_kind=="learn"),
# family=binomial,
# glmerControl(optimizer="bobyqa"))
# model still yields a singular fit
# remove random slope for round
# m <- glmer(
# is_right~condition_c*block_c*round_c*age_group_c+(1+round_c+block_c:round_c|subject),
# data=filter(d, trial_kind=="learn"),
# family=binomial,
# glmerControl(optimizer="bobyqa"))
# model still yields a singular fit
#retain only random intercept and random slope for block by round interaction
m <- glmer(
is_right~condition_c*block_c*round_c*age_group_c+(1+block_c:round_c|subject),
data=filter(d, trial_kind=="learn"),
family=binomial,
glmerControl(optimizer="bobyqa"))
summary(m)
## Generalized linear mixed model fit by maximum likelihood (Laplace
## Approximation) [glmerMod]
## Family: binomial ( logit )
## Formula: is_right ~ condition_c * block_c * round_c * age_group_c + (1 +
## block_c:round_c | subject)
## Data: filter(d, trial_kind == "learn")
## Control: glmerControl(optimizer = "bobyqa")
##
## AIC BIC logLik deviance df.resid
## 7671.7 7806.6 -3816.8 7633.7 8957
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -10.4395 0.0848 0.2591 0.5560 1.1921
##
## Random effects:
## Groups Name Variance Std.Dev. Corr
## subject (Intercept) 0.6619 0.8136
## block_c:round_c 0.1565 0.3956 -0.80
## Number of obs: 8976, groups: subject, 187
##
## Fixed effects:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) 2.01412 0.07930 25.399 < 2e-16
## condition_c 0.91625 0.15417 5.943 2.79e-09
## block_c 0.45778 0.05436 8.421 < 2e-16
## round_c 0.52080 0.09167 5.681 1.34e-08
## age_group_c 2.22158 0.15551 14.286 < 2e-16
## condition_c:block_c 0.37639 0.10856 3.467 0.000526
## condition_c:round_c 0.15993 0.18313 0.873 0.382498
## block_c:round_c -0.52740 0.12305 -4.286 1.82e-05
## condition_c:age_group_c 1.31402 0.30798 4.267 1.98e-05
## block_c:age_group_c 0.70070 0.10862 6.451 1.11e-10
## round_c:age_group_c 0.42989 0.18321 2.346 0.018951
## condition_c:block_c:round_c -0.16807 0.22659 -0.742 0.458250
## condition_c:block_c:age_group_c 0.30670 0.21711 1.413 0.157762
## condition_c:round_c:age_group_c 0.27354 0.36613 0.747 0.455007
## block_c:round_c:age_group_c -0.41194 0.23070 -1.786 0.074154
## condition_c:block_c:round_c:age_group_c -0.05257 0.45267 -0.116 0.907548
##
## (Intercept) ***
## condition_c ***
## block_c ***
## round_c ***
## age_group_c ***
## condition_c:block_c ***
## condition_c:round_c
## block_c:round_c ***
## condition_c:age_group_c ***
## block_c:age_group_c ***
## round_c:age_group_c *
## condition_c:block_c:round_c
## condition_c:block_c:age_group_c
## condition_c:round_c:age_group_c
## block_c:round_c:age_group_c .
## condition_c:block_c:round_c:age_group_c
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1