GLMM 中使用 poly() 前需要标准化预测变量吗?
通常不需要在默认的 poly(x, 2) 前再做 z-score 标准化。不过,生成的系数不能直接与其他 z-score 预测变量的系数比较;即使系数大了 2.5 倍,也不能据此认为生态效应更强。
poly() 的归一化与 z-score 有什么区别?
poly(x, 2) 默认使用 raw = FALSE,返回两列正交多项式基函数,分别表示一次和二次方向。第二列并不是简单的 x^2。R 文档说明了这一默认行为。
默认生成的每列都与常数列正交,且列内平方和为 1;z-score 标准化则使样本标准差为 1,两者的尺度不同。R 实现源码中可以看到相应的归一化运算。
由此可推导,对于同一组包含 n 个观测值的非恒定变量,若 z = (x - mean(x)) / sd(x),则第一列满足:
P1 = z / sqrt(n - 1)
两列正交基函数的样本标准差均约为 1 / sqrt(n - 1)。因此,它们各增加一个单位,与 z-score 变量增加一个单位所代表的变化幅度不同。
就同一个线性方向而言,把 z-score 列换成第一列正交基函数后,系数会相应乘以 sqrt(n - 1),以保持线性预测值不变。这解释了系数为什么可能明显增大,但不能用这个倍数解释不同变量之间的效应差异。
原来的模型应该怎么写?
可以保留原来的写法:
poly(var4, 2)
poly(var5, 2)
对于相同的观测值,先做 z-score 再调用默认的 poly(),通常会得到数值上相同的正交基函数,浮点误差除外。这里的模型包含截距和完整二次项,没有额外的系数惩罚。中心化和缩放不会改变它可表示的二次曲线,因此理论上拟合值也不会改变;实际拟合仍可能存在数值误差。
log 变换则不同于中心化和缩放。poly(log(x), 2) 拟合的是关于 log(x) 的二次关系,通常与 poly(x, 2) 表示不同的模型。是否取 log 应由生态学假设和数据特征决定。
如果希望用标准化变量表达二次曲线
可以先生成标准化变量,再使用原始多项式项。以下示例假设 plants 已限定为最终建模样本,相关变量没有缺失值,且标准差大于零:
library(glmmTMB)
var4_center <- mean(plants$var4)
var4_scale <- sd(plants$var4)
var5_center <- mean(plants$var5)
var5_scale <- sd(plants$var5)
plants$z_var4 <- (plants$var4 - var4_center) / var4_scale
plants$z_var5 <- (plants$var5 - var5_center) / var5_scale
model_raw <- glmmTMB(
nspecies ~
scaled_log_var1 +
scaled_log_var2 +
scaled_var3 +
z_var4 + I(z_var4^2) +
z_var5 + I(z_var5^2) +
(1 | region),
data = plants,
family = nbinom2
)
其中 z_var4 + I(z_var4^2) 等价于 poly(z_var4, 2, raw = TRUE)。这里的 raw = TRUE 关闭了正交化。
这种参数化便于解释曲线,但平方项本身的标准差并未标准化为 1,一次项与平方项也不保证正交。因此,改用这种写法不会让所有系数自动变得可比。
应该怎样比较预测变量的效应?
二次关系的效应取决于变量的起点。对于:
eta(z) = beta0 + beta1*z + beta2*z^2
变量从 a 变为 b 时,对线性预测子的影响为:
delta_eta = beta1*(b - a) + beta2*(b^2 - a^2)
因此,不能只拿一次项或二次项中的某一个系数与其他变量的线性系数比较。默认正交多项式的两列也应合起来解释。
更合适的做法是为每个变量选定有生态意义的变化范围,例如从第 25 百分位到第 75 百分位,再在其他条件相同的情况下比较预测响应及其不确定性。如果使用 log link,在其他预测项和随机效应取值相同的条件下,exp(delta_eta) 表示条件均值之比。
也可以绘制每个变量在观测范围内的预测曲线,同时查看变化幅度、非线性形状和数据支持的范围。
使用时还要注意什么?
- 默认
poly()的输入不能含缺失值;二次项至少需要 3 个不同取值。应先确定最终分析样本,再计算变换,避免基函数与实际拟合样本不一致。 - 正交性针对构造基函数时的观测点,不代表不同预测变量彼此独立,也不保证 GLMM 中的系数估计互不相关。
- 预测新数据时,必须沿用训练数据的变换参数。手动构造正交基函数时,可保存
p4 <- poly(plants$var4, 2),再用predict(p4, newdata = new_plants$var4);不要对新数据重新独立计算基函数。 - 使用手动 z-score 变量时,也应保存并复用训练集的均值和标准差。
备注:内容仅供参考。
