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

分年龄组生存与恢复状态空间模型参数估计偏差求助

分年龄组状态空间模型参数估计偏差问题

我使用状态空间模型(State-Space Model)模拟估计分年龄组的恢复概率(p)和生存概率(phi),但得到的参数估计结果与设定值偏差较大。

估计值:

beta [1] = 0.331
beta [2] = 0.634 
delta [1] = 0.469
delta [2] = 0.529

模拟设定的真实值:

beta [1] = 0.8
beta [2] = 0.8
delta [1] = 0.2
delta [2] = 0.1

以下是我的代码:

### Finding first capture year
get.first <- function(x)min(which(x!=0))

known.state.mr <- function (mr) {
  state <- matrix (NA, nrow=dim(mr)[1], ncol= dim(mr)[2])
  rec <- which(rowSums(mr)==2)
  for (i in 1: length(rec)){
    n1<- min(which(mr[rec[i],]==1)) #n1 time of capture
    n2<- max(which(mr[rec[i],]==1)) # Recovery time
    state[rec[i],n1:n2]<-1 
    state[rec[i],n1]<-NA 
    state[rec[i],n2:dim(mr)[2]]<- 0 
  }
  return(state)
}


mr.init.z<-function(mr){
  ch<-matrix(NA, nrow=dim(mr)[1],ncol=dim(mr)[2])
  rec<- which(rowSums(mr)==1) 
  for(i in 1:length(rec)){ 
    n1<-which(mr[rec[i],]==1)
    ch[rec[i], n1:dim(mr)[2]]<-0
    ch[rec[i],n1] <- NA 
  }
  return (ch)
}

# Define function to simulate mark-recovery data
simul.mr <- function(S, R, marked){
  n.occasions <- dim(S)[2]
  MR <- matrix(NA, ncol = n.occasions+1, nrow = sum(marked))
  # Define a vector with the occasion of marking
  mark.occ <- rep(1:n.occasions, marked)
  # Fill the CH matrix
  for (i in 1:sum(marked)){
    MR[i, mark.occ[i]] <- 1    
    for (t in mark.occ[i]:n.occasions){
      # Bernoulli trial: has individual survived occasion? 
      sur <- rbinom(1, 1, S[i,t])
      if (sur==1) next     
       
      rp <- rbinom(1, 1, R[i,t])
      if (rp==0){
        MR[i,t+1] <- 0
        break
      }
      if (rp==1){
        MR[i,t+1] <- 1
        break
      }
    } #t
  } #i
  # Replace the NA in the file by 0
  MR[which(is.na(MR))] <- 0
  return(MR)
}


########### Simulate Data #########################

# Juvenile Matrix
n.occasions <- 14                 # Number of release occasions
marked <- rep(50, n.occasions)    # Annual number of newly marked individuals
as <- rep(0.8, n.occasions)
ar <- rep(0.2, n.occasions)

# Define matrices with survival and recovery probabilities
aS <- matrix(as, ncol = n.occasions, nrow = sum(marked))
aR <- matrix(ar, ncol = n.occasions, nrow = sum(marked))


# Execute function
MR.A <- simul.mr(aS, aR, marked)


### Juvenile Matrix #####
js <- rep(0.8, n.occasions)
jr <- rep(0.1, n.occasions)

# Define matrices with survival and recovery probabilities
jS <- matrix(js, ncol = n.occasions, nrow = sum(marked))
jR <- matrix(jr, ncol = n.occasions, nrow = sum(marked))

# Execute function
MR.J <- simul.mr(jS, jR, marked)

get.first <- function(x) min(which(x!=0))
f.j <- apply(MR.J, 1, get.first)
f.a <- apply(MR.A, 1, get.first)

# Create matrices X indicating age classes
x.j <- matrix(NA, ncol = dim(MR.J)[2]-1, nrow = dim(MR.J)[1])
x.a <- matrix(NA, ncol = dim(MR.A)[2]-1, nrow = dim(MR.A)[1])

