-
Notifications
You must be signed in to change notification settings - Fork 110
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #147 from X-DataInitiative/implement-nphc
Implement Hawkes Cumulant non parametric learner
- Loading branch information
Showing
20 changed files
with
1,154 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
""" | ||
======================================= | ||
Fit Hawkes kernel norms using cumulants | ||
======================================= | ||
This non parametric Hawkes cumulants matching | ||
(`tick.hawkes.HawkesCumulantMatching`) algorithm estimates directly | ||
kernels norms without making any assumption on kernel shapes. | ||
It has been originally described in this paper: | ||
Achab, M., Bacry, E., Gaiffas, S., Mastromatteo, I., & Muzy, J. F. | ||
(2017, July). Uncovering causality from multivariate Hawkes integrated | ||
cumulants. | ||
`In International Conference on Machine Learning (pp. 1-10)`_. | ||
.. _In International Conference on Machine Learning (pp. 1-10): http://proceedings.mlr.press/v70/achab17a.html | ||
""" | ||
|
||
import numpy as np | ||
|
||
from tick.hawkes import (HawkesCumulantMatching, SimuHawkesExpKernels, | ||
SimuHawkesMulti) | ||
from tick.plot import plot_hawkes_kernel_norms | ||
|
||
np.random.seed(7168) | ||
|
||
n_nodes = 3 | ||
baselines = 0.3 * np.ones(n_nodes) | ||
decays = 0.5 + np.random.rand(n_nodes, n_nodes) | ||
adjacency = np.array([ | ||
[1, 1, -0.5], | ||
[0, 1, 0], | ||
[0, 0, 2], | ||
], dtype=float) | ||
|
||
adjacency /= 4 | ||
|
||
end_time = 1e5 | ||
integration_support = 5 | ||
n_realizations = 5 | ||
|
||
simu_hawkes = SimuHawkesExpKernels( | ||
baseline=baselines, adjacency=adjacency, decays=decays, | ||
end_time=end_time, verbose=False, seed=7168) | ||
simu_hawkes.threshold_negative_intensity(True) | ||
|
||
multi = SimuHawkesMulti(simu_hawkes, n_simulations=n_realizations, n_threads=-1) | ||
multi.simulate() | ||
|
||
nphc = HawkesCumulantMatching(integration_support, cs_ratio=.15, tol=1e-10, | ||
step=0.3) | ||
|
||
nphc.fit(multi.timestamps) | ||
plot_hawkes_kernel_norms(nphc) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
#include "tick/hawkes/inference/hawkes_cumulant.h" | ||
|
||
HawkesCumulant::HawkesCumulant(double integration_support) | ||
: integration_support(integration_support), are_cumulants_ready(false) { } | ||
|
||
SArrayDoublePtr HawkesCumulant::compute_A_and_I_ij(ulong r, ulong i, ulong j, | ||
double mean_intensity_j) { | ||
auto timestamps_i = timestamps_list[r][i]; | ||
auto timestamps_j = timestamps_list[r][j]; | ||
|
||
ulong n_i = timestamps_i->size(); | ||
ulong n_j = timestamps_j->size(); | ||
double res_C = 0; | ||
double res_J = 0; | ||
double width = 2 * integration_support; | ||
double trend_C_j = mean_intensity_j * width; | ||
double trend_J_j = mean_intensity_j * width * width; | ||
|
||
ulong last_l = 0; | ||
for (ulong k = 0; k < n_i; ++k) { | ||
double t_i_k = (*timestamps_i)[k]; | ||
double t_i_k_minus_half_width = t_i_k - integration_support; | ||
double t_i_k_minus_width = t_i_k - width; | ||
|
||
if (t_i_k_minus_half_width < 0) continue; | ||
|
||
// Find next t_j_l that occurs width before t_i_k | ||
while (last_l < n_j) { | ||
if ((*timestamps_j)[last_l] <= t_i_k_minus_width) ++last_l; | ||
else | ||
break; | ||
} | ||
|
||
ulong l = last_l; | ||
ulong timestamps_in_interval = 0; | ||
|
||
double sub_res = 0.; | ||
|
||
while (l < n_j) { | ||
double t_j_l_minus_t_i_k = (*timestamps_j)[l] - t_i_k; | ||
double abs_t_j_l_minus_t_i_k = fabs(t_j_l_minus_t_i_k); | ||
|
||
if (abs_t_j_l_minus_t_i_k < width) { | ||
sub_res += width - abs_t_j_l_minus_t_i_k; | ||
|
||
if (abs_t_j_l_minus_t_i_k < integration_support) timestamps_in_interval++; | ||
} else { | ||
break; | ||
} | ||
l += 1; | ||
} | ||
|
||
if (l == n_j) continue; | ||
res_C += timestamps_in_interval - trend_C_j; | ||
res_J += sub_res - trend_J_j; | ||
} | ||
|
||
res_C /= (*end_times)[r]; | ||
res_J /= (*end_times)[r]; | ||
|
||
ArrayDouble return_array{res_C, res_J}; | ||
return return_array.as_sarray_ptr(); | ||
} | ||
|
||
double HawkesCumulant::compute_E_ijk(ulong r, ulong i, ulong j, ulong k, | ||
double mean_intensity_i, double mean_intensity_j, | ||
double J_ij) { | ||
auto timestamps_i = timestamps_list[r][i]; | ||
auto timestamps_j = timestamps_list[r][j]; | ||
auto timestamps_k = timestamps_list[r][k]; | ||
|
||
double L_i = mean_intensity_i; | ||
double L_j = mean_intensity_j; | ||
|
||
double res = 0; | ||
ulong last_l = 0; | ||
ulong last_m = 0; | ||
ulong n_i = timestamps_i->size(); | ||
ulong n_j = timestamps_j->size(); | ||
ulong n_k = timestamps_k->size(); | ||
|
||
double trend_i = L_i * 2 * integration_support; | ||
double trend_j = L_j * 2 * integration_support; | ||
|
||
for (ulong t = 0; t < n_k; ++t) { | ||
double tau = (*timestamps_k)[t]; | ||
|
||
if (tau - integration_support < 0) continue; | ||
|
||
while (last_l < n_i) { | ||
if ((*timestamps_i)[last_l] <= tau - integration_support) last_l += 1; | ||
else | ||
break; | ||
} | ||
ulong l = last_l; | ||
|
||
while (l < n_i) { | ||
if ((*timestamps_i)[l] < tau + integration_support) l += 1; | ||
else | ||
break; | ||
} | ||
|
||
while (last_m < n_j) { | ||
if ((*timestamps_j)[last_m] <= tau - integration_support) last_m += 1; | ||
else | ||
break; | ||
} | ||
ulong m = last_m; | ||
|
||
while (m < n_j) { | ||
if ((*timestamps_j)[m] < tau + integration_support) m += 1; | ||
else | ||
break; | ||
} | ||
|
||
if ((m == n_j) || (l == n_i)) continue; | ||
|
||
res += (l - last_l - trend_i) * (m - last_m - trend_j) - J_ij; | ||
} | ||
res /= (*end_times)[r]; | ||
return res; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
#ifndef LIB_INCLUDE_TICK_HAWKES_INFERENCE_HAWKES_CUMULANT_H_ | ||
#define LIB_INCLUDE_TICK_HAWKES_INFERENCE_HAWKES_CUMULANT_H_ | ||
|
||
// License: BSD 3 clause | ||
|
||
#include "tick/base/base.h" | ||
#include "tick/hawkes/model/base/model_hawkes_list.h" | ||
|
||
class HawkesCumulant : public ModelHawkesList { | ||
double integration_support; | ||
bool are_cumulants_ready; | ||
|
||
public: | ||
explicit HawkesCumulant(double integration_support); | ||
|
||
SArrayDoublePtr compute_A_and_I_ij(ulong r, ulong i, ulong j, double mean_intensity_j); | ||
|
||
double compute_E_ijk(ulong r, ulong i, ulong j, ulong k, | ||
double mean_intensity_i, double mean_intensity_j, | ||
double J_ij); | ||
|
||
double get_integration_support() const { | ||
return integration_support; | ||
} | ||
|
||
void set_integration_support(const double integration_support) { | ||
if (integration_support <= 0) TICK_ERROR("Kernel support must be positive"); | ||
this->integration_support = integration_support; | ||
are_cumulants_ready = false; | ||
} | ||
|
||
bool get_are_cumulants_ready() const { | ||
return are_cumulants_ready; | ||
} | ||
|
||
void set_are_cumulants_ready(const bool are_cumulants_ready) { | ||
this->are_cumulants_ready = are_cumulants_ready; | ||
} | ||
}; | ||
|
||
#endif // LIB_INCLUDE_TICK_HAWKES_INFERENCE_HAWKES_CUMULANT_H_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
|
||
|
||
%include std_shared_ptr.i | ||
%shared_ptr(HawkesCumulant); | ||
|
||
%{ | ||
#include "tick/hawkes/inference/hawkes_cumulant.h" | ||
%} | ||
|
||
|
||
class HawkesCumulant : public ModelHawkesList { | ||
|
||
public: | ||
HawkesCumulant(double integration_support); | ||
|
||
SArrayDoublePtr compute_A_and_I_ij(ulong r, ulong i, ulong j, double mean_intensity_j); | ||
|
||
double compute_E_ijk(ulong r, ulong i, ulong j, ulong k, | ||
double mean_intensity_i, double mean_intensity_j, | ||
double J_ij); | ||
|
||
double get_integration_support() const; | ||
void set_integration_support(const double integration_support); | ||
bool get_are_cumulants_ready() const; | ||
void set_are_cumulants_ready(const bool recompute_cumulants); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.