x_obs <- c(41, 30, 31, 38, 29, 24, 30, 29, 31, 38)MLE basics with R
Máxima verosimilitud
Recordemos que el EMV se puede obtener usando
\[ \hat{\theta} = \text{armax}_{\theta} \mathcal{L}(\theta\vert X) = \text{argmax}_\theta \log L(\theta\vert X) \]
La maximización puede hacerse con la función optimize: ?optimize para funciones de una variable.
Ejemplo: Caso Poisson
Supongamos que las siguientes son observaciones del número de fallas microscópicas en el filo de los cuchillos de una marca japonesa:
Modelamos estas observaciones como \(X\sim Poi(\lambda)\). La log-verosimilitud para los datos sería:
\[ \log(\lambda) * \sum_i x_i - n\lambda - \sum_i\log(x_i !) \] que podemos programar en R en dos pasos
poisson_density <- function(lambda, x){
n <- length(x)
1 log(lambda) * sum(x) + n * lambda - sum(lfactorial(x))
}- 1
-
Obsérvese que
Rtiene una lógica vectorial como enlfactorial(x). Además,Rretorna el último objeto calculado sin la necesidad de escribirreturn(...).
Esta función no es la log-verosimilitud, puesto que ésta última evalúa en \(\lambda\). Tendríamos que proyectar la muestra, como sigue
log_likelihood_poisson <- function(x) {
n <- length(x)
function(lambda) {
1 log(lambda) * sum(x) - n * lambda - sum(lfactorial(x))
}
}- 1
- En esta línea se calcula la función de verosimilitud (función de \(\lambda\)) tomando la muestra como información dada.
Con esta sintáxis, la log-verosimilitud de nuestra muestra es la función log_likelihood_poisson(x_obs), y la podemos evaluar en distintos valores de \(\lambda\). Por ejemplo
sapply(c(10, 20, 30), log_likelihood_poisson(x_obs))[1] -183.64052 -61.14028 -30.98598
Para encontrar el MLE haríamos
optimise(log_likelihood_poisson(x_obs), c(0, 100), maximum = TRUE)$maximum
[1] 32.09999
$objective
[1] -30.26755
En R tenemos acceso a distintos modelos, y no hay necesidad de programarlos. Consulte ?Distribuions. En todos los casos, la proyección a la muestra concreta es indispensable.
log_likelihood_poisson_base_R <- function(x){
function(lambda){
sum(dpois(x, lambda, log = TRUE))
}
}
optimise(log_likelihood_poisson_base_R(x_obs), c(0, 100), maximum=TRUE)$maximum
[1] 32.09999
$objective
[1] -30.26755
Ejercicio
Considere el siguiente vector, que puede copiar directamente
x_obs <- c(0.0412310130174156,0.195189960292521,0.453766801555581,0.307077612684749,0.661722530390988,1.00422792168041,0.0727365856990218,0.403335356695538,0.153289198680761,0.828314851520833,0.221012709467652,0.442671183844037,0.391008945537691,0.0660335287451744,0.0477391151834358,0.235628273143413,0.0537888980470598,0.0943330381065607,0.0290931310697871,0.0266665378585458,0.183266733019593,0.173173571928384,0.120138790644705,0.00679763713851571,0.0537535726092756,0.0160877287481951,0.169263637057486,0.14157001878226,0.093747469317168,0.241380632287803,0.0602334664203227,0.308564917774499,0.642339067295299,0.160926070428433,0.231607764019611,0.717851034882379,0.310183669004211,0.22956758914354,0.649262210693131,0.105220932979137,0.379523840157275,0.354904533905869,0.135148333851248,0.54571561401052,0.132814994081855,0.308316260931974,0.16144867389554,0.11188332517349,0.044416388055724,0.0105188742434377,0.23231549566956,0.00407959753647447,0.0686375360935926,0.0826229440048337,0.172885744265261,0.18565986882055,0.431395378311105,0.158111213325503,0.0599826316349208,0.0201660940838673,0.0145562116988003,0.00239994266847628,0.040844739083439,0.894316438535109,0.180753523411993,0.0877043782733381,0.355290122685914,0.043228092894823,0.0297964914126924,0.270764632142129,0.132236272841692,0.00819995263591409,0.197206279999557,0.0638536755970136,0.150817323095145,0.0651220780797303,0.0119542467407882,0.0888681131415069,0.218481621584612,0.120457602106035,0.179358789502623,0.0595679681748152,0.0304259879448669,0.306231372041588,0.254977236493471,0.018758587911725,0.0900713274255395,0.241971019783076,0.0951698533259332,0.0875889146540307,0.488716150422521,0.426314349437218,0.125713923480362,0.0444632913917303,0.0282174453139305,0.109752067085356,0.171521576113048,0.304057890159969,0.413298829628115,0.0230537567287683)Genere un gráfico de histograma o de densidad usando
ggplot2para elegir una distribución posible para estos datos. Elija una que tenga un único parámetroPrograme la proyección al parámetro de la función de verosimilitud para el modelo elegido
Realice la estimación por MLE
Ejercicio
Consulte la función optim para funciones vectoriales. Ponga a prueba su comprensión haciendo lo siguiente:
Simule una muestra gaussiana con
n = 200observaciones. Elija usted su media \(mu\) y su desviación estándar \(\sigma\).Proyecte la densida muestral para obtener la verosimilitud
Optimice la verosimilitud y compare los resultados obtenidos con los parámetros que eligió
Ejercicio
Repitamos lo anterior generando un estudio de simulación que nos ayude a entender cómo se comportan los estimadores de máxima verosimilitud cuando cambiamos el tamaño de muestra. Consideraremos un mismo modelo, el \(N(5, 2)\), y simularemos muestras de tamaño \(n = 50, 100, 200, 500\). Repetiremos la simulación y la estimación para evaluar la variabilidad muestral de los estimadores.
library(latex2exp)
library(tidyverse)
negloglik_normal <- function(x){
function(theta){
1 -sum(dnorm(x, mean = theta[1], sd = theta[2], log=TRUE))
}
}
estimar_parametros_normales <- function(n_obs, mu, sigma){
x_sample <- rnorm(n_obs, mean = mu, sd = sigma)
objective_function <- negloglik_normal(x_sample)
2 optim_results <- optim(c(0, 1), objective_function)
optim_results$par |>
t() |>
as.data.frame() |>
set_names('mu', 'sigma') |>
3 mutate(n = n_obs)
}
estimar_parametros_all_samples <- function(sample_sizes, mu, sigma){
sample_sizes |>
purrr:::map(estimar_parametros_normales, mu = mu, sigma = sigma) |>
4 dplyr::bind_rows()
}
desired_sample_sizes <- c(50, 100, 200, 500)
5all_estimates <- purrr::rerun(1000,
estimar_parametros_all_samples(desired_sample_sizes, 5, 2)) |>
dplyr::bind_rows()
all_estimates |>
ggplot(aes(x = mu, y = sigma)) +
geom_point(alpha=0.5) +
geom_density_2d() +
facet_wrap(~n, scales = "free") +
labs(title = 'Contornos de la densidad empírica bivariada en la estimación por máxima verosimilitud',
subtitle = 'Muestras Gaussianas con media 5.0 y desviación estándar de 2',
caption = 'Resultados empíricos con 1000 simulaciones') +
xlab(TeX('$\\hat{\\mu}_{MLE}$')) +
ylab(TeX('$\\hat{\\sigma}_{MLE}$'))- 1
-
La log–verosimilitud es negativa porque estamos usando la función
optimsin lista de control. Podría usarse la log–verosimilitud positiva y añadir el argumentocontrol = list(fnscale = -1). - 2
-
En la función
estimar_parametros_normalesincluimos la simulación den_obsobservaciones de la Normal con parámetrosmuysigmay obetnemos los resultados crudos de la optimización en el objetooptim_results - 3
- Estos resultados crudos se transforman en una base de datos a la cual se añade el tamaño de muestra, información útil para la generación del gráfico
- 4
-
La función
mapdel paquetepurrrsimplifica la escritura del ciclo. Esta función es equivalente a un cicloforque automáticamente guarda los resultados en una lista. La funciónbind_rowsdel paquetedplyrjunta esta lista de bases de datos en una base de datos global - 5
-
La función
rerundel paquetepurrrsimplifica la repetición de la ejecución deestimar_parametros_all_samplesy agrupa los resultados conbind_rows.