├── .gitignore
├── Comparisons.ipynb
├── KDE.ipynb
├── Point processes.ipynb
├── Temporal points processes.ipynb
├── Temporal spatial processes.ipynb
├── readme.md
└── utils.py
/.gitignore:
--------------------------------------------------------------------------------
1 | __pycache__
2 | .ipy*
3 |
--------------------------------------------------------------------------------
/Comparisons.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": 1,
6 | "metadata": {
7 | "collapsed": false
8 | },
9 | "outputs": [],
10 | "source": [
11 | "%matplotlib inline\n",
12 | "import matplotlib.pyplot as plt\n",
13 | "import numpy as np\n",
14 | "import pandas as pd\n",
15 | "import scipy.stats\n",
16 | "import scipy.integrate"
17 | ]
18 | },
19 | {
20 | "cell_type": "markdown",
21 | "metadata": {},
22 | "source": [
23 | "# Comparisons\n",
24 | "\n",
25 | "To make things really easy, let's ignore time, and work in one dimension. Events will take place in $[0,1]$.\n",
26 | "\n",
27 | "## Example 1\n",
28 | "\n",
29 | "Actual pattern is [CSR](https://en.wikipedia.org/wiki/Complete_spatial_randomness) with some overall rate (say 10 events, on average). One \"prediction\" is the same, other other is a inhomogeneous Poisson process with intensity $2t$ for $0\\leq t\\leq 1$.\n",
30 | "\n",
31 | "## Hit rate\n",
32 | "\n",
33 | "We put a grid down (chunk $[0,1]$ into intervals), select 5% (or whatever) of the intervals by risk, and see how many events we capture. If grid cells have the same risk, we'll break at random.\n",
34 | "\n",
35 | "We cannot tell the difference (as should be)."
36 | ]
37 | },
38 | {
39 | "cell_type": "code",
40 | "execution_count": 2,
41 | "metadata": {
42 | "collapsed": false
43 | },
44 | "outputs": [],
45 | "source": [
46 | "def coverage1(total_cells, cells_to_pick):\n",
47 | " # Homogeneous, so pick at random\n",
48 | " return np.random.choice(total_cells, size=cells_to_pick, replace=False)\n",
49 | " \n",
50 | "def coverage2(total_cells, cells_to_pick):\n",
51 | " # Intensity increases, so top slice will always pick the last cells\n",
52 | " return np.arange(total_cells)[-cells_to_pick:]\n",
53 | "\n",
54 | "assert np.all(coverage2(10, 3) == [7,8,9])\n",
55 | "\n",
56 | "def score(events, total_cells, cells):\n",
57 | " count = 0\n",
58 | " for t in events:\n",
59 | " t = int(np.floor(t * total_cells))\n",
60 | " if t in cells:\n",
61 | " count += 1\n",
62 | " return count / len(events)"
63 | ]
64 | },
65 | {
66 | "cell_type": "code",
67 | "execution_count": 3,
68 | "metadata": {
69 | "collapsed": false
70 | },
71 | "outputs": [],
72 | "source": [
73 | "trials = 10000\n",
74 | "cells = 10\n",
75 | "coverage = 3\n",
76 | "\n",
77 | "hit_rate_1 = []\n",
78 | "hit_rate_2 = []\n",
79 | "for _ in range(trials):\n",
80 | " num_events = np.random.poisson(lam=10)\n",
81 | " events = np.random.random(size=num_events)\n",
82 | " if len(events) == 0:\n",
83 | " continue\n",
84 | " pred1 = coverage1(cells, coverage)\n",
85 | " pred2 = coverage2(cells, coverage)\n",
86 | " hit_rate_1.append( score(events, cells, pred1) )\n",
87 | " hit_rate_2.append( score(events, cells, pred2) )"
88 | ]
89 | },
90 | {
91 | "cell_type": "code",
92 | "execution_count": 4,
93 | "metadata": {
94 | "collapsed": false
95 | },
96 | "outputs": [
97 | {
98 | "data": {
99 | "text/html": [
100 | "
\n",
101 | "
\n",
102 | " \n",
103 | " \n",
104 | " | \n",
105 | " One | \n",
106 | " Two | \n",
107 | "
\n",
108 | " \n",
109 | " \n",
110 | " \n",
111 | " count | \n",
112 | " 10000.000000 | \n",
113 | " 10000.000000 | \n",
114 | "
\n",
115 | " \n",
116 | " mean | \n",
117 | " 0.302664 | \n",
118 | " 0.299560 | \n",
119 | "
\n",
120 | " \n",
121 | " std | \n",
122 | " 0.155089 | \n",
123 | " 0.156065 | \n",
124 | "
\n",
125 | " \n",
126 | " min | \n",
127 | " 0.000000 | \n",
128 | " 0.000000 | \n",
129 | "
\n",
130 | " \n",
131 | " 25% | \n",
132 | " 0.200000 | \n",
133 | " 0.200000 | \n",
134 | "
\n",
135 | " \n",
136 | " 50% | \n",
137 | " 0.300000 | \n",
138 | " 0.285714 | \n",
139 | "
\n",
140 | " \n",
141 | " 75% | \n",
142 | " 0.400000 | \n",
143 | " 0.400000 | \n",
144 | "
\n",
145 | " \n",
146 | " max | \n",
147 | " 1.000000 | \n",
148 | " 1.000000 | \n",
149 | "
\n",
150 | " \n",
151 | "
\n",
152 | "
"
153 | ],
154 | "text/plain": [
155 | " One Two\n",
156 | "count 10000.000000 10000.000000\n",
157 | "mean 0.302664 0.299560\n",
158 | "std 0.155089 0.156065\n",
159 | "min 0.000000 0.000000\n",
160 | "25% 0.200000 0.200000\n",
161 | "50% 0.300000 0.285714\n",
162 | "75% 0.400000 0.400000\n",
163 | "max 1.000000 1.000000"
164 | ]
165 | },
166 | "execution_count": 4,
167 | "metadata": {},
168 | "output_type": "execute_result"
169 | }
170 | ],
171 | "source": [
172 | "pd.DataFrame({\"One\":hit_rate_1, \"Two\":hit_rate_2}).describe()"
173 | ]
174 | },
175 | {
176 | "cell_type": "markdown",
177 | "metadata": {},
178 | "source": [
179 | "## Likelihood\n",
180 | "\n",
181 | "For each prediction, compute the likelihood of the events, the product of density function evaluated at each point. As ever, we really work with log likelihood, to avoid numerical errors. We can then:\n",
182 | "\n",
183 | "- Compute the likelihood ratio, to see which prediction is closer. This strongly favours model 1.\n",
184 | "- Normalise to give some absolute likelihood. Model 1 again is favoured."
185 | ]
186 | },
187 | {
188 | "cell_type": "code",
189 | "execution_count": 5,
190 | "metadata": {
191 | "collapsed": true
192 | },
193 | "outputs": [],
194 | "source": [
195 | "def likelihood1(events):\n",
196 | " return 0\n",
197 | "\n",
198 | "def likelihood2(events):\n",
199 | " return np.sum(np.log(np.asarray(events) * 2))"
200 | ]
201 | },
202 | {
203 | "cell_type": "code",
204 | "execution_count": 6,
205 | "metadata": {
206 | "collapsed": false
207 | },
208 | "outputs": [],
209 | "source": [
210 | "ratios = []\n",
211 | "\n",
212 | "for _ in range(10000):\n",
213 | " num_events = np.random.poisson(lam=10)\n",
214 | " events = np.random.random(size=num_events)\n",
215 | " log_ratio = likelihood1(events) - likelihood2(events)\n",
216 | " ratios.append(log_ratio)"
217 | ]
218 | },
219 | {
220 | "cell_type": "code",
221 | "execution_count": 7,
222 | "metadata": {
223 | "collapsed": false
224 | },
225 | "outputs": [
226 | {
227 | "data": {
228 | "text/html": [
229 | "\n",
230 | "
\n",
231 | " \n",
232 | " \n",
233 | " | \n",
234 | " 0 | \n",
235 | "
\n",
236 | " \n",
237 | " \n",
238 | " \n",
239 | " count | \n",
240 | " 10000.000000 | \n",
241 | "
\n",
242 | " \n",
243 | " mean | \n",
244 | " 3.063269 | \n",
245 | "
\n",
246 | " \n",
247 | " std | \n",
248 | " 3.319015 | \n",
249 | "
\n",
250 | " \n",
251 | " min | \n",
252 | " -4.781459 | \n",
253 | "
\n",
254 | " \n",
255 | " 25% | \n",
256 | " 0.640241 | \n",
257 | "
\n",
258 | " \n",
259 | " 50% | \n",
260 | " 2.633811 | \n",
261 | "
\n",
262 | " \n",
263 | " 75% | \n",
264 | " 4.994303 | \n",
265 | "
\n",
266 | " \n",
267 | " max | \n",
268 | " 20.325528 | \n",
269 | "
\n",
270 | " \n",
271 | "
\n",
272 | "
"
273 | ],
274 | "text/plain": [
275 | " 0\n",
276 | "count 10000.000000\n",
277 | "mean 3.063269\n",
278 | "std 3.319015\n",
279 | "min -4.781459\n",
280 | "25% 0.640241\n",
281 | "50% 2.633811\n",
282 | "75% 4.994303\n",
283 | "max 20.325528"
284 | ]
285 | },
286 | "execution_count": 7,
287 | "metadata": {},
288 | "output_type": "execute_result"
289 | }
290 | ],
291 | "source": [
292 | "pd.DataFrame(ratios).describe()"
293 | ]
294 | },
295 | {
296 | "cell_type": "code",
297 | "execution_count": 8,
298 | "metadata": {
299 | "collapsed": true
300 | },
301 | "outputs": [],
302 | "source": [
303 | "one, two = [], []\n",
304 | "for _ in range(10000):\n",
305 | " num_events = np.random.poisson(lam=10)\n",
306 | " events = np.random.random(size=num_events)\n",
307 | " if len(events) == 0:\n",
308 | " continue\n",
309 | " one.append( likelihood1(events) / len(events) )\n",
310 | " two.append( likelihood2(events) / len(events) )"
311 | ]
312 | },
313 | {
314 | "cell_type": "code",
315 | "execution_count": 9,
316 | "metadata": {
317 | "collapsed": false
318 | },
319 | "outputs": [
320 | {
321 | "data": {
322 | "text/html": [
323 | "\n",
324 | "
\n",
325 | " \n",
326 | " \n",
327 | " | \n",
328 | " one | \n",
329 | " two | \n",
330 | "
\n",
331 | " \n",
332 | " \n",
333 | " \n",
334 | " count | \n",
335 | " 10000.0 | \n",
336 | " 10000.000000 | \n",
337 | "
\n",
338 | " \n",
339 | " mean | \n",
340 | " 0.0 | \n",
341 | " -0.302210 | \n",
342 | "
\n",
343 | " \n",
344 | " std | \n",
345 | " 0.0 | \n",
346 | " 0.334594 | \n",
347 | "
\n",
348 | " \n",
349 | " min | \n",
350 | " 0.0 | \n",
351 | " -2.553526 | \n",
352 | "
\n",
353 | " \n",
354 | " 25% | \n",
355 | " 0.0 | \n",
356 | " -0.492402 | \n",
357 | "
\n",
358 | " \n",
359 | " 50% | \n",
360 | " 0.0 | \n",
361 | " -0.268450 | \n",
362 | "
\n",
363 | " \n",
364 | " 75% | \n",
365 | " 0.0 | \n",
366 | " -0.069880 | \n",
367 | "
\n",
368 | " \n",
369 | " max | \n",
370 | " 0.0 | \n",
371 | " 0.670229 | \n",
372 | "
\n",
373 | " \n",
374 | "
\n",
375 | "
"
376 | ],
377 | "text/plain": [
378 | " one two\n",
379 | "count 10000.0 10000.000000\n",
380 | "mean 0.0 -0.302210\n",
381 | "std 0.0 0.334594\n",
382 | "min 0.0 -2.553526\n",
383 | "25% 0.0 -0.492402\n",
384 | "50% 0.0 -0.268450\n",
385 | "75% 0.0 -0.069880\n",
386 | "max 0.0 0.670229"
387 | ]
388 | },
389 | "execution_count": 9,
390 | "metadata": {},
391 | "output_type": "execute_result"
392 | }
393 | ],
394 | "source": [
395 | "pd.DataFrame({\"one\":one, \"two\":two}).describe()"
396 | ]
397 | },
398 | {
399 | "cell_type": "markdown",
400 | "metadata": {},
401 | "source": [
402 | "## KDE and mean squared error\n",
403 | "\n",
404 | "Use the events and KDE to estimate a \"real\" density, and compare this with the model by integrating the error.\n",
405 | "\n",
406 | "This again favours model 1 (smaller average error)."
407 | ]
408 | },
409 | {
410 | "cell_type": "code",
411 | "execution_count": 10,
412 | "metadata": {
413 | "collapsed": false
414 | },
415 | "outputs": [
416 | {
417 | "data": {
418 | "text/plain": [
419 | "[]"
420 | ]
421 | },
422 | "execution_count": 10,
423 | "metadata": {},
424 | "output_type": "execute_result"
425 | },
426 | {
427 | "data": {
428 | "image/png": "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\n",
429 | "text/plain": [
430 | ""
431 | ]
432 | },
433 | "metadata": {},
434 | "output_type": "display_data"
435 | }
436 | ],
437 | "source": [
438 | "events = np.random.random(size=10)\n",
439 | "kernel = scipy.stats.kde.gaussian_kde(events)\n",
440 | "\n",
441 | "fig, ax = plt.subplots(figsize=(8,6))\n",
442 | "ax.scatter(events, [0.1 for e in events])\n",
443 | "x = np.linspace(0, 1, 100)\n",
444 | "ax.plot(x, kernel(x))"
445 | ]
446 | },
447 | {
448 | "cell_type": "code",
449 | "execution_count": 11,
450 | "metadata": {
451 | "collapsed": true
452 | },
453 | "outputs": [],
454 | "source": [
455 | "def func1(x):\n",
456 | " return 1\n",
457 | "\n",
458 | "def func2(x):\n",
459 | " return 2 * x"
460 | ]
461 | },
462 | {
463 | "cell_type": "code",
464 | "execution_count": 12,
465 | "metadata": {
466 | "collapsed": false
467 | },
468 | "outputs": [],
469 | "source": [
470 | "errors = []\n",
471 | "for _ in range(10000):\n",
472 | " num_events = np.random.poisson(lam=10)\n",
473 | " events = np.random.random(size=num_events)\n",
474 | " if len(events) < 2:\n",
475 | " continue\n",
476 | " kernel = scipy.stats.kde.gaussian_kde(events)\n",
477 | " e1, _ = scipy.integrate.quad(lambda x : (kernel(x) - func1(x))**2, 0, 1)\n",
478 | " e2, _ = scipy.integrate.quad(lambda x : (kernel(x) - func2(x))**2, 0, 1)\n",
479 | " errors.append((e1, e2))"
480 | ]
481 | },
482 | {
483 | "cell_type": "code",
484 | "execution_count": 13,
485 | "metadata": {
486 | "collapsed": false
487 | },
488 | "outputs": [
489 | {
490 | "data": {
491 | "text/html": [
492 | "\n",
493 | "
\n",
494 | " \n",
495 | " \n",
496 | " | \n",
497 | " one | \n",
498 | " two | \n",
499 | "
\n",
500 | " \n",
501 | " \n",
502 | " \n",
503 | " count | \n",
504 | " 9996.000000 | \n",
505 | " 9996.000000 | \n",
506 | "
\n",
507 | " \n",
508 | " mean | \n",
509 | " 0.146197 | \n",
510 | " 0.477317 | \n",
511 | "
\n",
512 | " \n",
513 | " std | \n",
514 | " 0.276629 | \n",
515 | " 0.383686 | \n",
516 | "
\n",
517 | " \n",
518 | " min | \n",
519 | " 0.031076 | \n",
520 | " 0.039300 | \n",
521 | "
\n",
522 | " \n",
523 | " 25% | \n",
524 | " 0.064386 | \n",
525 | " 0.275886 | \n",
526 | "
\n",
527 | " \n",
528 | " 50% | \n",
529 | " 0.092597 | \n",
530 | " 0.410025 | \n",
531 | "
\n",
532 | " \n",
533 | " 75% | \n",
534 | " 0.153332 | \n",
535 | " 0.588994 | \n",
536 | "
\n",
537 | " \n",
538 | " max | \n",
539 | " 12.790906 | \n",
540 | " 14.769045 | \n",
541 | "
\n",
542 | " \n",
543 | "
\n",
544 | "
"
545 | ],
546 | "text/plain": [
547 | " one two\n",
548 | "count 9996.000000 9996.000000\n",
549 | "mean 0.146197 0.477317\n",
550 | "std 0.276629 0.383686\n",
551 | "min 0.031076 0.039300\n",
552 | "25% 0.064386 0.275886\n",
553 | "50% 0.092597 0.410025\n",
554 | "75% 0.153332 0.588994\n",
555 | "max 12.790906 14.769045"
556 | ]
557 | },
558 | "execution_count": 13,
559 | "metadata": {},
560 | "output_type": "execute_result"
561 | }
562 | ],
563 | "source": [
564 | "pd.DataFrame({\"one\":[p[0] for p in errors], \"two\":[p[1] for p in errors]}).describe()"
565 | ]
566 | },
567 | {
568 | "cell_type": "markdown",
569 | "metadata": {},
570 | "source": [
571 | "# Nothing special about CSR\n",
572 | "\n",
573 | "Let's do the same, with the same models, but now \"ground truth\" will be that events are twice as likely in $[0,1/2]$ as opposed to $[1/2,1]$.\n",
574 | "\n",
575 | "The results are the same, except that now \"hit rate\" also favours model 1."
576 | ]
577 | },
578 | {
579 | "cell_type": "code",
580 | "execution_count": 14,
581 | "metadata": {
582 | "collapsed": false
583 | },
584 | "outputs": [
585 | {
586 | "data": {
587 | "image/png": "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\n",
588 | "text/plain": [
589 | ""
590 | ]
591 | },
592 | "metadata": {},
593 | "output_type": "display_data"
594 | }
595 | ],
596 | "source": [
597 | "def make_events(average_number):\n",
598 | " num_events = np.random.poisson(lam=average_number)\n",
599 | " events = np.random.random(size=num_events) * 1.5\n",
600 | " mask = events < 1\n",
601 | " events[mask] = events[mask] * 0.5\n",
602 | " events[~mask] = events[~mask] - 0.5\n",
603 | " return events\n",
604 | "\n",
605 | "plt.hist(make_events(100000), bins=np.linspace(0, 1, 20))\n",
606 | "None"
607 | ]
608 | },
609 | {
610 | "cell_type": "code",
611 | "execution_count": 15,
612 | "metadata": {
613 | "collapsed": false
614 | },
615 | "outputs": [
616 | {
617 | "data": {
618 | "text/html": [
619 | "\n",
620 | "
\n",
621 | " \n",
622 | " \n",
623 | " | \n",
624 | " One | \n",
625 | " Two | \n",
626 | "
\n",
627 | " \n",
628 | " \n",
629 | " \n",
630 | " count | \n",
631 | " 10000.000000 | \n",
632 | " 10000.000000 | \n",
633 | "
\n",
634 | " \n",
635 | " mean | \n",
636 | " 0.302555 | \n",
637 | " 0.199724 | \n",
638 | "
\n",
639 | " \n",
640 | " std | \n",
641 | " 0.160472 | \n",
642 | " 0.136016 | \n",
643 | "
\n",
644 | " \n",
645 | " min | \n",
646 | " 0.000000 | \n",
647 | " 0.000000 | \n",
648 | "
\n",
649 | " \n",
650 | " 25% | \n",
651 | " 0.200000 | \n",
652 | " 0.100000 | \n",
653 | "
\n",
654 | " \n",
655 | " 50% | \n",
656 | " 0.294118 | \n",
657 | " 0.187500 | \n",
658 | "
\n",
659 | " \n",
660 | " 75% | \n",
661 | " 0.400000 | \n",
662 | " 0.285714 | \n",
663 | "
\n",
664 | " \n",
665 | " max | \n",
666 | " 1.000000 | \n",
667 | " 1.000000 | \n",
668 | "
\n",
669 | " \n",
670 | "
\n",
671 | "
"
672 | ],
673 | "text/plain": [
674 | " One Two\n",
675 | "count 10000.000000 10000.000000\n",
676 | "mean 0.302555 0.199724\n",
677 | "std 0.160472 0.136016\n",
678 | "min 0.000000 0.000000\n",
679 | "25% 0.200000 0.100000\n",
680 | "50% 0.294118 0.187500\n",
681 | "75% 0.400000 0.285714\n",
682 | "max 1.000000 1.000000"
683 | ]
684 | },
685 | "execution_count": 15,
686 | "metadata": {},
687 | "output_type": "execute_result"
688 | }
689 | ],
690 | "source": [
691 | "trials = 10000\n",
692 | "cells = 10\n",
693 | "coverage = 3\n",
694 | "\n",
695 | "hit_rate_1 = []\n",
696 | "hit_rate_2 = []\n",
697 | "for _ in range(trials):\n",
698 | " events = make_events(10)\n",
699 | " if len(events) == 0:\n",
700 | " continue\n",
701 | " pred1 = coverage1(cells, coverage)\n",
702 | " pred2 = coverage2(cells, coverage)\n",
703 | " hit_rate_1.append( score(events, cells, pred1) )\n",
704 | " hit_rate_2.append( score(events, cells, pred2) )\n",
705 | "\n",
706 | "pd.DataFrame({\"One\":hit_rate_1, \"Two\":hit_rate_2}).describe()"
707 | ]
708 | },
709 | {
710 | "cell_type": "code",
711 | "execution_count": 16,
712 | "metadata": {
713 | "collapsed": false
714 | },
715 | "outputs": [
716 | {
717 | "data": {
718 | "text/html": [
719 | "\n",
720 | "
\n",
721 | " \n",
722 | " \n",
723 | " | \n",
724 | " 0 | \n",
725 | "
\n",
726 | " \n",
727 | " \n",
728 | " \n",
729 | " count | \n",
730 | " 10000.000000 | \n",
731 | "
\n",
732 | " \n",
733 | " mean | \n",
734 | " 5.419622 | \n",
735 | "
\n",
736 | " \n",
737 | " std | \n",
738 | " 3.777092 | \n",
739 | "
\n",
740 | " \n",
741 | " min | \n",
742 | " -3.657635 | \n",
743 | "
\n",
744 | " \n",
745 | " 25% | \n",
746 | " 2.688512 | \n",
747 | "
\n",
748 | " \n",
749 | " 50% | \n",
750 | " 4.904619 | \n",
751 | "
\n",
752 | " \n",
753 | " 75% | \n",
754 | " 7.595387 | \n",
755 | "
\n",
756 | " \n",
757 | " max | \n",
758 | " 24.506569 | \n",
759 | "
\n",
760 | " \n",
761 | "
\n",
762 | "
"
763 | ],
764 | "text/plain": [
765 | " 0\n",
766 | "count 10000.000000\n",
767 | "mean 5.419622\n",
768 | "std 3.777092\n",
769 | "min -3.657635\n",
770 | "25% 2.688512\n",
771 | "50% 4.904619\n",
772 | "75% 7.595387\n",
773 | "max 24.506569"
774 | ]
775 | },
776 | "execution_count": 16,
777 | "metadata": {},
778 | "output_type": "execute_result"
779 | }
780 | ],
781 | "source": [
782 | "ratios = []\n",
783 | "\n",
784 | "for _ in range(10000):\n",
785 | " events = make_events(10)\n",
786 | " log_ratio = likelihood1(events) - likelihood2(events)\n",
787 | " ratios.append(log_ratio)\n",
788 | " \n",
789 | "pd.DataFrame(ratios).describe()"
790 | ]
791 | },
792 | {
793 | "cell_type": "code",
794 | "execution_count": 17,
795 | "metadata": {
796 | "collapsed": false
797 | },
798 | "outputs": [
799 | {
800 | "data": {
801 | "text/html": [
802 | "\n",
803 | "
\n",
804 | " \n",
805 | " \n",
806 | " | \n",
807 | " one | \n",
808 | " two | \n",
809 | "
\n",
810 | " \n",
811 | " \n",
812 | " \n",
813 | " count | \n",
814 | " 9998.0 | \n",
815 | " 9998.000000 | \n",
816 | "
\n",
817 | " \n",
818 | " mean | \n",
819 | " 0.0 | \n",
820 | " -0.537126 | \n",
821 | "
\n",
822 | " \n",
823 | " std | \n",
824 | " 0.0 | \n",
825 | " 0.354822 | \n",
826 | "
\n",
827 | " \n",
828 | " min | \n",
829 | " 0.0 | \n",
830 | " -2.881477 | \n",
831 | "
\n",
832 | " \n",
833 | " 25% | \n",
834 | " 0.0 | \n",
835 | " -0.742671 | \n",
836 | "
\n",
837 | " \n",
838 | " 50% | \n",
839 | " 0.0 | \n",
840 | " -0.500278 | \n",
841 | "
\n",
842 | " \n",
843 | " 75% | \n",
844 | " 0.0 | \n",
845 | " -0.295465 | \n",
846 | "
\n",
847 | " \n",
848 | " max | \n",
849 | " 0.0 | \n",
850 | " 0.440049 | \n",
851 | "
\n",
852 | " \n",
853 | "
\n",
854 | "
"
855 | ],
856 | "text/plain": [
857 | " one two\n",
858 | "count 9998.0 9998.000000\n",
859 | "mean 0.0 -0.537126\n",
860 | "std 0.0 0.354822\n",
861 | "min 0.0 -2.881477\n",
862 | "25% 0.0 -0.742671\n",
863 | "50% 0.0 -0.500278\n",
864 | "75% 0.0 -0.295465\n",
865 | "max 0.0 0.440049"
866 | ]
867 | },
868 | "execution_count": 17,
869 | "metadata": {},
870 | "output_type": "execute_result"
871 | }
872 | ],
873 | "source": [
874 | "one, two = [], []\n",
875 | "for _ in range(10000):\n",
876 | " events = make_events(10)\n",
877 | " if len(events) == 0:\n",
878 | " continue\n",
879 | " one.append( likelihood1(events) / len(events) )\n",
880 | " two.append( likelihood2(events) / len(events) )\n",
881 | "pd.DataFrame({\"one\":one, \"two\":two}).describe()"
882 | ]
883 | },
884 | {
885 | "cell_type": "code",
886 | "execution_count": 18,
887 | "metadata": {
888 | "collapsed": true
889 | },
890 | "outputs": [],
891 | "source": [
892 | "errors = []\n",
893 | "for _ in range(10000):\n",
894 | " events = make_events(10)\n",
895 | " if len(events) < 2:\n",
896 | " continue\n",
897 | " kernel = scipy.stats.kde.gaussian_kde(events)\n",
898 | " e1, _ = scipy.integrate.quad(lambda x : (kernel(x) - func1(x))**2, 0, 1)\n",
899 | " e2, _ = scipy.integrate.quad(lambda x : (kernel(x) - func2(x))**2, 0, 1)\n",
900 | " errors.append((e1, e2))"
901 | ]
902 | },
903 | {
904 | "cell_type": "code",
905 | "execution_count": 19,
906 | "metadata": {
907 | "collapsed": false
908 | },
909 | "outputs": [
910 | {
911 | "data": {
912 | "text/html": [
913 | "\n",
914 | "
\n",
915 | " \n",
916 | " \n",
917 | " | \n",
918 | " one | \n",
919 | " two | \n",
920 | "
\n",
921 | " \n",
922 | " \n",
923 | " \n",
924 | " count | \n",
925 | " 9992.000000 | \n",
926 | " 9992.000000 | \n",
927 | "
\n",
928 | " \n",
929 | " mean | \n",
930 | " 0.200730 | \n",
931 | " 0.762903 | \n",
932 | "
\n",
933 | " \n",
934 | " std | \n",
935 | " 0.279527 | \n",
936 | " 0.461152 | \n",
937 | "
\n",
938 | " \n",
939 | " min | \n",
940 | " 0.032237 | \n",
941 | " 0.054530 | \n",
942 | "
\n",
943 | " \n",
944 | " 25% | \n",
945 | " 0.076875 | \n",
946 | " 0.481650 | \n",
947 | "
\n",
948 | " \n",
949 | " 50% | \n",
950 | " 0.125253 | \n",
951 | " 0.669875 | \n",
952 | "
\n",
953 | " \n",
954 | " 75% | \n",
955 | " 0.229443 | \n",
956 | " 0.936467 | \n",
957 | "
\n",
958 | " \n",
959 | " max | \n",
960 | " 10.078522 | \n",
961 | " 10.682809 | \n",
962 | "
\n",
963 | " \n",
964 | "
\n",
965 | "
"
966 | ],
967 | "text/plain": [
968 | " one two\n",
969 | "count 9992.000000 9992.000000\n",
970 | "mean 0.200730 0.762903\n",
971 | "std 0.279527 0.461152\n",
972 | "min 0.032237 0.054530\n",
973 | "25% 0.076875 0.481650\n",
974 | "50% 0.125253 0.669875\n",
975 | "75% 0.229443 0.936467\n",
976 | "max 10.078522 10.682809"
977 | ]
978 | },
979 | "execution_count": 19,
980 | "metadata": {},
981 | "output_type": "execute_result"
982 | }
983 | ],
984 | "source": [
985 | "pd.DataFrame({\"one\":[p[0] for p in errors], \"two\":[p[1] for p in errors]}).describe()"
986 | ]
987 | },
988 | {
989 | "cell_type": "markdown",
990 | "metadata": {},
991 | "source": [
992 | "# Finally...\n",
993 | "\n",
994 | "Flip it about, now \"ground truth\" will be that events are twice as likely in $[1/2,1]$ as opposed to $[0,1/2]$.\n",
995 | "\n",
996 | "Now hit rate favours model 2. Likelihood favours (weakly) model 1. KDE favours model 1."
997 | ]
998 | },
999 | {
1000 | "cell_type": "code",
1001 | "execution_count": 20,
1002 | "metadata": {
1003 | "collapsed": false
1004 | },
1005 | "outputs": [
1006 | {
1007 | "data": {
1008 | "image/png": "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\n",
1009 | "text/plain": [
1010 | ""
1011 | ]
1012 | },
1013 | "metadata": {},
1014 | "output_type": "display_data"
1015 | }
1016 | ],
1017 | "source": [
1018 | "def make_events1(average_number):\n",
1019 | " return 1 - make_events(average_number)\n",
1020 | "\n",
1021 | "plt.hist(make_events1(100000), bins=np.linspace(0, 1, 20))\n",
1022 | "None"
1023 | ]
1024 | },
1025 | {
1026 | "cell_type": "code",
1027 | "execution_count": 21,
1028 | "metadata": {
1029 | "collapsed": false
1030 | },
1031 | "outputs": [
1032 | {
1033 | "data": {
1034 | "text/html": [
1035 | "\n",
1036 | "
\n",
1037 | " \n",
1038 | " \n",
1039 | " | \n",
1040 | " One | \n",
1041 | " Two | \n",
1042 | "
\n",
1043 | " \n",
1044 | " \n",
1045 | " \n",
1046 | " count | \n",
1047 | " 9999.000000 | \n",
1048 | " 9999.000000 | \n",
1049 | "
\n",
1050 | " \n",
1051 | " mean | \n",
1052 | " 0.299005 | \n",
1053 | " 0.401429 | \n",
1054 | "
\n",
1055 | " \n",
1056 | " std | \n",
1057 | " 0.161717 | \n",
1058 | " 0.163036 | \n",
1059 | "
\n",
1060 | " \n",
1061 | " min | \n",
1062 | " 0.000000 | \n",
1063 | " 0.000000 | \n",
1064 | "
\n",
1065 | " \n",
1066 | " 25% | \n",
1067 | " 0.181818 | \n",
1068 | " 0.285714 | \n",
1069 | "
\n",
1070 | " \n",
1071 | " 50% | \n",
1072 | " 0.285714 | \n",
1073 | " 0.400000 | \n",
1074 | "
\n",
1075 | " \n",
1076 | " 75% | \n",
1077 | " 0.400000 | \n",
1078 | " 0.500000 | \n",
1079 | "
\n",
1080 | " \n",
1081 | " max | \n",
1082 | " 1.000000 | \n",
1083 | " 1.000000 | \n",
1084 | "
\n",
1085 | " \n",
1086 | "
\n",
1087 | "
"
1088 | ],
1089 | "text/plain": [
1090 | " One Two\n",
1091 | "count 9999.000000 9999.000000\n",
1092 | "mean 0.299005 0.401429\n",
1093 | "std 0.161717 0.163036\n",
1094 | "min 0.000000 0.000000\n",
1095 | "25% 0.181818 0.285714\n",
1096 | "50% 0.285714 0.400000\n",
1097 | "75% 0.400000 0.500000\n",
1098 | "max 1.000000 1.000000"
1099 | ]
1100 | },
1101 | "execution_count": 21,
1102 | "metadata": {},
1103 | "output_type": "execute_result"
1104 | }
1105 | ],
1106 | "source": [
1107 | "trials = 10000\n",
1108 | "cells = 10\n",
1109 | "coverage = 3\n",
1110 | "\n",
1111 | "hit_rate_1 = []\n",
1112 | "hit_rate_2 = []\n",
1113 | "for _ in range(trials):\n",
1114 | " events = make_events1(10)\n",
1115 | " if len(events) == 0:\n",
1116 | " continue\n",
1117 | " pred1 = coverage1(cells, coverage)\n",
1118 | " pred2 = coverage2(cells, coverage)\n",
1119 | " hit_rate_1.append( score(events, cells, pred1) )\n",
1120 | " hit_rate_2.append( score(events, cells, pred2) )\n",
1121 | "\n",
1122 | "pd.DataFrame({\"One\":hit_rate_1, \"Two\":hit_rate_2}).describe()"
1123 | ]
1124 | },
1125 | {
1126 | "cell_type": "code",
1127 | "execution_count": 22,
1128 | "metadata": {
1129 | "collapsed": false
1130 | },
1131 | "outputs": [
1132 | {
1133 | "data": {
1134 | "text/html": [
1135 | "\n",
1136 | "
\n",
1137 | " \n",
1138 | " \n",
1139 | " | \n",
1140 | " 0 | \n",
1141 | "
\n",
1142 | " \n",
1143 | " \n",
1144 | " \n",
1145 | " count | \n",
1146 | " 10000.000000 | \n",
1147 | "
\n",
1148 | " \n",
1149 | " mean | \n",
1150 | " 0.744658 | \n",
1151 | "
\n",
1152 | " \n",
1153 | " std | \n",
1154 | " 2.803817 | \n",
1155 | "
\n",
1156 | " \n",
1157 | " min | \n",
1158 | " -7.572446 | \n",
1159 | "
\n",
1160 | " \n",
1161 | " 25% | \n",
1162 | " -1.216704 | \n",
1163 | "
\n",
1164 | " \n",
1165 | " 50% | \n",
1166 | " 0.316195 | \n",
1167 | "
\n",
1168 | " \n",
1169 | " 75% | \n",
1170 | " 2.285786 | \n",
1171 | "
\n",
1172 | " \n",
1173 | " max | \n",
1174 | " 18.178649 | \n",
1175 | "
\n",
1176 | " \n",
1177 | "
\n",
1178 | "
"
1179 | ],
1180 | "text/plain": [
1181 | " 0\n",
1182 | "count 10000.000000\n",
1183 | "mean 0.744658\n",
1184 | "std 2.803817\n",
1185 | "min -7.572446\n",
1186 | "25% -1.216704\n",
1187 | "50% 0.316195\n",
1188 | "75% 2.285786\n",
1189 | "max 18.178649"
1190 | ]
1191 | },
1192 | "execution_count": 22,
1193 | "metadata": {},
1194 | "output_type": "execute_result"
1195 | }
1196 | ],
1197 | "source": [
1198 | "ratios = []\n",
1199 | "\n",
1200 | "for _ in range(10000):\n",
1201 | " events = make_events1(10)\n",
1202 | " log_ratio = likelihood1(events) - likelihood2(events)\n",
1203 | " ratios.append(log_ratio)\n",
1204 | " \n",
1205 | "pd.DataFrame(ratios).describe()"
1206 | ]
1207 | },
1208 | {
1209 | "cell_type": "code",
1210 | "execution_count": 23,
1211 | "metadata": {
1212 | "collapsed": false
1213 | },
1214 | "outputs": [
1215 | {
1216 | "data": {
1217 | "text/html": [
1218 | "\n",
1219 | "
\n",
1220 | " \n",
1221 | " \n",
1222 | " | \n",
1223 | " one | \n",
1224 | " two | \n",
1225 | "
\n",
1226 | " \n",
1227 | " \n",
1228 | " \n",
1229 | " count | \n",
1230 | " 10000.0 | \n",
1231 | " 10000.000000 | \n",
1232 | "
\n",
1233 | " \n",
1234 | " mean | \n",
1235 | " 0.0 | \n",
1236 | " -0.080728 | \n",
1237 | "
\n",
1238 | " \n",
1239 | " std | \n",
1240 | " 0.0 | \n",
1241 | " 0.301639 | \n",
1242 | "
\n",
1243 | " \n",
1244 | " min | \n",
1245 | " 0.0 | \n",
1246 | " -2.402754 | \n",
1247 | "
\n",
1248 | " \n",
1249 | " 25% | \n",
1250 | " 0.0 | \n",
1251 | " -0.247010 | \n",
1252 | "
\n",
1253 | " \n",
1254 | " 50% | \n",
1255 | " 0.0 | \n",
1256 | " -0.038585 | \n",
1257 | "
\n",
1258 | " \n",
1259 | " 75% | \n",
1260 | " 0.0 | \n",
1261 | " 0.133735 | \n",
1262 | "
\n",
1263 | " \n",
1264 | " max | \n",
1265 | " 0.0 | \n",
1266 | " 0.602009 | \n",
1267 | "
\n",
1268 | " \n",
1269 | "
\n",
1270 | "
"
1271 | ],
1272 | "text/plain": [
1273 | " one two\n",
1274 | "count 10000.0 10000.000000\n",
1275 | "mean 0.0 -0.080728\n",
1276 | "std 0.0 0.301639\n",
1277 | "min 0.0 -2.402754\n",
1278 | "25% 0.0 -0.247010\n",
1279 | "50% 0.0 -0.038585\n",
1280 | "75% 0.0 0.133735\n",
1281 | "max 0.0 0.602009"
1282 | ]
1283 | },
1284 | "execution_count": 23,
1285 | "metadata": {},
1286 | "output_type": "execute_result"
1287 | }
1288 | ],
1289 | "source": [
1290 | "one, two = [], []\n",
1291 | "for _ in range(10000):\n",
1292 | " events = make_events1(10)\n",
1293 | " if len(events) == 0:\n",
1294 | " continue\n",
1295 | " one.append( likelihood1(events) / len(events) )\n",
1296 | " two.append( likelihood2(events) / len(events) )\n",
1297 | "pd.DataFrame({\"one\":one, \"two\":two}).describe()"
1298 | ]
1299 | },
1300 | {
1301 | "cell_type": "code",
1302 | "execution_count": 24,
1303 | "metadata": {
1304 | "collapsed": true
1305 | },
1306 | "outputs": [],
1307 | "source": [
1308 | "errors = []\n",
1309 | "for _ in range(10000):\n",
1310 | " events = make_events1(10)\n",
1311 | " if len(events) < 2:\n",
1312 | " continue\n",
1313 | " kernel = scipy.stats.kde.gaussian_kde(events)\n",
1314 | " e1, _ = scipy.integrate.quad(lambda x : (kernel(x) - func1(x))**2, 0, 1)\n",
1315 | " e2, _ = scipy.integrate.quad(lambda x : (kernel(x) - func2(x))**2, 0, 1)\n",
1316 | " errors.append((e1, e2))"
1317 | ]
1318 | },
1319 | {
1320 | "cell_type": "code",
1321 | "execution_count": 26,
1322 | "metadata": {
1323 | "collapsed": false
1324 | },
1325 | "outputs": [
1326 | {
1327 | "data": {
1328 | "text/html": [
1329 | "\n",
1330 | "
\n",
1331 | " \n",
1332 | " \n",
1333 | " | \n",
1334 | " one | \n",
1335 | " two | \n",
1336 | "
\n",
1337 | " \n",
1338 | " \n",
1339 | " \n",
1340 | " count | \n",
1341 | " 9994.000000 | \n",
1342 | " 9994.000000 | \n",
1343 | "
\n",
1344 | " \n",
1345 | " mean | \n",
1346 | " 0.201497 | \n",
1347 | " 0.303939 | \n",
1348 | "
\n",
1349 | " \n",
1350 | " std | \n",
1351 | " 0.281399 | \n",
1352 | " 0.268947 | \n",
1353 | "
\n",
1354 | " \n",
1355 | " min | \n",
1356 | " 0.031006 | \n",
1357 | " 0.037054 | \n",
1358 | "
\n",
1359 | " \n",
1360 | " 25% | \n",
1361 | " 0.076810 | \n",
1362 | " 0.160567 | \n",
1363 | "
\n",
1364 | " \n",
1365 | " 50% | \n",
1366 | " 0.124121 | \n",
1367 | " 0.251117 | \n",
1368 | "
\n",
1369 | " \n",
1370 | " 75% | \n",
1371 | " 0.226164 | \n",
1372 | " 0.379557 | \n",
1373 | "
\n",
1374 | " \n",
1375 | " max | \n",
1376 | " 13.151977 | \n",
1377 | " 13.420936 | \n",
1378 | "
\n",
1379 | " \n",
1380 | "
\n",
1381 | "
"
1382 | ],
1383 | "text/plain": [
1384 | " one two\n",
1385 | "count 9994.000000 9994.000000\n",
1386 | "mean 0.201497 0.303939\n",
1387 | "std 0.281399 0.268947\n",
1388 | "min 0.031006 0.037054\n",
1389 | "25% 0.076810 0.160567\n",
1390 | "50% 0.124121 0.251117\n",
1391 | "75% 0.226164 0.379557\n",
1392 | "max 13.151977 13.420936"
1393 | ]
1394 | },
1395 | "execution_count": 26,
1396 | "metadata": {},
1397 | "output_type": "execute_result"
1398 | }
1399 | ],
1400 | "source": [
1401 | "pd.DataFrame({\"one\":[p[0] for p in errors], \"two\":[p[1] for p in errors]}).describe()"
1402 | ]
1403 | },
1404 | {
1405 | "cell_type": "code",
1406 | "execution_count": null,
1407 | "metadata": {
1408 | "collapsed": true
1409 | },
1410 | "outputs": [],
1411 | "source": []
1412 | }
1413 | ],
1414 | "metadata": {
1415 | "kernelspec": {
1416 | "display_name": "Python 3",
1417 | "language": "python",
1418 | "name": "python3"
1419 | },
1420 | "language_info": {
1421 | "codemirror_mode": {
1422 | "name": "ipython",
1423 | "version": 3
1424 | },
1425 | "file_extension": ".py",
1426 | "mimetype": "text/x-python",
1427 | "name": "python",
1428 | "nbconvert_exporter": "python",
1429 | "pygments_lexer": "ipython3",
1430 | "version": "3.6.0"
1431 | }
1432 | },
1433 | "nbformat": 4,
1434 | "nbformat_minor": 2
1435 | }
1436 |
--------------------------------------------------------------------------------
/Temporal spatial processes.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {
6 | "collapsed": true
7 | },
8 | "source": [
9 | "# Marked processes #\n",
10 | "\n",
11 | "We shall be interested in spatial processes which occur in time.\n",
12 | "\n",
13 | "- For example, we might wish to model a self-exciting process where events occur at a location in (2 or 3 dimensional) space, and the \"offspring\" events show a clustering behaviour close to the parent event.\n",
14 | "\n",
15 | "The standard way of treating such a process is via \"marks\". We start with a temporal process as already discussed, and to each event we also associate a \"mark\" from a \"mark space\".\n",
16 | "\n",
17 | "- Our mark space will be $\\mathbb R^2$, or a subset thereof, i.e. a 2 dimensional point in space.\n",
18 | "- Marks can also be discrete, for example to classify events into a number of different types."
19 | ]
20 | },
21 | {
22 | "cell_type": "markdown",
23 | "metadata": {},
24 | "source": [
25 | "We shall consider a restricted setup. Marks may occur in a \"mark space\" $M$ (probably $M\\subseteq \\mathbb R^2$).\n",
26 | "\n",
27 | "- Immigrants will have independently chosen marks, say with density $\\gamma(\\kappa,t)$.\n",
28 | "- The immigrant intensity may vary with time, $\\mu(t)$.\n",
29 | "- Offspring intensity is $\\alpha(\\kappa) \\beta(t,\\kappa)$ where $\\alpha$ is the \"total intensity\" depending on the mark, and $\\beta$ is taken to be a normalised intensity, depending on time and the mark.\n",
30 | "- The offspring marks are independent and only depend upon the time and mark of the parent.\n",
31 | "\n",
32 | "Thus the total intensity function is\n",
33 | "$$ \\lambda^*(t) = \\mu(t) + \\sum_{t_i < t} \\alpha(\\kappa_i) \\beta(t-t_i,\\kappa_i). $$"
34 | ]
35 | },
36 | {
37 | "cell_type": "markdown",
38 | "metadata": {},
39 | "source": [
40 | "An example of an ETAS (epidemic type aftershock) model has mark space consisting of triples $\\kappa=(m,x,y)$ where $m>0$ is the \"magnitude\" of the event, and $(x,y)$ are coordinates in a window $W$.\n",
41 | "\n",
42 | "- $\\mu(t) = \\mu_1$ for $t\\geq 0$. So background intensity is constant.\n",
43 | "- $\\alpha(\\kappa) = \\alpha_1 e^{m \\alpha_2}$. So the total intensity is exponential in the magnitude.\n",
44 | "- $\\beta(t,\\kappa) = \\beta(t)$ is some decaying function in $t$. For example, a power law\n",
45 | "$$ \\beta(t) = \\frac{\\beta_2}{\\beta_1} \\Big( 1+\\frac{t}{\\beta_1} \\Big)^{-\\beta_2-1} $$\n",
46 | "where we scale by $\\beta_1$, and decay at rate $\\beta_2$, and normalise. Notice that this example is independant of the mark.\n",
47 | "- For immigrants we have mark density $\\gamma_1 e^{-\\gamma_1 m} |W|^{-1}$ for $(x,y)\\in W$. So the coordinates of events are uniform in $W$, and the magnitude follows an exponential distribution.\n",
48 | "- For offspring, we have a more complicated mark density:\n",
49 | "$$ \\gamma(\\kappa | t, (t_p,\\kappa_p)) = \\gamma_1 e^{-\\gamma_1 m} \\frac{1}{2\\pi\\gamma_2^2}\n",
50 | "\\exp\\Big( - \\frac{\\| (x,y) - (x_p,y_p) \\|^2}{2\\gamma_2^2} \\Big) $$\n",
51 | "where the parent event occurred at time $t_p$ with mark $\\kappa_p$. Thus the magnitude continues to follow an exponential distribution, but the location of the \"aftershock\" follows a Gaussian distribution centred on the location of the parent event.\n",
52 | "\n",
53 | "Here we have followed [Rasmussen, \"Bayesian Inference for Hawkes Processes\"](https://doi.org/10.1007/s11009-011-9272-5)."
54 | ]
55 | },
56 | {
57 | "cell_type": "markdown",
58 | "metadata": {},
59 | "source": [
60 | "This approach via \"marks\" may seem complicated, but it allows us to easily adapt the simulation procedure from the unmarked case, by simply adding in the marks.\n",
61 | "\n",
62 | "Let us consider a one dimensional mark space, which is easier to visualise.\n",
63 | "\n",
64 | "- $\\mu(t) = \\mu$\n",
65 | "- $\\alpha(\\kappa)=\\alpha$\n",
66 | "- $\\beta(t,\\kappa) = (1+t)^{-2}$\n",
67 | "- Immigrants will have mark uniformly chosen in $[0,1]$\n",
68 | "- Offspring have mark density following a Gaussian centred on the parent location, say with variance $\\sigma^2$."
69 | ]
70 | },
71 | {
72 | "cell_type": "code",
73 | "execution_count": 235,
74 | "metadata": {
75 | "collapsed": true
76 | },
77 | "outputs": [],
78 | "source": [
79 | "%matplotlib inline\n",
80 | "import numpy as np\n",
81 | "import matplotlib.pyplot as plt\n",
82 | "import scipy.stats\n",
83 | "import utils"
84 | ]
85 | },
86 | {
87 | "cell_type": "code",
88 | "execution_count": 304,
89 | "metadata": {
90 | "collapsed": false
91 | },
92 | "outputs": [
93 | {
94 | "data": {
95 | "image/png": "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\nefNQs+OYqVJVF5L86SQ/miSttU+11p6JY5npdC7JC6rqXJK5JB+NY5kp0Fr7pSS/s6N5t2P34SRv\na61ttdY+nOTx9LPhriYRVu9L8pGh5Se322BqVNViki9L8stJXtxa+9j2Q7+R5MUT6hYc1A8k+RtJ\nnhtqcxwzbR5I8nSSf7w9pP3NVfXZcSwzZVprTyX5B0k2k3wsyY3W2s/Hscz02u3YPXQONMESHFJV\n3ZPkp5J8Z2vt94Yfa/1rQbkeFJ1VVX8uycdba4/tto7jmClxLsmXJ/nh1tqXJflkdgyTdCwzDbbP\n53s4/X/AfF6Sz66qbx1ex7HMtLrbY3cSYfWpJC8ZWr5/uw06r6o+K/2g2mutvX27+Ter6nO3H//c\nJB+fVP/gAP5kkj9fVU+kfxrGn6mqH4/jmOnzZJInW2u/vL38T9MPr45lps3XJvlwa+3p1tqnk7w9\nyX8YxzLTa7dj99A5cBJh9d1JHqyqB6rqeemfZPvoBPoBh1JVlf65Ue9vrf2PQw89muS121+/Nsk/\nO+m+wUG11v5ma+3+1tpi+u+/v9ha+9Y4jpkyrbXfSPKRqvqC7aavSfK+OJaZPptJvqqq5rY/a3xN\n+vNiOJaZVrsdu48meXVVPb+qHkjyYJJ/s9eGql+ZPVlV9ar0z5k6m+QtrbW1E+8EHFJVvTzJO5P8\nWm6d6/e30j9v9SeTzCfZSPKXWms7TzSHzqmq5SR/vbX256rqj8VxzJSpqkvpTxT2vCQfSvLt6f8j\n3rHMVKmqv5Pkm9K/8sCvJvnLSe6JY5mOq6qfSLKc5EVJfjPJ9yb56exy7FbV5ST/efrH+ne21n5m\nz+1PIqwCAADAXkywBAAAQOcIqwAAAHSOsAoAAEDnCKsAAAB0jrAKAABA5wirAAAAdI6wCgAAQOf8\n/9JZKnUu0t+EAAAAAElFTkSuQmCC\n",
96 | "text/plain": [
97 | ""
98 | ]
99 | },
100 | "metadata": {},
101 | "output_type": "display_data"
102 | }
103 | ],
104 | "source": [
105 | "from collections import namedtuple\n",
106 | "Event = namedtuple(\"Event\", [\"t\", \"loc\"])\n",
107 | "\n",
108 | "mu = 0.1\n",
109 | "alpha = 1\n",
110 | "sigma = 0.01\n",
111 | "\n",
112 | "def sort_with_causes(points, caused_by):\n",
113 | " \"\"\"Sorts `points` in time order, and maintains caused by information\"\"\"\n",
114 | " # caused_by[i] = j= alpha:\n",
131 | " return points\n",
132 | " loc = np.random.normal(loc=parent.loc, scale=sigma)\n",
133 | " points.append(Event(parent.t + t / (alpha - t), loc))\n",
134 | " \n",
135 | "def simulate(window_size=100):\n",
136 | " backgrounds = utils.sample_poisson_process(window_size, 1/mu)\n",
137 | " backgrounds = [Event(t, np.random.uniform()) for t in backgrounds]\n",
138 | " points = list(backgrounds)\n",
139 | " caused_by = [ i for i in range(len(points)) ]\n",
140 | " to_process = [(i,p) for i, p in enumerate(points)]\n",
141 | " while len(to_process) > 0:\n",
142 | " (index, next_point) = to_process.pop()\n",
143 | " for event in simulate_sub_process(next_point):\n",
144 | " if event.t < window_size:\n",
145 | " points.append(event)\n",
146 | " caused_by.append(index)\n",
147 | " to_process.append((len(points) - 1,event))\n",
148 | " points, caused_by = sort_with_causes(points, caused_by)\n",
149 | " return points, backgrounds, caused_by\n",
150 | "\n",
151 | "points, backgrounds, caused_by = simulate()\n",
152 | "width, _ = utils.slim_aspect()\n",
153 | "fig, ax = plt.subplots(nrows=1, ncols=1, figsize=(width,7))\n",
154 | "ax.set(xlim=[0,100], ylim=[-0.1,1.1], title=\"1D ETAS simulation\")\n",
155 | "_ = ax.scatter(x=[e.t for e in points], y=[e.loc for e in points], color=\"blue\", marker=\"+\")\n",
156 | "_ = ax.scatter(x=[e.t for e in backgrounds], y=[e.loc for e in backgrounds], color=\"black\")"
157 | ]
158 | },
159 | {
160 | "cell_type": "markdown",
161 | "metadata": {},
162 | "source": [
163 | "In this example, we have set the background rate to be low, and the mark distribution of offspring to be tightly bound to the location of the parent. This allows us to visualise how an immigrant sets off a chain of \"aftershocks\" which spread out slowly in space."
164 | ]
165 | },
166 | {
167 | "cell_type": "markdown",
168 | "metadata": {},
169 | "source": [
170 | "# Model extraction #\n",
171 | "\n",
172 | "Let us start by assuming we know the form, and parameters, of the distributions. We aim then to classify points as \"background\" or \"triggered by another point\". Let us consider a more \"bundled\" way to write the conditional intensity:\n",
173 | "\n",
174 | "$$ \\lambda^*(t,x) = \\mu(t,x) + \\sum_{t_ij$. Given our simplified form, we have that\n",
183 | "$$ p_{i,i} \\lambda^*(t_i,x_i) = \\mu(t_i,x_i), \\quad\n",
184 | "p_{i,j} \\lambda^*(t_i,x_i) = g(t_j-t_i, x_j-x_i). $$"
185 | ]
186 | },
187 | {
188 | "cell_type": "code",
189 | "execution_count": 305,
190 | "metadata": {
191 | "collapsed": false
192 | },
193 | "outputs": [],
194 | "source": [
195 | "def mu_func(t, x, mu):\n",
196 | " return mu * (x>=0) * (x<=1)\n",
197 | "\n",
198 | "def g_func(dt, dx, alpha, sigma):\n",
199 | " beta = (1 + dt)**(-2)\n",
200 | " beta_x = np.exp(-0.5 * (dx/sigma)**2) / np.sqrt(2*np.pi*sigma*sigma)\n",
201 | " return alpha * beta * beta_x"
202 | ]
203 | },
204 | {
205 | "cell_type": "code",
206 | "execution_count": 306,
207 | "metadata": {
208 | "collapsed": false
209 | },
210 | "outputs": [],
211 | "source": [
212 | "def make_probability_matrix(points, mu, alpha, sigma):\n",
213 | " p_matrix = np.zeros((len(points), len(points)))\n",
214 | " for i, point in enumerate(points):\n",
215 | " p_matrix[i][i] = mu_func(point.t, point.loc, mu)\n",
216 | " for j in range(i):\n",
217 | " j_point = points[j]\n",
218 | " p_matrix[j][i] = g_func(point.t - j_point.t, point.loc - j_point.loc, alpha, sigma)\n",
219 | "\n",
220 | " column_sums = np.sum(p_matrix, axis=0)\n",
221 | " p_matrix /= column_sums\n",
222 | " return p_matrix"
223 | ]
224 | },
225 | {
226 | "cell_type": "markdown",
227 | "metadata": {},
228 | "source": [
229 | "Using the matrix of probabilities, we can estimate which events were background events. Here we simply use a maximum likelihood estimate."
230 | ]
231 | },
232 | {
233 | "cell_type": "code",
234 | "execution_count": 307,
235 | "metadata": {
236 | "collapsed": false
237 | },
238 | "outputs": [],
239 | "source": [
240 | "p_matrix = make_probability_matrix(points, mu, alpha, sigma)\n",
241 | "percentage_array = (p_matrix*100+0.5).astype(int)\n",
242 | "max_index = [ np.argmax(percentage_array[:,i]) for i in range(len(points)) ]\n",
243 | "\n",
244 | "background_points, triggered_points = [], []\n",
245 | "for i, p in enumerate(points):\n",
246 | " if max_index[i] == i:\n",
247 | " background_points.append(p)\n",
248 | " else:\n",
249 | " triggered_points.append(p)"
250 | ]
251 | },
252 | {
253 | "cell_type": "code",
254 | "execution_count": 308,
255 | "metadata": {
256 | "collapsed": false,
257 | "scrolled": true
258 | },
259 | "outputs": [
260 | {
261 | "data": {
262 | "image/png": "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\n",
263 | "text/plain": [
264 | ""
265 | ]
266 | },
267 | "metadata": {},
268 | "output_type": "display_data"
269 | }
270 | ],
271 | "source": [
272 | "fig, ax = plt.subplots(nrows=1, ncols=2, figsize=(width,5))\n",
273 | "\n",
274 | "ax[0].set(xlim=[0,100], ylim=[-0.1,1.1], title=\"Actual data\")\n",
275 | "_ = ax[0].scatter(x=[e.t for e in points], y=[e.loc for e in points], color=\"blue\", marker=\"+\")\n",
276 | "_ = ax[0].scatter(x=[e.t for e in backgrounds], y=[e.loc for e in backgrounds], color=\"black\", marker=\"o\")\n",
277 | "\n",
278 | "ax[1].set(xlim=[0,100], ylim=[-0.1,1.1], title=\"Inferred background events\")\n",
279 | "_ = ax[1].scatter(x=[e.t for e in triggered_points], y=[e.loc for e in triggered_points], color=\"blue\", marker=\"+\")\n",
280 | "_ = ax[1].scatter(x=[e.t for e in background_points], y=[e.loc for e in background_points], color=\"black\", marker=\"o\")"
281 | ]
282 | },
283 | {
284 | "cell_type": "markdown",
285 | "metadata": {},
286 | "source": [
287 | "*TODO:* These keep changing, of course...\n",
288 | "\n",
289 | "I think these plots are intuitively explainable:\n",
290 | "\n",
291 | "- We miss a background event at time 40, but it fell in the middle of a clump of triggered events.\n",
292 | "- Three triggered event at time circa 70 are classified as background-- but they look like unlikely events, so this seems plausible."
293 | ]
294 | },
295 | {
296 | "cell_type": "markdown",
297 | "metadata": {},
298 | "source": [
299 | "# Iterative approximation for parametric distributions #\n",
300 | "\n",
301 | "Suppose now we do not know the parameters $\\mu, \\alpha$ and $\\sigma$. We take an iterative, monte carlo approach.\n",
302 | "\n",
303 | "1. Take an initial \"guess\" of the parameters\n",
304 | "2. Use these to form $\\mu$ and $g$ and hence form the matrix $p$.\n",
305 | "3. For each event, using the probabilities from the matrix, randomly decide if the event is background, or assign it to a \"triggering\" event.\n",
306 | "4. Use the background events to estimate the parameter $\\mu$ (e.g. via MLE) and similarly use the triggered events to estimate $\\alpha, \\sigma$.\n",
307 | "\n",
308 | "See below for calculations of what the MLEs are."
309 | ]
310 | },
311 | {
312 | "cell_type": "code",
313 | "execution_count": 309,
314 | "metadata": {
315 | "collapsed": false
316 | },
317 | "outputs": [],
318 | "source": [
319 | "def compute_backgrounds_deltas(causes, points):\n",
320 | " backgrounds, trigger_deltas = [], []\n",
321 | " causes = sample_causality(p_matrix)\n",
322 | " for i, p in enumerate(points):\n",
323 | " c = causes[i]\n",
324 | " if c == i:\n",
325 | " backgrounds.append(p)\n",
326 | " else:\n",
327 | " tp = points[c]\n",
328 | " delta = Event(p.t - tp.t, p.loc - tp.loc)\n",
329 | " trigger_deltas.append(delta)\n",
330 | " return backgrounds, trigger_deltas\n",
331 | "\n",
332 | "def make_estimates(causes, points):\n",
333 | " \"\"\"Returns MLEs for mu, alpha and sigma.\"\"\"\n",
334 | " backgrounds, trigger_deltas = compute_backgrounds_deltas(causes, points)\n",
335 | " #background_event_times = np.array([e.t for e in backgrounds])\n",
336 | " #background_event_time_deltas = background_event_times[1:] - background_event_times[:-1]\n",
337 | " #mu = 1 / np.mean(background_event_time_deltas)\n",
338 | " window_size = 100\n",
339 | " mu = len(backgrounds) / window_size\n",
340 | " \n",
341 | " space_points = [e.loc for e in trigger_deltas]\n",
342 | " sigma = np.std(space_points, ddof=1)\n",
343 | " \n",
344 | " # Biased...\n",
345 | " counts = np.empty(len(causes) - 1, dtype=np.int32)\n",
346 | " for i in range(len(causes) - 1):\n",
347 | " counts[i] = sum(c==i for c in causes[i+1:])\n",
348 | " alpha = np.mean(counts)\n",
349 | " \n",
350 | " return mu, alpha, sigma"
351 | ]
352 | },
353 | {
354 | "cell_type": "code",
355 | "execution_count": 314,
356 | "metadata": {
357 | "collapsed": true
358 | },
359 | "outputs": [],
360 | "source": [
361 | "def sample_causality(p_matrix):\n",
362 | " \"\"\"Returns a list where entry i is the j