-
Notifications
You must be signed in to change notification settings - Fork 0
/
section7_glm.jl
3409 lines (2779 loc) · 125 KB
/
section7_glm.jl
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
### A Pluto.jl notebook ###
# v0.19.46
using Markdown
using InteractiveUtils
# ╔═╡ 88154488-233d-11ed-1072-3dc0dd25d3fd
begin
using PlutoUI
using StatsPlots
using PlutoTeachingTools
using Plots; default(fontfamily="Computer Modern", framestyle=:box) # LaTex-style
using Turing
using DataFrames
using Random
using LaTeXStrings
using Logging; Logging.disable_logging(Logging.Warn);
end;
# ╔═╡ 52431ba0-762b-42d4-ab91-148998c90600
begin
using CSV
data_url= "https://exeter-data-analytics.github.io/StatModelling/_data/cuckoo.csv"
df_cuckoo=CSV.File(download(data_url)) |> DataFrame
end;
# ╔═╡ 89a55d82-d5a9-40cd-9247-9d5355d4fd7c
begin
using StatsBase
df_cuckoo[!, :Mass] = zscore(df_cuckoo[!, :Mass])
end;
# ╔═╡ ec93d30f-9d57-4598-8f64-ca706c4f0160
using GLM
# ╔═╡ fbb41799-8ce2-4286-be48-b6977930b6be
using StatsModels
# ╔═╡ 623efa9d-485d-4d9c-8e6d-aedb7dcbc00d
TableOfContents()
# ╔═╡ cc95fefe-9aee-4f16-97bd-9a0b8d09267e
md"[**↩ Home**](https://lf28.github.io/BayesianModelling/)
[**↪ Next Chapter**](./section8_nonlinear.html)
"
# ╔═╡ 0e52bc27-41e9-4361-a036-77eee3774e46
md"""
# Bayesian generalised linear models
Logistic regression can be viewed as a specific kind of generalised regression when the target ``y_n \in \{1,0\}`` is binary data. There are also other possible data types for ``y_n``, such as count data where the target takes integer values, *i.e.* ``y_n \in \mathbb{N}``, or ``y_n\in \mathbb{R}^+`` when the target can only take positive real values.
From a data generation perspective, we can simply choose the appropriate likelihood function such that the support matches the target's data type. For example, for real-valued data, a Gaussian is a good choice, while for binary data, a `Bernoulli` is a natural choice. In classific frequentist statistical terms, such a flexible regression model is called **generalised linear model** (GLM).
In this chapter, we are going to see how Bayesian GLMs can be used to do more flexible regression modelling. We will recap the frequentist's models first and then extend them to their Bayesian equivalences.
## A recap on frequentist's GLMs
A **generalised linear model** can be specified as
```math
p(y_n|\mathbf{x}_n, \boldsymbol{\beta}_1, \beta_0, \theta) = \mathcal{P}(y_n; g^{-1}(\mu_n), \theta)
```
where ``\mu`` as before is a linear function of the input ``\mathbf{x}_n``:
```math
\mu(\mathbf{x}_n) = \beta_0+\boldsymbol{\beta}_1^\top \mathbf{x}_n,
```
and ``\theta`` is some optional parameters associated with the likelihood function ``\mathcal P`` (for example, the observation's noise for the linear regression model).
Based on the above general definition, GLMs have three components:
1. A linear function ``\mu(\mathbf{x}_n)``, that's also why the model is called generalised **linear** models;
2. A suitable likelihood function ``\mathcal{P}``, such as Gaussian, Bernoulli, Poisson, *etc.*
3. A suitable **link function** ``g(\mu)`` that is associated with the requirement of the chosen likelihood function.
**Example (linear regression)** The likelihood function for linear regression is Gaussian:
```math
p(y_n|\mathbf{x}_n, \boldsymbol{\beta}) = \mathcal{N}(y_n; \beta_0+\mathbf{x}_n^\top \boldsymbol{\beta}_1, \sigma^2).
``` The link function here is simply an identity function, *i.e.* ``g^{-1}(x) = x``, since the mean parameter of a Gaussian is unconstrained. An extra parameter is needed for the observation noise ``\sigma^2``.
"""
# ╔═╡ f113ba37-1eeb-4101-8162-5402af63677a
md"
**Example (logistic regression)** Logistic regression assumes a ``\texttt{Bernoulli}`` likelihood:
```math
p(y_n|\mathbf{x}_n, \boldsymbol{\beta}) = \texttt{Bernoulli}(y_n; \sigma(\beta_0+\mathbf{x}_n^\top \boldsymbol{\beta}_1)).
```
Since the bias of a Bernoulli distribution should be between 0 and 1, a suitable (inverse) link function is logistic function: ``g^{-1}(\mu) = \sigma(\mu)``, which is a ``\mathbb{R} \rightarrow [0,1]`` deterministic transformation.
"
# ╔═╡ 73c61d37-9c26-43b7-ae99-9a79c6fe9804
md"""
The following table has summarised some commonly used GLMs.
|Distribution | Support | Typical uses | Inverse Link ``g^{-1}(\cdot)`` |
|:------------|:---------|:--------------|:--------------|
|Normal | ``\mathbb{R}, (-\infty, +\infty)``| Real valued regression|``\texttt{identity}(x) =x``|
| Bernoulli| ``\{0, 1\}``| binary classification| ``\texttt{logistic}(x)=\frac{1}{1+e^{-x}}``|
| Binomial| ``\{0, 1, \ldots, N\}``| count of # of positives out of N binary choices| ``\texttt{logistic}(x)=\frac{1}{1+e^{-x}}``|
| Categorical| ``\{1, 2,\ldots, K\}``| K class classification| ``\texttt{softmax}_i(\mathbf{x})= \frac{e^{x_i}}{\sum_{k=1}^K e^{x_k}}``|
| Poisson| ``\{0, 1,2,\ldots\}``| count of occurrences in fixed amount of time/space| ``\exp(x) = e^x``|
| Gamma/Exponential | ``(0, +\infty)``| scale parameters | ``\texttt{negInv}(x)=-(x^{-1})``|
"""
# ╔═╡ 5d01251e-5ea2-4d2c-82c8-d9c576264887
md"""
## Bayesian GLMs
The frequentist's GLMs have specified a likelihood function for the targets ``\mathbf{y}``:
```math
p(\mathbf{y}|\mathbf{X}, \beta_0, \boldsymbol{\beta}_1).
```
To fully specify a Bayesian model, we only need to add a prior distribution for the unknown regression parameters: ``p(\beta_0, \boldsymbol{\beta})``. Since the regression parameters take unconstrained real values, a sensible prior choice is therefore Gaussian, which was also used in the Bayesian linear and logistic regression models discussed earlier.
A general Bayesian GLM model therefore can be specified as:
!!! infor "Bayesian GLMs"
```math
\begin{align}
\text{Priors: }\;\;\;\;\;\;\beta_0 &\sim \mathcal{N}(m_0^{\beta_0}, v_0^{\beta_0})\\
\boldsymbol{\beta}_1 &\sim \mathcal{N}(\mathbf{m}_0^{\beta_1}, \mathbf{V}_0^{\beta_1})\\
\text{Likelihood: } \;\; \text{for } n &= 1,2,\ldots, N:\\
\mu_n &=\beta_0 + \boldsymbol{\beta}_1^\top \mathbf{x}_n \\
y_n &\sim \mathcal{P}(y_n; g^{-1}(\mu_n)).
\end{align}
```
In the following section, we are going to use Poisson regression as a concrete example to demonstrate how to do GLMs in a Bayesian way in `Turing`.
"""
# ╔═╡ 8b8471cd-6a77-4d8a-bbd9-ee28e0aab1f6
md"""
## Bayesian Poisson Regression
To make the illustration easier, we will consider a popular GLM: Poisson regression. The regression model is a popular choice for counting data which can only take non-negative integer values, such as the daily visitor number of a website.
### Poisson model
A Poisson distribution is parameterised with a rate parameter ``\lambda>0``, which should be strictly positive. The distribution, with a probability distribution
```math
\texttt{Poisson}(x=k; \lambda) \triangleq p(x=k|\lambda)= \frac{\lambda^k}{k!}e^{-\lambda}, \;\;\text{for } k= 0,1,2,\ldots,
```
is suitable to describe the number of independent events occurring within a unit time interval. And the rate ``\lambda`` is the average rate of occurrence of the event.
Some Poissons with increasing rate parameters are plotted below. It can be observed that when ``\lambda`` is larger, the distribution's probability mass shifts to the right and the variance or spread of the distribution gets wider. And this is because a Poisson distribution's mean and variance are both tied to ``\lambda``, which makes a Poisson's error structure less flexible. Careful model checking, therefore, is usually necessary for Poisson-based models.
"""
# ╔═╡ ba72ad42-87d6-4962-b56e-a8d6ba3d9733
let
λs = [1, 10, 5, 20]
plts = []
for i in 1:length(λs)
push!(plts, bar(Poisson(λs[i]), xlim =[0, 40], leg=false, c=i, title=L"\lambda=%$(λs[i])"))
end
plot(plts..., layout=(2,2))
end
# ╔═╡ ac69616e-14bf-48fe-adc9-7a810aa7a113
md"""
Since the rate parameter is strictly positive, when used in a GLM, we need to introduce an inverse link function that maps from the real number line to the positive part: ``g^{-1}: \mathbb{R} \rightarrow (0, +\infty)``. A common choice for Poisson regression is an exponential function (alternatively, ``\texttt{softplus}`` transformation can also be used). Therefore, a Poisson regression admits a likelihood function:
```math
p(y_n|\mathbf{x}_n, \boldsymbol{\beta}) = \texttt{Poisson}(y_n;\lambda_n=e^{\beta_0+\mathbf{x}_n^\top \boldsymbol{\beta}_1})
```
for ``n=1,2,\ldots, N`` observations. Note that the transformed rate ``e^{\beta_0+\mathbf{x}_n^\top \boldsymbol{\beta}_1}`` is always positive.
"""
# ╔═╡ ad45d197-0bae-4145-92b9-3b28064a692c
md"""
### An real-world counting data problem
To help illustrate the idea, a real-world `Cuckoo` dataset, described and analysed in the book [Statistical modelling in R](https://exeter-data-analytics.github.io/StatModelling/generalised-linear-models.html), is used as a concrete example.
$(Resource("https://exeter-data-analytics.github.io/StatModelling/_img/03-cuckoo.png", :align=>""))
The question of interest for the Cuckoo data is:
> How does nestling mass affect begging between two different species?
The begging rate is a count data, which takes non-negative integer values. Bayesian Poisson regression, therefore, is a suitable model.
We first **download** and **import** the data to the notebook's environment, and then carry out some initial data exploration.
"""
# ╔═╡ b2e26c07-43ad-47c1-a157-2368fbe5c707
first(df_cuckoo, 5)
# ╔═╡ e925ca4b-45c2-48fe-9d94-c34c15583a51
describe(df_cuckoo)
# ╔═╡ 39f3b1c0-e8bd-4d11-99ea-af9d74c7d77e
md"""
The dataset has three variables:
* `Mass`: continuous predictor
* `Species` ``\in\{\texttt{Cuckoo, Warbler}\}``: a binary predictor indicating the species of the bird
* `Beg`: non-negative integer count data.
The data is displayed below in a scatter plot.
"""
# ╔═╡ b2e54b06-91ad-4cb2-b398-fd7926f8c387
@df df_cuckoo scatter(:Mass, :Beg, group =:Species, legend=:outerright, xlabel="Mass", ylabel="Beg")
# ╔═╡ f39d0bab-3ce6-44c4-9fe0-77438884852a
md"""
It seems that the begging count is positively correlated with the mass variable for both species. The correlations, however, show different trends, which indicates there might be some interactions between the two predictors: `Mass` and `Species`. A model that accommodates such an interaction is:
```math
\ln(\mathbb{E}[\texttt{Beg}|\ldots]) = \beta_0 + \beta_1\cdot \texttt{Mass} + \beta_2 \cdot \texttt{Species} + \beta_3 \cdot (\texttt{Mass} \times \texttt{Species})
```
Since `Species` is a binary variable, *i.e.* `Species` ``\in \{0,1\}``, the model for `Species` ``=0`` is
```math
\ln(\mathbb{E}[\texttt{Beg}|\texttt{Species} = 0]) = \beta_0 + \beta_1\cdot \texttt{Mass} ,
```
On the other hand, when `Species` ``=1``,
```math
\ln(\mathbb{E}[\texttt{Beg}|\texttt{Species} = 1]) = (\beta_0 + \beta_2) + (\beta_1+\beta_3) \cdot \texttt{Mass}.
```
Therefore, ``\beta_3`` can be interpreted as the *add-on* effect of `Mass` on `Beg` when an observation is a ``\texttt{Warbler}``, assuming species ``\texttt{Warbler}`` is encoded as 1 and ``\texttt{Cuckoo}`` is encoded as 0.
"""
# ╔═╡ 0475637e-d092-472d-82f4-fac65f34024e
md"""
### Data preprocessing
"""
# ╔═╡ 3b02812e-bd5f-47d2-89e2-3deb6f243562
md"""
Most GLMs employ non-linear link functions, which can be problematic for a MCMC sampler to mix. It is therefore a common practice to standardise the numerical features such that they have zero means and unit variances.
"""
# ╔═╡ a422af52-c350-45a0-a886-59a8e71b62ba
md"""
### Frequentist inference
It is usually a good idea to fit a frequentist model as a reference. This can be easily accomplished with `GLM.jl`. To accommodate the two different trends of the two species, we have added an interaction term.
"""
# ╔═╡ d4f7d14c-2710-4d6c-869f-3c0ab75d3d51
begin
glm(@formula(Beg~Mass*Species), df_cuckoo, Poisson())
end
# ╔═╡ b6aa0ffe-c51f-4279-94b2-13c37797acf1
md"""
### Bayesian inference with `Turing`
"""
# ╔═╡ eac559ce-b05f-4b91-84b8-ed1f57a53c66
md"""
Based on the general Bayesian GLM model, we only need to subsitute in the required Poisson likelihood for ``\mathcal{P}`` and its associated (inverse) link function ``g^{-1}``, which is an exponential function. The final model is listed below.
!!! infor "Bayesian Poisson regression"
```math
\begin{align}
\text{Priors: }\;\;\;\;\;\;\beta_0 &\sim \mathcal{N}(m_0^{\beta_0}, v_0^{\beta_0})\\
\boldsymbol{\beta}_1 &\sim \mathcal{N}(\mathbf{m}_0^{\beta_1}, \mathbf{V}_0^{\beta_1})\\
\text{Likelihood: } \;\; \text{for } n &= 1,2,\ldots, N:\\
\mu_n &=\beta_0 + \boldsymbol{\beta}_1^\top \mathbf{x}_n \\
\lambda_n &= e^{\mu_n}\\
y_n &\sim \texttt{Poisson}(\lambda_n).
\end{align}
```
The model can be easily ported to `Turing`. Here we have assumed
* the prior mean are all zeros, i.e. ``m_0^{\beta_0}=0``, ``\mathbf{m}_0^{\beta}=\mathbf{0}``
* the prior variances are set to ``1``;
* since all features have been standardised, the prior variance should be weak-informative enough (we will carry out predictive checks at the end to make sure the prior parameters are reasonable)
"""
# ╔═╡ 47cafa8d-6eb9-40c8-a9a7-56c9e7909c3d
@model function bayesian_poisson_regression(X, y; v₀=1, V₀ = 1)
# priors
β₀ ~ Normal(0, sqrt(v₀))
nfeatures = size(X)[2]
β ~ MvNormal(zeros(nfeatures), sqrt(V₀))
# Likelihood
μs = β₀ .+ X * β
# inverse link function for Poisson is exponential
λs = exp.(μs)
for i in eachindex(y)
y[i] ~ Poisson(λs[i])
end
return (; μs, λs)
end
# ╔═╡ 8af86af4-5144-4c36-b185-1c91189c9061
md"""
#### Prepare design matrix ``\mathbf{X}``
Instead of preparing the input design matrix ``\mathbf{X}`` manually, we can use `StatsModels.jl` to do the hard work for us. We only need to specify the model by the familiar `@formula` format and the `ModelFrame` object can prepare the required design matrix for us. It will typically do dummy encoding for the categorical variables and encode the interaction terms automatically.
The prepared data are then passed to the `Turing` model to carry out the inference.
"""
# ╔═╡ 03064a4c-6445-446a-a4b5-f50d7d2332d5
begin
XX_cuckoo = ModelFrame(@formula(Beg~Mass*Species), df_cuckoo) |> modelmatrix
# remove the first column, the intercept
XX_cuckoo = XX_cuckoo[:, 2:end]
end;
# ╔═╡ 44fa5546-4abb-4e0b-bde3-d444aa912377
chain_poisson_cuckoo = let
yy = df_cuckoo[!, :Beg]
Random.seed!(100)
chain = sample(
bayesian_poisson_regression(XX_cuckoo, yy; v₀=1, V₀=1),
NUTS(),
MCMCThreads(),
1500,
3
)
chain
end;
# ╔═╡ 7fe35625-4796-4240-bcdd-03aef6ade093
md"""
The inference results look similar to the frequentist method. However, the posterior means are shrinked a little bit towards zero, the prior's mean. The credible intervals also show that all three predictors' parameters are not likely to be zeros, which is in agreement with the frequentist's test result.
"""
# ╔═╡ 1a949d5a-2795-4974-8ae9-83a4e3c7fc90
describe(chain_poisson_cuckoo)
# ╔═╡ fd583678-f289-4075-9dee-8bdd334ce17f
plot(chain_poisson_cuckoo)
# ╔═╡ 6456936d-423e-4c56-931e-15e23fcbd82d
md"""
Different from the frequentist's method, the Bayesian method provides us with uncertain measurements of all parameters within the model. For the Poisson regression model, we are interested in the posterior predictive of the expected begging count: ``\lambda_\ast = e^{\beta_0+x_\ast^\top \beta_1}``. The expected value has its posterior distribution, which can be approximated by the Monte Carlo method:
```math
p(\lambda_\ast | \mathcal{D}) \approx \frac{1}{R} \sum_r e^{\beta_0^{(r)}+x_\ast^\top \beta_1^{(r)}},
```
where ``\{\beta_0^{(r)}, \boldsymbol{\beta}_1^{(r)}\}_{r=1}^R`` are the posterior MCMC samples. The Monte Carlo formula can be interpreted as an *ensemble method*: multiple models, each indexed by one of the ``R`` posterior samples, all contribute to the final prediction.
We can use `Julia`'s `generated_quantities()` method to find the approximation.
"""
# ╔═╡ 6ea6d1a1-fde0-4eb8-aa4c-a99a4f6a22e2
begin
xs_test = collect(-1.5:0.1:3)
test_df = DataFrame(Mass = xs_test, Species = trues(length(xs_test)), Beg=zeros(length(xs_test)))
XX_test = ModelFrame(@formula(Beg~Mass*Species), test_df) |> modelmatrix
# remove the first column, the intercept
XX_test = XX_test[:, 2:end]
ys_ = Vector{Union{Missing, Int64}}(undef, size(XX_test)[1])
pred_model_poisson = bayesian_poisson_regression(XX_test, ys_; v₀=1, V₀=1)
gen_true = generated_quantities(pred_model_poisson, chain_poisson_cuckoo)
Xs_false =[xs_test falses(length(xs_test)) xs_test .* falses(length(xs_test))]
gen_false = generated_quantities(bayesian_poisson_regression(Xs_false, ys_; v₀=1, V₀=1), chain_poisson_cuckoo)
λs_true = map(x -> x.λs, gen_true)
λs_false = map(x -> x.λs, gen_false)
end;
# ╔═╡ 7a7a5641-2462-46fb-8ab0-5a76788af289
md"""
The Bayesian posterior distributions of ``\lambda`` are shown below. Note that the Bayesion inference not only provides us with a point estimator (the posterior mean) but also uncertainty measurement associated with the estimate.
"""
# ╔═╡ 79a32094-2dd4-484f-b91f-b5f9d99cc4bd
let
plt =@df df_cuckoo scatter(:Mass, :Beg, group =:Species, legend=:outerright, ylim=[-9,250], xlabel="Mass", ylabel="Beg", legendtitle=L"\texttt{Species}")
plot!(xs_test, mean(λs_false), lc=1, lw=1.5,label=L"\mathbb{E}[\lambda|\mathcal{D}]"*" Cuckoo")
plot!(xs_test, mean(λs_true), lc=2, lw=1.5,label=L"\mathbb{E}[\lambda|\mathcal{D}]"*" Warbler")
for i in 1:80
plot!(xs_test, λs_false[i, 1], lw=0.2, lc=1, alpha =0.5, label="")
plot!(xs_test, λs_true[i, 1], lw=0.2, lc=2,alpha=0.5, label="")
end
plt
end
# ╔═╡ b4227421-2b35-467f-b11f-f2425b12c9b9
md"""
#### Predictive checks
Lastly, we carry out predictive checks to make sure the Bayesian model's assumptions match the observed data. To simulate data from the posterior predictive distribution, we use the `predict()` method.
"""
# ╔═╡ 4ab38b80-0bae-4ea5-a109-3a88556daac5
pred_ys_poisson = let
yy_ = Vector{Union{Missing, Float64}}(undef, size(XX_cuckoo)[1])
gen = predict(
bayesian_poisson_regression(XX_cuckoo, yy_; v₀=1, V₀=1),
chain_poisson_cuckoo
)
end
# ╔═╡ 6ae3eb45-9577-4bfe-8363-0b3c47bd0421
md"""
The mean and (log-transformed) standard deviation of the simulated samples are first calculated; and then plotted to compare against the observed. It can be observed from the plot that the simulated data based on our model assumption matches what we have observed since the observed statistic sits well within the boundary of the simulated statistics.
"""
# ╔═╡ 9d2d1c39-6c64-4deb-a2ef-dbbfbfd88323
let
pred_y_μ_σ = DataFrame(mean= mean(Array(pred_ys_poisson), dims=2)[:], std=log.(std(Array(pred_ys_poisson), dims=2)[:]));
@df pred_y_μ_σ scatter(:mean, :std, ms=2, alpha=0.5, label="Predicted", xlabel=L"\mu(\mathbf{y})", ylabel=L"\ln(\sigma(\mathbf{y}))", legend=:topleft)
scatter!([mean(df_cuckoo.Beg)], [log(std(df_cuckoo.Beg))], ms=8,label="Observed")
end
# ╔═╡ 00000000-0000-0000-0000-000000000001
PLUTO_PROJECT_TOML_CONTENTS = """
[deps]
CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
GLM = "38e38edf-8417-5370-95a0-9cbb8c7f171a"
LaTeXStrings = "b964fa9f-0449-5b57-a5c2-d3ea65f4040f"
Logging = "56ddb016-857b-54e1-b83d-db4d58db5568"
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
PlutoTeachingTools = "661c6b06-c737-4d37-b85c-46df65de6f69"
PlutoUI = "7f904dfe-b85e-4ff6-b463-dae2292396a8"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91"
StatsModels = "3eaba693-59b7-5ba5-a881-562e759f1c8d"
StatsPlots = "f3b207a7-027a-5e70-b257-86293d7955fd"
Turing = "fce5fe82-541a-59a6-adf8-730c64b5f9a0"
[compat]
CSV = "~0.10.11"
DataFrames = "~1.7.0"
GLM = "~1.9.0"
LaTeXStrings = "~1.4.0"
Plots = "~1.40.8"
PlutoTeachingTools = "~0.2.15"
PlutoUI = "~0.7.54"
StatsBase = "~0.34.2"
StatsModels = "~0.7.3"
StatsPlots = "~0.15.6"
Turing = "~0.34.1"
"""
# ╔═╡ 00000000-0000-0000-0000-000000000002
PLUTO_MANIFEST_TOML_CONTENTS = """
# This file is machine-generated - editing it directly is not advised
julia_version = "1.11.0"
manifest_format = "2.0"
project_hash = "90b1d604389b057e0310931e838a1dbfdb7caa6f"
[[deps.ADTypes]]
git-tree-sha1 = "eea5d80188827b35333801ef97a40c2ed653b081"
uuid = "47edcb42-4c32-4615-8424-f2b9edc5f35b"
version = "1.9.0"
[deps.ADTypes.extensions]
ADTypesChainRulesCoreExt = "ChainRulesCore"
ADTypesEnzymeCoreExt = "EnzymeCore"
[deps.ADTypes.weakdeps]
ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
EnzymeCore = "f151be2c-9106-41f4-ab19-57ee4f262869"
[[deps.AbstractFFTs]]
deps = ["LinearAlgebra"]
git-tree-sha1 = "d92ad398961a3ed262d8bf04a1a2b8340f915fef"
uuid = "621f4979-c628-5d54-868e-fcf4e3e8185c"
version = "1.5.0"
weakdeps = ["ChainRulesCore", "Test"]
[deps.AbstractFFTs.extensions]
AbstractFFTsChainRulesCoreExt = "ChainRulesCore"
AbstractFFTsTestExt = "Test"
[[deps.AbstractMCMC]]
deps = ["BangBang", "ConsoleProgressMonitor", "Distributed", "FillArrays", "LogDensityProblems", "Logging", "LoggingExtras", "ProgressLogging", "Random", "StatsBase", "TerminalLoggers", "Transducers"]
git-tree-sha1 = "c732dd9f356d26cc48d3b484f3fd9886c0ba8ba3"
uuid = "80f14c24-f653-4e6a-9b94-39d6b0f70001"
version = "5.5.0"
[[deps.AbstractPPL]]
deps = ["AbstractMCMC", "Accessors", "DensityInterface", "Random"]
git-tree-sha1 = "6380a9a03a4207bac53ac310dd3a283bb4df54ef"
uuid = "7a57a42e-76ec-4ea3-a279-07e840d6d9cf"
version = "0.8.4"
[[deps.AbstractPlutoDingetjes]]
deps = ["Pkg"]
git-tree-sha1 = "6e1d2a35f2f90a4bc7c2ed98079b2ba09c35b83a"
uuid = "6e696c72-6542-2067-7265-42206c756150"
version = "1.3.2"
[[deps.AbstractTrees]]
git-tree-sha1 = "2d9c9a55f9c93e8887ad391fbae72f8ef55e1177"
uuid = "1520ce14-60c1-5f80-bbc7-55ef81b5835c"
version = "0.4.5"
[[deps.Accessors]]
deps = ["CompositionsBase", "ConstructionBase", "InverseFunctions", "LinearAlgebra", "MacroTools", "Markdown"]
git-tree-sha1 = "b392ede862e506d451fc1616e79aa6f4c673dab8"
uuid = "7d9f7c33-5ae7-4f3b-8dc6-eff91059b697"
version = "0.1.38"
[deps.Accessors.extensions]
AccessorsAxisKeysExt = "AxisKeys"
AccessorsDatesExt = "Dates"
AccessorsIntervalSetsExt = "IntervalSets"
AccessorsStaticArraysExt = "StaticArrays"
AccessorsStructArraysExt = "StructArrays"
AccessorsTestExt = "Test"
AccessorsUnitfulExt = "Unitful"
[deps.Accessors.weakdeps]
AxisKeys = "94b1ba4f-4ee9-5380-92f1-94cde586c3c5"
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
IntervalSets = "8197267c-284f-5f27-9208-e0e47529a953"
Requires = "ae029012-a4dd-5104-9daa-d747884805df"
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
StructArrays = "09ab397b-f2b6-538f-b94a-2f83cf4a842a"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d"
[[deps.Adapt]]
deps = ["LinearAlgebra", "Requires"]
git-tree-sha1 = "6a55b747d1812e699320963ffde36f1ebdda4099"
uuid = "79e6a3ab-5dfb-504d-930d-738a2a938a0e"
version = "4.0.4"
weakdeps = ["StaticArrays"]
[deps.Adapt.extensions]
AdaptStaticArraysExt = "StaticArrays"
[[deps.AdvancedHMC]]
deps = ["AbstractMCMC", "ArgCheck", "DocStringExtensions", "InplaceOps", "LinearAlgebra", "LogDensityProblems", "LogDensityProblemsAD", "ProgressMeter", "Random", "Requires", "Setfield", "SimpleUnPack", "Statistics", "StatsBase", "StatsFuns"]
git-tree-sha1 = "1da0961a400c28d1e5f057e922ff75ec5d6a5747"
uuid = "0bf59076-c3b1-5ca4-86bd-e02cd72cde3d"
version = "0.6.2"
[deps.AdvancedHMC.extensions]
AdvancedHMCCUDAExt = "CUDA"
AdvancedHMCMCMCChainsExt = "MCMCChains"
AdvancedHMCOrdinaryDiffEqExt = "OrdinaryDiffEq"
[deps.AdvancedHMC.weakdeps]
CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba"
MCMCChains = "c7f686f2-ff18-58e9-bc7b-31028e88f75d"
OrdinaryDiffEq = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed"
[[deps.AdvancedMH]]
deps = ["AbstractMCMC", "Distributions", "FillArrays", "LinearAlgebra", "LogDensityProblems", "Random", "Requires"]
git-tree-sha1 = "66ac4c7b320d2434f04d48116db02e73e6dabc8b"
uuid = "5b7e9947-ddc0-4b3f-9b55-0d8042f74170"
version = "0.8.3"
weakdeps = ["DiffResults", "ForwardDiff", "MCMCChains", "StructArrays"]
[deps.AdvancedMH.extensions]
AdvancedMHForwardDiffExt = ["DiffResults", "ForwardDiff"]
AdvancedMHMCMCChainsExt = "MCMCChains"
AdvancedMHStructArraysExt = "StructArrays"
[[deps.AdvancedPS]]
deps = ["AbstractMCMC", "Distributions", "Random", "Random123", "Requires", "SSMProblems", "StatsFuns"]
git-tree-sha1 = "5dcd3de7e7346f48739256e71a86d0f96690b8c8"
uuid = "576499cb-2369-40b2-a588-c64705576edc"
version = "0.6.0"
weakdeps = ["Libtask"]
[deps.AdvancedPS.extensions]
AdvancedPSLibtaskExt = "Libtask"
[[deps.AdvancedVI]]
deps = ["ADTypes", "Bijectors", "DiffResults", "Distributions", "DistributionsAD", "DocStringExtensions", "ForwardDiff", "LinearAlgebra", "ProgressMeter", "Random", "Requires", "StatsBase", "StatsFuns", "Tracker"]
git-tree-sha1 = "c217a9b531b4b752eb120a9f820527126ba68fb9"
uuid = "b5ca4192-6429-45e5-a2d9-87aec30a685c"
version = "0.2.8"
[deps.AdvancedVI.extensions]
AdvancedVIEnzymeExt = ["Enzyme"]
AdvancedVIFluxExt = ["Flux"]
AdvancedVIReverseDiffExt = ["ReverseDiff"]
AdvancedVIZygoteExt = ["Zygote"]
[deps.AdvancedVI.weakdeps]
Enzyme = "7da242da-08ed-463a-9acd-ee780be4f1d9"
Flux = "587475ba-b771-5e3f-ad9e-33799f191a9c"
ReverseDiff = "37e2e3b7-166d-5795-8a7a-e32c996b4267"
Zygote = "e88e6eb3-aa80-5325-afca-941959d7151f"
[[deps.AliasTables]]
deps = ["PtrArrays", "Random"]
git-tree-sha1 = "9876e1e164b144ca45e9e3198d0b689cadfed9ff"
uuid = "66dad0bd-aa9a-41b7-9441-69ab47430ed8"
version = "1.1.3"
[[deps.ArgCheck]]
git-tree-sha1 = "a3a402a35a2f7e0b87828ccabbd5ebfbebe356b4"
uuid = "dce04be8-c92d-5529-be00-80e4d2c0e197"
version = "2.3.0"
[[deps.ArgTools]]
uuid = "0dad84c5-d112-42e6-8d28-ef12dabb789f"
version = "1.1.2"
[[deps.ArnoldiMethod]]
deps = ["LinearAlgebra", "Random", "StaticArrays"]
git-tree-sha1 = "d57bd3762d308bded22c3b82d033bff85f6195c6"
uuid = "ec485272-7323-5ecc-a04f-4719b315124d"
version = "0.4.0"
[[deps.Arpack]]
deps = ["Arpack_jll", "Libdl", "LinearAlgebra", "Logging"]
git-tree-sha1 = "9b9b347613394885fd1c8c7729bfc60528faa436"
uuid = "7d9fca2a-8960-54d3-9f78-7d1dccf2cb97"
version = "0.5.4"
[[deps.Arpack_jll]]
deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "Libdl", "OpenBLAS_jll", "Pkg"]
git-tree-sha1 = "5ba6c757e8feccf03a1554dfaf3e26b3cfc7fd5e"
uuid = "68821587-b530-5797-8361-c406ea357684"
version = "3.5.1+1"
[[deps.ArrayInterface]]
deps = ["Adapt", "LinearAlgebra"]
git-tree-sha1 = "3640d077b6dafd64ceb8fd5c1ec76f7ca53bcf76"
uuid = "4fba245c-0d91-5ea0-9b3e-6abc04ee57a9"
version = "7.16.0"
[deps.ArrayInterface.extensions]
ArrayInterfaceBandedMatricesExt = "BandedMatrices"
ArrayInterfaceBlockBandedMatricesExt = "BlockBandedMatrices"
ArrayInterfaceCUDAExt = "CUDA"
ArrayInterfaceCUDSSExt = "CUDSS"
ArrayInterfaceChainRulesExt = "ChainRules"
ArrayInterfaceGPUArraysCoreExt = "GPUArraysCore"
ArrayInterfaceReverseDiffExt = "ReverseDiff"
ArrayInterfaceSparseArraysExt = "SparseArrays"
ArrayInterfaceStaticArraysCoreExt = "StaticArraysCore"
ArrayInterfaceTrackerExt = "Tracker"
[deps.ArrayInterface.weakdeps]
BandedMatrices = "aae01518-5342-5314-be14-df237901396f"
BlockBandedMatrices = "ffab5731-97b5-5995-9138-79e8c1846df0"
CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba"
CUDSS = "45b445bb-4962-46a0-9369-b4df9d0f772e"
ChainRules = "082447d4-558c-5d27-93f4-14fc19e9eca2"
GPUArraysCore = "46192b85-c4d5-4398-a991-12ede77f4527"
ReverseDiff = "37e2e3b7-166d-5795-8a7a-e32c996b4267"
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
StaticArraysCore = "1e83bf80-4336-4d27-bf5d-d5a4f845583c"
Tracker = "9f7883ad-71c0-57eb-9f7f-b5c9e6d3789c"
[[deps.Artifacts]]
uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33"
version = "1.11.0"
[[deps.Atomix]]
deps = ["UnsafeAtomics"]
git-tree-sha1 = "c06a868224ecba914baa6942988e2f2aade419be"
uuid = "a9b6321e-bd34-4604-b9c9-b65b8de01458"
version = "0.1.0"
[[deps.AxisAlgorithms]]
deps = ["LinearAlgebra", "Random", "SparseArrays", "WoodburyMatrices"]
git-tree-sha1 = "01b8ccb13d68535d73d2b0c23e39bd23155fb712"
uuid = "13072b0f-2c55-5437-9ae7-d433b7a33950"
version = "1.1.0"
[[deps.AxisArrays]]
deps = ["Dates", "IntervalSets", "IterTools", "RangeArrays"]
git-tree-sha1 = "16351be62963a67ac4083f748fdb3cca58bfd52f"
uuid = "39de3d68-74b9-583c-8d2d-e117c070f3a9"
version = "0.4.7"
[[deps.BangBang]]
deps = ["Accessors", "ConstructionBase", "InitialValues", "LinearAlgebra", "Requires"]
git-tree-sha1 = "e2144b631226d9eeab2d746ca8880b7ccff504ae"
uuid = "198e06fe-97b7-11e9-32a5-e1d131e6ad66"
version = "0.4.3"
[deps.BangBang.extensions]
BangBangChainRulesCoreExt = "ChainRulesCore"
BangBangDataFramesExt = "DataFrames"
BangBangStaticArraysExt = "StaticArrays"
BangBangStructArraysExt = "StructArrays"
BangBangTablesExt = "Tables"
BangBangTypedTablesExt = "TypedTables"
[deps.BangBang.weakdeps]
ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
StructArrays = "09ab397b-f2b6-538f-b94a-2f83cf4a842a"
Tables = "bd369af6-aec1-5ad0-b16a-f7cc5008161c"
TypedTables = "9d95f2ec-7b3d-5a63-8d20-e2491e220bb9"
[[deps.Base64]]
uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
version = "1.11.0"
[[deps.Baselet]]
git-tree-sha1 = "aebf55e6d7795e02ca500a689d326ac979aaf89e"
uuid = "9718e550-a3fa-408a-8086-8db961cd8217"
version = "0.1.1"
[[deps.Bijections]]
git-tree-sha1 = "d8b0439d2be438a5f2cd68ec158fe08a7b2595b7"
uuid = "e2ed5e7c-b2de-5872-ae92-c73ca462fb04"
version = "0.1.9"
[[deps.Bijectors]]
deps = ["ArgCheck", "ChainRules", "ChainRulesCore", "ChangesOfVariables", "Compat", "Distributions", "DocStringExtensions", "Functors", "InverseFunctions", "IrrationalConstants", "LinearAlgebra", "LogExpFunctions", "MappedArrays", "Random", "Reexport", "Requires", "Roots", "SparseArrays", "Statistics"]
git-tree-sha1 = "92edc3544607c4fda1b30357910597e2a70dc5ea"
uuid = "76274a88-744f-5084-9051-94815aaf08c4"
version = "0.13.18"
[deps.Bijectors.extensions]
BijectorsDistributionsADExt = "DistributionsAD"
BijectorsEnzymeExt = "Enzyme"
BijectorsForwardDiffExt = "ForwardDiff"
BijectorsLazyArraysExt = "LazyArrays"
BijectorsReverseDiffExt = "ReverseDiff"
BijectorsTapirExt = "Tapir"
BijectorsTrackerExt = "Tracker"
BijectorsZygoteExt = "Zygote"
[deps.Bijectors.weakdeps]
DistributionsAD = "ced4e74d-a319-5a8a-b0ac-84af2272839c"
Enzyme = "7da242da-08ed-463a-9acd-ee780be4f1d9"
ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210"
LazyArrays = "5078a376-72f3-5289-bfd5-ec5146d43c02"
ReverseDiff = "37e2e3b7-166d-5795-8a7a-e32c996b4267"
Tapir = "07d77754-e150-4737-8c94-cd238a1fb45b"
Tracker = "9f7883ad-71c0-57eb-9f7f-b5c9e6d3789c"
Zygote = "e88e6eb3-aa80-5325-afca-941959d7151f"
[[deps.BitFlags]]
git-tree-sha1 = "0691e34b3bb8be9307330f88d1a3c3f25466c24d"
uuid = "d1d4a3ce-64b1-5f1a-9ba4-7e7e69966f35"
version = "0.1.9"
[[deps.Bzip2_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "9e2a6b69137e6969bab0152632dcb3bc108c8bdd"
uuid = "6e34b625-4abd-537c-b88f-471c36dfa7a0"
version = "1.0.8+1"
[[deps.CEnum]]
git-tree-sha1 = "389ad5c84de1ae7cf0e28e381131c98ea87d54fc"
uuid = "fa961155-64e5-5f13-b03f-caf6b980ea82"
version = "0.5.0"
[[deps.CSV]]
deps = ["CodecZlib", "Dates", "FilePathsBase", "InlineStrings", "Mmap", "Parsers", "PooledArrays", "PrecompileTools", "SentinelArrays", "Tables", "Unicode", "WeakRefStrings", "WorkerUtilities"]
git-tree-sha1 = "6c834533dc1fabd820c1db03c839bf97e45a3fab"
uuid = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"
version = "0.10.14"
[[deps.Cairo_jll]]
deps = ["Artifacts", "Bzip2_jll", "CompilerSupportLibraries_jll", "Fontconfig_jll", "FreeType2_jll", "Glib_jll", "JLLWrappers", "LZO_jll", "Libdl", "Pixman_jll", "Xorg_libXext_jll", "Xorg_libXrender_jll", "Zlib_jll", "libpng_jll"]
git-tree-sha1 = "009060c9a6168704143100f36ab08f06c2af4642"
uuid = "83423d85-b0ee-5818-9007-b63ccbeb887a"
version = "1.18.2+1"
[[deps.ChainRules]]
deps = ["Adapt", "ChainRulesCore", "Compat", "Distributed", "GPUArraysCore", "IrrationalConstants", "LinearAlgebra", "Random", "RealDot", "SparseArrays", "SparseInverseSubset", "Statistics", "StructArrays", "SuiteSparse"]
git-tree-sha1 = "be227d253d132a6d57f9ccf5f67c0fb6488afd87"
uuid = "082447d4-558c-5d27-93f4-14fc19e9eca2"
version = "1.71.0"
[[deps.ChainRulesCore]]
deps = ["Compat", "LinearAlgebra"]
git-tree-sha1 = "3e4b134270b372f2ed4d4d0e936aabaefc1802bc"
uuid = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
version = "1.25.0"
weakdeps = ["SparseArrays"]
[deps.ChainRulesCore.extensions]
ChainRulesCoreSparseArraysExt = "SparseArrays"
[[deps.ChangesOfVariables]]
deps = ["LinearAlgebra"]
git-tree-sha1 = "799b25ca3a8a24936ae7b5c52ad194685fc3e6ef"
uuid = "9e997f8a-9a97-42d5-a9f1-ce6bfc15e2c0"
version = "0.1.9"
weakdeps = ["InverseFunctions", "Test"]
[deps.ChangesOfVariables.extensions]
ChangesOfVariablesInverseFunctionsExt = "InverseFunctions"
ChangesOfVariablesTestExt = "Test"
[[deps.Clustering]]
deps = ["Distances", "LinearAlgebra", "NearestNeighbors", "Printf", "Random", "SparseArrays", "Statistics", "StatsBase"]
git-tree-sha1 = "9ebb045901e9bbf58767a9f34ff89831ed711aae"
uuid = "aaaa29a8-35af-508c-8bc3-b662a17a0fe5"
version = "0.15.7"
[[deps.CodeTracking]]
deps = ["InteractiveUtils", "UUIDs"]
git-tree-sha1 = "7eee164f122511d3e4e1ebadb7956939ea7e1c77"
uuid = "da1fd8a2-8d9e-5ec2-8556-3022fb5608a2"
version = "1.3.6"
[[deps.CodecZlib]]
deps = ["TranscodingStreams", "Zlib_jll"]
git-tree-sha1 = "bce6804e5e6044c6daab27bb533d1295e4a2e759"
uuid = "944b1d66-785c-5afd-91f1-9de20f533193"
version = "0.7.6"
[[deps.ColorSchemes]]
deps = ["ColorTypes", "ColorVectorSpace", "Colors", "FixedPointNumbers", "PrecompileTools", "Random"]
git-tree-sha1 = "b5278586822443594ff615963b0c09755771b3e0"
uuid = "35d6a980-a343-548e-a6ea-1d62b119f2f4"
version = "3.26.0"
[[deps.ColorTypes]]
deps = ["FixedPointNumbers", "Random"]
git-tree-sha1 = "b10d0b65641d57b8b4d5e234446582de5047050d"
uuid = "3da002f7-5984-5a60-b8a6-cbb66c0b333f"
version = "0.11.5"
[[deps.ColorVectorSpace]]
deps = ["ColorTypes", "FixedPointNumbers", "LinearAlgebra", "Requires", "Statistics", "TensorCore"]
git-tree-sha1 = "a1f44953f2382ebb937d60dafbe2deea4bd23249"
uuid = "c3611d14-8923-5661-9e6a-0046d554d3a4"
version = "0.10.0"
weakdeps = ["SpecialFunctions"]
[deps.ColorVectorSpace.extensions]
SpecialFunctionsExt = "SpecialFunctions"
[[deps.Colors]]
deps = ["ColorTypes", "FixedPointNumbers", "Reexport"]
git-tree-sha1 = "362a287c3aa50601b0bc359053d5c2468f0e7ce0"
uuid = "5ae59095-9a9b-59fe-a467-6f913c188581"
version = "0.12.11"
[[deps.Combinatorics]]
git-tree-sha1 = "08c8b6831dc00bfea825826be0bc8336fc369860"
uuid = "861a8166-3701-5b0c-9a16-15d98fcdc6aa"
version = "1.0.2"
[[deps.CommonSolve]]
git-tree-sha1 = "0eee5eb66b1cf62cd6ad1b460238e60e4b09400c"
uuid = "38540f10-b2f7-11e9-35d8-d573e4eb0ff2"
version = "0.2.4"
[[deps.CommonSubexpressions]]
deps = ["MacroTools"]
git-tree-sha1 = "cda2cfaebb4be89c9084adaca7dd7333369715c5"
uuid = "bbf7d656-a473-5ed7-a52c-81e309532950"
version = "0.3.1"
[[deps.CommonWorldInvalidations]]
git-tree-sha1 = "ae52d1c52048455e85a387fbee9be553ec2b68d0"
uuid = "f70d9fcc-98c5-4d4a-abd7-e4cdeebd8ca8"
version = "1.0.0"
[[deps.Compat]]
deps = ["TOML", "UUIDs"]
git-tree-sha1 = "8ae8d32e09f0dcf42a36b90d4e17f5dd2e4c4215"
uuid = "34da2185-b29b-5c13-b0c7-acf172513d20"
version = "4.16.0"
weakdeps = ["Dates", "LinearAlgebra"]
[deps.Compat.extensions]
CompatLinearAlgebraExt = "LinearAlgebra"
[[deps.CompilerSupportLibraries_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "e66e0078-7015-5450-92f7-15fbd957f2ae"
version = "1.1.1+0"
[[deps.CompositeTypes]]
git-tree-sha1 = "bce26c3dab336582805503bed209faab1c279768"
uuid = "b152e2b5-7a66-4b01-a709-34e65c35f657"
version = "0.1.4"
[[deps.CompositionsBase]]
git-tree-sha1 = "802bb88cd69dfd1509f6670416bd4434015693ad"
uuid = "a33af91c-f02d-484b-be07-31d278c5ca2b"
version = "0.1.2"
weakdeps = ["InverseFunctions"]
[deps.CompositionsBase.extensions]
CompositionsBaseInverseFunctionsExt = "InverseFunctions"
[[deps.ConcurrentUtilities]]
deps = ["Serialization", "Sockets"]
git-tree-sha1 = "ea32b83ca4fefa1768dc84e504cc0a94fb1ab8d1"
uuid = "f0e56b4a-5159-44fe-b623-3e5288b988bb"
version = "2.4.2"
[[deps.ConsoleProgressMonitor]]
deps = ["Logging", "ProgressMeter"]
git-tree-sha1 = "3ab7b2136722890b9af903859afcf457fa3059e8"
uuid = "88cd18e8-d9cc-4ea6-8889-5259c0d15c8b"
version = "0.1.2"
[[deps.ConstructionBase]]
git-tree-sha1 = "76219f1ed5771adbb096743bff43fb5fdd4c1157"
uuid = "187b0558-2788-49d3-abe0-74a17ed4e7c9"
version = "1.5.8"
weakdeps = ["IntervalSets", "LinearAlgebra", "StaticArrays"]
[deps.ConstructionBase.extensions]
ConstructionBaseIntervalSetsExt = "IntervalSets"
ConstructionBaseLinearAlgebraExt = "LinearAlgebra"
ConstructionBaseStaticArraysExt = "StaticArrays"
[[deps.Contour]]
git-tree-sha1 = "439e35b0b36e2e5881738abc8857bd92ad6ff9a8"
uuid = "d38c429a-6771-53c6-b99e-75d170b6e991"
version = "0.6.3"
[[deps.Crayons]]
git-tree-sha1 = "249fe38abf76d48563e2f4556bebd215aa317e15"
uuid = "a8cc5b0e-0ffa-5ad4-8c14-923d3ee1735f"
version = "4.1.1"
[[deps.DSP]]
deps = ["Compat", "FFTW", "IterTools", "LinearAlgebra", "Polynomials", "Random", "Reexport", "SpecialFunctions", "Statistics"]
git-tree-sha1 = "0df00546373af8eee1598fb4b2ba480b1ebe895c"
uuid = "717857b8-e6f2-59f4-9121-6e50c889abd2"
version = "0.7.10"
[[deps.DataAPI]]
git-tree-sha1 = "abe83f3a2f1b857aac70ef8b269080af17764bbe"
uuid = "9a962f9c-6df0-11e9-0e5d-c546b8b5ee8a"
version = "1.16.0"
[[deps.DataFrames]]
deps = ["Compat", "DataAPI", "DataStructures", "Future", "InlineStrings", "InvertedIndices", "IteratorInterfaceExtensions", "LinearAlgebra", "Markdown", "Missings", "PooledArrays", "PrecompileTools", "PrettyTables", "Printf", "Random", "Reexport", "SentinelArrays", "SortingAlgorithms", "Statistics", "TableTraits", "Tables", "Unicode"]
git-tree-sha1 = "fb61b4812c49343d7ef0b533ba982c46021938a6"
uuid = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
version = "1.7.0"
[[deps.DataStructures]]
deps = ["Compat", "InteractiveUtils", "OrderedCollections"]
git-tree-sha1 = "1d0a14036acb104d9e89698bd408f63ab58cdc82"
uuid = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
version = "0.18.20"
[[deps.DataValueInterfaces]]
git-tree-sha1 = "bfc1187b79289637fa0ef6d4436ebdfe6905cbd6"
uuid = "e2d170a0-9d28-54be-80f0-106bbe20a464"
version = "1.0.0"
[[deps.Dates]]
deps = ["Printf"]
uuid = "ade2ca70-3891-5945-98fb-dc099432e06a"
version = "1.11.0"
[[deps.Dbus_jll]]
deps = ["Artifacts", "Expat_jll", "JLLWrappers", "Libdl"]
git-tree-sha1 = "fc173b380865f70627d7dd1190dc2fce6cc105af"
uuid = "ee1fde0b-3d02-5ea6-8484-8dfef6360eab"
version = "1.14.10+0"
[[deps.DefineSingletons]]
git-tree-sha1 = "0fba8b706d0178b4dc7fd44a96a92382c9065c2c"
uuid = "244e2a9f-e319-4986-a169-4d1fe445cd52"
version = "0.1.2"