BRT: 使用gbm.perspec为交互图添加渐变颜色

我想在我的三维依赖图中,根据拟合值添加一系列渐变颜色(例如,较高的拟合值使用较深的颜色,较低的拟合值使用较浅的颜色)。

我使用了dismo包中提供的示例:

library(dismo) data(Anguilla_train)angaus.tc5.lr01 <- gbm.step(data=Anguilla_train, gbm.x = 3:13, gbm.y = 2,family = "bernoulli", tree.complexity = 5, learning.rate = 0.01, bag.fraction = 0.5)# 在gbm模型中查找交互作用:find.int <- gbm.interactions( angaus.tc5.lr01)find.int$interactionsfind.int$rank.list

我只能将整个图设置为同一种颜色:

gbm.perspec( angaus.tc5.lr01, 7, 1,            x.label = "USRainDays",            y.label = "SegSumT",             z.label = "Fitted values",            z.range=c(0,0.435),            col="blue")

Interaction plot all in one colour

或者添加渐变色,但不依据拟合值:

    gbm.perspec( angaus.tc5.lr01, 7, 1,             x.label = "USRainDays",             y.label = "SegSumT",              z.label = "Fitted values",             col=heat.colors(50),             z.range=c(0,0.435))

Interaction plot with different colours not following fitted values

我还检查了gbm.perspec函数的代码,如果我理解正确的话,拟合值在公式中被称为“prediction”,后来成为了传递给最终绘图的“pred.matrix”的一部分:persp(x = x.var, y = y.var, z = pred.matrix…),但我无法从gbm.perspec公式中访问它们。我尝试通过在函数内的persp()中添加“col=heat.colors(100)[round(pred.matrix*100, 0)]”来修改gbm.perpec函数,但这并未达到我想要的效果:

persp(x = x.var, y = y.var, z = pred.matrix, zlim = z.range,       xlab = x.label, ylab = y.label, zlab = z.label,       theta = theta, phi = phi, r = sqrt(10), d = 3,       ticktype = ticktype,      col=heat.colors(100)[round(pred.matrix*100, 0)],       mgp = c(4, 1, 0), ...)

Interaction plot coloured following predicted values (?) but not showing the colours properly

我认为解决方案可能来自于修改gbm.perpec函数,您知道如何做吗?

感谢您的宝贵时间!


回答:

通过将这里找到的一些代码整合到gbm.perspec()的源代码中,您可以创建所需的效果。

首先运行

# 颜色调色板(100种颜色)col.pal<-colorRampPalette(c("blue", "red"))colors<-col.pal(100)

然后,在gbm.perspec()源代码中的else之后添加z.facet.center,并将代码中的z更改为pred.matrix,如下所示,

# 最后绘制结果#if (!perspective) {  image(x = x.var, y = y.var, z = pred.matrix, zlim = z.range)} else {  z.facet.center <- (pred.matrix[-1, -1] + pred.matrix[-1, -ncol(pred.matrix)] +                        pred.matrix[-nrow(pred.matrix), -1] + pred.matrix[-nrow(pred.matrix), -ncol(pred.matrix)])/4  # 面中心的范围按100比例(颜色数量)  z.facet.range<-cut(z.facet.center, 100)  persp(x=x.var, y=y.var, z=pred.matrix, zlim= z.range,      # 输入变量        xlab = x.label, ylab = y.label, zlab = z.label,   # 标签        theta=theta, phi=phi, r = sqrt(10), d = 3,        col=colors[z.facet.range],# 视图参数        ticktype = ticktype, mgp = c(4,1,0), ...) #

这将为您生成如下图表(请注意,这不是使用示例数据集绘制的,因此交互效果与问题中的图表不同)。 enter image description here

或者,您可以创建一个新函数。以下示例修改了gbm.perspec()以提供从白色到红色的渐变。只需在R中运行代码,然后将gbm.perspec()更改为gbm.perspec2()

