优化场景下R语言出现Non-conformable arrays错误的排查求助
R语言nloptr::isres优化报错:数组维度不匹配
单独调用自定义滑动窗口计算函数fxn(3, 2350000)可正常返回0.67,但将该函数改造为适配nloptr包isres优化的fn函数后,运行优化代码时出现如下错误:
Error in income == 1 & truth == 0 : non-conformable arrays
完整代码
# 辅助函数与初始数据定义 somefunc <- function(values, weightvec) crossprod(values, weightvec) tiny <- data.matrix(c(2293244, 2301521, 2318491, 2334855, 2350360, 2357444)) vec <- data.matrix(rep(1/3, 3)) roll <- data.matrix(unlist(lapply(seq(nrow(tiny) - 3 + 1), function(i) somefunc(tiny[i - 1 + seq(3), ], vec)))) zeros_ones <- data.matrix(c(0, 1, 1, 0, 0, 1)) deltat <- 3 truth <- data.matrix(zeros_ones[-1:-(deltat - 1), ]) # 可正常运行的函数 fxn <- function(deltat, thres) { truth <- data.matrix(zeros_ones[-1:-(deltat - 1), ]) income <- data.matrix(unlist(lapply(seq(nrow(tiny) - deltat + 1), function(i) somefunc(tiny[i - 1 + seq(deltat), ], data.matrix(rep(1/deltat, deltat)))))) income[income < thres] <- 1 income[income != 1] <- 0 FP <- length(which(income == 1 & truth == 0)) FN <- length(which(income == 0 & truth == 1)) TP <- length(which(income == 1 & truth == 1)) TN <- length(which(income == 0 & truth == 0)) return(2 * (TP/(TP + FP)) * (TP/(TP + FN))/((TP/(TP + FP)) + (TP/(TP + FN)))) } # 用于优化的函数(报错版本) fn <- function(input) { deltat <- input[1] thres <- input[2] truth <- data.matrix(zeros_ones[-1:-(deltat - 1), ]) income <- data.matrix(unlist(lapply(seq(nrow(tiny) - deltat + 1), function(i) somefunc(tiny[i - 1 + seq(deltat), ], data.matrix(rep(1/deltat, deltat)))))) income[income < thres] <- 1 income[income != 1] <- 0 FP <- length(which(income == 1 & truth == 0)) FN <- length(which(income == 0 & truth == 1)) TP <- length(which(income == 1 & truth == 1)) TN <- length(which(income == 0 & truth == 0)) return(1 - ((2 * (TP/(TP + FP)) * (TP/(TP + FN)))/((TP/(TP + FP)) + (TP/(TP + FN))))) } x0 <- c(3, 2350000) lb <- c(2, 2200000) ub <- c(3, 2500000) library(nloptr) isres(fn = fn, x0 = x0, lower = lb, upper = ub, maxeval = 100000)
错误原因
isres是全局优化算法,会在你设定的上下界内尝试浮点数类型的参数值,而不是仅整数。比如当deltat被传入2.1这类小数时:
truth <- data.matrix(zeros_ones[-1:-(deltat - 1), ])中,deltat-1=1.1,-1:-(1.1)会被R处理为-1:-1,导致truth的长度为5;- 而
income的长度由seq(nrow(tiny)-deltat+1)生成,此时nrow(tiny)-deltat+1=6-2.1+1=4.9,seq(4.9)等价于seq(1,4),所以income长度为4; - 两者长度不一致,执行
income == 1 & truth == 0时就会触发维度不匹配错误。
而单独调用fxn(3,2350000)时,你传入的是整数3,所以truth和income长度都是4,不会报错。
解决方案
在fn函数中,将deltat强制转换为整数,确保参数符合滑动窗口的整数要求。可以根据需求选择取整方式(如四舍五入、向下取整),这里用四舍五入:
fn <- function(input) { deltat <- as.integer(round(input[1])) # 新增:强制转为整数 thres <- input[2] truth <- data.matrix(zeros_ones[-1:-(deltat - 1), ]) income <- data.matrix(unlist(lapply(seq(nrow(tiny) - deltat + 1), function(i) somefunc(tiny[i - 1 + seq(deltat), ], data.matrix(rep(1/deltat, deltat)))))) income[income < thres] <- 1 income[income != 1] <- 0 FP <- length(which(income == 1 & truth == 0)) FN <- length(which(income == 0 & truth == 1)) TP <- length(which(income == 1 & truth == 1)) TN <- length(which(income == 0 & truth == 0)) return(1 - ((2 * (TP/(TP + FP)) * (TP/(TP + FN)))/((TP/(TP + FP)) + (TP/(TP + FN))))) }
修改后重新运行isres优化代码,即可避免维度不匹配错误。
内容的提问来源于stack exchange,提问作者jlewis
相关产品推荐
相关产品推荐

