我已经读过一些资料,包括本资料,其中“ 随机森林”对离群值不敏感(例如Logistic回归和其他ML方法都是如此)。
但是,有两种直觉告诉我:
每当构建决策树时,都必须对所有点进行分类。这意味着,甚至离群值也将被分类,因此会影响在增强期间选择它们的决策树。
自举是RandomForest进行子采样的一部分。自举容易受到异常值的影响。
有什么办法可以使我对直觉对异常值敏感的直觉与不同意的消息来源相吻合?
min_samples_leaf_nodeis是1,那么它可能会受到异常值的影响。
我已经读过一些资料,包括本资料,其中“ 随机森林”对离群值不敏感(例如Logistic回归和其他ML方法都是如此)。
但是,有两种直觉告诉我:
每当构建决策树时,都必须对所有点进行分类。这意味着,甚至离群值也将被分类,因此会影响在增强期间选择它们的决策树。
自举是RandomForest进行子采样的一部分。自举容易受到异常值的影响。
有什么办法可以使我对直觉对异常值敏感的直觉与不同意的消息来源相吻合?
min_samples_leaf_nodeis是1,那么它可能会受到异常值的影响。
Answers:
您的直觉是正确的。该答案仅在示例中进行了说明。
确实,人们普遍认为CART / RF对异常值具有一定的鲁棒性。
为了说明RF对单个异常值的存在缺乏鲁棒性,我们可以(轻轻地)修改上述Soren Havelund Welling答案中使用的代码,以表明单个 ' y '异常值足以完全影响拟合的RF模型。例如,如果我们将未污染观测值的平均预测误差计算为离群值与其余数据之间距离的函数,则可以看到(下图)引入单个离群值(通过替换原始观测值之一)在``y''空间上的任意值)足以使RF模型的预测任意远离它们(如果对原始(未污染)数据进行计算将获得的值):
library(forestFloor)
library(randomForest)
library(rgl)
set.seed(1)
X = data.frame(replicate(2,runif(2000)-.5))
y = -sqrt((X[,1])^4+(X[,2])^4)
X[1,]=c(0,0);
y2<-y
rg<-randomForest(X,y) #RF model fitted without the outlier
outlier<-rel_prediction_error<-rep(NA,10)
for(i in 1:10){
y2[1]=100*i+2
rf=randomForest(X,y2) #RF model fitted with the outlier
rel_prediction_error[i]<-mean(abs(rf$predict[-1]-y2[-1]))/mean(abs(rg$predict[-1]-y[-1]))
outlier[i]<-y2[1]
}
plot(outlier,rel_prediction_error,type='l',ylab="Mean prediction error (on the uncontaminated observations) \\\ relative to the fit on clean data",xlab="Distance of the outlier")
多远?在上面的示例中,单个离群值已更改了拟合量,以至于如果将模型拟合到未污染的数据上,那么(未污染的)观测值的平均预测误差现在将比原值大1-2个数量级。
因此,单个异常值不能影响RF拟合是不正确的。
此外,正如我在其他地方指出的那样,当可能存在多个异常值时,异常值将很难处理(尽管并不需要在数据中占很大比例才能显示其影响)。当然,受污染的数据可以包含多个异常值;要测量多个异常值对RF拟合的影响,请将通过RF从未经污染的数据上获得的左侧图与通过任意移动5%响应值获得的右侧图进行比较(代码在答案下方) 。
最后,在回归环境中,必须指出,离群值可以在设计和响应空间中的大量数据中脱颖而出(1)。在RF的特定上下文中,设计异常值将影响超参数的估计。但是,当维数较大时,第二个效果更加明显。
我们在这里观察到的是更普遍结果的特殊情况。基于凸损失函数的多元数据拟合方法对异常值的极端敏感性已被重新发现多次。有关ML方法特定上下文的说明,请参见(2)。
幸运的是,虽然基本的CART / RF算法着重于对离群值的鲁棒性不足,但有可能(且很容易实现)修改该过程,以将其对“ y”离群值的鲁棒性赋予优势。现在,我将集中讨论回归RF(因为这更是OP问题的对象)。更准确地说,将任意节点的分裂准则写为:
其中和是取决于的选择的新兴子节点(和是隐式函数), 表示落入左侧子节点的数据部分,而是份额的数据。然后,可以通过用健壮的替代方法替换原始定义中使用的方差函数,将“ y”空间的健壮性赋予回归树(从而得到RF)。从本质上讲,这是在(4)中使用的方法,其中方差被健壮的规模M估计器所取代。t R s ∗ t L t R s p L t L p R = 1 − p L t R
library(forestFloor)
library(randomForest)
library(rgl)
set.seed(1)
X<-data.frame(replicate(2,runif(2000)-.5))
y<--sqrt((X[,1])^4+(X[,2])^4)
Col<-fcol(X,1:2) #make colour pallete by x1 and x2
#insert outlier2 and colour it black
y2<-y;Col2<-Col
y2[1:100]<-rnorm(100,200,1); #outliers
Col[1:100]="#000000FF" #black
#plot training set
plot3d(X[,1],X[,2],y,col=Col)
rf=randomForest(X,y) #RF on clean data
rg=randomForest(X,y2) #RF on contaminated data
vec.plot(rg,X,1:2,col=Col,grid.lines=200)
mean(abs(rf$predict[-c(1:100)]-y[-c(1:100)]))
mean(abs(rg$predict[-c(1:100)]-y2[-c(1:100)]))
p和s公式吗?
离群值1a:此离群值具有一个或多个极端特征值,并且与任何其他样本都距离较远。异常值将像其他任何样本一样影响树木的初始分裂,因此没有强烈的影响。它与任何其他样本的接近度都较低,并且只会在要素空间的较远部分定义模型结构。在预测期间,大多数新样本可能与此异常值不相似,并且很少会出现在同一终端节点中。此外,决策树将要素视为序数(等级)。该值小于/等于或大于断点,因此特征值是否为极端异常值无关紧要。
离群值1b:对于分类,一个单独的样本嵌入到不同类别的许多样本中间时,可以视为离群值。前面我描述了默认的RF模型将如何受到这一奇数类样本的影响,但仅非常接近该样本。
离群值2:此离群值的极端目标值可能比其他任何值都高很多倍,但特征值是正常的。该样本中有0.631的树的末端节点。模型结构将在离异常点较近的地方受到局部影响。请注意,模型结构主要平行于特征轴受到影响,因为节点是单变量拆分的。
我包括了outlier_2的RF回归模拟。从光滑的圆形结构和一个离群值更高的目标值(y = 2, = 0, = 0)得出的点数为1999 。训练集显示在左侧。右侧显示了学习到的RF模型结构。
library(forestFloor)
library(randomForest)
library(rgl)
set.seed(1)
X = data.frame(replicate(2,runif(2000)-.5))
y = -sqrt((X[,1])^4+(X[,2])^4)^1
Col = fcol(X,1:2) #make colour pallete by x1 and x2
#insert outlier2 and colour it black
X[1,] = c(0,0);y[1]=2 ;Col[1] = "#000000FF" #black
#plot training set
plot3d(X[,1],X[,2],y,col=Col)
rf = randomForest(X,y)
vec.plot(rf,X,1:2,col=Col,grid.lines = 400)
编辑:评论到user603
是的,对于目标范围上的极端异常,应该在运行RF之前考虑转换目标范围。我在下面添加了一个对randomForest进行调整的robustModel()函数。另一个解决方案是在训练之前进行对数转换。
.
##---code by user603
library(forestFloor)
library(randomForest)
library(rgl)
set.seed(1)
X<-data.frame(replicate(2,runif(2000)-.5))
y<--sqrt((X[,1])^4+(X[,2])^4)
Col<-fcol(X,1:2) #make colour pallete by x1 and x2
#insert outlier2 and colour it black
y2<-y;Col2<-Col
y2[1:100]<-rnorm(100,200,1); #outliers
Col2[1:100]="#000000FF" #black
##---
#function to make models robust
robustModel = function(model,keep.outliers=TRUE) {
f = function(X,y,lim=c(0.1,.9),keep.outliers="dummy",...) {
limits = quantile(y,lim)
if(keep.outliers) {#keep but reduce outliers
y[limits[1]>y] = limits[1] #lower limit
y[limits[2]<y] = limits[2] #upper limit
} else {#completely remove outliers
thrashThese = mapply("||",limits[1]>y,limits[2]>y)
y = y[thrashThese]
X = X[thrashThese,]
}
obj = model(x=X,y=y,...)
class(obj) = c("robustMod",class(obj))
return(obj)
}
formals(f)$keep.outliers = keep.outliers
return(f)
}
robustRF = robustModel(randomForest) #make RF robust
rh = robustRF(X,y2,sampsize=250) #train robustRF
vec.plot(rh,X,1:2,col=Col2) #plot model surface
mean(abs(rh$predict[-c(1:100)]-y2[-c(1:100)]))
y[1]=200您会发现它一手导致未受污染的观测值的预测误差跳升了20倍!
对异常值具有鲁棒性的不是Random Forest算法本身,而是它的基础学习者:决策树。决策树将非典型观察结果隔离为小叶子(即原始空间的小子空间)。此外,决策树是局部模型。与线性回归不同,线性回归中的整个空间都具有相同的方程式,因此非常简单的模型可以局部地拟合到每个子空间(即每个叶子)。
因此,例如,对于回归,极值不会影响整个模型,因为它们会在本地平均。因此,与其他值的拟合不受影响。
实际上,这种理想的特性会延续到其他树状结构,如树状图。例如,分层聚类长期以来一直用于数据清理,因为它可以将异常的观察结果自动隔离到较小的聚类中。例如参见Loureiro等。(2004)。使用聚类方法的异常值检测:数据清理应用程序。
因此,简而言之,RF通过递归分区和局部模型拟合继承了其对异常值的不敏感性。
请注意,决策树是低偏差但高方差模型:决策树的结构易于在对训练集进行少量修改(删除或添加一些观察值)后发生变化。但这不应误认为是对异常值的敏感性,这是另一回事。
labeled还是unlabeled数据?又如何在包含分类和数值特征的异构数据上实现这种聚类呢?