Answers:
由于RF可以处理非线性但不能提供系数,因此使用随机森林收集最重要的特征,然后将这些特征插入多元线性回归模型以解释其符号是否明智?
我将OP的一句话问题解释为OP希望理解以下分析管道的可取性:
我认为该管道无法完成您想要的事情。在随机森林中重要的变量不一定与结果具有任何线性加成关系。这句话不足为奇:这就是使随机森林如此有效地发现非线性关系的原因。
这是一个例子。我创建了一个具有10个噪声特征,两个“信号”特征和一个圆形决策边界的分类问题。
set.seed(1)
N <- 500
x1 <- rnorm(N, sd=1.5)
x2 <- rnorm(N, sd=1.5)
y <- apply(cbind(x1, x2), 1, function(x) (x%*%x)<1)
plot(x1, x2, col=ifelse(y, "red", "blue"))
lines(cos(seq(0, 2*pi, len=1000)), sin(seq(0, 2*pi, len=1000)))
当我们应用RF模型时,我们并不惊讶地发现这些特征很容易被模型选为重要对象。(注:这种模式不调整在所有。)
x_junk <- matrix(rnorm(N*10, sd=1.5), ncol=10)
x <- cbind(x1, x2, x_junk)
names(x) <- paste("V", 1:ncol(x), sep="")
rf <- randomForest(as.factor(y)~., data=x, mtry=4)
importance(rf)
MeanDecreaseGini
x1 49.762104
x2 54.980725
V3 5.715863
V4 5.010281
V5 4.193836
V6 7.147988
V7 5.897283
V8 5.338241
V9 5.338689
V10 5.198862
V11 4.731412
V12 5.221611
但是,当我们只选择这两个有用的功能时,所得到的线性模型非常糟糕。
summary(badmodel <- glm(y~., data=data.frame(x1,x2), family="binomial"))
摘要的重要部分是残余偏差和零偏差的比较。我们可以看到,该模型基本上没有任何作用来“消除”偏差。此外,系数估计基本上为零。
Call:
glm(formula = as.factor(y) ~ ., family = "binomial", data = data.frame(x1,
x2))
Deviance Residuals:
Min 1Q Median 3Q Max
-0.6914 -0.6710 -0.6600 -0.6481 1.8079
Coefficients:
Estimate Std. Error z value Pr(>|z|)
(Intercept) -1.398378 0.112271 -12.455 <2e-16 ***
x1 -0.020090 0.076518 -0.263 0.793
x2 -0.004902 0.071711 -0.068 0.946
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
(Dispersion parameter for binomial family taken to be 1)
Null deviance: 497.62 on 499 degrees of freedom
Residual deviance: 497.54 on 497 degrees of freedom
AIC: 503.54
Number of Fisher Scoring iterations: 4
是什么造成这两种模型之间的巨大差异?好吧,很显然,我们要学习的决策边界不是两个“信号”特征的线性函数。显然,如果您在估算回归之前知道决策边界的功能形式,则可以应用某种转换对数据进行编码,以使回归可以发现...(但是我从来不知道前面的边界形式)由于在这种情况下我们仅使用两个信号功能,即类别标签中没有噪声的合成数据集,因此在我们的绘图中类别之间的边界非常明显。但是,当处理数量众多的真实数据时,它并不那么明显。
而且,通常,随机森林可以将不同的模型拟合到数据的不同子集。在一个更复杂的示例中,从单个图上根本看不到发生了什么,而建立具有相似预测能力的线性模型将变得更加困难。
因为我们只关心二维,所以我们可以制作一个预测图。正如预期的那样,随机模型得知原点周围的邻域很重要。
M <- 100
x_new <- seq(-4,4, len=M)
x_new_grid <- expand.grid(x_new, x_new)
names(x_new_grid) <- c("x1", "x2")
x_pred <- data.frame(x_new_grid, matrix(nrow(x_new_grid)*10, ncol=10))
names(x_pred) <- names(x)
y_hat <- predict(object=rf, newdata=x_pred, "vote")[,2]
library(fields)
y_hat_mat <- as.matrix(unstack(data.frame(y_hat, x_new_grid), y_hat~x1))
image.plot(z=y_hat_mat, x=x_new, y=x_new, zlim=c(0,1), col=tim.colors(255),
main="RF Prediction surface", xlab="x1", ylab="x2")
正如我们的糟糕模型输出所暗示的那样,减少变量对数回归模型的预测面基本上是平坦的。
bad_y_hat <- predict(object=badmodel, newdata=x_new_grid, type="response")
bad_y_hat_mat <- as.matrix(unstack(data.frame(bad_y_hat, x_new_grid), bad_y_hat~x1))
image.plot(z=bad_y_hat_mat, x=x_new, y=x_new, zlim=c(0,1), col=tim.colors(255),
main="Logistic regression prediction surface", xlab="x1", ylab="x2")
HongOoi指出,类成员关系不是这些功能的线性函数,但是它是一个线性函数,需要转换。由于决策边界为 如果对这些特征求平方,就可以构建更有用的线性模型。这是故意的。尽管RF模型无需转换即可在这两个功能中找到信号,但分析人员必须更加具体,才能在GLM中获得类似的有用结果。也许这对OP来说就足够了:为2个特征找到一组有用的变换比12个要容易。但是我的观点是,即使变换会产生有用的线性模型,RF特征的重要性也不会单独提出变换。
@Sycorax的答案太棒了。除了那些与模型拟合有关的问题的充分描述的方面之外,还有另一个原因是不追求多步骤的过程,例如运行随机森林,套索或弹性网来“学习”,以适应传统回归。普通的回归不会知道随机森林或其他方法的开发过程中,妥善继续予以处罚,并会适合那些unpenalized影响严重偏向于出现在预测太强。这与运行逐步变量选择并在不考虑最终模型如何报告的情况下报告最终模型没有什么不同。
适用于更“适合随机森林”的问题的正确执行的随机森林可以用作过滤器,以消除噪声,并获得更有用的结果作为其他分析工具的输入。
免责声明:
我必须对制作“蜘蛛”的“偷窥者”大声疾呼。(链接)他们的榜样问题为我提供了解决方法。(链接)我也喜欢Theil-Sen的估算器,希望我能给Theil和Sen提供道具。
我的答案不是关于如何弄错它,而是关于如果您正确地将其工作可能如何工作。当我使用“琐碎”的噪音时,我希望您考虑“非琐碎”或“结构化”的噪音。
随机森林的优点之一是如何很好地解决高维问题。我无法以清晰的视觉方式显示20k列(也就是20k尺寸的空间)。这不是一件容易的事。但是,如果您遇到20k维的问题,那么当大多数其他人平躺在其“面孔”上时,随机森林可能是一个不错的工具。
这是使用随机森林从信号中去除噪声的示例。
#housekeeping
rm(list=ls())
#library
library(randomForest)
#for reproducibility
set.seed(08012015)
#basic
n <- 1:2000
r <- 0.05*n +1
th <- n*(4*pi)/max(n)
#polar to cartesian
x1=r*cos(th)
y1=r*sin(th)
#add noise
x2 <- x1+0.1*r*runif(min = -1,max = 1,n=length(n))
y2 <- y1+0.1*r*runif(min = -1,max = 1,n=length(n))
#append salt and pepper
x3 <- runif(min = min(x2),max = max(x2),n=length(n)/2)
y3 <- runif(min = min(y2),max = max(y2),n=length(n)/2)
x4 <- c(x2,x3)
y4 <- c(y2,y3)
z4 <- as.vector(matrix(1,nrow=length(x4)))
#plot class "A" derivation
plot(x1,y1,pch=18,type="l",col="Red", lwd=2)
points(x2,y2)
points(x3,y3,pch=18,col="Blue")
legend(x = 65,y=65,legend = c("true","sampled","false"),
col = c("Red","Black","Blue"),lty = c(1,-1,-1),pch=c(-1,1,18))
让我描述一下这是怎么回事。下图显示了“ 1”级的训练数据。类“ 2”是在相同域和范围上的统一随机。您可以看到“ 1”的“信息”主要是螺旋形的,但是已经被“ 2”中的材料破坏了。对于许多拟合工具而言,使33%的数据损坏可能是一个问题。Theil-Sen的降解率约为29%。(链接)
现在我们分离出信息,只知道什么是噪音。
#Create "B" class of uniform noise
x5 <- runif(min = min(x4),max = max(x4),n=length(x4))
y5 <- runif(min = min(y4),max = max(y4),n=length(x4))
z5 <- 2*z4
#assemble data into frame
data <- data.frame(c(x4,x5),c(y4,y5),as.factor(c(z4,z5)))
names(data) <- c("x","y","z")
#train random forest - I like h2o, but this is textbook Breimann
fit.rf <- randomForest(z~.,data=data,
ntree = 1000, replace=TRUE, nodesize = 20)
data2 <- predict(fit.rf,newdata=data[data$z==1,c(1,2)],type="response")
#separate class "1" from training data
idx1a <- which(data[,3]==1)
#separate class "1" from the predicted data
idx1b <- which(data2==1)
#show the difference in classes before and after RF based filter
plot(data[idx1a,1],data[idx1a,2])
points(data[idx1b,1],data[idx1b,2],col="Red")
这是拟合结果:
我真的很喜欢这样做,因为它可以同时显示出解决难题的体面方法的优点和缺点。如果您靠近中心看,您会看到如何减少过滤。信息的几何尺度很小,而随机森林则缺少这种信息。它说明了有关第2类的节点数,树数和样本密度的信息。在(-50,-50)附近还存在一个“间隙”,在几个位置中还存在“喷射”。但是,总的来说,过滤是不错的。
比较与SVM
这是允许与SVM比较的代码:
#now to fit to svm
fit.svm <- svm(z~., data=data, kernel="radial",gamma=10,type = "C")
x5 <- seq(from=min(x2),to=max(x2),by=1)
y5 <- seq(from=min(y2),to=max(y2),by=1)
count <- 1
x6 <- numeric()
y6 <- numeric()
for (i in 1:length(x5)){
for (j in 1:length(y5)){
x6[count]<-x5[i]
y6[count]<-y5[j]
count <- count+1
}
}
data4 <- data.frame(x6,y6)
names(data4) <- c("x","y")
data4$z <- predict(fit.svm,newdata=data4)
idx4 <- which(data4$z==1,arr.ind=TRUE)
plot(data4[idx4,1],data4[idx4,2],col="Gray",pch=20)
points(data[idx1b,1],data[idx1b,2],col="Blue",pch=20)
lines(x1,y1,pch=18,col="Green", lwd=2)
grid()
legend(x = 65,y=65,
legend = c("true","from RF","From SVM"),
col = c("Green","Blue","Gray"),lty = c(1,-1,-1),pch=c(-1,20,15),pt.cex=c(1,1,2.25))
结果如下图所示。
这是一个不错的SVM。灰色是SVM与类“ 1”关联的域。蓝点是RF与类别“ 1”关联的样本。 在没有明确规定的基础上,基于RF的滤波器的性能与SVM相当。 可以看出,螺旋中心附近的“紧密数据”被RF更“紧密”地解析了。RF还发现有朝向“尾巴”的“孤岛”,RF会找到SVM没有的关联。
我很高兴。在没有背景的情况下,我所做的早期工作之一也是由该领域的出色贡献者完成的。原始作者使用“参考分布”(link,link)。
编辑:
将随机森林应用于此模型:
尽管user777对CART是随机森林的元素有很好的想法,但随机森林的前提是“弱学习者的整体聚集”。CART是一个已知的弱学习者,但离“合奏团”不远。尽管在随机森林中,“集合”的目的是“在大量样本的限制内”。在散点图中,user777的答案至少使用了500个样本,在这种情况下,这说明了人类的可读性和样本量。人类视觉系统(本身就是学习者的集合)是一个了不起的传感器和数据处理器,它发现该值足以简化处理。
如果我们甚至在随机森林工具上采用默认设置,我们都可以观察到前几棵树的分类误差增加,并且直到大约有十棵树时才达到一棵树的水平。最初,错误会增加,减少的错误会稳定在60棵树附近。稳定是指
x <- cbind(x1, x2)
plot(rf,type="b",ylim=c(0,0.06))
grid()
如果不是查看“最小弱学习者”,而是查看针对工具默认设置的非常简短的启发式建议的“最小弱学习者”,则结果会有所不同。
请注意,我使用“线”来绘制表示近似值边缘的圆。您可以看到它是不完美的,但是比单个学习者的质量要好得多。
原始采样有88个“内部”采样。如果样本数量增加(允许整体应用),则近似质量也会提高。拥有20,000个样本的相同数量的学习者可以更好地适应需求。
质量更高的输入信息还可以评估适当数量的树木。对收敛性的检查表明,在这种特定情况下,至少有20棵树是足以表示数据的足够数量。