Source code for tick.hawkes.model.model_hawkes_sumexpkern_leastsq
# License: BSD 3 clause
import sys
from warnings import warn
import numpy as np
from tick.base_model import LOSS_AND_GRAD
from tick.hawkes.model.build.hawkes_model import (
ModelHawkesSumExpKernLeastSq as _ModelHawkesSumExpKernLeastSq)
from .base import ModelHawkes
[docs]class ModelHawkesSumExpKernLeastSq(ModelHawkes):
"""Hawkes process model for sum-exponential kernels with fixed and
given decays.
It is modeled with least square loss:
.. math::
\\sum_{i=1}^{D} \\left(
\\int_0^T \\lambda_i(t)^2 dt
- 2 \\int_0^T \\lambda_i(t) dN_i(t)
\\right)
where :math:`\\lambda_i` is the intensity:
.. math::
\\forall i \\in [1 \\dots D], \\quad
\\lambda_i(t) = \\mu_i(t) + \\sum_{j=1}^D
\\sum_{t_k^j < t} \\phi_{ij}(t - t_k^j)
where
* :math:`D` is the number of nodes
* :math:`\mu_i(t)` are the baseline intensities
* :math:`\phi_{ij}` are the kernels
* :math:`t_k^j` are the timestamps of all events of node :math:`j`
and with a sum-exponential parametrisation of the kernels
.. math::
\phi_{ij}(t) = \sum_{u=1}^{U} \\alpha^u_{ij} \\beta^u
\exp (- \\beta^u t) 1_{t > 0}
In our implementation we denote:
* Integer :math:`D` by the attribute `n_nodes`
* Integer :math:`U` by the attribute `n_decays`
* Vector :math:`\\beta \in \mathbb{R}^{U}` by the
parameter `decays`. This parameter is given to the model
Parameters
----------
decays : `numpy.ndarray`, shape=(n_decays, )
An array giving the different decays of the exponentials kernels.
n_baselines : `int`, default=1
In this model baseline is supposed to be either constant or piecewise
constant. If `n_baseline > 1` then piecewise constant setting is
enabled. In this case :math:`\\mu_i(t)` is piecewise constant on
intervals of size `period_length / n_baselines` and periodic.
period_length : `float`, default=None
In piecewise constant setting this denotes the period of the
piecewise constant baseline function.
approx : `int`, default=0 (read-only)
Level of approximation used for computing exponential functions
* if 0: no approximation
* if 1: a fast approximated exponential function is used
n_threads : `int`, default=-1 (read-only)
Number of threads used for parallel computation.
* if ``int <= 0``: the number of threads available on
the CPU
* otherwise the desired number of threads
Attributes
----------
n_nodes : `int` (read-only)
Number of components, or dimension of the Hawkes model
n_decays : `int` (read-only)
Number of decays used in the sum-exponential kernel
baseline_intervals : `np.ndarray`, shape=(n_baselines)
Start time of each interval on which baseline is piecewise constant.
data : `list` of `numpy.array` (read-only)
The events given to the model through `fit` method.
Note that data given through `incremental_fit` is not stored
"""
# In Hawkes case, getting value and grad at the same time need only
# one pas over the data
pass_per_operation = \
{k: v for d in [ModelHawkes.pass_per_operation,
{LOSS_AND_GRAD: 2}] for k, v in d.items()}
_attrinfos = {
"decays": {
"writable": True,
"cpp_setter": "set_decays"
},
"n_baselines": {
"writable": True,
"cpp_setter": "set_n_baselines"
},
"_period_length": {
"writable": False,
},
}
[docs] def __init__(self, decays: np.ndarray, n_baselines=1, period_length=None,
approx: int = 0, n_threads: int = 1):
ModelHawkes.__init__(self, approx=approx, n_threads=n_threads)
self._end_times = None
if n_baselines <= 0:
raise ValueError('n_baselines must be positive')
if n_baselines > 1 and period_length is None:
raise ValueError('period_length must be given if multiple '
'baselines are used')
if period_length is not None and n_baselines == 1:
warn('period_length has no effect when using a constant baseline')
if isinstance(decays, list):
decays = np.array(decays, dtype=float)
elif decays.dtype != float:
decays = decays.astype(float)
self.decays = decays.copy()
self.n_baselines = n_baselines
self.period_length = period_length
self._model = _ModelHawkesSumExpKernLeastSq(
self.decays, self.n_baselines, self.cast_period_length(),
self.n_threads, self.approx)
@property
def n_decays(self):
return self._model.get_n_decays()
@property
def _epoch_size(self):
# This gives the typical size of an epoch when using a
# stochastic optimization algorithm
return self.n_nodes
@property
def _rand_max(self):
# This allows to obtain the range of the random sampling when
# using a stochastic optimization algorithm
return self.n_nodes
@property
def period_length(self):
return self._period_length
@period_length.setter
def period_length(self, val):
self._set("_period_length", val)
if hasattr(self, '_model') and self._model is not None:
self._model.set_period_length(self.cast_period_length())
def cast_period_length(self):
if self.period_length is None:
return sys.float_info.max
else:
return self.period_length
@property
def baseline_intervals(self):
return np.arange(self.n_baselines) * (
self._model.get_period_length() / self.n_baselines)