/
2022-06-17-deep-gaussian-processes-a-motivation-and-introduction-sheffield.html
1402 lines (1397 loc) · 145 KB
/
2022-06-17-deep-gaussian-processes-a-motivation-and-introduction-sheffield.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
---
title: "Deep Gaussian Processes: A Motivation and Introduction"
venue: "Sheffield ML Network"
abstract: "<p>Modern machine learning methods have driven significant advances in artificial intelligence, with notable examples coming from Deep Learning, enabling super-human performance in the game of Go and highly accurate prediction of protein folding e.g. AlphaFold. In this talk we look at deep learning from the perspective of Gaussian processes. Deep Gaussian processes extend the notion of deep learning to propagate uncertainty alongside function values. We’ll explain why this is important and show some simple examples.</p>"
author:
- given: Neil D.
family: Lawrence
url: http://inverseprobability.com
institute: University of Cambridge
twitter: lawrennd
gscholar: r3SJcvoAAAAJ
orcid:
edit_url: https://github.com/lawrennd/talks/edit/gh-pages/_deepgp/deep-gaussian-processes-a-motivation-and-introduction-sheffield.md
date: 2022-06-17
published: 2022-06-17
week: 0
reveal: 2022-06-17-deep-gaussian-processes-a-motivation-and-introduction-sheffield.slides.html
ipynb: 2022-06-17-deep-gaussian-processes-a-motivation-and-introduction-sheffield.ipynb
edit_url: https://github.com/lawrennd/talks/edit/gh-pages/_deepgp/deep-gaussian-processes-a-motivation-and-introduction-sheffield.md
layout: talk
categories:
- notes
---
<!-- Do not edit this file locally. -->
<!---->
<!-- Do not edit this file locally. -->
<!-- Do not edit this file locally. -->
<!-- The last names to be defined. Should be defined entirely in terms of macros from above-->
<!--
-->
<!--https://twitter.com/demishassabis/status/1453794436056502274?s=20 -->
<h1 id="introduction">Introduction</h1>
<h2 id="the-fourth-industrial-revolution">The Fourth Industrial Revolution</h2>
<div style="text-align:right">
<span class="editsection-bracket" style="">[</span><span class="editsection" style=""><a href="https://github.com/lawrennd/snippets/edit/main/_ai/includes/the-fourth-industrial-revolution-intro.md" target="_blank" onclick="ga('send', 'event', 'Edit Page', 'Edit', 'https://github.com/lawrennd/snippets/edit/main/_ai/includes/the-fourth-industrial-revolution-intro.md', 13);">edit</a></span><span class="editsection-bracket" style="">]</span>
</div>
<p>The fourth industrial revolution bears the particular hallmark of being the first revolution that has been named before it has happened. This is particularly unfortunate, because it is not in fact an industrial revolution at all. Nor is it necessarily a distinct phenomenon. It is part of a revolution in information, one that goes back to digitisation and the invention of the silicon chip.</p>
<p>Or to put it more precisely, it is a revolution in how information can affect the physical world. The interchange between information and the physical world.</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="op">%</span>pip install mlai</span></code></pre></div>
<div class="sourceCode" id="cb2"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="op">%</span>pip install notutils</span></code></pre></div>
<h1 id="what-is-machine-learning">What is Machine Learning?</h1>
<div style="text-align:right">
<span class="editsection-bracket" style="">[</span><span class="editsection" style=""><a href="https://github.com/lawrennd/snippets/edit/main/_ml/includes/what-is-ml.md" target="_blank" onclick="ga('send', 'event', 'Edit Page', 'Edit', 'https://github.com/lawrennd/snippets/edit/main/_ml/includes/what-is-ml.md', 13);">edit</a></span><span class="editsection-bracket" style="">]</span>
</div>
<p>What is machine learning? At its most basic level machine learning is a combination of</p>
<p><span class="math display">\[\text{data} + \text{model} \stackrel{\text{compute}}{\rightarrow} \text{prediction}\]</span></p>
<p>where <em>data</em> is our observations. They can be actively or passively acquired (meta-data). The <em>model</em> contains our assumptions, based on previous experience. That experience can be other data, it can come from transfer learning, or it can merely be our beliefs about the regularities of the universe. In humans our models include our inductive biases. The <em>prediction</em> is an action to be taken or a categorization or a quality score. The reason that machine learning has become a mainstay of artificial intelligence is the importance of predictions in artificial intelligence. The data and the model are combined through computation.</p>
<p>In practice we normally perform machine learning using two functions. To combine data with a model we typically make use of:</p>
<p><strong>a prediction function</strong> a function which is used to make the predictions. It includes our beliefs about the regularities of the universe, our assumptions about how the world works, e.g., smoothness, spatial similarities, temporal similarities.</p>
<p><strong>an objective function</strong> a function which defines the cost of misprediction. Typically, it includes knowledge about the world’s generating processes (probabilistic objectives) or the costs we pay for mispredictions (empirical risk minimization).</p>
<p>The combination of data and model through the prediction function and the objective function leads to a <em>learning algorithm</em>. The class of prediction functions and objective functions we can make use of is restricted by the algorithms they lead to. If the prediction function or the objective function are too complex, then it can be difficult to find an appropriate learning algorithm. Much of the academic field of machine learning is the quest for new learning algorithms that allow us to bring different types of models and data together.</p>
<p>A useful reference for state of the art in machine learning is the UK Royal Society Report, <a href="https://royalsociety.org/~/media/policy/projects/machine-learning/publications/machine-learning-report.pdf">Machine Learning: Power and Promise of Computers that Learn by Example</a>.</p>
<p>You can also check my post blog post on <a href="http://inverseprobability.com/2017/07/17/what-is-machine-learning">What is Machine Learning?</a>.</p>
<h2 id="what-does-machine-learning-do">What does Machine Learning do?</h2>
<div style="text-align:right">
<span class="editsection-bracket" style="">[</span><span class="editsection" style=""><a href="https://github.com/lawrennd/snippets/edit/main/_ml/includes/what-does-machine-learning-do.md" target="_blank" onclick="ga('send', 'event', 'Edit Page', 'Edit', 'https://github.com/lawrennd/snippets/edit/main/_ml/includes/what-does-machine-learning-do.md', 13);">edit</a></span><span class="editsection-bracket" style="">]</span>
</div>
<p>Any process of automation allows us to scale what we do by codifying a process in some way that makes it efficient and repeatable. Machine learning automates by emulating human (or other actions) found in data. Machine learning codifies in the form of a mathematical function that is learnt by a computer. If we can create these mathematical functions in ways in which they can interconnect, then we can also build systems.</p>
<p>Machine learning works through codifing a prediction of interest into a mathematical function. For example, we can try and predict the probability that a customer wants to by a jersey given knowledge of their age, and the latitude where they live. The technique known as logistic regression estimates the odds that someone will by a jumper as a linear weighted sum of the features of interest.</p>
<p><span class="math display">\[ \text{odds} = \frac{p(\text{bought})}{p(\text{not bought})} \]</span></p>
<p><span class="math display">\[ \log \text{odds} = \beta_0 + \beta_1 \text{age} + \beta_2 \text{latitude}.\]</span> Here <span class="math inline">\(\beta_0\)</span>, <span class="math inline">\(\beta_1\)</span> and <span class="math inline">\(\beta_2\)</span> are the parameters of the model. If <span class="math inline">\(\beta_1\)</span> and <span class="math inline">\(\beta_2\)</span> are both positive, then the log-odds that someone will buy a jumper increase with increasing latitude and age, so the further north you are and the older you are the more likely you are to buy a jumper. The parameter <span class="math inline">\(\beta_0\)</span> is an offset parameter, and gives the log-odds of buying a jumper at zero age and on the equator. It is likely to be negative<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a> indicating that the purchase is odds-against. This is actually a classical statistical model, and models like logistic regression are widely used to estimate probabilities from ad-click prediction to risk of disease.</p>
<p>This is called a generalized linear model, we can also think of it as estimating the <em>probability</em> of a purchase as a nonlinear function of the features (age, lattitude) and the parameters (the <span class="math inline">\(\beta\)</span> values). The function is known as the <em>sigmoid</em> or <a href="https://en.wikipedia.org/wiki/Logistic_regression">logistic function</a>, thus the name <em>logistic</em> regression.</p>
<p><span class="math display">\[ p(\text{bought}) = \sigma\left(\beta_0 + \beta_1 \text{age} + \beta_2 \text{latitude}\right).\]</span> In the case where we have <em>features</em> to help us predict, we sometimes denote such features as a vector, <span class="math inline">\(\mathbf{ x}\)</span>, and we then use an inner product between the features and the parameters, <span class="math inline">\(\boldsymbol{\beta}^\top \mathbf{ x}= \beta_1 x_1 + \beta_2 x_2 + \beta_3 x_3 ...\)</span>, to represent the argument of the sigmoid.</p>
<p><span class="math display">\[ p(\text{bought}) = \sigma\left(\boldsymbol{\beta}^\top \mathbf{ x}\right).\]</span> More generally, we aim to predict some aspect of our data, <span class="math inline">\(y\)</span>, by relating it through a mathematical function, <span class="math inline">\(f(\cdot)\)</span>, to the parameters, <span class="math inline">\(\boldsymbol{\beta}\)</span> and the data, <span class="math inline">\(\mathbf{ x}\)</span>.</p>
<p><span class="math display">\[ y= f\left(\mathbf{ x}, \boldsymbol{\beta}\right).\]</span> We call <span class="math inline">\(f(\cdot)\)</span> the <em>prediction function</em>.</p>
<p>To obtain the fit to data, we use a separate function called the <em>objective function</em> that gives us a mathematical representation of the difference between our predictions and the real data.</p>
<p><span class="math display">\[E(\boldsymbol{\beta}, \mathbf{Y}, \mathbf{X})\]</span> A commonly used examples (for example in a regression problem) is least squares, <span class="math display">\[E(\boldsymbol{\beta}, \mathbf{Y}, \mathbf{X}) = \sum_{i=1}^n\left(y_i - f(\mathbf{ x}_i, \boldsymbol{\beta})\right)^2.\]</span></p>
<p>If a linear prediction function is combined with the least squares objective function then that gives us a classical <em>linear regression</em>, another classical statistical model. Statistics often focusses on linear models because it makes interpretation of the model easier. Interpretation is key in statistics because the aim is normally to validate questions by analysis of data. Machine learning has typically focussed more on the prediction function itself and worried less about the interpretation of parameters, which are normally denoted by <span class="math inline">\(\mathbf{w}\)</span> instead of <span class="math inline">\(\boldsymbol{\beta}\)</span>. As a result <em>non-linear</em> functions are explored more often as they tend to improve quality of predictions but at the expense of interpretability.</p>
<h1 id="deep-learning">Deep Learning</h1>
<div style="text-align:right">
<span class="editsection-bracket" style="">[</span><span class="editsection" style=""><a href="https://github.com/lawrennd/snippets/edit/main/_ml/includes/deep-learning-overview.md" target="_blank" onclick="ga('send', 'event', 'Edit Page', 'Edit', 'https://github.com/lawrennd/snippets/edit/main/_ml/includes/deep-learning-overview.md', 13);">edit</a></span><span class="editsection-bracket" style="">]</span>
</div>
<p>Classical statistical models and simple machine learning models have a great deal in common. The main difference between the fields is philosophical. Machine learning practitioners are typically more concerned with the quality of prediciton (e.g. measured by ROC curve) while statisticians tend to focus more on the interpretability of the model and the validity of any decisions drawn from that interpretation. For example, a statistical model may be used to validate whether a large scale intervention (such as the mass provision of mosquito nets) has had a long term effect on disease (such as malaria). In this case one of the covariates is likely to be the provision level of nets in a particular region. The response variable would be the rate of malaria disease in the region. The parmaeter, <span class="math inline">\(\beta_1\)</span> associated with that covariate will demonstrate a positive or negative effect which would be validated in answering the question. The focus in statistics would be less on the accuracy of the response variable and more on the validity of the interpretation of the effect variable, <span class="math inline">\(\beta_1\)</span>.</p>
<p>A machine learning practitioner on the other hand would typically denote the parameter <span class="math inline">\(w_1\)</span>, instead of <span class="math inline">\(\beta_1\)</span> and would only be interested in the output of the prediction function, <span class="math inline">\(f(\cdot)\)</span> rather than the parameter itself. The general formalism of the prediction function allows for <em>non-linear</em> models. In machine learning, the emphasis on prediction over interpretability means that non-linear models are often used. The parameters, <span class="math inline">\(\mathbf{w}\)</span>, are a means to an end (good prediction) rather than an end in themselves (interpretable).</p>
<!-- No slide titles in this context -->
<h2 id="deepface">DeepFace</h2>
<div style="text-align:right">
<span class="editsection-bracket" style="">[</span><span class="editsection" style=""><a href="https://github.com/lawrennd/snippets/edit/main/_ml/includes/deep-face.md" target="_blank" onclick="ga('send', 'event', 'Edit Page', 'Edit', 'https://github.com/lawrennd/snippets/edit/main/_ml/includes/deep-face.md', 13);">edit</a></span><span class="editsection-bracket" style="">]</span>
</div>
<div class="figure">
<div id="deep-face-figure" class="figure-frame">
<div class="centered" style="">
<img class="" src="https://inverseprobability.com/slides/diagrams//deepface_neg.png" width="100%" height="auto" align="center" style="background:none; border:none; box-shadow:none; display:block; margin-left:auto; margin-right:auto;vertical-align:middle">
</div>
</div>
<div id="deep-face-magnify" class="magnify" onclick="magnifyFigure('deep-face')">
<img class="img-button" src="{{ '/assets/images/Magnify_Large.svg' | relative_url }}" style="width:1.5ex">
</div>
<div id="deep-face-caption" class="caption-frame">
<p>Figure: The DeepFace architecture <span class="citation" data-cites="Taigman:deepface14">(Taigman et al., 2014)</span>, visualized through colors to represent the functional mappings at each layer. There are 120 million parameters in the model.</p>
</div>
</div>
<p>The DeepFace architecture <span class="citation" data-cites="Taigman:deepface14">(Taigman et al., 2014)</span> consists of layers that deal with <em>translation</em> invariances, known as convolutional layers. These layers are followed by three locally-connected layers and two fully-connected layers. Color illustrates feature maps produced at each layer. The neural network includes more than 120 million parameters, where more than 95% come from the local and fully connected layers.</p>
<h3 id="deep-learning-as-pinball">Deep Learning as Pinball</h3>
<div style="text-align:right">
<span class="editsection-bracket" style="">[</span><span class="editsection" style=""><a href="https://github.com/lawrennd/snippets/edit/main/_ml/includes/deep-learning-as-pinball.md" target="_blank" onclick="ga('send', 'event', 'Edit Page', 'Edit', 'https://github.com/lawrennd/snippets/edit/main/_ml/includes/deep-learning-as-pinball.md', 13);">edit</a></span><span class="editsection-bracket" style="">]</span>
</div>
<div class="figure">
<div id="early-pinball-figure" class="figure-frame">
<div class="centered centered" style="">
<img class="" src="https://inverseprobability.com/slides/diagrams//576px-Early_Pinball.jpg" width="50%" height="auto" align="center" style="background:none; border:none; box-shadow:none; display:block; margin-left:auto; margin-right:auto;vertical-align:middle">
</div>
</div>
<div id="early-pinball-magnify" class="magnify" onclick="magnifyFigure('early-pinball')">
<img class="img-button" src="{{ '/assets/images/Magnify_Large.svg' | relative_url }}" style="width:1.5ex">
</div>
<div id="early-pinball-caption" class="caption-frame">
<p>Figure: Deep learning models are composition of simple functions. We can think of a pinball machine as an analogy. Each layer of pins corresponds to one of the layers of functions in the model. Input data is represented by the location of the ball from left to right when it is dropped in from the top. Output class comes from the position of the ball as it leaves the pins at the bottom.</p>
</div>
</div>
<p>Sometimes deep learning models are described as being like the brain, or too complex to understand, but one analogy I find useful to help the gist of these models is to think of them as being similar to early pin ball machines.</p>
<p>In a deep neural network, we input a number (or numbers), whereas in pinball, we input a ball.</p>
<p>Think of the location of the ball on the left-right axis as a single number. Our simple pinball machine can only take one number at a time. As the ball falls through the machine, each layer of pins can be thought of as a different layer of ‘neurons.’ Each layer acts to move the ball from left to right.</p>
<p>In a pinball machine, when the ball gets to the bottom it might fall into a hole defining a score, in a neural network, that is equivalent to the decision: a classification of the input object.</p>
<p>An image has more than one number associated with it, so it is like playing pinball in a <em>hyper-space</em>.</p>
<div class="figure">
<div id="pinball-initialization-figure" class="figure-frame">
<object class="svgplot " data="https://inverseprobability.com/slides/diagrams//pinball001.svg" width="80%" style=" ">
</object>
</div>
<div id="pinball-initialization-magnify" class="magnify" onclick="magnifyFigure('pinball-initialization')">
<img class="img-button" src="{{ '/assets/images/Magnify_Large.svg' | relative_url }}" style="width:1.5ex">
</div>
<div id="pinball-initialization-caption" class="caption-frame">
<p>Figure: At initialization, the pins, which represent the parameters of the function, aren’t in the right place to bring the balls to the correct decisions.</p>
</div>
</div>
<div class="figure">
<div id="pinball-trained-figure" class="figure-frame">
<object class="svgplot " data="https://inverseprobability.com/slides/diagrams//pinball002.svg" width="80%" style=" ">
</object>
</div>
<div id="pinball-trained-magnify" class="magnify" onclick="magnifyFigure('pinball-trained')">
<img class="img-button" src="{{ '/assets/images/Magnify_Large.svg' | relative_url }}" style="width:1.5ex">
</div>
<div id="pinball-trained-caption" class="caption-frame">
<p>Figure: After learning the pins are now in the right place to bring the balls to the correct decisions.</p>
</div>
</div>
<p>Learning involves moving all the pins to be in the correct position, so that the ball ends up in the right place when it’s fallen through the machine. But moving all these pins in hyperspace can be difficult.</p>
<p>In a hyper-space you have to put a lot of data through the machine for to explore the positions of all the pins. Even when you feed many millions of data points through the machine, there are likely to be regions in the hyper-space where no ball has passed. When future test data passes through the machine in a new route unusual things can happen.</p>
<p><em>Adversarial examples</em> exploit this high dimensional space. If you have access to the pinball machine, you can use gradient methods to find a position for the ball in the hyper space where the image looks like one thing, but will be classified as another.</p>
<p>Probabilistic methods explore more of the space by considering a range of possible paths for the ball through the machine. This helps to make them more data efficient and gives some robustness to adversarial examples.</p>
<h2 id="deep-neural-network">Deep Neural Network</h2>
<div style="text-align:right">
<span class="editsection-bracket" style="">[</span><span class="editsection" style=""><a href="https://github.com/lawrennd/snippets/edit/main/_deepnn/includes/deep-neural-network.md" target="_blank" onclick="ga('send', 'event', 'Edit Page', 'Edit', 'https://github.com/lawrennd/snippets/edit/main/_deepnn/includes/deep-neural-network.md', 13);">edit</a></span><span class="editsection-bracket" style="">]</span>
</div>
<div class="sourceCode" id="cb3"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="op">%</span>pip install daft</span></code></pre></div>
<div class="figure">
<div id="deep-neural-network-figure" class="figure-frame">
<object class="svgplot " data="https://inverseprobability.com/slides/diagrams//deepgp/deep-nn2.svg" width="70%" style=" ">
</object>
</div>
<div id="deep-neural-network-magnify" class="magnify" onclick="magnifyFigure('deep-neural-network')">
<img class="img-button" src="{{ '/assets/images/Magnify_Large.svg' | relative_url }}" style="width:1.5ex">
</div>
<div id="deep-neural-network-caption" class="caption-frame">
<p>Figure: A deep neural network. Input nodes are shown at the bottom. Each hidden layer is the result of applying an affine transformation to the previous layer and placing through an activation function.</p>
</div>
</div>
<p>Mathematically, each layer of a neural network is given through computing the activation function, <span class="math inline">\(\phi(\cdot)\)</span>, contingent on the previous layer, or the inputs. In this way the activation functions, are composed to generate more complex interactions than would be possible with any single layer. <span class="math display">\[
\begin{align*}
\mathbf{ h}_{1} &= \phi\left(\mathbf{W}_1 \mathbf{ x}\right)\\
\mathbf{ h}_{2} &= \phi\left(\mathbf{W}_2\mathbf{ h}_{1}\right)\\
\mathbf{ h}_{3} &= \phi\left(\mathbf{W}_3 \mathbf{ h}_{2}\right)\\
f&= \mathbf{ w}_4 ^\top\mathbf{ h}_{3}
\end{align*}
\]</span></p>
<h2 id="alphago">AlphaGo</h2>
<div style="text-align:right">
<span class="editsection-bracket" style="">[</span><span class="editsection" style=""><a href="https://github.com/lawrennd/snippets/edit/main/_ai/includes/sedolian-voids.md" target="_blank" onclick="ga('send', 'event', 'Edit Page', 'Edit', 'https://github.com/lawrennd/snippets/edit/main/_ai/includes/sedolian-voids.md', 13);">edit</a></span><span class="editsection-bracket" style="">]</span>
</div>
<p>In January 2016, the UK company DeepMind’s machine learning system AlphaGo won a challenge match in which it beat the world champion Go player, Lee Se-Deol.</p>
<div class="figure">
<div id="nature-go-figure" class="figure-frame">
<div class="centered centered" style="">
<img class="" src="https://inverseprobability.com/slides/diagrams//ai/nature-go.jpg" width="50%" height="auto" align="center" style="background:none; border:none; box-shadow:none; display:block; margin-left:auto; margin-right:auto;vertical-align:middle">
</div>
</div>
<div id="nature-go-magnify" class="magnify" onclick="magnifyFigure('nature-go')">
<img class="img-button" src="{{ '/assets/images/Magnify_Large.svg' | relative_url }}" style="width:1.5ex">
</div>
<div id="nature-go-caption" class="caption-frame">
<p>Figure: AlphaGo’s win made the front cover of the journal Nature.</p>
</div>
</div>
<p>Go is a board game that is known to be over 2,500 years old. It is considered challenging for computer systems becaue of its branching factor: the number of possible moves that can be made at a given board postion. The branching factor of Chess is around 35. The branching factor of Go is around 250. This makes Go less susceptible to exhaustive search techniques which were a foundation of DeepBlue, the chess machine that was able to win against Gary Kasparov in 1997. As a result, many commentators predicted that Go was out of the reach of contemporary AI systems, with some predicting that beating the world champion wouldn’t occur until 2025.</p>
<div class="figure">
<div id="alpha-go-documentary-figure" class="figure-frame">
<iframe width="600" height="450" src="https://www.youtube.com/embed/WXuK6gekU1Y?start=" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen>
</iframe>
</div>
<div id="alpha-go-documentary-magnify" class="magnify" onclick="magnifyFigure('alpha-go-documentary')">
<img class="img-button" src="{{ '/assets/images/Magnify_Large.svg' | relative_url }}" style="width:1.5ex">
</div>
<div id="alpha-go-documentary-caption" class="caption-frame">
<p>Figure: The AlphaGo documentary tells the story of the tournament between Lee Se-dol and AlphaGo.</p>
</div>
</div>
<p>While exhaustive search was beyond the reach of computer systems, they combined stochastic search of the game tree with neural networks. But when training those neural networks vast quantities of data and game play were used. I wrote more about this at the time in the Guardian article “Guardian article on <a href="https://www.theguardian.com/media-network/2016/jan/28/google-ai-go-grandmaster-real-winner-deepmind">Google AI versus the Go grandmaster</a>.”</p>
<p>However, despite the many millions of matches that AlphaGo had played, Lee Sedol managed to find a board position that was distinct from anything AlphaGo had seen before. Within the high dimensional pinball machine that made up AlphaGo’s decision making systems, Lee Sedol found a niche, an Achillean chink in AlphaGo’s armour. He found a path through the neural network where no data had every been before. He found a location in feature space “where there be dragons.” A space where the model had not seen data before and one where it became confused.</p>
<div class="figure">
<div id="lee-se-dol-move-78-figure" class="figure-frame">
<table>
<tr>
<td width="49%">
<div class="centered" style="">
<img class="" src="https://inverseprobability.com/slides/diagrams//ai/lee-se-dol-alpha-go-game-4-move-78.png" width="60%" height="auto" align="center" style="background:none; border:none; box-shadow:none; display:block; margin-left:auto; margin-right:auto;vertical-align:middle">
</div>
</td>
<td width="49%">
<div class="centered centered" style="">
<img class="" src="https://inverseprobability.com/slides/diagrams//ai/lee-se-dol.jpg" width="60%" height="auto" align="center" style="background:none; border:none; box-shadow:none; display:block; margin-left:auto; margin-right:auto;vertical-align:middle">
</div>
</td>
</tr>
</table>
</div>
<div id="lee-se-dol-move-78-magnify" class="magnify" onclick="magnifyFigure('lee-se-dol-move-78')">
<img class="img-button" src="{{ '/assets/images/Magnify_Large.svg' | relative_url }}" style="width:1.5ex">
</div>
<div id="lee-se-dol-move-78-caption" class="caption-frame">
<p>Figure: Move 78 of <a href="https://en.wikipedia.org/wiki/AlphaGo_versus_Lee_Sedol#Game_4">Game 4</a> was critical in allowing Lee Se-dol to win the match. Described by <a href="https://en.wikipedia.org/wiki/Gu_Li_(Go_player)">Gu Li</a> as a ‘divine move.’</p>
</div>
</div>
<p>This is a remarkable achievement, a human, with far less experience than the machine of the game, was able to outplay by placing the machine in an unfamiliar situation. In honour of this achievements, I like to call these voids in the machines understanding “Sedolian voids.”</p>
<h2 id="uber-atg">Uber ATG</h2>
<p>Unfortunately, such Sedolian voids are not constrained to game playing machines. On March 18th 2018, just two years after AlphaGo’s victory, the Uber ATG self-driving vehicle killed a pedestrian in Tuscson Arizona. The neural networks that were trained on pedestrian detection did not detect Elaine because she was pushing a bicycle, laden with her bags, across the highway.<a href="#fn2" class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a> This situation represented a Sedolian void for the neural network, and it failed to stop the car.</p>
<div class="figure">
<div id="uber-atg-elaine-figure" class="figure-frame">
<iframe width="600" height="450" src="https://www.youtube.com/embed/iWGhXof45zI?start=" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen>
</iframe>
</div>
<div id="uber-atg-elaine-magnify" class="magnify" onclick="magnifyFigure('uber-atg-elaine')">
<img class="img-button" src="{{ '/assets/images/Magnify_Large.svg' | relative_url }}" style="width:1.5ex">
</div>
<div id="uber-atg-elaine-caption" class="caption-frame">
<p>Figure: A vehicle operated by Uber ATG was involved in a fatal crash when it killed pedestrian Elaine Herzberg, 49.</p>
</div>
</div>
<p>Characterising the regions where this is happening for these models remains an outstanding challenge.</p>
<p>In practice, we normally also have uncertainty associated with these functions. Uncertainty in the prediction function arises from</p>
<ol type="1">
<li>scarcity of training data and</li>
<li>mismatch between the set of prediction functions we choose and all possible prediction functions.</li>
</ol>
<p>There are also challenges around specification of the objective function, but for we will save those for another day. For the moment, let us focus on the prediction function.</p>
<h2 id="bayesian-inference-by-rejection-sampling">Bayesian Inference by Rejection Sampling</h2>
<div style="text-align:right">
<span class="editsection-bracket" style="">[</span><span class="editsection" style=""><a href="https://github.com/lawrennd/snippets/edit/main/_gp/includes/gp-intro-very-short.md" target="_blank" onclick="ga('send', 'event', 'Edit Page', 'Edit', 'https://github.com/lawrennd/snippets/edit/main/_gp/includes/gp-intro-very-short.md', 13);">edit</a></span><span class="editsection-bracket" style="">]</span>
</div>
<p>One view of Bayesian inference is to assume we are given a mechanism for generating samples, where we assume that mechanism is representing an accurate view on the way we believe the world works.</p>
<p>This mechanism is known as our <em>prior</em> belief.</p>
<p>We combine our prior belief with our observations of the real world by discarding all those prior samples that are inconsistent with our observations. The <em>likelihood</em> defines mathematically what we mean by inconsistent with the observations. The higher the noise level in the likelihood, the looser the notion of consistent.</p>
<p>The samples that remain are samples from the <em>posterior</em>.</p>
<p>This approach to Bayesian inference is closely related to two sampling techniques known as <em>rejection sampling</em> and <em>importance sampling</em>. It is realized in practice in an approach known as <em>approximate Bayesian computation</em> (ABC) or likelihood-free inference.</p>
<p>In practice, the algorithm is often too slow to be practical, because most samples will be inconsistent with the observations and as a result the mechanism must be operated many times to obtain a few posterior samples.</p>
<p>However, in the Gaussian process case, when the likelihood also assumes Gaussian noise, we can operate this mechanism mathematically, and obtain the posterior density <em>analytically</em>. This is the benefit of Gaussian processes.</p>
<p>First, we will load in two python functions for computing the covariance function.</p>
<p>Next, we sample from a multivariate normal density (a multivariate Gaussian), using the covariance function as the covariance matrix.</p>
<div class="figure">
<div id="gp-rejection-samples-figure" class="figure-frame">
<div class="centered" style="">
<img class="" src="https://inverseprobability.com/slides/diagrams//gp/gp_rejection_sample003.png" width="100%" height="auto" align="center" style="background:none; border:none; box-shadow:none; display:block; margin-left:auto; margin-right:auto;vertical-align:middle">
</div>
<div class="centered" style="">
<img class="" src="https://inverseprobability.com/slides/diagrams//gp/gp_rejection_sample004.png" width="100%" height="auto" align="center" style="background:none; border:none; box-shadow:none; display:block; margin-left:auto; margin-right:auto;vertical-align:middle">
</div>
<div class="centered" style="">
<img class="" src="https://inverseprobability.com/slides/diagrams//gp/gp_rejection_sample005.png" width="100%" height="auto" align="center" style="background:none; border:none; box-shadow:none; display:block; margin-left:auto; margin-right:auto;vertical-align:middle">
</div>
</div>
<div id="gp-rejection-samples-magnify" class="magnify" onclick="magnifyFigure('gp-rejection-samples')">
<img class="img-button" src="{{ '/assets/images/Magnify_Large.svg' | relative_url }}" style="width:1.5ex">
</div>
<div id="gp-rejection-samples-caption" class="caption-frame">
<p>Figure: One view of Bayesian inference is we have a machine for generating samples (the <em>prior</em>), and we discard all samples inconsistent with our data, leaving the samples of interest (the <em>posterior</em>). This is a rejection sampling view of Bayesian inference. The Gaussian process allows us to do this analytically by multiplying the <em>prior</em> by the <em>likelihood</em>.</p>
</div>
</div>
<h2 id="structure-of-priors">Structure of Priors</h2>
<div style="text-align:right">
<span class="editsection-bracket" style="">[</span><span class="editsection" style=""><a href="https://github.com/lawrennd/snippets/edit/main/_gp/includes/mackay-bathwater.md" target="_blank" onclick="ga('send', 'event', 'Edit Page', 'Edit', 'https://github.com/lawrennd/snippets/edit/main/_gp/includes/mackay-bathwater.md', 13);">edit</a></span><span class="editsection-bracket" style="">]</span>
</div>
<p>Even in the early days of Gaussian processes in machine learning, it was understood that we were throwing something fundamental away. This is perhaps captured best by David MacKay in his 1997 NeurIPS tutorial on Gaussian processes, where he asked “Have we thrown out the baby with the bathwater?” The quote below is from his summarization paper.</p>
<blockquote>
<p>According to the hype of 1987, neural networks were meant to be intelligent models which discovered features and patterns in data. Gaussian processes in contrast are simply smoothing devices. How can Gaussian processes possibly replace neural networks? What is going on?</p>
<p><span class="citation" data-cites="MacKay:gpintroduction98">MacKay (n.d.)</span></p>
</blockquote>
<h2 id="overfitting">Overfitting</h2>
<div style="text-align:right">
<span class="editsection-bracket" style="">[</span><span class="editsection" style=""><a href="https://github.com/lawrennd/snippets/edit/main/_deepgp/includes/overfitting-low-rank.md" target="_blank" onclick="ga('send', 'event', 'Edit Page', 'Edit', 'https://github.com/lawrennd/snippets/edit/main/_deepgp/includes/overfitting-low-rank.md', 13);">edit</a></span><span class="editsection-bracket" style="">]</span>
</div>
<p>One potential problem is that as the number of nodes in two adjacent layers increases, the number of parameters in the affine transformation between layers, <span class="math inline">\(\mathbf{W}\)</span>, increases. If there are <span class="math inline">\(k_{i-1}\)</span> nodes in one layer, and <span class="math inline">\(k_i\)</span> nodes in the following, then that matrix contains <span class="math inline">\(k_i k_{i-1}\)</span> parameters, when we have layer widths in the 1000s that leads to millions of parameters.</p>
<p>One proposed solution is known as <em>dropout</em> where only a sub-set of the neural network is trained at each iteration. An alternative solution would be to reparameterize <span class="math inline">\(\mathbf{W}\)</span> with its <em>singular value decomposition</em>. <span class="math display">\[
\mathbf{W}= \mathbf{U}\boldsymbol{ \Lambda}\mathbf{V}^\top
\]</span> or <span class="math display">\[
\mathbf{W}= \mathbf{U}\mathbf{V}^\top
\]</span> where if <span class="math inline">\(\mathbf{W}\in \Re^{k_1\times k_2}\)</span> then <span class="math inline">\(\mathbf{U}\in \Re^{k_1\times q}\)</span> and <span class="math inline">\(\mathbf{V}\in \Re^{k_2\times q}\)</span>, i.e. we have a low rank matrix factorization for the weights.</p>
<div class="figure">
<div id="low-rank-mapping-figure" class="figure-frame">
<object class="svgplot " data="https://inverseprobability.com/slides/diagrams//wisuvt.svg" width="80%" style=" ">
</object>
</div>
<div id="low-rank-mapping-magnify" class="magnify" onclick="magnifyFigure('low-rank-mapping')">
<img class="img-button" src="{{ '/assets/images/Magnify_Large.svg' | relative_url }}" style="width:1.5ex">
</div>
<div id="low-rank-mapping-caption" class="caption-frame">
<p>Figure: Pictorial representation of the low rank form of the matrix <span class="math inline">\(\mathbf{W}\)</span>.</p>
</div>
</div>
<p>In practice there is evidence that deep models seek these low rank solutions where we expect better generalisation. See e.g. <span class="citation" data-cites="Arora-convergence19">Arora et al. (2019)</span>;<span class="citation" data-cites="Jacot-deeplinear21">Jacot et al. (2021)</span>.</p>
<h2 id="bottleneck-layers-in-deep-neural-networks">Bottleneck Layers in Deep Neural Networks</h2>
<div style="text-align:right">
<span class="editsection-bracket" style="">[</span><span class="editsection" style=""><a href="https://github.com/lawrennd/snippets/edit/main/_deepgp/includes/deep-gp.md" target="_blank" onclick="ga('send', 'event', 'Edit Page', 'Edit', 'https://github.com/lawrennd/snippets/edit/main/_deepgp/includes/deep-gp.md', 13);">edit</a></span><span class="editsection-bracket" style="">]</span>
</div>
<div class="figure">
<div id="deep-nn-bottleneck-figure" class="figure-frame">
<object class="svgplot " data="https://inverseprobability.com/slides/diagrams//deepgp/deep-nn-bottleneck2.svg" width="70%" style=" ">
</object>
</div>
<div id="deep-nn-bottleneck-magnify" class="magnify" onclick="magnifyFigure('deep-nn-bottleneck')">
<img class="img-button" src="{{ '/assets/images/Magnify_Large.svg' | relative_url }}" style="width:1.5ex">
</div>
<div id="deep-nn-bottleneck-caption" class="caption-frame">
<p>Figure: Inserting the bottleneck layers introduces a new set of variables.</p>
</div>
</div>
<p>Including the low rank decomposition of <span class="math inline">\(\mathbf{W}\)</span> in the neural network, we obtain a new mathematical form. Effectively, we are adding additional <em>latent</em> layers, <span class="math inline">\(\mathbf{ z}\)</span>, in between each of the existing hidden layers. In a neural network these are sometimes known as <em>bottleneck</em> layers. The network can now be written mathematically as <span class="math display">\[
\begin{align}
\mathbf{ z}_{1} &= \mathbf{V}^\top_1 \mathbf{ x}\\
\mathbf{ h}_{1} &= \phi\left(\mathbf{U}_1 \mathbf{ z}_{1}\right)\\
\mathbf{ z}_{2} &= \mathbf{V}^\top_2 \mathbf{ h}_{1}\\
\mathbf{ h}_{2} &= \phi\left(\mathbf{U}_2 \mathbf{ z}_{2}\right)\\
\mathbf{ z}_{3} &= \mathbf{V}^\top_3 \mathbf{ h}_{2}\\
\mathbf{ h}_{3} &= \phi\left(\mathbf{U}_3 \mathbf{ z}_{3}\right)\\
\mathbf{ y}&= \mathbf{ w}_4^\top\mathbf{ h}_{3}.
\end{align}
\]</span></p>
<p><span class="math display">\[
\begin{align}
\mathbf{ z}_{1} &= \mathbf{V}^\top_1 \mathbf{ x}\\
\mathbf{ z}_{2} &= \mathbf{V}^\top_2 \phi\left(\mathbf{U}_1 \mathbf{ z}_{1}\right)\\
\mathbf{ z}_{3} &= \mathbf{V}^\top_3 \phi\left(\mathbf{U}_2 \mathbf{ z}_{2}\right)\\
\mathbf{ y}&= \mathbf{ w}_4 ^\top \mathbf{ z}_{3}
\end{align}
\]</span></p>
<h2 id="cascade-of-gaussian-processes">Cascade of Gaussian Processes</h2>
<div style="text-align:right">
<span class="editsection-bracket" style="">[</span><span class="editsection" style=""><a href="https://github.com/lawrennd/snippets/edit/main/_deepgp/includes/cascade-of-gps.md" target="_blank" onclick="ga('send', 'event', 'Edit Page', 'Edit', 'https://github.com/lawrennd/snippets/edit/main/_deepgp/includes/cascade-of-gps.md', 13);">edit</a></span><span class="editsection-bracket" style="">]</span>
</div>
<p>Now if we replace each of these neural networks with a Gaussian process. This is equivalent to taking the limit as the width of each layer goes to infinity, while appropriately scaling down the outputs.</p>
<p><span class="math display">\[
\begin{align}
\mathbf{ z}_{1} &= \mathbf{ f}_1\left(\mathbf{ x}\right)\\
\mathbf{ z}_{2} &= \mathbf{ f}_2\left(\mathbf{ z}_{1}\right)\\
\mathbf{ z}_{3} &= \mathbf{ f}_3\left(\mathbf{ z}_{2}\right)\\
\mathbf{ y}&= \mathbf{ f}_4\left(\mathbf{ z}_{3}\right)
\end{align}
\]</span></p>
<h2 id="stochastic-process-composition">Stochastic Process Composition</h2>
<div style="text-align:right">
<span class="editsection-bracket" style="">[</span><span class="editsection" style=""><a href="https://github.com/lawrennd/snippets/edit/main/_deepgp/includes/stochastic-process-composition.md" target="_blank" onclick="ga('send', 'event', 'Edit Page', 'Edit', 'https://github.com/lawrennd/snippets/edit/main/_deepgp/includes/stochastic-process-composition.md', 13);">edit</a></span><span class="editsection-bracket" style="">]</span>
</div>
<p><span class="math display">\[\mathbf{ y}= \mathbf{ f}_4\left(\mathbf{ f}_3\left(\mathbf{ f}_2\left(\mathbf{ f}_1\left(\mathbf{ x}\right)\right)\right)\right)\]</span></p>
<p>Mathematically, a deep Gaussian process can be seen as a composite <em>multivariate</em> function, <span class="math display">\[
\mathbf{g}(\mathbf{ x})=\mathbf{ f}_5(\mathbf{ f}_4(\mathbf{ f}_3(\mathbf{ f}_2(\mathbf{ f}_1(\mathbf{ x}))))).
\]</span> Or if we view it from the probabilistic perspective we can see that a deep Gaussian process is specifying a factorization of the joint density, the standard deep model takes the form of a Markov chain.</p>
<p><span class="math display">\[
p(\mathbf{ y}|\mathbf{ x})= p(\mathbf{ y}|\mathbf{ f}_5)p(\mathbf{ f}_5|\mathbf{ f}_4)p(\mathbf{ f}_4|\mathbf{ f}_3)p(\mathbf{ f}_3|\mathbf{ f}_2)p(\mathbf{ f}_2|\mathbf{ f}_1)p(\mathbf{ f}_1|\mathbf{ x})
\]</span></p>
<div class="figure">
<div id="deep-markov-figure" class="figure-frame">
<object class="svgplot " data="https://inverseprobability.com/slides/diagrams//deepgp/deep-markov.svg" width="80%" style=" ">
</object>
</div>
<div id="deep-markov-magnify" class="magnify" onclick="magnifyFigure('deep-markov')">
<img class="img-button" src="{{ '/assets/images/Magnify_Large.svg' | relative_url }}" style="width:1.5ex">
</div>
<div id="deep-markov-caption" class="caption-frame">
<p>Figure: Probabilistically the deep Gaussian process can be represented as a Markov chain. Indeed they can even be analyzed in this way <span class="citation" data-cites="Dunlop:deep2017">(Dunlop et al., n.d.)</span>.</p>
</div>
</div>
<div class="figure">
<div id="deep-markov-vertical-figure" class="figure-frame">
<object class="svgplot " data="https://inverseprobability.com/slides/diagrams//deepgp/deep-markov-vertical.svg" width="7%" style=" ">
</object>
</div>
<div id="deep-markov-vertical-magnify" class="magnify" onclick="magnifyFigure('deep-markov-vertical')">
<img class="img-button" src="{{ '/assets/images/Magnify_Large.svg' | relative_url }}" style="width:1.5ex">
</div>
<div id="deep-markov-vertical-caption" class="caption-frame">
<p>Figure: More usually deep probabilistic models are written vertically rather than horizontally as in the Markov chain.</p>
</div>
</div>
<h2 id="why-composition">Why Composition?</h2>
<div style="text-align:right">
<span class="editsection-bracket" style="">[</span><span class="editsection" style=""><a href="https://github.com/lawrennd/snippets/edit/main/_deepgp/includes/process-composition.md" target="_blank" onclick="ga('send', 'event', 'Edit Page', 'Edit', 'https://github.com/lawrennd/snippets/edit/main/_deepgp/includes/process-composition.md', 13);">edit</a></span><span class="editsection-bracket" style="">]</span>
</div>
<p>If the result of composing many functions together is simply another function, then why do we bother? The key point is that we can change the class of functions we are modeling by composing in this manner. A Gaussian process is specifying a prior over functions, and one with a number of elegant properties. For example, the derivative process (if it exists) of a Gaussian process is also Gaussian distributed. That makes it easy to assimilate, for example, derivative observations. But that also might raise some alarm bells. That implies that the <em>marginal derivative distribution</em> is also Gaussian distributed. If that’s the case, then it means that functions which occasionally exhibit very large derivatives are hard to model with a Gaussian process. For example, a function with jumps in.</p>
<p>A one off discontinuity is easy to model with a Gaussian process, or even multiple discontinuities. They can be introduced in the mean function, or independence can be forced between two covariance functions that apply in different areas of the input space. But in these cases we will need to specify the number of discontinuities and where they occur. In otherwords we need to <em>parameterise</em> the discontinuities. If we do not know the number of discontinuities and don’t wish to specify where they occur, i.e. if we want a non-parametric representation of discontinuities, then the standard Gaussian process doesn’t help.</p>
<h2 id="stochastic-process-composition-1">Stochastic Process Composition</h2>
<p>The deep Gaussian process leads to <em>non-Gaussian</em> models, and non-Gaussian characteristics in the covariance function. In effect, what we are proposing is that we change the properties of the functions we are considering by <em>composing stochastic processes</em>. This is an approach to creating new stochastic processes from well known processes.</p>
<p>Additionally, we are not constrained to the formalism of the chain. For example, we can easily add single nodes emerging from some point in the depth of the chain. This allows us to combine the benefits of the graphical modelling formalism, but with a powerful framework for relating one set of variables to another, that of Gaussian processes</p>
<div class="figure">
<div id="deep-markov-vertical-side-figure" class="figure-frame">
<object class="svgplot " data="https://inverseprobability.com/slides/diagrams//deepgp/deep-markov-vertical-side.svg" width="15%" style=" ">
</object>
</div>
<div id="deep-markov-vertical-side-magnify" class="magnify" onclick="magnifyFigure('deep-markov-vertical-side')">
<img class="img-button" src="{{ '/assets/images/Magnify_Large.svg' | relative_url }}" style="width:1.5ex">
</div>
<div id="deep-markov-vertical-side-caption" class="caption-frame">
<p>Figure: More generally we aren’t constrained by the Markov chain. We can design structures that respect our belief about the underlying conditional dependencies. Here we are adding a side note from the chain.</p>
</div>
</div>
<h1 id="deep-gaussian-processes">Deep Gaussian Processes</h1>
<div class="centered" style="">
<svg viewBox="0 0 200 200" style="width:15%">
<defs> <clipPath id="clip0">
<style>
circle {
fill: black;
}
</style>
<circle cx="100" cy="100" r="100"/> </clipPath> </defs>
<title>
Andreas Damianou
</title>
<image preserveAspectRatio="xMinYMin slice" width="100%" xlink:href="https://inverseprobability.com/slides/diagrams//people/andreas-damianou.png" clip-path="url(#clip0)"/>
</svg>
</div>
<p><span class="citation" data-cites="Damianou:thesis2015">Damianou (2015)</span></p>
<h2 id="universe-isnt-as-gaussian-as-it-was">Universe isn’t as Gaussian as it Was</h2>
<div style="text-align:right">
<span class="editsection-bracket" style="">[</span><span class="editsection" style=""><a href="https://github.com/lawrennd/snippets/edit/main/_gp/includes/planck-cmp-master-gp.md" target="_blank" onclick="ga('send', 'event', 'Edit Page', 'Edit', 'https://github.com/lawrennd/snippets/edit/main/_gp/includes/planck-cmp-master-gp.md', 13);">edit</a></span><span class="editsection-bracket" style="">]</span>
</div>
<p>The <a href="https://en.wikipedia.org/wiki/Planck_(spacecraft)">Planck space craft</a> was a European Space Agency space telescope that mapped the cosmic microwave background (CMB) from 2009 to 2013. The <a href="https://en.wikipedia.org/wiki/Cosmic_microwave_background">Cosmic Microwave Background</a> is the first observable echo we have of the big bang. It dates to approximately 400,000 years after the big bang, at the time the Universe was approximately <span class="math inline">\(10^8\)</span> times smaller and the temperature of the Universe was high, around <span class="math inline">\(3 \times 10^8\)</span> degrees Kelvin. The Universe was in the form of a hydrogen plasma. The echo we observe is the moment when the Universe was cool enough for Protons and electrons to combine to form hydrogen atoms. At this moment, the Universe became transparent for the first time, and photons could travel through space.</p>
<div class="figure">
<div id="planck-spacecraft-figure" class="figure-frame">
<div class="centered centered" style="">
<img class="" src="https://inverseprobability.com/slides/diagrams//physics/Front_view_of_the_European_Space_Agency_Planck_satellite.jpg" width="60%" height="auto" align="center" style="background:none; border:none; box-shadow:none; display:block; margin-left:auto; margin-right:auto;vertical-align:middle">
</div>
</div>
<div id="planck-spacecraft-magnify" class="magnify" onclick="magnifyFigure('planck-spacecraft')">
<img class="img-button" src="{{ '/assets/images/Magnify_Large.svg' | relative_url }}" style="width:1.5ex">
</div>
<div id="planck-spacecraft-caption" class="caption-frame">
<p>Figure: Artist’s impression of the Planck spacecraft which measured the Cosmic Microwave Background between 2009 and 2013.</p>
</div>
</div>
<p>The objective of the Planck spacecraft was to measure the anisotropy and statistics of the Cosmic Microwave Background. This was important, because if the standard model of the Universe is correct the variations around the very high temperature of the Universe of the CMB should be distributed according to a Gaussian process.<a href="#fn3" class="footnote-ref" id="fnref3" role="doc-noteref"><sup>3</sup></a> Currently our best estimates show this to be the case <span class="citation" data-cites="Jaffe:cmb98 Pontzen-cmb10 Elsner-unbiased15 Elsner-unbiased16">(Elsner et al., 2016, 2015; Jaffe et al., 1998; Pontzen and Peiris, 2010)</span>.</p>
<p>To the high degree of precision that we could measure with the Planck space telescope, the CMB appears to be a Gaussian process. The parameters of its covariance function are given by the fundamental parameters of the universe, for example the amount of dark matter and matter in the universe</p>
<div class="figure">
<div id="cosmic-microwave-background-figure" class="figure-frame">
<div class="centered" style="">
<img class="vertical-align:middle" src="https://inverseprobability.com/slides/diagrams//Planck_CMB.png" width="50%" height="auto" align="center" style="background:none; border:none; box-shadow:none; display:block; margin-left:auto; margin-right:auto;vertical-align:middle">
</div>
</div>
<div id="cosmic-microwave-background-magnify" class="magnify" onclick="magnifyFigure('cosmic-microwave-background')">
<img class="img-button" src="{{ '/assets/images/Magnify_Large.svg' | relative_url }}" style="width:1.5ex">
</div>
<div id="cosmic-microwave-background-caption" class="caption-frame">
<p>Figure: The cosmic microwave background is, to a very high degree of precision, a Gaussian process. The parameters of its covariance function are given by fundamental parameters of the universe, such as the amount of dark matter and mass.</p>
</div>
</div>
<h2 id="simulating-a-cmb-map">Simulating a CMB Map</h2>
<p>The simulation was created by <a href="https://ixkael.github.io/">Boris Leistedt</a>, see the <a href="https://github.com/ixkael/Prob-tools/blob/master/notebooks/The%20CMB%20as%20a%20Gaussian%20Process.ipynb">original Jupyter notebook here</a>.</p>
<p>Here we use that code to simulate our own universe and sample from what it looks like.</p>
<p>First, we install some specialist software as well as <code>matplotlib</code>, <code>scipy</code>, <code>numpy</code> we require</p>
<ul>
<li><code>camb</code>: <a href="http://camb.readthedocs.io/en/latest/" class="uri">http://camb.readthedocs.io/en/latest/</a></li>
<li><code>healpy</code>: <a href="https://healpy.readthedocs.io/en/latest/" class="uri">https://healpy.readthedocs.io/en/latest/</a></li>
</ul>
<div class="sourceCode" id="cb4"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="op">%</span>pip install camb</span></code></pre></div>
<div class="sourceCode" id="cb5"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="op">%</span>pip install healpy</span></code></pre></div>
<div class="sourceCode" id="cb6"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="im">import</span> healpy <span class="im">as</span> hp</span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a><span class="im">import</span> camb</span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a><span class="im">from</span> camb <span class="im">import</span> model, initialpower</span></code></pre></div>
<p>Now we use the theoretical power spectrum to design the covariance function.</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a>nside <span class="op">=</span> <span class="dv">512</span> <span class="co"># Healpix parameter, giving 12*nside**2 equal-area pixels on the sphere.</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>lmax <span class="op">=</span> <span class="dv">3</span><span class="op">*</span>nside <span class="co"># band-limit. Should be 2*nside < lmax < 4*nside to get information content.</span></span></code></pre></div>
<p>Now we design our Universe. It is parameterized according to the <a href="https://en.wikipedia.org/wiki/Lambda-CDM_model"><span class="math inline">\(\Lambda\)</span>CDM model</a>. The variables are as follows. <code>H0</code> is the Hubble parameter (in Km/s/Mpc). The <code>ombh2</code> is Physical Baryon density parameter. The <code>omch2</code> is the physical dark matter density parameter. <code>mnu</code> is the sum of the neutrino masses (in electron Volts). <code>omk</code> is the <span class="math inline">\(\Omega_k\)</span> is the curvature parameter, which is here set to 0, giving the minimal six parameter Lambda-CDM model. <code>tau</code> is the reionization optical depth.</p>
<p>Then we set <code>ns</code>, the “scalar spectral index.” This was estimated by Planck to be 0.96. Then there’s <code>r</code>, the ratio of the tensor power spectrum to scalar power spectrum. This has been estimated by Planck to be under 0.11. Here we set it to zero. These parameters are associated <a href="https://en.wikipedia.org/wiki/Primordial_fluctuations">with inflation</a>.</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="co"># Mostly following http://camb.readthedocs.io/en/latest/CAMBdemo.html with parameters from https://en.wikipedia.org/wiki/Lambda-CDM_model</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a>pars <span class="op">=</span> camb.CAMBparams()</span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a>pars.set_cosmology(H0<span class="op">=</span><span class="fl">67.74</span>, ombh2<span class="op">=</span><span class="fl">0.0223</span>, omch2<span class="op">=</span><span class="fl">0.1188</span>, mnu<span class="op">=</span><span class="fl">0.06</span>, omk<span class="op">=</span><span class="dv">0</span>, tau<span class="op">=</span><span class="fl">0.066</span>)</span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a>pars.InitPower.set_params(ns<span class="op">=</span><span class="fl">0.96</span>, r<span class="op">=</span><span class="dv">0</span>)</span></code></pre></div>
<p>Having set the parameters, we now use the python software “Code for Anisotropies in the Microwave Background” to get the results.</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a>pars.set_for_lmax(lmax, lens_potential_accuracy<span class="op">=</span><span class="dv">0</span>)<span class="op">;</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>results <span class="op">=</span> camb.get_results(pars)</span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a>powers <span class="op">=</span> results.get_cmb_power_spectra(pars)</span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a>totCL <span class="op">=</span> powers[<span class="st">'total'</span>]</span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a>unlensedCL <span class="op">=</span> powers[<span class="st">'unlensed_scalar'</span>]</span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a>ells <span class="op">=</span> np.arange(totCL.shape[<span class="dv">0</span>])</span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true" tabindex="-1"></a>Dells <span class="op">=</span> totCL[:, <span class="dv">0</span>]</span>
<span id="cb9-9"><a href="#cb9-9" aria-hidden="true" tabindex="-1"></a>Cells <span class="op">=</span> Dells <span class="op">*</span> <span class="dv">2</span><span class="op">*</span>np.pi <span class="op">/</span> ells <span class="op">/</span> (ells <span class="op">+</span> <span class="dv">1</span>) <span class="co"># change of convention to get C_ell</span></span>
<span id="cb9-10"><a href="#cb9-10" aria-hidden="true" tabindex="-1"></a>Cells[<span class="dv">0</span>:<span class="dv">2</span>] <span class="op">=</span> <span class="dv">0</span></span></code></pre></div>
<div class="sourceCode" id="cb10"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a>cmbmap <span class="op">=</span> hp.synfast(Cells, nside, </span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a> lmax<span class="op">=</span>lmax, mmax<span class="op">=</span><span class="va">None</span>, alm<span class="op">=</span><span class="va">False</span>, pol<span class="op">=</span><span class="va">False</span>, </span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a> pixwin<span class="op">=</span><span class="va">False</span>, fwhm<span class="op">=</span><span class="fl">0.0</span>, sigma<span class="op">=</span><span class="va">None</span>, new<span class="op">=</span><span class="va">False</span>, verbose<span class="op">=</span><span class="va">True</span>)</span></code></pre></div>
<div class="figure">
<div id="mollweide-sample-cmb-figure" class="figure-frame">
<div class="centered" style="">
<img class="vertical-align:middle" src="https://inverseprobability.com/slides/diagrams//physics/mollweide-sample-cmb.png" width="50%" height="auto" align="center" style="background:none; border:none; box-shadow:none; display:block; margin-left:auto; margin-right:auto;vertical-align:middle">
</div>
</div>
<div id="mollweide-sample-cmb-magnify" class="magnify" onclick="magnifyFigure('mollweide-sample-cmb')">
<img class="img-button" src="{{ '/assets/images/Magnify_Large.svg' | relative_url }}" style="width:1.5ex">
</div>
<div id="mollweide-sample-cmb-caption" class="caption-frame">
<p>Figure: A simulation of the Cosmic Microwave Background obtained through sampling from the relevant Gaussian process covariance (in polar co-ordinates).</p>
</div>
</div>
<p>The world we see today, of course, is not a Gaussian process. There are many discontinuities, for example, in the density of matter, and therefore in the temperature of the Universe.</p>
<div class="figure">
<div id="modern-universe-non-linear-function-figure" class="figure-frame">
<div style="fontsize:120px;vertical-align:middle">
<img src="https://inverseprobability.com/slides/diagrams//earth_PNG37.png" width="20%" style="display:inline-block;background:none;vertical-align:middle;border:none;box-shadow:none;"><span class="math inline">\(=f\Bigg(\)</span><img src="https://inverseprobability.com/slides/diagrams//Planck_CMB.png" width="50%" style="display:inline-block;background:none;vertical-align:middle;border:none;box-shadow:none;"><span class="math inline">\(\Bigg)\)</span>
</div>
</div>
<div id="modern-universe-non-linear-function-magnify" class="magnify" onclick="magnifyFigure('modern-universe-non-linear-function')">
<img class="img-button" src="{{ '/assets/images/Magnify_Large.svg' | relative_url }}" style="width:1.5ex">
</div>
<div id="modern-universe-non-linear-function-caption" class="caption-frame">
<p>Figure: What we observe today is some non-linear function of the cosmic microwave background.</p>
</div>
</div>
<p>We can think of today’s observed Universe, though, as a being a consequence of those temperature fluctuations in the CMB. Those fluctuations are only order <span class="math inline">\(10^{-6}\)</span> of the scale of the overall temperature of the Universe. But minor fluctuations in that density are what triggered the pattern of formation of the Galaxies. They determined how stars formed and created the elements that are the building blocks of our Earth <span class="citation" data-cites="Vogelsberger-cosmological20">(Vogelsberger et al., 2020)</span>.</p>
<h2 id="modern-review">Modern Review</h2>
<ul>
<li><p><em>A Unifying Framework for Gaussian Process Pseudo-Point Approximations using Power Expectation Propagation</em> <span class="citation" data-cites="Thang:unifying17">Bui et al. (2017)</span></p></li>
<li><p><em>Deep Gaussian Processes and Variational Propagation of Uncertainty</em> <span class="citation" data-cites="Damianou:thesis2015">Damianou (2015)</span></p></li>
</ul>
<div class="sourceCode" id="cb11"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="op">%</span>pip install gpy</span></code></pre></div>
<h2 id="gpy-a-gaussian-process-framework-in-python">GPy: A Gaussian Process Framework in Python</h2>
<div style="text-align:right">
<span class="editsection-bracket" style="">[</span><span class="editsection" style=""><a href="https://github.com/lawrennd/snippets/edit/main/_software/includes/gpy-software.md" target="_blank" onclick="ga('send', 'event', 'Edit Page', 'Edit', 'https://github.com/lawrennd/snippets/edit/main/_software/includes/gpy-software.md', 13);">edit</a></span><span class="editsection-bracket" style="">]</span>
</div>
<p>Gaussian processes are a flexible tool for non-parametric analysis with uncertainty. The GPy software was started in Sheffield to provide a easy to use interface to GPs. One which allowed the user to focus on the modelling rather than the mathematics.</p>
<div class="figure">
<div id="gpy-software-figure" class="figure-frame">
<div class="centered" style="">
<img class="" src="https://inverseprobability.com/slides/diagrams//gp/gpy.png" width="70%" height="auto" align="center" style="background:none; border:none; box-shadow:none; display:block; margin-left:auto; margin-right:auto;vertical-align:middle">
</div>
</div>
<div id="gpy-software-magnify" class="magnify" onclick="magnifyFigure('gpy-software')">
<img class="img-button" src="{{ '/assets/images/Magnify_Large.svg' | relative_url }}" style="width:1.5ex">
</div>
<div id="gpy-software-caption" class="caption-frame">
<p>Figure: GPy is a BSD licensed software code base for implementing Gaussian process models in Python. It is designed for teaching and modelling. We welcome contributions which can be made through the GitHub repository <a href="https://github.com/SheffieldML/GPy" class="uri">https://github.com/SheffieldML/GPy</a></p>
</div>
</div>
<p>GPy is a BSD licensed software code base for implementing Gaussian process models in python. This allows GPs to be combined with a wide variety of software libraries.</p>
<p>The software itself is available on <a href="https://github.com/SheffieldML/GPy">GitHub</a> and the team welcomes contributions.</p>
<p>The aim for GPy is to be a probabilistic-style programming language, i.e., you specify the model rather than the algorithm. As well as a large range of covariance functions the software allows for non-Gaussian likelihoods, multivariate outputs, dimensionality reduction and approximations for larger data sets.</p>
<p>The documentation for GPy can be found <a href="https://gpy.readthedocs.io/en/latest/">here</a>.</p>
<p>This notebook depends on PyDeepGP. This library can be installed via pip.</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="op">%</span>pip install <span class="op">--</span>upgrade git<span class="op">+</span>https:<span class="op">//</span>github.com<span class="op">/</span>SheffieldML<span class="op">/</span>PyDeepGP.git</span></code></pre></div>
<div class="sourceCode" id="cb13"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="co"># Late bind setup methods to DeepGP object</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a><span class="im">from</span> mlai.deepgp_tutorial <span class="im">import</span> initialize</span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a><span class="im">from</span> mlai.deepgp_tutorial <span class="im">import</span> staged_optimize</span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a><span class="im">from</span> mlai.deepgp_tutorial <span class="im">import</span> posterior_sample</span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a><span class="im">from</span> mlai.deepgp_tutorial <span class="im">import</span> visualize</span>
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true" tabindex="-1"></a><span class="im">from</span> mlai.deepgp_tutorial <span class="im">import</span> visualize_pinball</span>
<span id="cb13-7"><a href="#cb13-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-8"><a href="#cb13-8" aria-hidden="true" tabindex="-1"></a><span class="im">import</span> deepgp</span>
<span id="cb13-9"><a href="#cb13-9" aria-hidden="true" tabindex="-1"></a>deepgp.DeepGP.initialize<span class="op">=</span>initialize</span>
<span id="cb13-10"><a href="#cb13-10" aria-hidden="true" tabindex="-1"></a>deepgp.DeepGP.staged_optimize<span class="op">=</span>staged_optimize</span>
<span id="cb13-11"><a href="#cb13-11" aria-hidden="true" tabindex="-1"></a>deepgp.DeepGP.posterior_sample<span class="op">=</span>posterior_sample</span>
<span id="cb13-12"><a href="#cb13-12" aria-hidden="true" tabindex="-1"></a>deepgp.DeepGP.visualize<span class="op">=</span>visualize</span>
<span id="cb13-13"><a href="#cb13-13" aria-hidden="true" tabindex="-1"></a>deepgp.DeepGP.visualize_pinball<span class="op">=</span>visualize_pinball</span></code></pre></div>
<h2 id="olympic-marathon-data">Olympic Marathon Data</h2>
<div style="text-align:right">
<span class="editsection-bracket" style="">[</span><span class="editsection" style=""><a href="https://github.com/lawrennd/snippets/edit/main/_datasets/includes/olympic-marathon-data.md" target="_blank" onclick="ga('send', 'event', 'Edit Page', 'Edit', 'https://github.com/lawrennd/snippets/edit/main/_datasets/includes/olympic-marathon-data.md', 13);">edit</a></span><span class="editsection-bracket" style="">]</span>
</div>
<table>
<tr>
<td width="70%">
<ul>
<li>Gold medal times for Olympic Marathon since 1896.</li>
<li>Marathons before 1924 didn’t have a standardized distance.</li>
<li>Present results using pace per km.</li>
<li>In 1904 Marathon was badly organized leading to very slow times.</li>
</ul>
</td>
<td width="30%">
<div class="centered centered" style="">
<img class="" src="https://inverseprobability.com/slides/diagrams//Stephen_Kiprotich.jpg" width="100%" height="auto" align="center" style="background:none; border:none; box-shadow:none; display:block; margin-left:auto; margin-right:auto;vertical-align:middle">
</div>
<small>Image from Wikimedia Commons <a href="http://bit.ly/16kMKHQ" class="uri">http://bit.ly/16kMKHQ</a></small>
</td>
</tr>
</table>
<p>The first thing we will do is load a standard data set for regression modelling. The data consists of the pace of Olympic Gold Medal Marathon winners for the Olympics from 1896 to present. Let’s load in the data and plot.</p>
<div class="sourceCode" id="cb14"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="op">%</span>pip install pods</span></code></pre></div>
<div class="sourceCode" id="cb15"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a><span class="im">import</span> numpy <span class="im">as</span> np</span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a><span class="im">import</span> pods</span></code></pre></div>
<div class="sourceCode" id="cb16"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a>data <span class="op">=</span> pods.datasets.olympic_marathon_men()</span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a>x <span class="op">=</span> data[<span class="st">'X'</span>]</span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a>y <span class="op">=</span> data[<span class="st">'Y'</span>]</span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true" tabindex="-1"></a>offset <span class="op">=</span> y.mean()</span>
<span id="cb16-6"><a href="#cb16-6" aria-hidden="true" tabindex="-1"></a>scale <span class="op">=</span> np.sqrt(y.var())</span>
<span id="cb16-7"><a href="#cb16-7" aria-hidden="true" tabindex="-1"></a>yhat <span class="op">=</span> (y <span class="op">-</span> offset)<span class="op">/</span>scale</span></code></pre></div>
<div class="figure">
<div id="olympic-marathon-figure" class="figure-frame">
<object class="svgplot " data="https://inverseprobability.com/slides/diagrams//datasets/olympic-marathon.svg" width="80%" style=" ">
</object>
</div>
<div id="olympic-marathon-magnify" class="magnify" onclick="magnifyFigure('olympic-marathon')">
<img class="img-button" src="{{ '/assets/images/Magnify_Large.svg' | relative_url }}" style="width:1.5ex">
</div>
<div id="olympic-marathon-caption" class="caption-frame">
<p>Figure: Olympic marathon pace times since 1896.</p>
</div>
</div>
<p>Things to notice about the data include the outlier in 1904, in that year the Olympics was in St Louis, USA. Organizational problems and challenges with dust kicked up by the cars following the race meant that participants got lost, and only very few participants completed. More recent years see more consistently quick marathons.</p>
<h2 id="alan-turing">Alan Turing</h2>
<div style="text-align:right">
<span class="editsection-bracket" style="">[</span><span class="editsection" style=""><a href="https://github.com/lawrennd/snippets/edit/main/_ml/includes/alan-turing-marathon.md" target="_blank" onclick="ga('send', 'event', 'Edit Page', 'Edit', 'https://github.com/lawrennd/snippets/edit/main/_ml/includes/alan-turing-marathon.md', 13);">edit</a></span><span class="editsection-bracket" style="">]</span>
</div>
<div class="figure">
<div id="turing-run-times-figure" class="figure-frame">
<table>
<tr>
<td width="50%">
<div class="centered" style="">
<img class="" src="https://inverseprobability.com/slides/diagrams//turing-times.gif" width="100%" height="auto" align="center" style="background:none; border:none; box-shadow:none; display:block; margin-left:auto; margin-right:auto;vertical-align:middle">
</div>
</td>
<td width="50%">
<div class="centered centered" style="">
<img class="" src="https://inverseprobability.com/slides/diagrams//turing-run.jpg" width="50%" height="auto" align="center" style="background:none; border:none; box-shadow:none; display:block; margin-left:auto; margin-right:auto;vertical-align:middle">
</div>
</td>
</tr>
</table>
</div>
<div id="turing-run-times-magnify" class="magnify" onclick="magnifyFigure('turing-run-times')">
<img class="img-button" src="{{ '/assets/images/Magnify_Large.svg' | relative_url }}" style="width:1.5ex">
</div>
<div id="turing-run-times-caption" class="caption-frame">
<p>Figure: Alan Turing, in 1946 he was only 11 minutes slower than the winner of the 1948 games. Would he have won a hypothetical games held in 1946? Source: <a href="http://www.turing.org.uk/scrapbook/run.html" target="_blank">Alan Turing Internet Scrapbook</a>.</p>
</div>
</div>
<p>If we had to summarise the objectives of machine learning in one word, a very good candidate for that word would be <em>generalization</em>. What is generalization? From a human perspective it might be summarised as the ability to take lessons learned in one domain and apply them to another domain. If we accept the definition given in the first session for machine learning, <span class="math display">\[
\text{data} + \text{model} \stackrel{\text{compute}}{\rightarrow} \text{prediction}
\]</span> then we see that without a model we can’t generalise: we only have data. Data is fine for answering very specific questions, like “Who won the Olympic Marathon in 2012?” because we have that answer stored, however, we are not given the answer to many other questions. For example, Alan Turing was a formidable marathon runner, in 1946 he ran a time 2 hours 46 minutes (just under four minutes per kilometer, faster than I and most of the other <a href="http://www.parkrun.org.uk/sheffieldhallam/">Endcliffe Park Run</a> runners can do 5 km). What is the probability he would have won an Olympics if one had been held in 1946?</p>
<p>To answer this question we need to generalize, but before we formalize the concept of generalization let’s introduce some formal representation of what it means to generalize in machine learning.</p>
<h2 id="gaussian-process-fit">Gaussian Process Fit</h2>
<div style="text-align:right">
<span class="editsection-bracket" style="">[</span><span class="editsection" style=""><a href="https://github.com/lawrennd/snippets/edit/main/_gp/includes/olympic-marathon-gp.md" target="_blank" onclick="ga('send', 'event', 'Edit Page', 'Edit', 'https://github.com/lawrennd/snippets/edit/main/_gp/includes/olympic-marathon-gp.md', 13);">edit</a></span><span class="editsection-bracket" style="">]</span>
</div>
<p>Our first objective will be to perform a Gaussian process fit to the data, we’ll do this using the <a href="https://github.com/SheffieldML/GPy">GPy software</a>.</p>
<div class="sourceCode" id="cb17"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a><span class="im">import</span> GPy</span></code></pre></div>
<div class="sourceCode" id="cb18"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a>m_full <span class="op">=</span> GPy.models.GPRegression(x,yhat)</span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a>_ <span class="op">=</span> m_full.optimize() <span class="co"># Optimize parameters of covariance function</span></span></code></pre></div>
<p>The first command sets up the model, then <code>m_full.optimize()</code> optimizes the parameters of the covariance function and the noise level of the model. Once the fit is complete, we’ll try creating some test points, and computing the output of the GP model in terms of the mean and standard deviation of the posterior functions between 1870 and 2030. We plot the mean function and the standard deviation at 200 locations. We can obtain the predictions using <code>y_mean, y_var = m_full.predict(xt)</code></p>
<div class="sourceCode" id="cb19"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a>xt <span class="op">=</span> np.linspace(<span class="dv">1870</span>,<span class="dv">2030</span>,<span class="dv">200</span>)[:,np.newaxis]</span>
<span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a>yt_mean, yt_var <span class="op">=</span> m_full.predict(xt)</span>
<span id="cb19-3"><a href="#cb19-3" aria-hidden="true" tabindex="-1"></a>yt_sd<span class="op">=</span>np.sqrt(yt_var)</span></code></pre></div>
<p>Now we plot the results using the helper function in <code>mlai.plot</code>.</p>
<div class="figure">
<div id="olympic-marathon-gp-figure" class="figure-frame">
<object class="svgplot " data="https://inverseprobability.com/slides/diagrams//gp/olympic-marathon-gp.svg" width="80%" style=" ">
</object>
</div>
<div id="olympic-marathon-gp-magnify" class="magnify" onclick="magnifyFigure('olympic-marathon-gp')">
<img class="img-button" src="{{ '/assets/images/Magnify_Large.svg' | relative_url }}" style="width:1.5ex">
</div>
<div id="olympic-marathon-gp-caption" class="caption-frame">
<p>Figure: Gaussian process fit to the Olympic Marathon data. The error bars are too large, perhaps due to the outlier from 1904.</p>
</div>
</div>
<h2 id="fit-quality">Fit Quality</h2>
<p>In the fit we see that the error bars (coming mainly from the noise variance) are quite large. This is likely due to the outlier point in 1904, ignoring that point we can see that a tighter fit is obtained. To see this make a version of the model, <code>m_clean</code>, where that point is removed.</p>
<div class="sourceCode" id="cb20"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb20-1"><a href="#cb20-1" aria-hidden="true" tabindex="-1"></a>x_clean<span class="op">=</span>np.vstack((x[<span class="dv">0</span>:<span class="dv">2</span>, :], x[<span class="dv">3</span>:, :]))</span>
<span id="cb20-2"><a href="#cb20-2" aria-hidden="true" tabindex="-1"></a>y_clean<span class="op">=</span>np.vstack((yhat[<span class="dv">0</span>:<span class="dv">2</span>, :], yhat[<span class="dv">3</span>:, :]))</span>
<span id="cb20-3"><a href="#cb20-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-4"><a href="#cb20-4" aria-hidden="true" tabindex="-1"></a>m_clean <span class="op">=</span> GPy.models.GPRegression(x_clean,y_clean)</span>
<span id="cb20-5"><a href="#cb20-5" aria-hidden="true" tabindex="-1"></a>_ <span class="op">=</span> m_clean.optimize()</span></code></pre></div>
<h2 id="deep-gp-fit">Deep GP Fit</h2>
<div style="text-align:right">
<span class="editsection-bracket" style="">[</span><span class="editsection" style=""><a href="https://github.com/lawrennd/snippets/edit/main/_deepgp/includes/olympic-marathon-deep-gp.md" target="_blank" onclick="ga('send', 'event', 'Edit Page', 'Edit', 'https://github.com/lawrennd/snippets/edit/main/_deepgp/includes/olympic-marathon-deep-gp.md', 13);">edit</a></span><span class="editsection-bracket" style="">]</span>
</div>
<p>Let’s see if a deep Gaussian process can help here. We will construct a deep Gaussian process with one hidden layer (i.e. one Gaussian process feeding into another).</p>
<p>Build a Deep GP with an additional hidden layer (one dimensional) to fit the model.</p>
<div class="sourceCode" id="cb21"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a><span class="im">import</span> GPy</span>
<span id="cb21-2"><a href="#cb21-2" aria-hidden="true" tabindex="-1"></a><span class="im">import</span> deepgp</span></code></pre></div>
<div class="sourceCode" id="cb22"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb22-1"><a href="#cb22-1" aria-hidden="true" tabindex="-1"></a>hidden <span class="op">=</span> <span class="dv">1</span></span>
<span id="cb22-2"><a href="#cb22-2" aria-hidden="true" tabindex="-1"></a>m <span class="op">=</span> deepgp.DeepGP([y.shape[<span class="dv">1</span>],hidden,x.shape[<span class="dv">1</span>]],Y<span class="op">=</span>yhat, X<span class="op">=</span>x, inits<span class="op">=</span>[<span class="st">'PCA'</span>,<span class="st">'PCA'</span>], </span>
<span id="cb22-3"><a href="#cb22-3" aria-hidden="true" tabindex="-1"></a> kernels<span class="op">=</span>[GPy.kern.RBF(hidden,ARD<span class="op">=</span><span class="va">True</span>),</span>
<span id="cb22-4"><a href="#cb22-4" aria-hidden="true" tabindex="-1"></a> GPy.kern.RBF(x.shape[<span class="dv">1</span>],ARD<span class="op">=</span><span class="va">True</span>)], <span class="co"># the kernels for each layer</span></span>
<span id="cb22-5"><a href="#cb22-5" aria-hidden="true" tabindex="-1"></a> num_inducing<span class="op">=</span><span class="dv">50</span>, back_constraint<span class="op">=</span><span class="va">False</span>)</span></code></pre></div>
<div class="sourceCode" id="cb23"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb23-1"><a href="#cb23-1" aria-hidden="true" tabindex="-1"></a><span class="co"># Call the initalization</span></span>
<span id="cb23-2"><a href="#cb23-2" aria-hidden="true" tabindex="-1"></a>m.initialize()</span></code></pre></div>
<p>Now optimize the model.</p>
<div class="sourceCode" id="cb24"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb24-1"><a href="#cb24-1" aria-hidden="true" tabindex="-1"></a><span class="cf">for</span> layer <span class="kw">in</span> m.layers:</span>
<span id="cb24-2"><a href="#cb24-2" aria-hidden="true" tabindex="-1"></a> layer.likelihood.variance.constrain_positive(warning<span class="op">=</span><span class="va">False</span>)</span>
<span id="cb24-3"><a href="#cb24-3" aria-hidden="true" tabindex="-1"></a>m.optimize(messages<span class="op">=</span><span class="va">True</span>,max_iters<span class="op">=</span><span class="dv">10000</span>)</span></code></pre></div>
<div class="sourceCode" id="cb25"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb25-1"><a href="#cb25-1" aria-hidden="true" tabindex="-1"></a>m.staged_optimize(messages<span class="op">=</span>(<span class="va">True</span>,<span class="va">True</span>,<span class="va">True</span>))</span></code></pre></div>
<h2 id="olympic-marathon-data-deep-gp">Olympic Marathon Data Deep GP</h2>
<div class="figure">
<div id="olympic-marathon-deep-gp-figure" class="figure-frame">
<object class="svgplot " data="https://inverseprobability.com/slides/diagrams//deepgp/olympic-marathon-deep-gp.svg" width="100%" style=" ">
</object>
</div>
<div id="olympic-marathon-deep-gp-magnify" class="magnify" onclick="magnifyFigure('olympic-marathon-deep-gp')">
<img class="img-button" src="{{ '/assets/images/Magnify_Large.svg' | relative_url }}" style="width:1.5ex">
</div>
<div id="olympic-marathon-deep-gp-caption" class="caption-frame">
<p>Figure: Deep GP fit to the Olympic marathon data. Error bars now change as the prediction evolves.</p>
</div>
</div>
<h2 id="olympic-marathon-data-deep-gp-1">Olympic Marathon Data Deep GP</h2>
<div class="figure">
<div id="olympic-marathon-deep-gp-samples-figure" class="figure-frame">
<object class="svgplot " data="https://inverseprobability.com/slides/diagrams//deepgp/olympic-marathon-deep-gp-samples.svg" width style=" ">
</object>
</div>
<div id="olympic-marathon-deep-gp-samples-magnify" class="magnify" onclick="magnifyFigure('olympic-marathon-deep-gp-samples')">
<img class="img-button" src="{{ '/assets/images/Magnify_Large.svg' | relative_url }}" style="width:1.5ex">
</div>
<div id="olympic-marathon-deep-gp-samples-caption" class="caption-frame">
<p>Figure: Point samples run through the deep Gaussian process show the distribution of output locations.</p>
</div>
</div>
<h2 id="fitted-gp-for-each-layer">Fitted GP for each layer</h2>
<p>Now we explore the GPs the model has used to fit each layer. First of all, we look at the hidden layer.</p>
<div class="figure">
<div id="olympic-marathon-deep-gp-layer-0-figure" class="figure-frame">
<object class="svgplot " data="https://inverseprobability.com/slides/diagrams//deepgp/olympic-marathon-deep-gp-layer-0.svg" width style=" ">
</object>
</div>
<div id="olympic-marathon-deep-gp-layer-0-magnify" class="magnify" onclick="magnifyFigure('olympic-marathon-deep-gp-layer-0')">
<img class="img-button" src="{{ '/assets/images/Magnify_Large.svg' | relative_url }}" style="width:1.5ex">
</div>
<div id="olympic-marathon-deep-gp-layer-0-caption" class="caption-frame">
<p>Figure: The mapping from input to the latent layer is broadly, with some flattening as time goes on. Variance is high across the input range.</p>
</div>
</div>
<div class="figure">
<div id="olympic-marathon-deep-gp-layer-1-figure" class="figure-frame">
<object class="svgplot " data="https://inverseprobability.com/slides/diagrams//deepgp/olympic-marathon-deep-gp-layer-1.svg" width style=" ">
</object>
</div>
<div id="olympic-marathon-deep-gp-layer-1-magnify" class="magnify" onclick="magnifyFigure('olympic-marathon-deep-gp-layer-1')">
<img class="img-button" src="{{ '/assets/images/Magnify_Large.svg' | relative_url }}" style="width:1.5ex">
</div>
<div id="olympic-marathon-deep-gp-layer-1-caption" class="caption-frame">
<p>Figure: The mapping from the latent layer to the output layer.</p>
</div>
</div>
<h2 id="olympic-marathon-pinball-plot">Olympic Marathon Pinball Plot</h2>
<div class="figure">
<div id="olympic-marathon-deep-gp-pinball-figure" class="figure-frame">
<object class="svgplot " data="https://inverseprobability.com/slides/diagrams//deepgp/olympic-marathon-deep-gp-pinball.svg" width="80%" style=" ">
</object>
</div>
<div id="olympic-marathon-deep-gp-pinball-magnify" class="magnify" onclick="magnifyFigure('olympic-marathon-deep-gp-pinball')">
<img class="img-button" src="{{ '/assets/images/Magnify_Large.svg' | relative_url }}" style="width:1.5ex">
</div>
<div id="olympic-marathon-deep-gp-pinball-caption" class="caption-frame">
<p>Figure: A pinball plot shows the movement of the ‘ball’ as it passes through each layer of the Gaussian processes. Mean directions of movement are shown by lines. Shading gives one standard deviation of movement position. At each layer, the uncertainty is reset. The overal uncertainty is the cumulative uncertainty from all the layers. There is some grouping of later points towards the right in the first layer, which also injects a large amount of uncertainty. Due to flattening of the curve in the second layer towards the right the uncertainty is reduced in final output.</p>
</div>
</div>
<p>The pinball plot shows the flow of any input ball through the deep Gaussian process. In a pinball plot a series of vertical parallel lines would indicate a purely linear function. For the olypmic marathon data we can see the first layer begins to shift from input towards the right. Note it also does so with some uncertainty (indicated by the shaded backgrounds). The second layer has less uncertainty, but bunches the inputs more strongly to the right. This input layer of uncertainty, followed by a layer that pushes inputs to the right is what gives the heteroschedastic noise.</p>
<h2 id="step-function">Step Function</h2>
<div style="text-align:right">
<span class="editsection-bracket" style="">[</span><span class="editsection" style=""><a href="https://github.com/lawrennd/snippets/edit/main/_ml/includes/step-function-data.md" target="_blank" onclick="ga('send', 'event', 'Edit Page', 'Edit', 'https://github.com/lawrennd/snippets/edit/main/_ml/includes/step-function-data.md', 13);">edit</a></span><span class="editsection-bracket" style="">]</span>
</div>
<p>Next we consider a simple step function data set.</p>
<div class="sourceCode" id="cb26"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb26-1"><a href="#cb26-1" aria-hidden="true" tabindex="-1"></a>num_low<span class="op">=</span><span class="dv">25</span></span>
<span id="cb26-2"><a href="#cb26-2" aria-hidden="true" tabindex="-1"></a>num_high<span class="op">=</span><span class="dv">25</span></span>
<span id="cb26-3"><a href="#cb26-3" aria-hidden="true" tabindex="-1"></a>gap <span class="op">=</span> <span class="op">-</span><span class="fl">.1</span></span>
<span id="cb26-4"><a href="#cb26-4" aria-hidden="true" tabindex="-1"></a>noise<span class="op">=</span><span class="fl">0.0001</span></span>
<span id="cb26-5"><a href="#cb26-5" aria-hidden="true" tabindex="-1"></a>x <span class="op">=</span> np.vstack((np.linspace(<span class="op">-</span><span class="dv">1</span>, <span class="op">-</span>gap<span class="op">/</span><span class="fl">2.0</span>, num_low)[:, np.newaxis],</span>
<span id="cb26-6"><a href="#cb26-6" aria-hidden="true" tabindex="-1"></a> np.linspace(gap<span class="op">/</span><span class="fl">2.0</span>, <span class="dv">1</span>, num_high)[:, np.newaxis]))</span>
<span id="cb26-7"><a href="#cb26-7" aria-hidden="true" tabindex="-1"></a>y <span class="op">=</span> np.vstack((np.zeros((num_low, <span class="dv">1</span>)), np.ones((num_high,<span class="dv">1</span>))))</span>
<span id="cb26-8"><a href="#cb26-8" aria-hidden="true" tabindex="-1"></a>scale <span class="op">=</span> np.sqrt(y.var())</span>
<span id="cb26-9"><a href="#cb26-9" aria-hidden="true" tabindex="-1"></a>offset <span class="op">=</span> y.mean()</span>
<span id="cb26-10"><a href="#cb26-10" aria-hidden="true" tabindex="-1"></a>yhat <span class="op">=</span> (y<span class="op">-</span>offset)<span class="op">/</span>scale</span></code></pre></div>
<h2 id="step-function-data">Step Function Data</h2>
<div class="figure">
<div id="step-function-data-figure" class="figure-frame">
<object class="svgplot " data="https://inverseprobability.com/slides/diagrams//datasets/step-function.svg" width="80%" style=" ">
</object>
</div>
<div id="step-function-data-magnify" class="magnify" onclick="magnifyFigure('step-function-data')">
<img class="img-button" src="{{ '/assets/images/Magnify_Large.svg' | relative_url }}" style="width:1.5ex">
</div>
<div id="step-function-data-caption" class="caption-frame">
<p>Figure: Simulation study of step function data artificially generated. Here there is a small overlap between the two lines.</p>
</div>
</div>
<h2 id="step-function-data-gp">Step Function Data GP</h2>
<p>We can fit a Gaussian process to the step function data using <code>GPy</code> as follows.</p>
<div class="sourceCode" id="cb27"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb27-1"><a href="#cb27-1" aria-hidden="true" tabindex="-1"></a>m_full <span class="op">=</span> GPy.models.GPRegression(x,yhat)</span>
<span id="cb27-2"><a href="#cb27-2" aria-hidden="true" tabindex="-1"></a>_ <span class="op">=</span> m_full.optimize() <span class="co"># Optimize parameters of covariance function</span></span></code></pre></div>
<p>Where <code>GPy.models.GPRegression()</code> gives us a standard GP regression model with exponentiated quadratic covariance function.</p>
<p>The model is optimized using <code>m_full.optimize()</code> which calls an L-BGFS gradient based solver in python.</p>
<div class="figure">
<div id="step-function-gp-figure" class="figure-frame">
<object class="svgplot " data="https://inverseprobability.com/slides/diagrams//gp/step-function-gp.svg" width="80%" style=" ">
</object>
</div>
<div id="step-function-gp-magnify" class="magnify" onclick="magnifyFigure('step-function-gp')">
<img class="img-button" src="{{ '/assets/images/Magnify_Large.svg' | relative_url }}" style="width:1.5ex">
</div>
<div id="step-function-gp-caption" class="caption-frame">
<p>Figure: Gaussian process fit to the step function data. Note the large error bars and the over-smoothing of the discontinuity. Error bars are shown at two standard deviations.</p>
</div>
</div>
<p>The resulting fit to the step function data shows some challenges. In particular, the over smoothing at the discontinuity. If we know how many discontinuities there are, we can parameterize them in the step function. But by doing this, we form a semi-parametric model. The parameters indicate how many discontinuities are, and where they are. They can be optimized as part of the model fit. But if new, unforeseen, discontinuities arise when the model is being deployed in practice, these won’t be accounted for in the predictions.</p>
<h2 id="step-function-data-deep-gp">Step Function Data Deep GP</h2>
<div style="text-align:right">
<span class="editsection-bracket" style="">[</span><span class="editsection" style=""><a href="https://github.com/lawrennd/snippets/edit/main/_deepgp/includes/step-function-deep-gp.md" target="_blank" onclick="ga('send', 'event', 'Edit Page', 'Edit', 'https://github.com/lawrennd/snippets/edit/main/_deepgp/includes/step-function-deep-gp.md', 13);">edit</a></span><span class="editsection-bracket" style="">]</span>
</div>
<p>First we initialize a deep Gaussian process with three latent layers (four layers total). Within each layer we create a GP with an exponentiated quadratic covariance (<code>GPy.kern.RBF</code>).</p>
<p>At each layer we use 20 inducing points for the variational approximation.</p>
<div class="sourceCode" id="cb28"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb28-1"><a href="#cb28-1" aria-hidden="true" tabindex="-1"></a>layers <span class="op">=</span> [y.shape[<span class="dv">1</span>], <span class="dv">1</span>, <span class="dv">1</span>, <span class="dv">1</span>,x.shape[<span class="dv">1</span>]]</span>
<span id="cb28-2"><a href="#cb28-2" aria-hidden="true" tabindex="-1"></a>inits <span class="op">=</span> [<span class="st">'PCA'</span>]<span class="op">*</span>(<span class="bu">len</span>(layers)<span class="op">-</span><span class="dv">1</span>)</span>
<span id="cb28-3"><a href="#cb28-3" aria-hidden="true" tabindex="-1"></a>kernels <span class="op">=</span> []</span>
<span id="cb28-4"><a href="#cb28-4" aria-hidden="true" tabindex="-1"></a><span class="cf">for</span> i <span class="kw">in</span> layers[<span class="dv">1</span>:]:</span>
<span id="cb28-5"><a href="#cb28-5" aria-hidden="true" tabindex="-1"></a> kernels <span class="op">+=</span> [GPy.kern.RBF(i)]</span>
<span id="cb28-6"><a href="#cb28-6" aria-hidden="true" tabindex="-1"></a> </span>
<span id="cb28-7"><a href="#cb28-7" aria-hidden="true" tabindex="-1"></a>m <span class="op">=</span> deepgp.DeepGP(layers,Y<span class="op">=</span>yhat, X<span class="op">=</span>x, </span>
<span id="cb28-8"><a href="#cb28-8" aria-hidden="true" tabindex="-1"></a> inits<span class="op">=</span>inits, </span>
<span id="cb28-9"><a href="#cb28-9" aria-hidden="true" tabindex="-1"></a> kernels<span class="op">=</span>kernels, <span class="co"># the kernels for each layer</span></span>
<span id="cb28-10"><a href="#cb28-10" aria-hidden="true" tabindex="-1"></a> num_inducing<span class="op">=</span><span class="dv">20</span>, back_constraint<span class="op">=</span><span class="va">False</span>)</span></code></pre></div>
<p>Once the model is constructed we initialize the parameters, and perform the staged optimization which starts by optimizing variational parameters with a low noise and proceeds to optimize the whole model.</p>
<div class="sourceCode" id="cb29"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb29-1"><a href="#cb29-1" aria-hidden="true" tabindex="-1"></a>m.initialize()</span>
<span id="cb29-2"><a href="#cb29-2" aria-hidden="true" tabindex="-1"></a>m.staged_optimize()</span></code></pre></div>
<p>We plot the output of the deep Gaussian process fitted to the step data as follows.</p>
<p>The deep Gaussian process does a much better job of fitting the data. It handles the discontinuity easily, and error bars drop to smaller values in the regions of data.</p>
<div class="figure">
<div id="step-function-deep-gp-figure" class="figure-frame">
<object class="svgplot " data="https://inverseprobability.com/slides/diagrams//deepgp/step-function-deep-gp.svg" width="80%" style=" ">
</object>
</div>
<div id="step-function-deep-gp-magnify" class="magnify" onclick="magnifyFigure('step-function-deep-gp')">
<img class="img-button" src="{{ '/assets/images/Magnify_Large.svg' | relative_url }}" style="width:1.5ex">
</div>
<div id="step-function-deep-gp-caption" class="caption-frame">
<p>Figure: Deep Gaussian process fit to the step function data.</p>
</div>
</div>
<h2 id="step-function-data-deep-gp-1">Step Function Data Deep GP</h2>
<p>The samples of the model can be plotted with the helper function from <code>mlai.plot</code>, <code>model_sample</code></p>
<p>The samples from the model show that the error bars, which are informative for Gaussian outputs, are less informative for this model. They make clear that the data points lie, in output mainly at 0 or 1, or occasionally in between.</p>
<div class="figure">
<div id="step-function-deep-gp-samples-figure" class="figure-frame">
<object class="svgplot " data="https://inverseprobability.com/slides/diagrams//deepgp/step-function-deep-gp-samples.svg" width="80%" style=" ">
</object>
</div>
<div id="step-function-deep-gp-samples-magnify" class="magnify" onclick="magnifyFigure('step-function-deep-gp-samples')">
<img class="img-button" src="{{ '/assets/images/Magnify_Large.svg' | relative_url }}" style="width:1.5ex">
</div>
<div id="step-function-deep-gp-samples-caption" class="caption-frame">
<p>Figure: Samples from the deep Gaussian process model for the step function fit.</p>
</div>
</div>
<p>The visualize code allows us to inspect the intermediate layers in the deep GP model to understand how it has reconstructed the step function.</p>
<div class="figure">
<div id="step-function-deep-gp-mappings-figure" class="figure-frame">
<object class="svgplot " data="https://inverseprobability.com/slides/diagrams//deepgp/step-function-deep-gp-layer-0.svg" width="60%" style=" ">
</object>
<object class="svgplot " data="https://inverseprobability.com/slides/diagrams//deepgp/step-function-deep-gp-layer-1.svg" width="60%" style=" ">
</object>
<object class="svgplot " data="https://inverseprobability.com/slides/diagrams//deepgp/step-function-deep-gp-layer-2.svg" width="60%" style=" ">
</object>
<object class="svgplot " data="https://inverseprobability.com/slides/diagrams//deepgp/step-function-deep-gp-layer-3.svg" width="60%" style=" ">
</object>
</div>
<div id="step-function-deep-gp-mappings-magnify" class="magnify" onclick="magnifyFigure('step-function-deep-gp-mappings')">
<img class="img-button" src="{{ '/assets/images/Magnify_Large.svg' | relative_url }}" style="width:1.5ex">
</div>
<div id="step-function-deep-gp-mappings-caption" class="caption-frame">
<p>Figure: From top to bottom, the Gaussian process mapping function that makes up each layer of the resulting deep Gaussian process.</p>
</div>
</div>
<p>A pinball plot can be created for the resulting model to understand how the input is being translated to the output across the different layers.</p>
<div class="figure">
<div id="step-function-deep-gp-pinball-figure" class="figure-frame">
<object class="svgplot " data="https://inverseprobability.com/slides/diagrams//deepgp/step-function-deep-gp-pinball.svg" width="60%" style=" ">
</object>
</div>
<div id="step-function-deep-gp-pinball-magnify" class="magnify" onclick="magnifyFigure('step-function-deep-gp-pinball')">
<img class="img-button" src="{{ '/assets/images/Magnify_Large.svg' | relative_url }}" style="width:1.5ex">
</div>
<div id="step-function-deep-gp-pinball-caption" class="caption-frame">
<p>Figure: Pinball plot of the deep GP fitted to the step function data. Each layer of the model pushes the ‘ball’ towards the left or right, saturating at 1 and 0. This causes the final density to be be peaked at 0 and 1. Transitions occur driven by the uncertainty of the mapping in each layer.</p>
</div>
</div>
<div class="sourceCode" id="cb30"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb30-1"><a href="#cb30-1" aria-hidden="true" tabindex="-1"></a><span class="im">import</span> pods</span></code></pre></div>
<div class="sourceCode" id="cb31"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb31-1"><a href="#cb31-1" aria-hidden="true" tabindex="-1"></a>data <span class="op">=</span> pods.datasets.mcycle()</span>
<span id="cb31-2"><a href="#cb31-2" aria-hidden="true" tabindex="-1"></a>x <span class="op">=</span> data[<span class="st">'X'</span>]</span>
<span id="cb31-3"><a href="#cb31-3" aria-hidden="true" tabindex="-1"></a>y <span class="op">=</span> data[<span class="st">'Y'</span>]</span>
<span id="cb31-4"><a href="#cb31-4" aria-hidden="true" tabindex="-1"></a>scale<span class="op">=</span>np.sqrt(y.var())</span>
<span id="cb31-5"><a href="#cb31-5" aria-hidden="true" tabindex="-1"></a>offset<span class="op">=</span>y.mean()</span>
<span id="cb31-6"><a href="#cb31-6" aria-hidden="true" tabindex="-1"></a>yhat <span class="op">=</span> (y <span class="op">-</span> offset)<span class="op">/</span>scale</span></code></pre></div>
<h2 id="motorcycle-helmet-data">Motorcycle Helmet Data</h2>
<div style="text-align:right">
<span class="editsection-bracket" style="">[</span><span class="editsection" style=""><a href="https://github.com/lawrennd/snippets/edit/main/_datasets/includes/motorcycle-helmet-data.md" target="_blank" onclick="ga('send', 'event', 'Edit Page', 'Edit', 'https://github.com/lawrennd/snippets/edit/main/_datasets/includes/motorcycle-helmet-data.md', 13);">edit</a></span><span class="editsection-bracket" style="">]</span>
</div>
<div class="figure">
<div id="motorcycle-helment-data-figure" class="figure-frame">
<object class="svgplot " data="https://inverseprobability.com/slides/diagrams//datasets/motorcycle-helmet.svg" width="80%" style=" ">
</object>
</div>
<div id="motorcycle-helment-data-magnify" class="magnify" onclick="magnifyFigure('motorcycle-helment-data')">
<img class="img-button" src="{{ '/assets/images/Magnify_Large.svg' | relative_url }}" style="width:1.5ex">
</div>
<div id="motorcycle-helment-data-caption" class="caption-frame">
<p>Figure: Motorcycle helmet data. The data consists of acceleration readings on a motorcycle helmet undergoing a collision. The data exhibits heteroschedastic (time varying) noise levles and non-stationarity.</p>
</div>
</div>
<div class="sourceCode" id="cb32"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb32-1"><a href="#cb32-1" aria-hidden="true" tabindex="-1"></a>m_full <span class="op">=</span> GPy.models.GPRegression(x,yhat)</span>
<span id="cb32-2"><a href="#cb32-2" aria-hidden="true" tabindex="-1"></a>_ <span class="op">=</span> m_full.optimize() <span class="co"># Optimize parameters of covariance function</span></span></code></pre></div>
<h2 id="motorcycle-helmet-data-gp">Motorcycle Helmet Data GP</h2>
<div style="text-align:right">
<span class="editsection-bracket" style="">[</span><span class="editsection" style=""><a href="https://github.com/lawrennd/snippets/edit/main/_gp/includes/motorcycle-helmet-gp.md" target="_blank" onclick="ga('send', 'event', 'Edit Page', 'Edit', 'https://github.com/lawrennd/snippets/edit/main/_gp/includes/motorcycle-helmet-gp.md', 13);">edit</a></span><span class="editsection-bracket" style="">]</span>
</div>
<div class="figure">
<div id="motorcycle-helmet-gp-figure" class="figure-frame">
<object class="svgplot " data="https://inverseprobability.com/slides/diagrams//gp/motorcycle-helmet-gp.svg" width="80%" style=" ">
</object>
</div>
<div id="motorcycle-helmet-gp-magnify" class="magnify" onclick="magnifyFigure('motorcycle-helmet-gp')">
<img class="img-button" src="{{ '/assets/images/Magnify_Large.svg' | relative_url }}" style="width:1.5ex">
</div>
<div id="motorcycle-helmet-gp-caption" class="caption-frame">
<p>Figure: Gaussian process fit to the motorcycle helmet accelerometer data.</p>
</div>
</div>
<h2 id="motorcycle-helmet-data-deep-gp">Motorcycle Helmet Data Deep GP</h2>
<div style="text-align:right">
<span class="editsection-bracket" style="">[</span><span class="editsection" style=""><a href="https://github.com/lawrennd/snippets/edit/main/_deepgp/includes/motorcycle-helmet-deep-gp.md" target="_blank" onclick="ga('send', 'event', 'Edit Page', 'Edit', 'https://github.com/lawrennd/snippets/edit/main/_deepgp/includes/motorcycle-helmet-deep-gp.md', 13);">edit</a></span><span class="editsection-bracket" style="">]</span>
</div>
<div class="sourceCode" id="cb33"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb33-1"><a href="#cb33-1" aria-hidden="true" tabindex="-1"></a><span class="im">import</span> deepgp</span></code></pre></div>
<div class="sourceCode" id="cb34"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb34-1"><a href="#cb34-1" aria-hidden="true" tabindex="-1"></a>layers <span class="op">=</span> [y.shape[<span class="dv">1</span>], <span class="dv">1</span>, x.shape[<span class="dv">1</span>]]</span>
<span id="cb34-2"><a href="#cb34-2" aria-hidden="true" tabindex="-1"></a>inits <span class="op">=</span> [<span class="st">'PCA'</span>]<span class="op">*</span>(<span class="bu">len</span>(layers)<span class="op">-</span><span class="dv">1</span>)</span>
<span id="cb34-3"><a href="#cb34-3" aria-hidden="true" tabindex="-1"></a>kernels <span class="op">=</span> []</span>
<span id="cb34-4"><a href="#cb34-4" aria-hidden="true" tabindex="-1"></a><span class="cf">for</span> i <span class="kw">in</span> layers[<span class="dv">1</span>:]:</span>
<span id="cb34-5"><a href="#cb34-5" aria-hidden="true" tabindex="-1"></a> kernels <span class="op">+=</span> [GPy.kern.RBF(i)]</span>
<span id="cb34-6"><a href="#cb34-6" aria-hidden="true" tabindex="-1"></a>m <span class="op">=</span> deepgp.DeepGP(layers,Y<span class="op">=</span>yhat, X<span class="op">=</span>x, </span>
<span id="cb34-7"><a href="#cb34-7" aria-hidden="true" tabindex="-1"></a> inits<span class="op">=</span>inits, </span>
<span id="cb34-8"><a href="#cb34-8" aria-hidden="true" tabindex="-1"></a> kernels<span class="op">=</span>kernels, <span class="co"># the kernels for each layer</span></span>
<span id="cb34-9"><a href="#cb34-9" aria-hidden="true" tabindex="-1"></a> num_inducing<span class="op">=</span><span class="dv">20</span>, back_constraint<span class="op">=</span><span class="va">False</span>)</span>
<span id="cb34-10"><a href="#cb34-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb34-11"><a href="#cb34-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb34-12"><a href="#cb34-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb34-13"><a href="#cb34-13" aria-hidden="true" tabindex="-1"></a>m.initialize()</span></code></pre></div>
<div class="sourceCode" id="cb35"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb35-1"><a href="#cb35-1" aria-hidden="true" tabindex="-1"></a>m.staged_optimize(iters<span class="op">=</span>(<span class="dv">1000</span>,<span class="dv">1000</span>,<span class="dv">10000</span>), messages<span class="op">=</span>(<span class="va">True</span>, <span class="va">True</span>, <span class="va">True</span>))</span></code></pre></div>
<div class="figure">
<div id="motorcycle-helmet-deep-gp-figure" class="figure-frame">
<object class="svgplot " data="https://inverseprobability.com/slides/diagrams//deepgp/motorcycle-helmet-deep-gp.svg" width="80%" style=" ">
</object>
</div>
<div id="motorcycle-helmet-deep-gp-magnify" class="magnify" onclick="magnifyFigure('motorcycle-helmet-deep-gp')">
<img class="img-button" src="{{ '/assets/images/Magnify_Large.svg' | relative_url }}" style="width:1.5ex">
</div>
<div id="motorcycle-helmet-deep-gp-caption" class="caption-frame">
<p>Figure: Deep Gaussian process fit to the motorcycle helmet accelerometer data.</p>
</div>
</div>
<h2 id="motorcycle-helmet-data-deep-gp-1">Motorcycle Helmet Data Deep GP</h2>
<div class="figure">
<div id="motorcycle-helmet-deep-gp-samples-figure" class="figure-frame">
<object class="svgplot " data="https://inverseprobability.com/slides/diagrams//deepgp/motorcycle-helmet-deep-gp-samples.svg" width="80%" style=" ">
</object>
</div>
<div id="motorcycle-helmet-deep-gp-samples-magnify" class="magnify" onclick="magnifyFigure('motorcycle-helmet-deep-gp-samples')">
<img class="img-button" src="{{ '/assets/images/Magnify_Large.svg' | relative_url }}" style="width:1.5ex">
</div>
<div id="motorcycle-helmet-deep-gp-samples-caption" class="caption-frame">
<p>Figure: Samples from the deep Gaussian process as fitted to the motorcycle helmet accelerometer data.</p>
</div>
</div>
<h2 id="motorcycle-helmet-data-latent-1">Motorcycle Helmet Data Latent 1</h2>
<div class="figure">
<div id="motorcycle-helmet-deep-gp-layer-0-figure" class="figure-frame">
<object class="svgplot " data="https://inverseprobability.com/slides/diagrams//deepgp/motorcycle-helmet-deep-gp-layer-0.svg" width="60%" style=" ">
</object>
</div>
<div id="motorcycle-helmet-deep-gp-layer-0-magnify" class="magnify" onclick="magnifyFigure('motorcycle-helmet-deep-gp-layer-0')">
<img class="img-button" src="{{ '/assets/images/Magnify_Large.svg' | relative_url }}" style="width:1.5ex">
</div>
<div id="motorcycle-helmet-deep-gp-layer-0-caption" class="caption-frame">
<p>Figure: Mappings from the input to the latent layer for the motorcycle helmet accelerometer data.</p>
</div>
</div>
<h2 id="motorcycle-helmet-data-latent-2">Motorcycle Helmet Data Latent 2</h2>