Aquí está mi solución a "¿Cuál es el método práctico más simple de implementar?" usando python, específicamente numpy, scipy y tick.
Una modificación es que establezco el núcleo exponencial tal que alfa x beta x exp (-beta (t - ti)), para que coincida con la forma en que tick define los núcleos exponenciales: https://x-datainitiative.github.io/tick/modules/generated/tick.hawkes.HawkesExpKern.html#tick.hawkes.HawkesExpKern
Asumo que el lector puede no estar familiarizado con python.
Importe las bibliotecas correspondientes:
import numpy as np
from scipy.optimize import minimize
from tick.hawkes import SimuHawkesExpKernels
Defina la función recursiva (R(i) en la pregunta anterior) que devuelve una matriz del mismo tamaño que el número de eventos:
def _recursive(timestamps, beta):
r_array = np.zeros(len(timestamps))
for i in range(1, len(timestamps)):
r_array[i] = np.exp(-beta * (timestamps[i] - timestamps[i - 1])) * (1 + r_array[i - 1])
return r_array
Defina la función de probabilidad logarítmica especificando los distintos parámetros:
def log_likelihood(timestamps, mu, alpha, beta, runtime):
r = _recursive(timestamps, beta)
return -runtime * mu + alpha * np.sum(np.exp(-beta * (runtime - timestamps)) - 1) + \
np.sum(np.log(mu + alpha * beta * r))
Simule algunos datos de Hawkes utilizando la biblioteca de ticks (o algún otro medio):
m = 0.5
a = 0.2
b = 0.3
rt = 1000
simu = SimuHawkesExpKernels([[a]], b, [m], rt, seed=0)
simu.simulate()
t = simu.timestamps[0]
La función minimizar de Scipy es probablemente la optimización más común de python para las funciones escalares. Espera una función con sólo dos conjuntos de parámetros; los que quieres minimizar y los que son fijos. Hay varios métodos de minimización posibles, yo estoy usando el predeterminado que es L-BFGS-B para problemas acotados y es un método cuasi-newton.
Ten en cuenta que debería haber empezado con una búsqueda bruta primero, pero la pregunta pedía el método práctico más sencillo. También podría haber dividido en una minimización sobre mu y alfa y luego utilizar el recocido simulado sobre beta ya que el logaritmo es convexo sobre mu y alfa solamente.
Define una nueva función que será utilizada por la función minimizar y devuelve la log-verosimilitud negativa:
def crit(params, *args):
mu, alpha, beta = params
timestamps, runtime = args
return -log_likelihood(timestamps, mu, alpha, beta, runtime)
Llama a la función minimizar y establece que los límites de m,a y b sean positivos:
minimize(crit, [m + 0.1, a + 0.1, b+ 0.1], args=(t, rt), bounds=((1e-10, None), (1e-10, None), (1e-10, None),))
Lo que da estimaciones de m,a,b: array([0.43835767, 0.25823306, 0.14769243])
2 votos
He tenido éxito en la instalación de $\mu$ y $\alpha$ maximizando el MLE la implementación de LBFGS en scipy. La log-verosimilitud no es cóncava en $\beta$ por lo que simplemente he iterado sobre un rango de $\beta$ valores y eligió el de máxima probabilidad. Tenga en cuenta que $\alpha < \beta$ es necesario para la estacionariedad del proceso.
1 votos
Por curiosidad, ¿cuál es la forma correcta de la función (t) utilizando los valores de R(i) en lugar de resumir en cada paso?