You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

R中optimx报错:无法在初始参数处评估函数求助

解决optimx无法评估初始参数的问题(Lee-Carter模型参数估计)

你的报错核心原因是计算链完全断裂:calculate_error函数直接调用convert2时,Lx、lx等关键中间变量从未生成,导致R无法在初始参数处计算函数值。以下是代码中的关键错误及修正方案:

关键问题梳理

  1. 计算流程缺失:calculate_error跳过了从kt到mx、qx、lx、dx、Lx的完整推导步骤,直接调用最终转换函数,导致变量未定义。
  2. 函数参数冗余/未定义:多个辅助函数存在无效参数(如convert1的mx、qx),或引用了函数外部未定义的变量(如calculate_dx中的l0)。
  3. 循环与公式错误:calculate_lx的循环逻辑重复赋值,calculate_Lx的公式不符合预期寿命推导逻辑,且循环语法有误。
  4. 初始参数不合理:Lee-Carter模型中kt通常是中心化数值(均值接近0),你给出的初始值接近预期寿命,可能导致优化难以收敛。

修正后的完整代码

# 简化的ax和bx矩阵
ax <- c(-4.3198094, -5.8995814, -6.1240039, -7.0870399, -7.0525417)
bx <- c(0.04522097, 0.02488256, 0.02452534, -3.2110186, -3.0955417)

data <- data.frame(
  DATE = as.Date(c("2019-01-01", "2020-01-01", "2021-01-01", "2022-01-01", "2023-01-01")),
  LE = c(77.76000, 77.05507, 76.34821, 75.64329, 74.93836)
)
e0_expert <- data$LE

# 从kt计算mx并转换为qx(移除冗余参数)
mx_to_qx <- function(ax, bx, kt) {
  mx <- exp(ax + kt * bx)
  # 死亡均匀分布假设下的qx近似,限制qx不超过1避免负数lx
  qx <- pmin((2 * mx) / (2 + mx), 0.9999)
  return(qx)
}

# 从qx计算lx(修正循环逻辑)
calculate_lx <- function(qx, l0 = 10000) {
  n <- length(qx)
  lx <- numeric(n + 1)  # lx长度比qx多1(l0到ln)
  lx[1] <- l0
  for (i in 1:n) {
    lx[i + 1] <- lx[i] * (1 - qx[i])
  }
  return(lx)
}

# 从lx计算dx(移除冗余参数,修复未定义变量)
calculate_dx <- function(lx) {
  n <- length(lx) - 1
  dx <- numeric(n)
  for (i in 1:n) {
    dx[i] <- lx[i] - lx[i + 1]
  }
  return(dx)
}

# 从lx和dx计算Lx(修正公式与循环语法)
calculate_Lx <- function(lx, dx) {
  n <- length(dx)
  Lx <- numeric(n)
  # 0岁组特殊处理(死亡集中在前半年)
  Lx[1] <- lx[2] + 0.5 * dx[1]
  # 其他年龄组使用死亡均匀分布假设
  for (i in 2:n) {
    Lx[i] <- (lx[i] + lx[i + 1]) / 2
  }
  # 最后一个年龄组Lx(假设寿命极限,简化为lx[n+1]/0.001)
  Lx[n] <- lx[n + 1] / 0.001
  return(Lx)
}

# 从Lx和lx计算出生预期寿命e0(移除冗余参数)
Lx_to_e0 <- function(Lx, lx) {
  Tx <- rev(cumsum(rev(Lx)))  # 计算剩余寿命总和Tx
  ex <- Tx / lx[1:length(Tx)] # 预期寿命ex = Tx/lx
  return(ex[1])               # 返回出生预期寿命e0
}

# 误差计算函数(补全完整计算链)
calculate_error <- function(kt, e0_expert, ax, bx) {
  if (length(kt) != length(e0_expert)) {
    stop("kt长度必须与e0_expert一致")
  }
  total_error <- 0
  for (t in 1:length(kt)) {
    # 完整推导链:kt -> qx -> lx -> dx -> Lx -> e0
    qx <- mx_to_qx(ax, bx, kt[t])
    lx <- calculate_lx(qx)
    dx <- calculate_dx(lx)
    Lx <- calculate_Lx(lx, dx)
    e0_est <- Lx_to_e0(Lx, lx)
    total_error <- total_error + (e0_est - e0_expert[t])^2
  }
  cat("当前误差平方和:", total_error, "\n")
  return(total_error)
}

# 使用符合Lee-Carter特性的初始kt(中心化,均值为0)
initial_kt <- rep(0, length(e0_expert))

# 运行optimx优化
library(optimx)
result <- optimx(
  par = initial_kt,
  fn = calculate_error,
  e0_expert = e0_expert,
  ax = ax,
  bx = bx,
  method = "Nelder-Mead",
  control = list(trace = 1, maxit = 1000, abstol = 1e-6, minimize = TRUE)
)

# 输出最优kt
optimal_kt <- result$par
cat("最优kt值:", optimal_kt, "\n")

修正说明

  1. 补全计算链:在calculate_error中实现了从kt到e0的完整推导,确保所有中间变量都被正确生成。
  2. 优化函数设计:移除冗余参数,每个函数仅接收必要输入,避免引用外部未定义变量。
  3. 修复逻辑错误:调整循环逻辑,修正Lx的计算方法(符合预期寿命的标准推导),并处理边界情况。
  4. 调整初始参数:将kt初始值设为均值0的向量,匹配Lee-Carter模型的参数特性,帮助优化收敛。

内容的提问来源于stack exchange,提问作者Cassiopea

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 12:55:55