library(betareg)
set.seed(1)
# create modelled data
n <- 10^3
x <- runif(n,0,100)
m <- rbeta(n,2,1)
X <- cbind(rep(1,n),x,x^2)
f <- 10+xX %*% c(10,1,-0.005)
y <- f*m
colnames(X) <- c("1","x","x^2")
# likelihood to optimize
loglik <- function(par,dat=dat) {
# linear model pars
bt0#bt0 <- par[1]
bt1#bt1 <- par[2]
# ratio Y/f(X) which should relate to beta distributed var
f <- bt0 + bt1*dat[dat[,2]-1] %*% par
yf <- dat[,1] / f
#to prevent values outside (0,1) or values condensing in one point
neg_penalty <- which(abs(yf-0.5) < 0.4999)
# fit beta distribution to Y/f(x)
# note under the hood betareg is a call to optim
modfit <- betareg(yf[neg_penalty] ~ 1, link ="log")
a <- exp(modfit$coefficients$mean) * modfit$coefficients$precision
b <- (1-exp(modfit$coefficients$mean)) * modfit$coefficients$precision
# return loglikelihood or penalty
penalty_size <- length(dat[-neg_penalty,1])
if (penalty_size == 0) {
result <- -modfit$loglik + sum(log(f))
# the sum(log(f)) term is because we actually do not wish the
# probability for yf but instead the probability for y which relates
# to a scaled beta distribution and this scaling factor occurs in the density as log(f)
} else {
result <- penalty_size*10^6
}
result
}
# data
dat <- cbind(y,xX)
# start condition
mod <- lm(y ~ x0+X)
par <- c(2*mod$coefficients) # we assume that the starting line is twice the mean
# optimize
p <- optim(par, loglik, dat=dat, control = list(trace=2, maxit=100maxit=10^3))
p
# outcome
p$par
loglik(par,dat)
loglik(p$par,dat)
yf <- dat[,1] / (p$par[1] + p$par[2]*dat[,2])
modfit <- betareg(yf ~ 1, link ="log")
parfin <- c(exp(modfit$coefficients$mean)*modfit$coefficients$precision,
(1-exp(modfit$coefficients$mean))*modfit$coefficients$precision,
X %*% p$par[1],
p$par[2]$par)
modfit <- betareg(yf ~ 1, link ="log")
parfin <- c(exp(modfit$coefficients$mean)*modfit$coefficients$precision,
(1-exp(modfit$coefficients$mean))*modfit$coefficients$precision,
p$par)
# view result
plot(x, y,
pch=21, col=rgb(0,0,0,0.1),bg=rgb(0,0,0,0.1))
hf <- dat[,1] / (parfin[3] + parfin[4]*dat[,2])
sig <- 0.02
brks <- seq(0,1,sig)
hist(hfyf, breaks = brks,sig,xlim=c(min(hf),max(hf)),xlab = "Y/f(X)",main="")
lines(brks,dbeta(brks, parfin[1],parfin[2])*n*sig,col=2)
parfin