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

ffr*_*end 7 r linear-regression lm

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

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

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

lm()R中的函数有weights参数,但这些是观察的权重而不是变量(如果这是错误的,请纠正我).我也试着玩配方,但只有翻译错误.有没有办法将变量的权重合并在一起lm()?

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

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

price = 300 + 30 * memory + 56 * screen_size + 12 * os_android + 9 * os_win8
Run Code Online (Sandbox Code Playgroud)

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

price = 300 + 60 * memory + 56 * screen_size + 12 * os_android + 9 * os_win8
Run Code Online (Sandbox Code Playgroud)

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

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

coef(model)[2] <- 60
Run Code Online (Sandbox Code Playgroud)

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

Jul*_*ora 4

下面的代码有点复杂,因为lm() 最小化残差平方和,并且使用固定的非最优系数,它不再是最小的,因此这将违背正在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"
Run Code Online (Sandbox Code Playgroud)

另外,可能您mod2只会用于预测(实际上我不知道现在还可以在哪里使用它),这样就可以以更简单的方式进行,而无需setCoeffs:

# Data for forecasting with e.g. price unknown
df2 <- data.frame(x1 = rpois(10, 10), x2 = rpois(5, 5), y = NA)
mat <- model.matrix(frml, model.frame(frml, df2, na.action = NULL))
# Forecasts
rowSums(t(t(mat) * weights))
Run Code Online (Sandbox Code Playgroud)