# 交互函数 # 颜色调色板(100种颜色)col.pal<-colorRampPalette(c("white", "pink", "red"))colors<-col.pal(100)gbm.perspec2 <- function(gbm.object,                         x = 1,                # 要绘制的第一个变量                        y = 2,                # 要绘制的第二个变量                        pred.means = NULL,    # 允许为其他变量指定值                        x.label = NULL,       # 允许手动指定x轴标签                        x.range = NULL,       # 手动指定x变量的范围                        y.label = NULL,       # 以及y轴标签                        z.label = "fitted value", #默认z轴标签                        y.range = NULL,       # 以及y                        z.range = NULL,       # 允许控制垂直轴                        leg.coords = NULL,  #可以指定图例的坐标(x, y)                        ticktype = "detailed",# 指定详细类型 - 否则为"simple"                        theta = 55,           # 旋转角度                         phi=40,               # 和仰角                         smooth = "none",      # 控制预测表面的平滑                        mask = FALSE,         # 控制是否使用样本强度模型进行掩蔽                        perspective = TRUE,   # 控制是绘制轮廓图还是透视图                        ...)                  # 允许传递额外的参数给绘图例程# 有用的选项包括shade, ltheta, lphi来控制照明# 和cex来控制文本大小 - cex.axis和cex.lab没有效果{    if (! requireNamespace('gbm') ) { stop('您需要安装gbm包来使用此函数') }  requireNamespace('splines')  #获取提升模型的详细信息    gbm.call <- gbm.object$gbm.call  gbm.x <- gbm.call$gbm.x  n.preds <- length(gbm.x)  gbm.y <- gbm.call$gbm.y  pred.names <- gbm.call$predictor.names  family = gbm.call$family    # 现在为x和y预测变量设置范围变量    have.factor <- FALSE    x.name <- gbm.call$predictor.names[x]  if (is.null(x.label)) {    x.label <- gbm.call$predictor.names[x]  }      y.name <- gbm.call$predictor.names[y]  if (is.null(y.label)) {    y.label <- gbm.call$predictor.names[y]  }  data <- gbm.call$dataframe[ , gbm.x, drop=FALSE]    n.trees <- gbm.call$best.trees    # 如果边缘变量是向量,则在范围内创建间隔    if (is.vector(data[,x])) {    if (is.null(x.range)) {      x.var <- seq(min(data[,x],na.rm=T),max(data[,x],na.rm=T),length = 50)    } else {      x.var <- seq(x.range[1],x.range[2],length = 50)     }  } else {    x.var <- names(table(data[,x]))    have.factor <- TRUE  }  if (is.vector(data[,y])) {    if (is.null(y.range)) {      y.var <- seq(min(data[,y],na.rm=T),max(data[,y],na.rm=T),length = 50)    }  else {y.var <- seq(y.range[1],y.range[2],length = 50)}  } else {    y.var <- names(table(data[,y]))    if (have.factor) {  #检查我们是否已经有一个因子       stop("至少有一个边缘预测变量必须是向量!")    } else {have.factor <- TRUE}  }  pred.frame <- expand.grid(list(x.var,y.var))  names(pred.frame) <- c(x.name,y.name)  pred.rows <- nrow(pred.frame)    #确保因子变量首先出现    if (have.factor) {    if (is.factor(pred.frame[,2])) {  # 交换它们      pred.frame <- pred.frame[,c(2,1)]      x.var <- y.var    }  }    j <- 3  # 循环遍历预测变量  # 如果是非目标变量,找到均值  for (i in 1:n.preds) {    if (i != x & i != y) {      if (is.vector(data[,i])) {        m <- match(pred.names[i],names(pred.means))        if (is.na(m)) {          pred.frame[,j] <- mean(data[,i],na.rm=T)        } else pred.frame[,j] <- pred.means[m]      }      if (is.factor(data[,i])) {        m <- match(pred.names[i],names(pred.means))        temp.table <- table(data[,i])        if (is.na(m)) {          pred.frame[,j] <- rep(names(temp.table)[2],pred.rows)        } else {          pred.frame[,j] <- pred.means[m]        }        pred.frame[,j] <- factor(pred.frame[,j],levels=names(temp.table))      }      names(pred.frame)[j] <- pred.names[i]      j <- j + 1    }  }    #  # 形成预测  #  #assign("pred.frame", pred.frame, pos=1)  prediction <- gbm::predict.gbm(gbm.object,pred.frame,n.trees = n.trees, type="response")  #assign("prediction", prediction, pos=1, immediate =T)    # 如果需要,模型平滑    if (smooth == "model") {    pred.glm <- glm(prediction ~ ns(pred.frame[,1], df = 8) * ns(pred.frame[,2], df = 8), data=pred.frame,family=poisson)    prediction <- fitted(pred.glm)  }    # 报告最大值并为z设置现实范围    max.pred <- max(prediction)  message("最大值 = ",round(max.pred,2),"\n")    if (is.null(z.range)) {    if (family == "bernoulli") {      z.range <- c(0,1)    } else if (family == "poisson") {      z.range <- c(0,max.pred * 1.1)    } else {      z.min <- min(data[,y],na.rm=T)      z.max <- max(data[,y],na.rm=T)      z.delta <- z.max - z.min      z.range <- c(z.min - (1.1 * z.delta), z.max + (1.1 * z.delta))    }  }    # 现在处理假设x和y都是向量    if (have.factor == FALSE) {        # 形成矩阵        pred.matrix <- matrix(prediction,ncol=50,nrow=50)        # 如果需要,进行核平滑        if (smooth == "average") {  #应用3x3平滑平均      pred.matrix.smooth <- pred.matrix      for (i in 2:49) {        for (j in 2:49) {          pred.matrix.smooth[i,j] <- mean(pred.matrix[c((i-1):(i+1)),c((j-1):(j+1))])        }      }      pred.matrix <- pred.matrix.smooth    }        # 屏蔽超矩形内但样本空间外的值        if (mask) {      mask.trees <- gbm.object$gbm.call$best.trees      point.prob <- gbm::predict.gbm(gbm.object[[1]],pred.frame, n.trees = mask.trees, type="response")      point.prob <- matrix(point.prob,ncol=50,nrow=50)      pred.matrix[point.prob < 0.5] <- 0.0    }    #    # 最后绘制结果    #    if (!perspective) {      image(x = x.var, y = y.var, z = pred.matrix, zlim = z.range)    } else {      z.facet.center <- (pred.matrix[-1, -1] + pred.matrix[-1, -ncol(pred.matrix)] +                            pred.matrix[-nrow(pred.matrix), -1] + pred.matrix[-nrow(pred.matrix), -ncol(pred.matrix)])/4      # 面中心的范围按100比例(颜色数量)      z.facet.range<-cut(z.facet.center, 100)      persp(x=x.var, y=y.var, z=pred.matrix, zlim= z.range,      # 输入变量            xlab = x.label, ylab = y.label, zlab = z.label,   # 标签            theta=theta, phi=phi, r = sqrt(10), d = 3,            col=colors[z.facet.range],# 视图参数            ticktype = ticktype, mgp = c(4,1,0), ...) #    }  }  if (have.factor) {    # 我们需要为每个x绘制y的值    factor.list <- names(table(pred.frame[,1]))    n <- 1    #添加这一部分,以便z.range仍然按预期工作:    if (is.null(z.range)) {      vert.limits <- c(0, max.pred * 1.1)    } else {      vert.limits <- z.range    }        plot(pred.frame[pred.frame[,1]==factor.list[1],2],         prediction[pred.frame[,1]==factor.list[1]],         type = 'l',          #ylim = c(0, max.pred * 1.1),          ylim = vert.limits,         xlab = y.label,         ylab = z.label, ...)    for (i in 2:length(factor.list)) {       #factor.level in factor.list) {      factor.level <- factor.list[i]      lines(pred.frame[pred.frame[,1]==factor.level,2],            prediction[pred.frame[,1]==factor.level], lty = i)    }        # 现在绘制图例    if(is.null(leg.coords)){      x.max <- max(pred.frame[,2])      x.min <- min(pred.frame[,2])      x.range <- x.max - x.min      x.pos <- c(x.min + (0.02 * x.range),x.min + (0.3 * x.range))            y.max <- max(prediction)      y.min <- min(prediction)      y.range <- y.max - y.min      y.pos <- c(y.min + (0.8 * y.range),y.min + (0.95 * y.range))      legend(x = x.pos, y = y.pos, factor.list, lty = c(1:length(factor.list)), bty = "n")    } else {      legend(x = leg.coords[1], y = leg.coords[2], factor.list, lty = c(1:length(factor.list)), bty = "n", ncol = 2)    }  }}

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注