当预测变量为scale(x)^ 2时,如何从lm()中去除参数

时间:2016-03-26 01:45:56

标签: r regression

我有一个模型,我在其中缩放变量x,然后使用缩放的x和缩放的x的平方作为预测变量。即,lm(y ~ I(scale(x)) + I(scale(x)^2)。我想让系数适用于原始x单位,但我很难弄清楚如何做到这一点。我认为问题是因为缩放后的平方,但我不知道。

我认为,{p> This answer让我非常接近。同样,差异可能是缩放后的平方。

下面是一个R脚本,显示了我创建虚假数据并尝试取消缩放的过程。对不起,我想这有点长了。

最奇怪的是,最终,我得到了平方项的重新缩放权,但不是线性项或截距。鉴于我使用了上述答案中的方法,我猜想我会得到平方系数错误!

如何'缩放'参数?

set.seed(1)
# ---- Create Covariates ----
# Define dimensions for simulation
n <- 100
# Covariate Simulation Parameters
mean.temp <- 10
sd.temp <- 5
mean.depth <- 200
sd.depth <- 20
# Simulate Covariates
temperature <- rnorm(n=n, mean=mean.temp, sd=sd.temp)
depth <- rnorm(n=n, mean=mean.depth, sd=sd.depth)
# Create Unscaled Data Matrix
dmat <- data.frame( 
    temp=temperature, temp2=temperature^2, 
    depth=depth, depth2=depth^2
)
# Scale Covariates
temp.scale <- scale(temperature)
depth.scale <- scale(depth)
# Create Scaled Data Matrix
dmat.scale <- data.frame(
    temp=temp.scale, temp2=temp.scale^2, 
    depth=depth.scale, depth2=depth.scale^2
)
# Record Scaling Factors
mu.vec <- c(
    "temp.mu"=attr(temp.scale,'scaled:center'),
    "temp2.mu"= attr(temp.scale,'scaled:center')^2, # is this right?
    "depth.mu"=attr(depth.scale,'scaled:center'),
    "depth2.mu"= attr(depth.scale,'scaled:center')^2 # is this right?
)
sd.vec <- c(
    "temp.sd"=attr(temp.scale,'scaled:scale'),
    "temp2.sd"= attr(temp.scale,'scaled:scale')^2,
    "depth.sd"=attr(depth.scale,'scaled:scale'),
    "depth2.sd"= attr(depth.scale,'scaled:scale')^2
)
# ---- Create Parameters ----
beta <- matrix(c(0.5, 0.1, -0.8, 1.2, -0.1),ncol=1)
# ---- Simulate ----
eps <- rnorm(n=n, mean=0, sd=0.001)
y <- (cbind(1,as.matrix(dmat))%*%beta + eps)[,1]
# ---- Fit Models ----
mod <- lm(y~as.matrix(dmat))
mod.scale <- lm(y~as.matrix(dmat.scale))

beta.orig <- coef(mod)
beta.scale <- coef(mod.scale)
# ---- Rescale Function ----
# From: https://stackoverflow.com/a/23643740/2343633
rescale.coefs <- function(beta,mu,sigma) {
    beta2 <- beta ## inherit names etc.
    beta2[-1] <- sigma[1]*beta[-1]/sigma[-1]
    beta2[1]  <- sigma[1]*beta[1]+mu[1]-sum(beta2[-1]*mu[-1])
    beta2
}
beta.rescale <- rescale.coefs(beta.scale, mu=c(0,mu.vec), sigma=c(1,sd.vec))

# ---- Compare ----
beta.orig
beta.rescale

1 个答案:

答案 0 :(得分:0)

好的,明白了。截距应该只是1个值,其他参数可以是相同长度的向量,相应的元素与相同的协变量相关联(例如,每个的第一个元素与温度或温度平方相关,第二个与深度相关)。

重新调整二次项是最简单的,只需除以sd()^2即可。以前我只做了线性系数去除的第一个术语,第二个术语涉及更多。我在拦截重新缩放方面犯了很多错误(错过了整个第三学期,在第二学期没有被西格玛分开)。

unscale <- function(intercept, betaLinear, betaQuad, mu, sigma){
    i2 <- intercept + sum(-(betaLinear*mu/sigma) + betaQuad*mu^2/sigma^2)
    bl2 <- betaLinear/sigma - 2*betaQuad*mu/sigma^2
    bq2 <- betaQuad/sigma^2
    return(c(i2, bl2, bq2))
}
beta.unscale <- unscale(
    intercept = beta.scale[1], 
    betaLinear = beta.scale[c(2,4)], 
    betaQuad = beta.scale[c(3,5)], 
    mu = mu.vec[c(1,3)], 
    sigma = sd.vec[c(1,3)]
)[names(beta.scale)]
beta.orig
beta.unscale

修改

或者,如果你想要一个在每个参数有数千个时能够快速运行的函数,这里是矢量化版本:

unscale <- function(a1, a2, a3, a4, a5, mu1, mu2, sigma1, sigma2){
    # i2 <- intercept + sum(-(betaLinear*mu/sigma) + betaQuad*mu^2/sigma^2)
    i2 <- a1 - a2*mu1/sigma1 - a4*mu2/sigma2 + a3*mu1^2/sigma1^2 + a5*mu2^2/sigma2^2
    # bl2 <- betaLinear/sigma - 2*betaQuad*mu/sigma^2
    a22 <- a2/sigma1 - 2*a3*mu1/sigma1^2
    a42 <- a4/sigma2 - 2*a5*mu2/sigma2^2
    # bq2 <- betaQuad/sigma^2
    a32 <- a3/sigma1^2
    a52 <- a5/sigma2^2

    if(length(a1)==1){
       return(c(i2, a22, a32, a42, a52))
    }else{
        return(cbind(i2, a22, a32, a42, a52))
    }
}