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

如何在R语言中为样本拟合Erlang混合模型?

R语言拟合Erlang混合模型实现方法

Erlang分布是Gamma分布的特例,其shape参数必须为正整数,这是拟合Erlang混合模型时需要重点约束的核心条件。以下是针对你生成的样本数据,实现Erlang混合模型拟合的具体步骤:

1. 样本数据准备(你的原始代码)

首先运行你提供的代码生成样本并可视化:

set.seed(123)
n <- 500
data1 <- rgamma(n / 2, shape = 9, rate = 10) 
data2 <- mean(data1) + rgamma(n / 2, shape = 5, rate = 5)
sample <- c(data1, data2)

# 绘制直方图与核密度曲线
hist(sample, breaks = 50, prob = T)
lines(density(sample), lwd = 2, col = "red")

2. 手动构建似然函数拟合(最灵活的方式)

由于多数混合模型包默认支持Gamma分布(无整数约束),我们可以手动定义对数似然函数,通过优化器约束shape为整数来拟合:

步骤2.1 定义对数似然函数

# 混合Erlang分布的对数似然函数
log_likelihood <- function(params, x) {
  pi1 <- params[1]
  k1 <- round(params[2])  # 强制shape为整数
  lambda1 <- params[3]
  k2 <- round(params[4])
  lambda2 <- params[5]
  
  # 参数合法性校验,避免无效值
  if (pi1 <= 0 || pi1 >= 1 || k1 < 1 || k2 < 1 || lambda1 <= 0 || lambda2 <= 0) {
    return(-Inf)
  }
  
  # 计算混合密度并求和对数
  dens <- pi1 * dgamma(x, shape = k1, rate = lambda1) + (1 - pi1) * dgamma(x, shape = k2, rate = lambda2)
  sum(log(dens))
}

步骤2.2 设置初始参数

基于你之前的分组策略,估计初始参数(保证优化收敛):

# 分组获取初始值
sample1 <- sample[sample < 1.3]
sample2 <- sample[sample > 1.3]

pi_init <- length(sample1)/length(sample)
# Gamma分布中shape ≈ mean²/var,取整作为Erlang的初始k
k1_init <- round(mean(sample1)^2 / var(sample1))
lambda1_init <- k1_init / mean(sample1)  # Gamma的mean=shape/rate → rate=shape/mean

k2_init <- round(mean(sample2)^2 / var(sample2))
lambda2_init <- k2_init / mean(sample2)

init_params <- c(pi_init, k1_init, lambda1_init, k2_init, lambda2_init)

步骤2.3 最大化对数似然

使用optim函数进行优化,约束参数范围:

fit <- optim(init_params, log_likelihood, x = sample, method = "L-BFGS-B", 
             lower = c(0.01, 1, 0.01, 1, 0.01), upper = c(0.99, 20, 20, 20, 20),
             control = list(fnscale = -1))  # fnscale=-1表示最大化似然

# 提取拟合结果
pi1_est <- fit$par[1]
k1_est <- round(fit$par[2])
lambda1_est <- fit$par[3]
k2_est <- round(fit$par[4])
lambda2_est <- fit$par[5]

# 打印参数
cat("拟合得到的混合Erlang模型参数:\n")
cat("组1:权重=", round(pi1_est, 3), ",shape(k)=", k1_est, ",rate(λ)=", round(lambda1_est, 3), "\n")
cat("组2:权重=", round(1-pi1_est, 3), ",shape(k)=", k2_est, ",rate(λ)=", round(lambda2_est, 3), "\n")

步骤2.4 可视化拟合结果

将拟合的混合密度曲线与原始数据对比:

x_seq <- seq(min(sample), max(sample), length.out = 1000)
mix_dens <- pi1_est * dgamma(x_seq, shape = k1_est, rate = lambda1_est) + 
  (1 - pi1_est) * dgamma(x_seq, shape = k2_est, rate = lambda2_est)

hist(sample, breaks = 50, prob = T, main = "混合Erlang模型拟合结果")
lines(density(sample), lwd = 2, col = "red", lty = 2, label = "核密度")
lines(x_seq, mix_dens, lwd = 2, col = "blue", label = "拟合Erlang混合")
legend("topright", legend = c("核密度", "拟合Erlang混合"), col = c("red", "blue"), lwd = 2, lty = c(2,1))

3. 使用flexmix包拟合(更简洁的封装方式)

flexmix支持自定义分布组件,我们可以封装Erlang分布进行拟合:

install.packages("flexmix")
library(flexmix)

# 定义Erlang密度函数
dErlang <- function(x, k, rate) {
  dgamma(x, shape = k, rate = rate)
}

# 定义Erlang混合组件
erlang_dist <- FLXMRdist(dist = "Erlang", d = dErlang, 
                         start = function(x) {
                           k <- round(mean(x)^2 / var(x))
                           lambda <- k / mean(x)
                           c(k, lambda)
                         })

# 拟合2组分的混合模型
fit_flex <- flexmix(sample ~ 1, k = 2, model = erlang_dist)

# 查看结果
cat("组件权重:", prior(fit_flex), "\n")
cat("组件参数:\n")
print(parameters(fit_flex))

关键注意事项

  • Erlang分布的shape参数必须为正整数,拟合时必须通过取整或整数约束实现,这是与普通Gamma混合模型的核心差异。
  • 初始参数的选择会影响优化收敛结果,建议基于数据分组先获取合理初始值,避免陷入局部最优。
  • 可以尝试多组初始参数,对比对数似然值选择最优拟合结果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 09:38:11