您呈现的图像与此处的图像相同:链接。
以下是一些代码,经过一些调整翻译成 R,以解决这个问题。选择的 RF(2 棵树)是不可接受的。这不是苹果对苹果,所以作者关于“熵”的任何断言都可能是错误的信息。
首先我们得到数据:
#reproducibility
set.seed(136526) #I like to use question number as random seed
#libraries
library(data.table) #to read the url
library(randomForest) #to have randomForests
library(miscTools) #column medians
#main program
#get data
wine_df = fread("https://archive.ics.uci.edu/ml/machine-learning-databases/wine-quality/winequality-red.csv")
#conver to frame
wine_df <- as.data.frame(wine_df)
#parse data
Y <- (wine_df[,12])
X <- wine_df[,-12]
接下来我们为它找到合适大小的随机森林。
max_trees <- 100 #same range
N_retest <- 35 #fair sample size
err <- matrix(0,max_trees,N_retest) #initialize for the loop
for (i in 1:max_trees){
for (j in 1:N_retest){
#fit random forest with "i" number of trees
my_rf <- randomForest(x = X, y = Y, ntree = i)
#pop out sum of squared residuals divided by n
temp <- mean(my_rf$mse)
err[i,j] <- temp
}
}
现在我们可以看看集合中应该有多少元素:
#make friendly for boxplot
err_frame <- as.data.frame(t(err))
names(err_frame) <- as.character(1:max_trees)
#central tendency
my_meds <- colMedians((err_frame))
#normalized slope of central tendency
est <- smooth.spline(x = 1:max_trees,y = my_meds,spar = 0.7)
pred <- predict(est)
my_sl <- c(diff(pred$y)/diff(pred$x))
my_sl <- (0.7-0.4)*(my_sl-min(my_sl))/(max(my_sl)-min(my_sl))+0.4
#make boxplot
boxplot(err_frame,
main = "MSE vs. number of trees",
xlab = "number of trees",
ylab = "forest mean MSE", xlim= c(0,75))
#draw central tendency (red)
lines(est, col="red", lwd=2)
#draw slope
lines(pred$x,c(0.4,my_sl),col="green")
points(pred$x,c(0.4,my_sl),col="green", pch=16)
grid()
legend(x = 60,y = 0.6,c("bxp","fit","slope"),
col = c("black","Red","Green"),
lty = c(NA, 1,1),
pch = c(22,-1,20),
pt.cex = c(1.2,1,1) )
它给了我们这个,然后我在 midangle-skree 启发式的一个版本中手动绘制蓝色和黑色线,以获得 30 的“体面”集合大小。它是斜坡的两条切线:一条在最高坡度,一条在域的右端。我们从这些切线的交点沿中角向斜线发出一条射线。交叉点后的下一个最高点通知树数。
现在我们有了一个不错的随机森林,我们可以查看错误。首先我们计算误差。
# make "final" model
my_rf_fin <- randomForest(x = X, y = (Y), ntree = 30)
#predict on it
pred_fin <- predict(my_rf_fin)
#compute error
fit_err <- pred_fin - Y
首先开始的图是基本的EDA 图,包括4误差图。
#EDA on error
par(mfrow = n2mfrow(4) )
#run seq
plot(fit_err, type="l")
grid()
#lag plot
plot(fit_err[2:length(fit_err)],fit_err[1:(length(fit_err)-1)] )
abline(a = 0,b=1, col="Green", lwd=2)
grid()
#histogram
hist(fit_err,breaks = 128, main = "")
grid()
#normal quantile
qqnorm(fit_err, main = "")
grid()
par(mfrow = c(1,1))
产生:
该错误表现得相当好。它的尾巴很窄。滞后图右侧有一组非高斯样本。分布的中心部分看起来是三角形的。它不是高斯的,但没想到会如此。这是建模为连续的离散电平输出。
这是实际与预测以及误差与预测的可变性图。
如果系统地高估最差的班级比额定的好,而低估最高的班级比额定的差。
这个随机森林的构造不那么糟糕,并且可能是一个更健康的函数逼近器。
下一步:在前 2 个主成分上制作与您类似的边界图。
代码注释:
- 我不是 scikit.learn 的大佬,所以我会误解他们在做什么的部分内容。标准免责声明适用。
- 合奏中的两棵树在“一人
军队”这样的术语中是矛盾的。随机森林不是“单人军队”,因为它将
CART 作为非弱学习器。作者
通过选择 2 个元素作为 ensemble size 对 ensemble learner 造成了伤害。随机森林的
最大乐趣在于您可以添加整体元素。永远不要
(永远)接受小于 20 棵树的随机森林。仔细检查
任何小于 50 棵树的森林。
- 作者没有区分训练/验证或测试。他们
使用所有数据来适应学习者。更好的方法是分成这些组,然后确定集成参数,然后使用组合的训练/有效数据制作模型。我在这里看不到。
- 作者没有说明“y”是离散的还是连续的。这意味着 RF 可能生活在回归而不是分类中。