如何在线性模型中手动设置变量系数?

时间:2012-09-07 18:55:38

标签: r linear-regression lm

在R中,我如何为特定变量设置权重而不是lm()函数中的观察?

上下文如下。我正在尝试为特定产品建立个人排名系统,比如手机。我可以建立基于价格的线性模型作为因变量和其他特征,如屏幕尺寸,内存,操作系统等作为自变量。然后,我可以用它来预测手机的实际成本(与宣布的价格相反),从而找到最佳的价格/良好系数。这就是我已经做过的事情。

现在我想“突出显示”仅对我很重要的一些功能。例如,我可能需要一个具有大内存的手机,因此我想给它更高的权重,以便线性模型针对内存变量进行优化。

R中的

lm()函数具有weights参数,但这些是观察值而非变量的权重(如果这是错误的,请纠正我)。我也试着玩配方,但只有翻译错误。有没有办法在lm()

中合并变量的权重

当然,lm()功能不是唯一的选择。如果你知道如何使用其他类似的解决方案(例如glm()),这也很好。

UPD。经过几次评论,我明白了我对这个问题的思考方式是错误的。通过调用lm()获得的线性模型为训练样例提供了最佳系数,并且没有办法(也没有必要)改变变量的权重,对不起我所做的混乱。我实际上正在寻找的是改变现有线性模型中系数的方法,以手动使一些参数比其他参数更重要。继续前面的例子,假设我们有以下价格公式:

price = 300 + 30 * memory + 56 * screen_size + 12 * os_android + 9 * os_win8

此公式描述了价格和电话参数之间依赖关系的最佳可能线性模型。但是,现在我想手动将memory变量前面的数字30更改为60,因此它变为:

price = 300 + 60 * memory + 56 * screen_size + 12 * os_android + 9 * os_win8

当然,这个公式不再反映价格和手机参数之间的最佳关系。同时因变量并不显示实际价格,只是一些良好的价值,考虑到记忆对我来说比一般人重要两倍(基于第一个公式的系数)。但是这种善良的价值(或者更确切地说,分数goodness/price的价值)正是我所需要的 - 拥有这个我能找到最好的(在我看来)最好的价格手机。

希望所有这一切都有道理。现在我有一个(可能非常简单)的问题。如何手动设置现有线性模型中的系数,使用lm()获得?也就是说,我正在寻找类似的东西:

coef(model)[2] <- 60

这段代码当然不起作用,但你应该明白这个想法。注意:显然可以在数据框中的memory列中加倍值,但我正在寻找更优雅的解决方案,影响模型,而不是数据。

2 个答案:

答案 0 :(得分:4)

看起来您正在进行优化,而不是模型拟合(尽管可以在模型拟合中进行优化)。您可能需要类似optim函数的内容,或者查看线性或二次编程(linprogquadprog包)。

如果你坚持使用像lm这样的建模工具,那么使用公式中的offset参数来指定你自己的乘法器,而不是计算一个。

答案 1 :(得分:4)

以下代码有点复杂,因为lm() 最小化残差平方和,并且具有固定的非最佳系数,它不是最小的,所以这将与{{{ 1}}正在尝试做,唯一的方法是修复所有其余的系数。

为此,我们必须首先了解无限制模型的系数。所有调整都必须通过更改模型的公式来完成,例如我们有 lm(),当然还有一个隐藏的拦截。现在既不直接更改数据也不使用price ~ memory + screen_size是个好主意。 I(c*memory)就像临时更改数据一样,但通过转换变量只改变一个系数将会困难得多。

首先,我们将I(c*memory)更改为price ~ memory + screen_size。但是我们还没有修改截距,现在它会尝试最小化残差平方和,并且可能与原始模型不同。最后一步是删除截距并添加一个新的伪变量,即与其他变量具有相同数量的观察值:

price ~ offset(c1*memory) + offset(c2*screen_size)

price ~ offset(c1*memory) + offset(c2*screen_size) + rep(c0, length(memory)) - 1

此外,您可能只会将# Function to fix coefficients setCoeffs <- function(frml, weights, len){ el <- paste0("offset(", weights[-1], "*", unlist(strsplit(as.character(frml)[-(1:2)], " +\\+ +")), ")") el <- c(paste0("offset(rep(", weights[1], ",", len, "))"), el) as.formula(paste(as.character(frml)[2], "~", paste(el, collapse = " + "), " + -1")) } # Example data df <- data.frame(x1 = rnorm(10), x2 = rnorm(10, sd = 5), y = rnorm(10, mean = 3, sd = 10)) # Writing formula explicitly frml <- y ~ x1 + x2 # Basic model mod <- lm(frml, data = df) # Prime coefficients and any modifications. Note that "weights" contains # intercept value too weights <- mod$coef # Setting coefficient of x1. All the rest remain the same weights[2] <- 3 # Final model mod2 <- update(mod, setCoeffs(frml, weights, nrow(df))) # It is fine that mod2 returns "No coefficients" 用于预测(实际上我不知道它现在可以在哪里使用),因此可以更简单的方式使用mod2

setCoeffs