Tidymodels下不平衡嵌套数据的多层跑步损伤预测实现问询
跑步者损伤预测多层建模问题解答
1. 嵌套结构不平衡数据的重采样方案
- 合成类重采样优先选择多级SMOTE(Multi-level SMOTE):该算法会按跑步者ID分层,仅在存在损伤阳性样本的组内合成少数类样本,完全保留嵌套结构与组间异质性,不会破坏同一跑步者的特征关联。也可基于现有阳性样本的随机效应分布生成合成样本,适配多层模型的输入要求。
- 若无法实现合成方案,可采用无损伤样本欠采样,但必须按组欠采样:仅对无损伤记录的跑步者整体删除部分完整观测序列,不可跨组随机抽选样本,避免破坏同一跑步者的时间序列连续性。欠采样比例建议控制在阴性:阳性=3:1~5:1区间,避免过度丢失全局信息。
2. Tidymodels生态多层建模路径可行性
multilevelmod对接stan-glmer的方案本身可行,报错多为语法或预处理顺序问题,修正后可正常运行。- 按跑步者ID嵌套的多模型方案效果不稳定是必然问题,核心原因是单个跑步者样本量不足以支撑独立建模。
embed包拟合混合效应广义线性模型的路径完全可行:使用step_lencode_glm()可将跑步者ID的随机效应编码为固定特征,本质是对混合效应的经验贝叶斯估计,可对接常规逻辑回归,完美适配Tidymodels全工作流,适合当前场景。
3. 两类报错修正方案
不存在'Patient'列报错
属于模板代码残留问题,将公式、预处理步骤中所有的Patient字段替换为Runner即可,当前数据集仅存在Runner作为用户ID列。
All columns selected for the step should be numeric报错
错误来源于预处理步骤顺序错误,以及未正确定义ID列角色,修正后的Recipe与代码逻辑如下:
# 修正模型定义 mlbr_mod <- logistic_reg() %>% set_engine("stan-glmer") %>% set_mode("classification") # 修正预处理Recipe mlbr_mod_recipe <- recipe(NewRRI ~ ., data = RunningData_train) %>% # 将Runner设为ID列,不参与常规预处理与SMOTE计算 update_role(Runner, new_role = "ID") %>% # 对所有名义预测变量做哑变量编码,转换为数值型 step_dummy(all_nominal_predictors()) %>% # SMOTE仅在训练集生效,测试集跳过 step_smote(NewRRI, over_ratio = 0.5, skip = TRUE) # 修正工作流与拟合逻辑 mlbr_mod_workflow <- workflow() %>% add_recipe(mlbr_mod_recipe) %>% add_model(mlbr_mod, formula = NewRRI ~ . + (1|Runner)) # 拟合时替换拆分对象为正确的Df_splits mlbr_last_fit <- mlbr_mod_workflow %>% last_fit(Df_splits, metrics = metric_set(bal_accuracy, accuracy, f_meas, precision, roc_auc, sensitivity, recall, kap))
额外需注意原代码中大量赋值运算符、管道符书写错误,需统一修正为<-与%>%。
4. 嵌套多模型与多层模型的效果对比
按跑步者nest()单独建模的方案完全无法替代多层模型的效果:多层模型的核心优势是通过**部分池化(Partial pooling)**同时利用群体级信息和个体级信息,对于样本量极少的个体,会向群体均值收缩估计,避免过拟合;而单独建模每个跑步者属于完全无池化,个体样本量不足的情况下估计偏差极大,效果不稳定,无法达到多层模型的性能。
5. SMOTE-NC/ENC方案适用性
SMOTE-NC/ENC完全适用于本场景:你提到的新增样本需依附现有Runner ID的特性不属于缺陷,正好适配嵌套结构要求:合成的阳性样本直接归属到对应跑步者ID下,保留该跑步者的静态特征(性别、年龄、BMI、既往损伤史),仅对动态训练特征(距离、心率等)做插值合成,不会破坏嵌套结构,可直接对接后续多层模型。
内容的提问来源于stack exchange,提问作者LB.
相关产品推荐
相关产品推荐

