Did you know: a single Eurasian jay hides several thousand acorns in autumn, mainly in October,
and feeds on them through winter, spring and early summer.
Source: Bossema (1979), Behaviour
As in lecture 5: you work in pairs, the task slides say what to do,
checkpoints show what you should get, and the solutions are in the
.Rmd file of these slides on GitHub.
Today’s data hide a trap that is easy to fall into with grouped data. See whether you find it before the slides point it out.
A simulated accent study: 30 speakers, 15 with English as their L1 and 15 Italian learners of English, read 40 English words each. Six acoustic measures per token:
| Variable | What it measures |
|---|---|
vot |
voice onset time of the initial /p t k/ (ms) |
vowel_ratio |
duration of a tense vowel relative to its lax partner |
rate |
articulation rate (syllables per second) |
f0 |
mean fundamental frequency (Hz) |
h1h2 |
H1–H2, a measure of voice quality (dB) |
intensity |
mean intensity (dB) |
set.seed(2033)
speakers <- tibble(speaker = sprintf("S%02d", 1:30), l1 = rep(c("English", "Italian"), each = 15),
gender = rep(c("female", "male"), 15)) |>
mutate(f0_s = if_else(gender == "female", 210, 120) + rnorm(30, 0, 15), h1h2_s = rnorm(30, 4, 2.5),
vot_s = if_else(l1 == "English", 70, 45) + rnorm(30, 0, 10),
ratio_s = if_else(l1 == "English", 1.6, 1.2) + rnorm(30, 0, 0.15),
rate_s = if_else(l1 == "English", 5.2, 4.7) + rnorm(30, 0, 0.5))
accent <- crossing(speakers, token = 1:40) |>
mutate(vot = round(vot_s + rnorm(n(), 0, 15)), vowel_ratio = round(ratio_s + rnorm(n(), 0, 0.25), 2),
rate = round(rate_s + rnorm(n(), 0, 0.6), 2), f0 = round(f0_s + rnorm(n(), 0, 10)),
h1h2 = round(h1h2_s + rnorm(n(), 0, 1), 1), intensity = round(rnorm(n(), 68, 4), 1)) |>
mutate(across(c(speaker, l1, gender), factor)) |>
select(speaker, l1, gender, vot, vowel_ratio, rate, f0, h1h2, intensity)VOT, the vowel ratio and, less clearly, articulation rate differ between the groups. f0 mostly separates women from men. The baseline is 50%.
Did you know: a jay can carry up to six
acorns on one trip. It swallows the first ones and carries the
last in its bill, and the more acorns it carries, the farther it flies
before hiding them.
Source: Bossema (1979), Behaviour
f_all <- l1 ~ vot + vowel_ratio + rate + f0 + h1h2 + intensity
rf_all <- ranger(f_all, data = accent, num.trees = 1000, importance = ___, seed = 1)
rf_all
1 - rf_all$prediction.errorOOB accuracy: 0.892. Before you go on: f0 and H1–H2 have no link with L1 in the simulation. Why could the forest find them useful?
Every speaker’s 40 tokens are in the data. A tree’s bootstrap sample therefore almost always contains other tokens of the speaker whose OOB token it predicts.
The OOB error assumes independent observations. With grouped data, it rewards predictors that merely identify the group (Roberts et al., 2017).
Each column holds one speaker’s 40 tokens. They cluster tightly, while English and Italian speakers are mixed along the whole range. A token’s f0 tells the forest who is speaking, and the speaker’s other tokens tell it the L1.
set.seed(2)
folds <- distinct(accent, speaker, l1) |>
mutate(fold = sample(rep(1:5, length.out = n())), .by = l1)
cv_speakers <- function(formula) {
map(1:5, \(k) {
train <- filter(accent, speaker %in% folds$speaker[folds$fold != k])
test <- filter(accent, speaker %in% ___)
m <- ranger(formula, data = train, num.trees = 500, seed = k)
tibble(speaker = test$speaker, l1 = test$l1, pred = predict(m, test)$predictions)
}) |> list_rbind()
}Complete the test set, run cv_speakers(f_all), and
compute the accuracy on held-out speakers. Each fold leaves out three
speakers from each group.
Refit with only the three measures that differed between the groups
in Task 1: vot, vowel_ratio and
rate.
Only cross-validation by speaker estimates how well the forest classifies speakers it has not seen. The dashed line is the baseline.
Did you know: many oak seedlings grow from acorns that
jays hid the autumn before. Bossema could tell from the bill prints left on the shells.
Source: Bossema (1979), Behaviour
The research question asks about speakers, so the last step goes from tokens to people. Use the cross-validated predictions of the three-measure forest:
Fit a probability forest with the three measures on all data, and draw a partial dependence plot for VOT, as in lecture 6.
30 of 30 held-out speakers classified correctly by majority vote.
Write a short methods and results paragraph. It should say:
mtry and the
seed, and why you chose the predictors you keptThen swap with another pair: could a reviewer object to anything in theirs?
mtry for the three-measure
forest, using speaker-wise cross-validation and not the OOB errorlme4::glmer(l1 ~ scale(vot) + scale(vowel_ratio) + scale(rate) + (1 | speaker), family = binomial).
What does the mixed model tell you that the forest does not, and what
does it fail to see?These slides
mcanzi.de/ss27_advanced_statistics/
Code and all lectures
github.com/mcanzi/ss27_advanced_statistics