R语言optim()函数迭代时报'type 'closure' not subsettable'错误咨询
错误原因
核心问题来自两个低级错误:
- 目标函数参数顺序不符合optim要求:
optim规定传入的损失函数第一个入参必须是待优化的参数向量,你定义的fit_nm2参数顺序是(data, par),第一个是固定数据集,第二个才是待优化参数。迭代时optim会把自动生成的候选参数传给损失函数的第一个入参,而你指定的data=rep被传给了第二个入参par,后续代码执行par[1]时,par实际是R内置的rep函数(closure类型),对函数取子集就会触发type 'closure' not subsettable报错。 - 变量命名冲突:你用R内置的重复函数名
rep作为测试数据的变量名,进一步放大了参数传递错误的影响,即使调整参数顺序后,后续调用rep函数也可能出现变量覆盖问题。
迭代到中途才报错的原因是:前几轮迭代生成的参数刚好没触发par子集调用的校验,后续参数变化后才暴露了变量类型错误。
解决方法
按照以下步骤修正即可正常运行:
- 调整损失函数的参数顺序,将待优化的
par放到第一个位置,同时增加参数合理性校验,避免无效参数(如标准差趋近于0、混合权重趋近于0/1)触发distr包内部报错:
library(distr) library(e1071) pmn2 <- function(p,mean1,mean2,sd1,sd2,w) { distr::p( distr::UnivarMixingDistribution(distr::Norm(mean1,sd1), distr::Norm(mean2,sd2), mixCoeff = c(w,1-w)) )(p) } # 调整参数顺序,par放第一位 fit_nm2 <- function(par, data) { n <- nrow(data) bins <- data[,1] probs <- data[,2] wid <- (bins[n] - bins[1])/(n-1) # 先做参数校验,无效参数直接返回大损失值,让优化器跳过该区间 w <- sigmoid(par[5]) if (w < 1e-4 || w > 1 - 1e-4) return(1e10) sd1 <- exp(par[3]) sd2 <- exp(par[4]) if (sd1 < 1e-3 || sd2 < 1e-3) return(1e10) # 合并两次pmn2调用,减少重复计算 mix_cdf <- p(UnivarMixingDistribution(Norm(par[1], sd1), Norm(par[2], sd2), mixCoeff = c(w, 1-w))) dif <- sum((mix_cdf(bins + wid) - mix_cdf(bins) - probs)^2) return(dif) }
- 不要用
rep作为数据变量名,换为无冲突的名称比如bin_data:
bin_data <- structure(c(4, 4.1, 4.2, 4.3, 4.4, 4.5, 4.6, 4.7, 4.8, 4.9, 5, 5.1, 5.2, 5.3, 5.4, 5.5, 5.6, 5.7, 5.8, 5.9, 6, 0.042145594, 0.026819923, 0.003831418, 0.061302682, 0.011494253, 0.057471264, 0.076628352, 0.042145594, 0.0651341, 0.042145594, 0.076628352, 0.053639847, 0.026819923, 0.053639847, 0.08045977, 0.019157088, 0.068965517, 0.072796935, 0.011494253, 0.049808429, 0.057471264 ), .Dim = c(21L, 2L), .Dimnames = list(NULL, c("bins", "probs")))
- 重新调用optim即可正常运行:
fitnm2 <- optim(fn = fit_nm2, data = bin_data, par = c(5, 1, 5, 1, .5))
如果需要优化更稳定,可以指定method = "L-BFGS-B"给参数加上合理上下界,避免优化器探索到极端无效参数区间。
内容的提问来源于stack exchange,提问作者spencergw
相关产品推荐
相关产品推荐

