2014-09-05 57 views
6

我装配在我的数据集的75%,其包括线性回归模型〜11000次的观测和143个变量:R平方测试数据

gl.fit <- lm(y[1:ceiling(length(y)*(3/4))] ~ ., data= x[1:ceiling(length(y)*(3/4)),]) #3/4 for training

,并收到R^2 0.43 。然后我尝试使用其他数据对我的测试数据来预测:

ytest=y[(ceiling(length(y)*(3/4))+1):length(y)] x.test <- cbind(1,x[(ceiling(length(y)*(3/4))+1):length(y),]) #The rest for test yhat <- as.matrix(x.test)%*%gl.fit$coefficients #Calculate the predicted values

我现在想计算我的测试数据的R^2的值。有没有简单的方法来计算?

如果你想有一个功能,miscTools包有rSquared功能谢谢

+0

请参阅[此类似的问题(http://stats.stackexchange.com/questions/863 CrossValidated上的14/higher-r-squared-on-test-data-than-training-data)。 – nrussell 2014-09-05 17:41:13

+0

@nrussell谢谢;我在提到的问题中使用了公式,并得到了一个负数(-0.59)作为我的R^2值。我对我的lm模型有疑问,我应该添加一个拦截(我认为R会自动执行)?那为什么我会得到负面的R^2呢? – 2014-09-05 18:06:37

+0

您是否在问题下面的评论中使用公式或注释中的公式?因为问题中的公式不正确 - 请参阅@Panos对该问题的评论。 – nrussell 2014-09-05 18:41:21

回答

16

这里有几个问题。首先,这不是使用lm(...)的好方法。 lm(...)旨在与数据框一起使用,公式表达式引用df中的列。因此,假设你的数据在两个向量xy

set.seed(1) # for reproducible example 
x <- 1:11000 
y <- 3+0.1*x + rnorm(11000,sd=1000) 

df <- data.frame(x,y) 
# training set 
train <- sample(1:nrow(df),0.75*nrow(df)) # random sample of 75% of data 

fit <- lm(y~x,data=df[train,]) 

现在fit具有基于训练集模型。使用lm(...)这种方式可以让您例如生成预测,而不用全部矩阵乘法。

第二个问题是R平方的定义。所述conventional definition是:

1 - SS.residuals/SS.total

对于训练集,和训练ONLY设置,

SS.total = SS。回归+ SS.residual

so

SS.regression = SS.total - SS.residual,

因此

R.sq = SS.regression/SS.total

所以R. sq是由模型解释的数据集中变化的分数,并且始终在0和1之间。

您可以看到th在下面。

SS.total  <- with(df[train,],sum((y-mean(y))^2)) 
SS.residual <- sum(residuals(fit)^2) 
SS.regression <- sum((fitted(fit)-mean(df[train,]$y))^2) 
SS.total - (SS.regression+SS.residual) 
# [1] 1.907349e-06 
SS.regression/SS.total  # fraction of variation explained by the model 
# [1] 0.08965502 
1-SS.residual/SS.total  # same thing, for model frame ONLY!!! 
# [1] 0.08965502   
summary(fit)$r.squared  # both are = R.squared 
# [1] 0.08965502 

但这确实与测试集不工作(例如,当你从一个模型的预测)。

test <- -train 
test.pred <- predict(fit,newdata=df[test,]) 
test.y <- df[test,]$y 

SS.total  <- sum((test.y - mean(test.y))^2) 
SS.residual <- sum((test.y - test.pred)^2) 
SS.regression <- sum((test.pred - mean(test.y))^2) 
SS.total - (SS.regression+SS.residual) 
# [1] 8958890 

# NOT the fraction of variability explained by the model 
test.rsq <- 1 - SS.residual/SS.total 
test.rsq 
# [1] 0.0924713 

# fraction of variability explained by the model 
SS.regression/SS.total 
# [1] 0.08956405 

在这个人为的例子中没有太大的区别,但是很可能有一个R-sq。值小于0(当以这种方式定义时)。

例如,如果模型对于测试集来说是一个非常差的预测变量,那么残差实际上可能大于测试集中的总变化量。这相当于说,使用平均值来比使用从训练集派生的模型更好地模拟测试集。

我注意到,你使用你的数据的前四个季度作为训练集,而不是随机抽样(如本例中)。如果yx的依赖是非线性的,并且x是有序的,那么您可以得到具有测试集的负R-sq。

关于下面的OP评论,一种用测试集评估模型的方法是通过比较模型内模型和模型外均方误差(MSE)。

mse.train <- summary(fit)$sigma^2 
mse.test <- sum((test.pred - test.y)^2)/(nrow(df)-length(train)-2) 

如果我们假设训练和测试组都通常与相同的方差分布并且具有遵循相同的模型公式的装置,则该比率应该有一个F-分布(n.train-2 )和(n.test-2)自由度。如果MSE基于F测试显着不同,那么该模型确实适合测试数据,而不是而不是

你有没有绘制你的test.y和pred.y和x?只有这一点会告诉你很多。

+0

非常感谢你为这个精心设计的例子。在这种情况下,在测试数据集上评估我的模型的最佳方式是什么? – 2014-09-05 21:49:18

+0

我刚刚编辑了这个响应,使它与更传统的R-sq定义保持一致,但主要结论未变。关于你的问题,请看我最后的评论。 – jlhoward 2014-09-05 22:17:56

+0

像往常一样的优秀答案。我按照你的建议改变了我的火车/测试组,随机抽取积分。我不再为我的测试获得负R平方(假设它有意义)。我还计算了训练和测试中小企业:训练0.00056,测试0.00036,比率约0.65。与此相比:'qf(0.95,长度(列车)-2,长度(测试)-2)= 1.036603',模型正在做一些事情。如果我犯了错,请纠正我。 – 2014-09-05 22:54:24

2

require(miscTools) 
r2 <- rSquared(ytest, resid = ytest-yhat) 
+0

我找不到这个软件包:在'C:/Users/Haidar/Documents/R/win-library/3.1'中安装软件包' (as'lib'is unspecified) install.packages中的警告: package'micsTools '不可用(对于R版本3.1.1) – 2014-09-05 18:02:29

+0

@H_A,我的错字,对不起。它是'miscTools'。 – cdeterman 2014-09-05 19:10:53

+0

谢谢,它的工作原理,我仍然对我的R^2产生负面影响,我怀疑我的回归/预测程序有问题。 – 2014-09-05 19:31:06

1

计算测试数据的R平方有点棘手,因为您必须记住您的基线是什么。您的基线预测是您的培训数据的平均值。

因此,延伸通过@jlhoward上面提供的示例:

SS.test.total  <- sum((test.y - mean(df[train,]$y))^2) 
SS.test.residual <- sum((test.y - test.pred)^2) 
SS.test.regression <- sum((test.pred - mean(df[train,]$y))^2) 
SS.test.total - (SS.test.regression+SS.test.residual) 
# [1] 11617720 not 8958890 

test.rsq <- 1 - SS.test.residual/SS.test.total 
test.rsq 
# [1] 0.09284556 not 0.0924713 

# fraction of variability explained by the model 
SS.test.regression/SS.test.total 
# [1] 0.08907705 not 0.08956405 

更新:miscTools::rSquared()功能使得该R平方是对同一数据集,在该模型被训练计算的假设,因为它计算

yy <- y - mean(y) 

在这里线184幕后:https://github.com/cran/miscTools/blob/master/R/utils.R