在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
列中加倍值,但我正在寻找更优雅的解决方案,影响模型,而不是数据。
答案 0 :(得分:4)
看起来您正在进行优化,而不是模型拟合(尽管可以在模型拟合中进行优化)。您可能需要类似optim
函数的内容,或者查看线性或二次编程(linprog
和quadprog
包)。
如果你坚持使用像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