R中的数值比较精度;在函数之间传递值

时间:2013-11-22 23:40:45

标签: r precision equality rpart

看了这个问题:Numeric comparison difficulty in R

我仍然卡住了,因为我依赖于一些我无法编​​辑的功能深层次的相等比较(或者我可以吗?)

我在本地环境中测试三个数字是否总和为一个(sum(p)==1 --> TRUE),但是当我将这三个数字的向量传递给另一个函数时,类似的相等测试失败了 - 这让我觉得数字正在改变,因为他们从一个功能传递到下一个功能 - 这可能吗?

更多细节:我正在尝试“优化”提供给CART模型的先验概率,使用优化器(dfoptim package, nmkb)选择先验组合,将它们发送到rpart包进行模型拟合,然后验证(rps函数)包用于评分 - 但在rpart包中的某个地方,我之前的概率是抛出错误,因为rpart认为他们没有总和为1.

这是一个可重复的例子:

require('rpart')
require('verification')
require('dfoptim')
data(iris)
set.seed(1)
tmp1 <- paste0(names(iris),collapse="+")
tmp2 <- gsub("\\+Species","",tmp1)
fmlatext <- paste0("Species~",tmp2)
tree <- rpart(as.formula(fmlatext),data=iris,method="class")
objfun <- function(priors,fmlatext,data){
  p <- priors/sum(priors) # turn arbitrary threesome into numbers that sum to 1
  p[1] <- 1-(sum(p)-p[1]) # ensure that numbers sum to 1
  print(c(p,sum(p)),digits=16)
  tree <- rpart(as.formula(fmlatext),data=data,parms=list(prior=p),
                method="class") 
  rpst <- rps(data$Species,predict(tree,data=data))
  return(rpst$rpss)
}
nlev <- nlevels(iris$Species)
guess <- seq(nlev)*10
lb <- rep(1,nlev)
ub <- rep(100,nlev)
bestpriors <- nmkb(par=guess,fn=objfun,lower=lb,upper=ub,
                   control=list(maximize=TRUE),fmlatext=fmlatext,data=iris)

运行此代码会给我输出:

[1] 0.1666666666666667 0.3333333333333333 0.5000000000000000 1.0000000000000000
[1] 0.4353687449261023 0.2354416940871099 0.3291895609867877 1.0000000000000000
[1] 0.1224920651311070 0.5548713793562775 0.3226365555126156 1.0000000000000000
[1] 0.1268712138061573 0.2390044736120877 0.6341243125817551 1.0000000000000000
[1] 0.35141687748184969 0.57028058689316308 0.07830253562498726 1.00000000000000000
[1] 0.2997590406445614 0.5077659444797995 0.1924750148756391 1.0000000000000000
[1] 0.3598141573675122 0.4350423262345758 0.2051435163979119 0.9999999999999999
Error in get(paste("rpart", method, sep = "."), envir = environment())(Y,  : 
  Priors must sum to 1

在我的真正的代码中,这种情况发生的次数不一致,具体取决于数据和猜测值,但它确实发生了,并且真的很痛苦。

如何通过此错误? 干杯,R

1 个答案:

答案 0 :(得分:0)

潜在答案;不确定它是否强大或者尚未确定,但是我创建了这个函数并且它正在为之前失败的一些测试用例工作:

makeSumToOne <- function(vec) {
  p <- round(1024*vec/sum(vec),0)
  p[1] <- 1024-(sum(p)-p[1])
  p <- p/1024
  return(p)
}

并用原始代码替换这些行:

  p <- priors/sum(priors) # turn arbitrary threesome into numbers that sum to 1
  p[1] <- 1-(sum(p)-p[1]) # ensure that numbers sum to 1

这一个:

  p <- makeSumToOne(priors)

我正在阅读关于精确度的文章,并指出'2的权力'经常出现,所以我认为在我的程序中使用'2'2^10=1024的力量可能会有所帮助...它到目前为止有所帮助,但是我怀疑它是否健壮。除非没有人想出更好的答案,否则我不认为这是答案。 (或解释为什么此解决方案有效,并且roundsignif或其他函数的解决方案失败。)