循环内/外设置随机种子对线性混合模型模拟的影响及方案验证
关于循环内设置随机种子的疑问
我用simr包在循环中模拟线性混合模型,现在在循环内设置了set.seed(42),想咨询三个问题:
- 循环内设置种子的具体作用
- 和在循环外设置种子的差异
- 我的选择是否符合自身的研究设计逻辑
研究背景与模型
Age和Hemisphere是二分类变量,模拟模型代码:
Simulatedmodelfulloop <- makeLmer(LC_z_scored ~ 1 + Hemisphere + Age + (1|Subject), fixef=fixedfullloop, VarCorr=vars2, sigma=res, data=artificial_data)
我测试Age的不同beta值并计算对应的partial R²,公式为:
partial_r_squared = ((sigma(null )^2 - sigma(full)^2))/sigma(null )^2
为保证除Age的beta外其他条件恒定,我在循环内的模型模拟步骤前设置种子,完整代码及运行结果如下:
完整代码
#generate artificial dataset nparticipants = 1000 subject_ID <- (1:nparticipants) levels_hemisphere <- c("L", "R") levels_age <- c("Y", "O") artificial_data <- expand.grid(Age = levels_age, Hemisphere = levels_hemisphere, Subject = subject_ID ) #fixed parameters vars2<- 0.49098 res <- 0.5683859 fixedhemisphereonly <- c( 0.473863, -1.043858) #possible beta tested for Age possibleβ = seq(from = 0.1, to = 1, by = 0.1) #range of absolute values tested # Initialize an empty data frame to store stuff combined_df <- data.frame( beta_tested = numeric(0), partialr_result = numeric(0), residulas_null = numeric(0), residulas_full = numeric(0) ) # Loop over each beta for (β_tested in possibleβ) { set.seed(42)# set seed #simulate model fixedfullloop <- c(fixedhemisphereonly, β_tested) # tested b age Simulatedmodelfulloop <- makeLmer(LC_z_scored ~ 1 + Hemisphere + Age + (1|Subject), fixef=fixedfullloop, VarCorr=vars2, sigma=res, data=artificial_data) #calculate partial r2 datasimulated <- Simulatedmodelfulloop@frame null <- lmer(LC_z_scored ~ 1+ Hemisphere + (1|Subject), data =datasimulated, REML = FALSE) partial_r_squared = ((sigma(null )^2 - sigma(Simulatedmodelfulloop)^2))/sigma(null )^2 combined_df <- rbind(combined_df, data.frame( beta_tested = β_tested, partialr_result = partial_r_squared, residulas_null = sigma(null)^2, residulas__full = sigma(Simulatedmodelfulloop)^2)) }
运行结果
print(combined_df) beta_tested partialr_result residulas_null residulas__full 1 0.1 0.004139411 0.3244054 0.3230625 2 0.2 0.036372843 0.3352568 0.3230625 3 0.3 0.084224629 0.3527749 0.3230625 4 0.4 0.142978344 0.3769596 0.3230625 5 0.5 0.207813127 0.4078110 0.3230625 6 0.6 0.274553269 0.4453291 0.3230625 7 0.7 0.340033904 0.4895138 0.3230625 8 0.8 0.402140426 0.5403652 0.3230625 9 0.9 0.459656218 0.5978833 0.3230625 10 1.0 0.512040299 0.6620681 0.3230625
问题解答
1. 循环内设置种子的具体作用
每次循环开头调用set.seed(42),会把R的随机数生成器重置到相同的起始状态,带来两个关键效果:
- 每次循环中,
makeLmer()生成的Subject组间随机效应、残差误差完全一致,不受循环次数干扰。 - 除了你主动调整的Age的beta值,模拟数据里的所有随机波动成分完全恒定,确保不同beta值的对比只受beta本身影响,彻底排除随机噪声的干扰。
从你的结果也能验证这一点:所有行的residulas__full都是0.3230625,正是因为每次模拟的残差和随机效应完全相同,full模型的残差方差没有变化,完全符合你控制变量的需求。
2. 和循环外设置种子的差异
如果把set.seed(42)放在循环外面(比如循环启动前),效果会完全不同:
- 随机数生成器只会被初始化一次,每次循环会按顺序生成新的随机数。
- 这会导致每次循环的随机效应、残差都不一样,不同beta值对应的模拟数据会混入额外的随机差异,你的partial R²结果会掺杂随机噪声,无法单纯归因于beta的变化。
- 举个直观的例子:循环外设种子的话,第1次循环用种子42生成的随机数,第2次循环会接着用下一组随机数,两次模拟的残差、Subject效应都不同,
residulas__full也会出现波动。
3. 你的选择是否符合设计逻辑
完全符合。你的核心需求是只改变Age的beta值,控制其他所有条件恒定,以此观察beta变化对partial R²的影响:
- 循环内设置固定种子,完美实现了“除Age的beta外,其他随机成分完全一致”的控制变量设计。
- 从结果来看,full模型的残差方差恒定,partial R²随beta增大单调上升,完全反映了beta对效应量的真实影响,没有被随机噪声干扰,这正是你想要的结果。
唯一可优化的小细节:artificial_data是用expand.grid生成的确定性数据,可以把它的生成代码移到循环外面,不过这对结果没有影响,只是能让代码更高效。
内容的提问来源于stack exchange,提问作者Martina
相关产品推荐
相关产品推荐