for (i in 1:dim(MR.J)[1]){
  for (t in f.j[i]:(dim(MR.J)[2]-1)){
    x.j[i,t] <- 2
    x.j[i,f.j[i]] <- 1   
  } #t
} #i

for (i in 1:dim(MR.A)[1]){
  for (t in f.a[i]:(dim(MR.A)[2]-1)){
    x.a[i,t] <- 2
  } #t
} #i

MR <- rbind(MR.J, MR.A)
f <- c(f.j, f.a)
x <- rbind(x.j, x.a)


# Specify model in BUGS language
sink("Model_MR")
cat("
model {
# Priors and constraints
for (i in 1:nind){
   for (t in f[i]:(n.occasions-1)){
      
      phi[i,t] <- beta[x[i,t]]
      p[i,t] <- delta[x[i,t]]
      
      } #t
   } #i
   
for (u in 1:2){
   
   beta[u] ~ dunif(0,1) # Priors for age-specific survival
   delta[u] ~ dunif(0,1)
   
}
   
mean.p ~ dunif(0, 1)                  # Prior for mean recapture
# Likelihood 
for (i in 1:nind){
   
   # Define latent state at first capture
   
   z[i,f[i]] <- 1
   for (t in (f[i]+1):n.occasions){
      
      # State process
      
      z[i,t] ~ dbern(mu1[i,t])
      mu1[i,t] <- phi[i,t-1] * z[i,t-1]
      
      # Observation process
      
      y[i,t] ~ dbern(mu2[i,t])
      mu2[i,t] <- p[i,t-1] * (z[i,t-1]-z[i,t])
      
      } #t
   } #i
}
",fill = TRUE)
sink()

# Bundle data
bugs.data <- list(y = MR, 
                  f = f, 
                  nind = dim(MR)[1],
                  n.occasions = dim(MR)[2],
                  z = known.state.mr(MR), 
                  x = x)

# Initial values
inits <- function(){list(z = mr.init.z(MR), 
                         beta = runif(2, 0, 1), 
                         mean.p = runif(1, 0, 1))}  

# Parameters monitored
parameters <- c("beta", "mean.p","delta")

# MCMC settings
ni <- 2000
nt <- 3
nb <- 1000
nc <- 3

# Call WinBUGS from R (BRT 3 min)
cjs.age <- jags(bugs.data, inits, parameters, "Model_MR", 
n.chains = nc, n.thin = nt, n.iter = ni, n.burnin = nb)

print(cjs.age, digits = 3)

问题排查方向:

  1. 初始值函数逻辑错误
    mr.init.z函数中,对仅被标记无恢复记录的个体,直接将标记后所有时刻的状态z设为0,但这类个体可能存活到研究结束,初始值设为0会误导MCMC收敛,应改为将标记后到最后时刻的z初始化为1。

  2. 年龄组矩阵赋值冗余
    构建x.j时,循环内每次都重新赋值x.j[i,f.j[i]] <- 1,虽然最终结果正确,但逻辑冗余,可调整为仅在t=f.j[i]时赋值1,其余时刻赋值2:

    for (i in 1:dim(MR.J)[1]){
      x.j[i,f.j[i]] <- 1
      if(f.j[i] < dim(MR.J)[2]-1){
        x.j[i,(f.j[i]+1):(dim(MR.J)[2]-1)] <- 2
      }
    }
    
  3. BUGS模型时间索引不匹配
    模拟数据中,MR的列数是n.occasions+1,对应标记时刻1到恢复时刻n.occasions+1;但模型中n.occasions设为dim(MR)[2],观测方程里t对应恢复时刻,而phi[i,t-1]和p[i,t-1]对应t-1时刻的生存/恢复概率,需确认时间步是否与模拟逻辑完全对应。

  4. MCMC迭代次数不足
    当前设置ni=2000,nb=1000,有效样本量可能不足,导致估计值不稳定。建议增加迭代次数至ni=10000,nb=5000,并检查Rhat值是否接近1,确认模型收敛。

  5. 冗余参数干扰
    模型中定义了mean.p但未使用,应删除该参数的先验定义,减少MCMC不必要的计算。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 22:59:52