-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsearch.json
More file actions
1129 lines (1129 loc) · 530 KB
/
search.json
File metadata and controls
1129 lines (1129 loc) · 530 KB
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
[
{
"objectID": "tempfiles/bme423-ejercicios.html",
"href": "tempfiles/bme423-ejercicios.html",
"title": "BME423 - Ejercicios",
"section": "",
"text": "En el siguiente enlace encontrará una guía de ejercicios 🖥️"
},
{
"objectID": "tempfiles/bme423-planificacion.html",
"href": "tempfiles/bme423-planificacion.html",
"title": "BME423 - Planificación y material de clases",
"section": "",
"text": "Tipo\nFecha\nTópico\nMaterial\nLab\nMICB\nDCIS\n\n\n\n\nCátedra\n14-08\nIntroducciónDefiniciones\n\n\n\n\n\n\nLab\n20-08\n\n\nLab 1 📖\nLab 1\nLab 1\n\n\nCátedra\n21-08\nOperaciones puntuales y en histogramasRuido / degradaciónFiltros espaciales\nEjemplo convolución\n\n\n\n\n\nLab\n27-08\n\n\n\n\n\n\n\nCátedra\n28-08\nFiltros mediante PDE\n🖥️ - difusión lineal\n\nEntrega de temas de proyecto\nEntrega de temas de proyecto\n\n\nLab\n03-09\n\n\n\n\n\n\n\nCátedra\n04-09\nClase suspendida\n\n\n\n\n\n\nLab\n10-09\n\n\nLab 2\nLab 2\nLab 2\n\n\nCátedra\n11-09\nFourier\n\n\n\n\n\n\nLab\n17-09\nFiestas patrias\n\n\n\n\n\n\nCátedra\n18-09\nFiestas patrias\n\n\n\n\n\n\nLab\n24-09\n\n\n\n\n\n\n\nCátedra\n25-09\n\n\n\n\n\n\n\nLab\n01-10\n\n\nLab 3\nLab 3\nLab 3\n\n\nCátedra\n02-10\nPrueba 1\n\n\nPresentación avance\nPresentación avance\n\n\nLab\n08-10\n\n\n\n\n\n\n\nCátedra\n09-10\nTransformaciones geométricas\n🖥️\n\n\n\n\n\nLab\n15-10\nPausa\n\n\n\n\n\n\nCátedra\n16-10\nPausa\n\n\n\n\n\n\nLab\n22-10\n\n\n\n\n\n\n\nCátedra\n23-10\nSegmentación I\n🖥️\n\n\n\n\n\nLab\n29-10\n\n\nLab 4\nLab 4\nLab 4\n\n\nCátedra\n30-10\nSegmentación I\n\n\n\n\n\n\nLab\n05-11\n\n\n\n\n\n\n\nCátedra\n06-11\nMorfología matemática\n🖥️🖥️🖥️\n\n\n\n\n\nLab\n12-11\n\n\n\n\n\n\n\nCátedra\n13-11\nPrueba 2\n\n\nPresentación avance\nPresentación avance\n\n\nLab\n19-11\n\n\nLab 5\nLab 5\nLab 5\n\n\nCátedra\n20-11\nIA en procesamiento de imágenes\nslides FANNslides CNN-1slides CNN-2slides repr🖥️ - conv🖥️ - modelos preentrenados🖥️ - arquitecturas🖥️ - fully convolutional🖥️ - object localization\n\n\n\n\n\nLab\n26-11\n\n\n\n\n\n\n\nCátedra\n27-11\nSegmentación II\n\n\n\n\n\n\nLab\n03-12\n\n\n\n\n\n\n\nCátedra\n04-12\nReconstrucciónReconstrucción a partir de proyecciones\n🖥️🖥️\n\nEntrega proyecto\nEntrega proyecto\n\n\nLab\n10-12\n\n\n\n\n\n\n\nCátedra\n11-12\nPrueba 3\n\n\nPrueba\nPrueba\n\n\nLab\n17-12\nPruebas extraordinarias\n\n\n\n\n\n\nCátedra\n18-12\nPruebas extraordinarias"
},
{
"objectID": "inf398/index.html",
"href": "inf398/index.html",
"title": "INF398 - Introducción al aprendizaje automático",
"section": "",
"text": "Descripción. Este curso aborda los fundamentos teóricos y prácticos del aprendizaje automático para el diseño de sistemas capaces de aprender a partir de datos. Los y las estudiantes aplican técnicas modernas de clasificación y regresión a problemas reales en ciencia e ingeniería, seleccionando herramientas adecuadas y siguiendo buenas prácticas en el desarrollo de soluciones basadas en datos."
},
{
"objectID": "inf398/index.html#tareas",
"href": "inf398/index.html#tareas",
"title": "INF398 - Introducción al aprendizaje automático",
"section": "Tareas",
"text": "Tareas\n\nTarea 1. Modelos lineales, regularización.\nTarea 2. Redes neuronales.\nTarea 3. Procesos gaussianos y métodos basados en kernels.\nTarea 4. Métodos basados en árboles y ensamblados.\nTarea 5. Modelos en grafos y neurodifusos.\nTarea 6. Aprendizaje no supervisado."
},
{
"objectID": "inf398/index.html#integridad-académica",
"href": "inf398/index.html#integridad-académica",
"title": "INF398 - Introducción al aprendizaje automático",
"section": "Integridad Académica",
"text": "Integridad Académica\nSe espera que los estudiantes actúen con honestidad e integridad. No mentir, hacer trampa ni plagiar en trabajos académicos o no académicos. Todo trabajo presentado debe ser propio, a menos que se permita expresamente la colaboración. Debe citar adecuadamente todas las fuentes utilizadas, incluyendo código tomado de recursos en línea. El material no citado o mal referenciado puede considerarse plagio."
},
{
"objectID": "inf398/index.html#uso-de-herramientas-de-inteligencia-artificial-ia",
"href": "inf398/index.html#uso-de-herramientas-de-inteligencia-artificial-ia",
"title": "INF398 - Introducción al aprendizaje automático",
"section": "Uso de Herramientas de Inteligencia Artificial (IA)",
"text": "Uso de Herramientas de Inteligencia Artificial (IA)\nEl uso de herramientas de Inteligencia Artificial no está prohibido (¡broma!). De hecho, su utilización está permitida y fomentada. Sin embargo, es importante declarar de forma explícita cuándo y cómo se emplean estas herramientas en las tareas y trabajos del curso, especificando qué contenidos o códigos fueron generados mediante IA. Se requiere total transparencia para asegurar la integridad académica: omitir esta información puede considerarse una falta a las políticas del curso."
},
{
"objectID": "inf398/index.html#colaboración",
"href": "inf398/index.html#colaboración",
"title": "INF398 - Introducción al aprendizaje automático",
"section": "Colaboración",
"text": "Colaboración\nSalvo que expresamente se indique trabajo en grupo, todas las tareas deben realizarse de forma individual. Se permite la discusión general con compañeros, pero no compartir respuestas detalladas ni código. Para proyectos en equipo, debe colaborar únicamente dentro de su grupo."
},
{
"objectID": "inf398/index.html#uso-de-código-y-recursos-online",
"href": "inf398/index.html#uso-de-código-y-recursos-online",
"title": "INF398 - Introducción al aprendizaje automático",
"section": "Uso de código y recursos online",
"text": "Uso de código y recursos online\nPuede consultar y utilizar recursos en línea. Todo código o material tomado de fuentes externas debe ser citado correctamente."
},
{
"objectID": "inf398/index.html#entregas-tardias",
"href": "inf398/index.html#entregas-tardias",
"title": "INF398 - Introducción al aprendizaje automático",
"section": "Entregas tardías",
"text": "Entregas tardías\nDispone de un total de 4 días de retraso que puede utilizar a gusto a lo largo del semestre en cualquiera de las evaluaciones del curso. Los días de retraso le permiten entregar laboratorios, tareas sin penalización. Retrasos superiores a 12 horas, se consideran como un día completo de retraso. Considere hacer uso de este beneficio en situaciones significativas o imprevistas. Si tiene problemas a largo plazo que afecten tu desempeño, se recomienda informar al profesor o jefe de carrera."
},
{
"objectID": "inf398/index.html#recalificaciones",
"href": "inf398/index.html#recalificaciones",
"title": "INF398 - Introducción al aprendizaje automático",
"section": "Recalificaciones",
"text": "Recalificaciones\nLas solicitudes de revisión deben hacerse dentro de la semana posterior a la devolución de la calificación. Solo se considerarán solicitudes fundamentadas en base a la rúbrica proporcionada. Toda la pregunta será revisada nuevamente, lo que puede implicar aumento o disminución de puntos."
},
{
"objectID": "bme321/bme321.html",
"href": "bme321/bme321.html",
"title": "BME321 - Mediciones Biomédicas",
"section": "",
"text": "Bienvenidos al sitio web del curso BME321 Mediciones Biomédicas. En este sitio encontrarás la información y el material relacionado con el desarrollo del curso. Puedes comunicarte con el profesor al correo alejandro.veloz@uv.cl."
},
{
"objectID": "bme321/bme321.html#objetivos",
"href": "bme321/bme321.html#objetivos",
"title": "BME321 - Mediciones Biomédicas",
"section": "Objetivos",
"text": "Objetivos\nAl finalizar el semestre, será capaz de:\n\nComprender y aplicar los conceptos fundamentales relacionados con sensores biomédicos y mediciones biomédicas.\nComprender principios de bioinstrumentación relacionados con las mediciones biomédicas.\nComprender bloques funcionales de todo instrumento de medición biomédica.\nAnalizar e interpretar parámetros y especificaciones técnicas necesarias en aplicaciones de mediciones biomédicas."
},
{
"objectID": "bme321/bme321.html#fechas-de-pruebas",
"href": "bme321/bme321.html#fechas-de-pruebas",
"title": "BME321 - Mediciones Biomédicas",
"section": "Fechas de pruebas",
"text": "Fechas de pruebas\n\n03-10. Prueba 1.\n14-11. Prueba 2.\n12-12. Prueba 3."
},
{
"objectID": "bme321/bme321.html#clases-y-laboratorios",
"href": "bme321/bme321.html#clases-y-laboratorios",
"title": "BME321 - Mediciones Biomédicas",
"section": "Clases y laboratorios",
"text": "Clases y laboratorios\n\n\n\n\n\n\n\n\n\n\nDía\nHora\nLugar\n\n\n\n\nCátedra\nViernes\n08:30 - 11:45\n212 (Hucke)\n\n\nLab\nLunes\n10:15 - 13:30\nLab. Electrom."
},
{
"objectID": "bme321/bme321.html#material",
"href": "bme321/bme321.html#material",
"title": "BME321 - Mediciones Biomédicas",
"section": "Material",
"text": "Material\nSistemas de medición Parámetros Transductores Transductores resistivos, ejemplo Transductores capacitivos y piezoeléctricos Transductores inductivos Transductores térmicos Transductores de radiación Aplicación - fotopletismografía Aplicación - oximetría Aplicación - sistema circulatorio y respiratorio Biopotenciales"
},
{
"objectID": "bme321/bme321.html#políticas-del-curso",
"href": "bme321/bme321.html#políticas-del-curso",
"title": "BME321 - Mediciones Biomédicas",
"section": "Políticas del Curso",
"text": "Políticas del Curso\n\nIntegridad Académica\nSe espera que los estudiantes actúen con honestidad e integridad. No mentir, hacer trampa ni plagiar en trabajos académicos o no académicos. Todo trabajo presentado debe ser propio, a menos que se permita expresamente la colaboración. Debe citar adecuadamente todas las fuentes utilizadas. El material no citado o mal referenciado puede considerarse plagio.\n\n\nRecalificaciones\nLas solicitudes de revisión deben hacerse dentro de la semana posterior a la devolución de la calificación. Solo se considerarán solicitudes fundamentadas en base a la rúbrica proporcionada. Toda la pregunta será revisada nuevamente, lo que puede implicar aumento o disminución de puntos."
},
{
"objectID": "bme513/ejemplos/gp01-regression-pytorch.html",
"href": "bme513/ejemplos/gp01-regression-pytorch.html",
"title": "Basic GP Regression (Pytorch and GPyTorch)",
"section": "",
"text": "This notebook shows how to do Gaussian process regression:\n\ndefine a GP prior, 2) learn kernel hyperparameters by marginal likelihood,\nmake predictions, and 4) repeat the same using GPyTorch.\n\n\n!pip install \"gpytorch\"\n\n\nimport math\nimport os\nimport gpytorch\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport torch\nfrom scipy import optimize\nfrom scipy.spatial import distance_matrix\n\nplt.rcParams[\"figure.figsize\"] = (4, 3)\n\n# simple RBF kernel (squared‑exponential)\ndef rbf_kernel(X, Y, ls=1.0, amp=1.0):\n X = np.atleast_2d(X).reshape(-1, 1)\n Y = np.atleast_2d(Y).reshape(-1, 1)\n d2 = distance_matrix(X, Y) ** 2\n return amp**2 * np.exp(-0.5 * d2 / ls**2)\n\nGaussian Process Regression\nWe observe noisy data y(x) = f(x) + ε with ε ~ N(0, σ²).\nA GP prior f(x) ~ GP(0, k) with RBF kernel defines a distribution over functions.\nFor regression, the posterior over f and the predictive distribution are available in closed form.\nSynthetic data\n\ndef data_maker1(x, sig):\n x = np.asarray(x)\n return np.sin(x) + 0.5 * np.sin(4 * x) + np.random.randn(*x.shape) * sig\n\nsig = 0.25\ntrain_x = np.linspace(0, 5, 50)\ntest_x = np.linspace(0, 5, 500)\ntrain_y = data_maker1(train_x, sig=sig)\ntest_y = data_maker1(test_x, sig=0.0)\n\nplt.scatter(train_x, train_y)\nplt.plot(test_x, test_y)\nplt.xlabel(\"x\")\nplt.ylabel(\"Observations y\")\nplt.show()\n\n\n\n\n\n\n\n\nCircles are noisy observations, the blue curve is the underlying noise‑free function.\nPrior GP samples\n\nmean = np.zeros_like(test_x)\ncov = rbf_kernel(test_x, test_x, ls=0.2)\n\nprior_samples = np.random.multivariate_normal(mean=mean, cov=cov, size=5)\nplt.plot(test_x, prior_samples.T, color=\"black\", alpha=0.5)\nplt.plot(test_x, mean, linewidth=2.)\nstd = np.sqrt(np.diag(cov))\nplt.fill_between(test_x, mean - 2 * std, mean + 2 * std, alpha=0.25)\nplt.show()\n\n\n\n\n\n\n\n\nShort length‑scale gives very wiggly sample functions.\nHyperparameter learning (from scratch)\n\nell_est = 0.4\npost_sig_est = 0.5\n\ndef neg_MLL(pars):\n ell, noise = pars\n K = rbf_kernel(train_x, train_x, ls=ell)\n Ky = K + noise**2 * np.eye(*train_x.shape)\n L = np.linalg.cholesky(Ky)\n alpha = np.linalg.solve(L.T, np.linalg.solve(L, train_y))\n kernel_term = -0.5 * train_y @ alpha\n logdet = -np.sum(np.log(np.diag(L)))\n const = -0.5 * train_x.shape[0] * np.log(2 * np.pi)\n return -(kernel_term + logdet + const)\n\nres = optimize.minimize(\n neg_MLL,\n x0=np.array([ell_est, post_sig_est]),\n bounds=((0.01, 10.), (0.01, 10.))\n)\nell, post_sig_est = res.x\n\nprint(\"Learned length‑scale:\", ell)\nprint(\"Learned noise std:\", post_sig_est)\n\nLearned length‑scale: 0.5780687474139707\nLearned noise std: 0.22470850523850983\n\n\nNow we compute the posterior mean and covariance at test points.\n\nK_x_x = rbf_kernel(train_x, train_x, ls=ell)\nK_x_xstar = rbf_kernel(train_x, test_x, ls=ell)\nK_xstar_xstar = rbf_kernel(test_x, test_x, ls=ell)\n\nKy = K_x_x + post_sig_est**2 * np.eye(*train_x.shape)\nL = np.linalg.cholesky(Ky)\nalpha = np.linalg.solve(L.T, np.linalg.solve(L, train_y))\n\npost_mean = K_x_xstar.T @ alpha\nv = np.linalg.solve(L, K_x_xstar)\npost_cov = K_xstar_xstar - v.T @ v\n\npost_std = np.sqrt(np.diag(post_cov))\nlw_bd = post_mean - 2 * post_std\nup_bd = post_mean + 2 * post_std\n\nplt.scatter(train_x, train_y)\nplt.plot(test_x, test_y, linewidth=2.)\nplt.plot(test_x, post_mean, linewidth=2.)\nplt.fill_between(test_x, lw_bd, up_bd, alpha=0.25)\nplt.legend([\"True Function\", \"Predictive Mean\", \"Observed Data\", \"95% set (latent)\"])\nplt.show()\n\n\n\n\n\n\n\n\nThe posterior mean closely follows the true function.\nThe shaded band is a 95% credible set for the latent noise‑free function f(x).\nTo include observation noise in the band, add σ² on the diagonal:\n\nlw_bd_obs = post_mean - 2 * np.sqrt(post_std**2 + post_sig_est**2)\nup_bd_obs = post_mean + 2 * np.sqrt(post_std**2 + post_sig_est**2)\n\nPosterior samples\n\npost_samples = np.random.multivariate_normal(post_mean, post_cov, size=20)\nplt.scatter(train_x, train_y)\nplt.plot(test_x, test_y, linewidth=2.)\nplt.plot(test_x, post_mean, linewidth=2.)\nplt.plot(test_x, post_samples.T, color=\"gray\", alpha=0.25)\nplt.fill_between(test_x, lw_bd, up_bd, alpha=0.25)\nplt.legend([\"True Function\", \"Predictive Mean\", \"Observed Data\", \"Posterior Samples\"])\nplt.show()\n\n\n\n\n\n\n\n\nNext we reproduce the same regression using GPyTorch.\nGPyTorch implementation\n\ntrain_x_t = torch.tensor(train_x, dtype=torch.float32)\ntrain_y_t = torch.tensor(train_y, dtype=torch.float32)\ntest_x_t = torch.tensor(test_x, dtype=torch.float32)\ntest_y_t = torch.tensor(test_y, dtype=torch.float32)\n\nclass ExactGPModel(gpytorch.models.ExactGP):\n def __init__(self, train_x, train_y, likelihood):\n super().__init__(train_x, train_y, likelihood)\n self.mean_module = gpytorch.means.ZeroMean()\n self.covar_module = gpytorch.kernels.ScaleKernel(\n gpytorch.kernels.RBFKernel()\n )\n\n def forward(self, x):\n mean_x = self.mean_module(x)\n covar_x = self.covar_module(x)\n return gpytorch.distributions.MultivariateNormal(mean_x, covar_x)\n\nlikelihood = gpytorch.likelihoods.GaussianLikelihood()\nmodel = ExactGPModel(train_x_t, train_y_t, likelihood)\n\ntraining_iter = 50\nmodel.train()\nlikelihood.train()\noptimizer = torch.optim.Adam(model.parameters(), lr=0.1)\nmll = gpytorch.mlls.ExactMarginalLogLikelihood(likelihood, model)\n\nfor i in range(training_iter):\n optimizer.zero_grad()\n output = model(train_x_t)\n loss = -mll(output, train_y_t)\n loss.backward()\n if i % 10 == 0:\n print(\n f\"Iter {i+1:d}/{training_iter:d} - Loss: {loss.item():.3f} \"\n f\"squared lengthscale: \"\n f\"{model.covar_module.base_kernel.lengthscale.item():.3f} \"\n f\"noise variance: {model.likelihood.noise.item():.3f}\"\n )\n optimizer.step()\n\nIter 1/50 - Loss: 0.983 squared lengthscale: 0.693 noise variance: 0.693\nIter 11/50 - Loss: 0.695 squared lengthscale: 0.522 noise variance: 0.313\nIter 21/50 - Loss: 0.429 squared lengthscale: 0.549 noise variance: 0.127\nIter 31/50 - Loss: 0.304 squared lengthscale: 0.541 noise variance: 0.055\nIter 41/50 - Loss: 0.319 squared lengthscale: 0.545 noise variance: 0.038\n\n\n\nmodel.eval()\nlikelihood.eval()\nwith torch.no_grad():\n observed_pred = likelihood(model(test_x_t))\n lower, upper = observed_pred.confidence_region()\n f, ax = plt.subplots(1, 1, figsize=(4, 3))\n ax.scatter(train_x_t.numpy(), train_y_t.numpy())\n ax.plot(test_x_t.numpy(), test_y_t.numpy(), linewidth=2.)\n ax.plot(test_x_t.numpy(), observed_pred.mean.numpy(), linewidth=2.)\n ax.fill_between(test_x_t.numpy(), lower.numpy(), upper.numpy(), alpha=0.25)\n ax.set_ylim([-1.5, 1.5])\n ax.legend([\"True Function\", \"Predictive Mean\", \"Observed Data\",\n \"95% credible set (observations)\"])\n\n\n\n\n\n\n\n\nThe GPyTorch model recovers almost the same fit.\nHere the band is a 95% credible set for noisy observations (latent plus noise)."
},
{
"objectID": "bme513/ejemplos/gp02-example-noiseest-sklearn.html",
"href": "bme513/ejemplos/gp02-example-noiseest-sklearn.html",
"title": "Ability of Gaussian process regression (GPR) to estimate data noise-level",
"section": "",
"text": "Taken from sklearn\nThis example shows the ability of the :class:~sklearn.gaussian_process.kernels.WhiteKernel to estimate the noise level in the data. Moreover, we show the importance of kernel hyperparameters initialization."
},
{
"objectID": "bme513/ejemplos/gp02-example-noiseest-sklearn.html#data-generation",
"href": "bme513/ejemplos/gp02-example-noiseest-sklearn.html#data-generation",
"title": "Ability of Gaussian process regression (GPR) to estimate data noise-level",
"section": "Data generation",
"text": "Data generation\nWe will work in a setting where X will contain a single feature. We create a function that will generate the target to be predicted. We will add an option to add some noise to the generated target.\n\nimport numpy as np\n\n\ndef target_generator(X, add_noise=False):\n target = 0.5 + np.sin(3 * X)\n if add_noise:\n rng = np.random.RandomState(1)\n target += rng.normal(0, 0.3, size=target.shape)\n return target.squeeze()\n\nLet’s have a look to the target generator where we will not add any noise to observe the signal that we would like to predict.\n\nX = np.linspace(0, 5, num=80).reshape(-1, 1)\ny = target_generator(X, add_noise=False)\n\n\nimport matplotlib.pyplot as plt\n\nplt.plot(X, y, label=\"Expected signal\")\nplt.legend()\nplt.xlabel(\"X\")\n_ = plt.ylabel(\"y\")\n\n\n\n\n\n\n\n\nThe target is transforming the input X using a sine function. Now, we will generate few noisy training samples. To illustrate the noise level, we will plot the true signal together with the noisy training samples.\n\nrng = np.random.RandomState(0)\nX_train = rng.uniform(0, 5, size=20).reshape(-1, 1)\ny_train = target_generator(X_train, add_noise=True)\n\n\nplt.plot(X, y, label=\"Expected signal\")\nplt.scatter(\n x=X_train[:, 0],\n y=y_train,\n color=\"black\",\n alpha=0.4,\n label=\"Observations\",\n)\nplt.legend()\nplt.xlabel(\"X\")\n_ = plt.ylabel(\"y\")"
},
{
"objectID": "bme513/ejemplos/gp02-example-noiseest-sklearn.html#optimisation-of-kernel-hyperparameters-in-gpr",
"href": "bme513/ejemplos/gp02-example-noiseest-sklearn.html#optimisation-of-kernel-hyperparameters-in-gpr",
"title": "Ability of Gaussian process regression (GPR) to estimate data noise-level",
"section": "Optimisation of kernel hyperparameters in GPR",
"text": "Optimisation of kernel hyperparameters in GPR\nNow, we will create a :class:~sklearn.gaussian_process.GaussianProcessRegressor using an additive kernel adding a :class:~sklearn.gaussian_process.kernels.RBF and :class:~sklearn.gaussian_process.kernels.WhiteKernel kernels. The :class:~sklearn.gaussian_process.kernels.WhiteKernel is a kernel that will able to estimate the amount of noise present in the data while the :class:~sklearn.gaussian_process.kernels.RBF will serve at fitting the non-linearity between the data and the target.\nHowever, we will show that the hyperparameter space contains several local minima. It will highlights the importance of initial hyperparameter values.\nWe will create a model using a kernel with a high noise level and a large length scale, which will explain all variations in the data by noise.\n\nfrom sklearn.gaussian_process import GaussianProcessRegressor\nfrom sklearn.gaussian_process.kernels import RBF, WhiteKernel\n\nkernel = 1.0 * RBF(length_scale=1e1, length_scale_bounds=(1e-2, 1e3)) + WhiteKernel(\n noise_level=1, noise_level_bounds=(1e-10, 1e1)\n)\ngpr = GaussianProcessRegressor(kernel=kernel, alpha=0.0)\ngpr.fit(X_train, y_train)\ny_mean, y_std = gpr.predict(X, return_std=True)\n\n/Users/aveloz/miniconda3/lib/python3.9/site-packages/sklearn/gaussian_process/kernels.py:452: ConvergenceWarning: The optimal value found for dimension 0 of parameter k1__k2__length_scale is close to the specified upper bound 1000.0. Increasing the bound and calling fit again may find a better value.\n warnings.warn(\n\n\n\nplt.plot(X, y, label=\"Expected signal\")\nplt.scatter(x=X_train[:, 0], y=y_train, color=\"black\", alpha=0.4, label=\"Observations\")\nplt.errorbar(X, y_mean, y_std, label=\"Posterior mean ± std\")\nplt.legend()\nplt.xlabel(\"X\")\nplt.ylabel(\"y\")\n_ = plt.title(\n (\n f\"Initial: {kernel}\\nOptimum: {gpr.kernel_}\\nLog-Marginal-Likelihood: \"\n f\"{gpr.log_marginal_likelihood(gpr.kernel_.theta)}\"\n ),\n fontsize=8,\n)\n\n\n\n\n\n\n\n\nWe see that the optimum kernel found still has a high noise level and an even larger length scale. The length scale reaches the maximum bound that we allowed for this parameter and we got a warning as a result.\nMore importantly, we observe that the model does not provide useful predictions: the mean prediction seems to be constant: it does not follow the expected noise-free signal.\nNow, we will initialize the :class:~sklearn.gaussian_process.kernels.RBF with a larger length_scale initial value and the :class:~sklearn.gaussian_process.kernels.WhiteKernel with a smaller initial noise level lower while keeping the parameter bounds unchanged.\n\nkernel = 1.0 * RBF(length_scale=1e-1, length_scale_bounds=(1e-2, 1e3)) + WhiteKernel(\n noise_level=1e-2, noise_level_bounds=(1e-10, 1e1)\n)\ngpr = GaussianProcessRegressor(kernel=kernel, alpha=0.0)\ngpr.fit(X_train, y_train)\ny_mean, y_std = gpr.predict(X, return_std=True)\n\n\nplt.plot(X, y, label=\"Expected signal\")\nplt.scatter(x=X_train[:, 0], y=y_train, color=\"black\", alpha=0.4, label=\"Observations\")\nplt.errorbar(X, y_mean, y_std, label=\"Posterior mean ± std\")\nplt.legend()\nplt.xlabel(\"X\")\nplt.ylabel(\"y\")\n_ = plt.title(\n (\n f\"Initial: {kernel}\\nOptimum: {gpr.kernel_}\\nLog-Marginal-Likelihood: \"\n f\"{gpr.log_marginal_likelihood(gpr.kernel_.theta)}\"\n ),\n fontsize=8,\n)\n\n\n\n\n\n\n\n\nFirst, we see that the model’s predictions are more precise than the previous model’s: this new model is able to estimate the noise-free functional relationship.\nLooking at the kernel hyperparameters, we see that the best combination found has a smaller noise level and shorter length scale than the first model.\nWe can inspect the negative Log-Marginal-Likelihood (LML) of :class:~sklearn.gaussian_process.GaussianProcessRegressor for different hyperparameters to get a sense of the local minima.\n\nfrom matplotlib.colors import LogNorm\n\nlength_scale = np.logspace(-2, 4, num=80)\nnoise_level = np.logspace(-2, 1, num=80)\nlength_scale_grid, noise_level_grid = np.meshgrid(length_scale, noise_level)\n\nlog_marginal_likelihood = [\n gpr.log_marginal_likelihood(theta=np.log([0.36, scale, noise]))\n for scale, noise in zip(length_scale_grid.ravel(), noise_level_grid.ravel())\n]\nlog_marginal_likelihood = np.reshape(log_marginal_likelihood, noise_level_grid.shape)\n\n\nvmin, vmax = (-log_marginal_likelihood).min(), 50\nlevel = np.around(np.logspace(np.log10(vmin), np.log10(vmax), num=20), decimals=1)\nplt.contour(\n length_scale_grid,\n noise_level_grid,\n -log_marginal_likelihood,\n levels=level,\n norm=LogNorm(vmin=vmin, vmax=vmax),\n)\nplt.colorbar()\nplt.xscale(\"log\")\nplt.yscale(\"log\")\nplt.xlabel(\"Length-scale\")\nplt.ylabel(\"Noise-level\")\nplt.title(\"Negative log-marginal-likelihood\")\nplt.show()\n\n\n\n\n\n\n\n\nWe see that there are two local minima that correspond to the combination of hyperparameters previously found. Depending on the initial values for the hyperparameters, the gradient-based optimization might or might not converge to the best model. It is thus important to repeat the optimization several times for different initializations. This can be done by setting the n_restarts_optimizer parameter of the :class:~sklearn.gaussian_process.GaussianProcessRegressor class.\nLet’s try again to fit our model with the bad initial values but this time with 10 random restarts.\n\nkernel = 1.0 * RBF(length_scale=1e1, length_scale_bounds=(1e-2, 1e3)) + WhiteKernel(\n noise_level=1, noise_level_bounds=(1e-10, 1e1)\n)\ngpr = GaussianProcessRegressor(\n kernel=kernel, alpha=0.0, n_restarts_optimizer=10, random_state=0\n)\ngpr.fit(X_train, y_train)\ny_mean, y_std = gpr.predict(X, return_std=True)\n\n\nplt.plot(X, y, label=\"Expected signal\")\nplt.scatter(x=X_train[:, 0], y=y_train, color=\"black\", alpha=0.4, label=\"Observations\")\nplt.errorbar(X, y_mean, y_std, label=\"Posterior mean ± std\")\nplt.legend()\nplt.xlabel(\"X\")\nplt.ylabel(\"y\")\n_ = plt.title(\n (\n f\"Initial: {kernel}\\nOptimum: {gpr.kernel_}\\nLog-Marginal-Likelihood: \"\n f\"{gpr.log_marginal_likelihood(gpr.kernel_.theta)}\"\n ),\n fontsize=8,\n)\n\n\n\n\n\n\n\n\nAs we hoped, random restarts allow the optimization to find the best set of hyperparameters despite the bad initial values."
},
{
"objectID": "bme513/ejemplos/gp03-sensors-network.html",
"href": "bme513/ejemplos/gp03-sensors-network.html",
"title": "Multi-output Gaussian Process (Sensor Network)",
"section": "",
"text": "import numpy as np\nimport matplotlib.pyplot as plt\nimport os\nimport pandas as pd\nimport mogptk\nimport torch\n\n\nplot_params = {'legend.fontsize': 18,\n 'figure.figsize': (15, 7),\n 'xtick.labelsize':'18',\n 'ytick.labelsize':'18',\n 'axes.titlesize':'24',\n 'axes.labelsize':'22'}\nplt.rcParams.update(plot_params)\n\n\nrng = np.random.default_rng(123)\n\nT = 500\nn_nodes = 5\n\nt = np.linspace(0, 10, T)\nt1_lost = np.linspace(4, 5, 100)\nX = np.zeros((T,n_nodes))\n\nX[:,0] = np.sin(t * (2 * np.pi)) + np.sin(t * (3 * np.pi))\nX[:,1] = np.sin((t-1) * (2 * np.pi)) + np.sin((t-1) * (3 * np.pi))\nX[:,2] = np.sin(t * (2 * np.pi)) + np.sin(t * (4 * np.pi))\nX[:,3] = np.sin((t-1) * (2 * np.pi)) + 0.5*np.sin((t-1) * (4 * np.pi))\nX[:,4] = 0.3*np.sin((t-1) * (2 * np.pi)) + 0.8*np.sin((t-1) * (8 * np.pi))\n\n\ntorch.manual_seed(1);\n\nT = 500\nn_nodes = 5\nt = np.linspace(0, 10, T)\nX = np.zeros((T, n_nodes))\nX[:, 0] = np.sin(t * (2 * np.pi)) + np.sin(t * (3 * np.pi))\nX[:, 1] = np.sin((t-1) * (2 * np.pi)) + np.sin((t-1) * (3 * np.pi))\nX[:, 2] = np.sin(t * (2 * np.pi)) + np.sin(t * (4 * np.pi))\nX[:, 3] = np.sin((t-1) * (2 * np.pi)) + 0.5*np.sin((t-1) * (4 * np.pi))\nX[:, 4] = 0.3*np.sin((t-1) * (2 * np.pi)) + 0.8*np.sin((t-1) * (8 * np.pi))\ncolumns = [f\"Node{i+1}\" for i in range(n_nodes)]\ndf_synth = pd.DataFrame(X, columns=columns)\ndf_synth['Time'] = t\ndf_synth = df_synth[['Time'] + columns]\ndataset = mogptk.LoadDataFrame(df_synth, x_col='Time', y_col=columns)\n\nfor channel in dataset:\n channel.remove_randomly(pct=0.4)\n\n# drop relative ranges to simulate sensor failure\ndataset[0].remove_relative_range(0.2, 0.3)\ndataset[1].remove_relative_range(0.8, 1.0)\ndataset[2].remove_relative_range(0.9, 1.0)\ndataset[3].remove_relative_range(0.8, 1.0)\ndataset[4].remove_relative_range(0.0, 0.2)\n\nchannels = []\nfor channel in dataset:\n channel.transform(mogptk.TransformDetrend(degree=1))\n channel.transform(mogptk.TransformStandard())\n channels.append(channel)\n\n# dataset.plot(transformed=True, figsize=(10,10));\nn_train = channels[0].get_train_data()[0].shape[0]\nn_test = channels[0].get_test_data()[0].shape[0]\nn_train+n_test\n\n500\n\n\n\noffset = 6.0\ny_offsets = np.arange(n_nodes) * offset\n\nfig, ax = plt.subplots(nrows=1, sharex=True, sharey=True)\nfor i in range(n_nodes):\n plt.plot(t, X[:,i] + y_offsets[i], alpha=0.4, color='r')\n\nax.set_yticks(y_offsets, [f\"node {i+1}\" for i in range(n_nodes)])\nax.spines['top'].set_visible(False)\nax.spines['right'].set_visible(False)\nax.invert_yaxis()\nax.set_xlim([0, 10])\nax.set_ylim([-5, 27])\nplt.xlabel(\"time\")\nplt.tight_layout()\n\nfig, ax = plt.subplots(nrows=1, sharex=True, sharey=True)\nfor i in range(n_nodes):\n plt.plot(t, X[:,i] + y_offsets[i], alpha=0.4, color='k')\n t_train, x_train = channels[i].get_train_data()\n plt.scatter(t_train, x_train + y_offsets[i], color='red')\n\nax.set_yticks(y_offsets, [f\"node {i+1}\" for i in range(n_nodes)])\nax.spines['top'].set_visible(False)\nax.spines['right'].set_visible(False)\nax.invert_yaxis()\nax.set_xlim([0, 10])\nax.set_ylim([-5, 27])\nplt.xlabel(\"time\")\nplt.tight_layout()\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nmodel = mogptk.MOSM(dataset, Q=3)\nmodel.init_parameters(method='BNSE')\n\nXt, Mu, Lower, Upper = model.predict()\n\nfig, ax = plt.subplots(nrows=1, sharex=True, sharey=True)\nfor i in range(n_nodes):\n plt.plot(Xt[i], Mu[i] + y_offsets[i], alpha=0.4, color='b')\n plt.fill_between( np.squeeze(Xt[i]), Lower[i] + y_offsets[i], Upper[i] + y_offsets[i], alpha=0.4, color='b' )\n plt.plot(t, X[:,i] + y_offsets[i], alpha=0.4, color='r')\n t_test, x_test = channels[i].get_test_data()\n plt.scatter(t_test, x_test + y_offsets[i], color='green')\n\nax.set_yticks(y_offsets, [f\"node {i+1}\" for i in range(n_nodes)])\nax.spines['top'].set_visible(False)\nax.spines['right'].set_visible(False)\nax.invert_yaxis()\nax.set_xlim([0, 10])\nax.set_ylim([-5, 27])\nplt.xlabel(\"time\")\nplt.tight_layout()\n\n\n\n\n\n\n\n\n\nmodel.train(method='Adam', lr=0.01, iters=1000, verbose=True);\n\nStarting optimization using Adam\n‣ Model: Exact\n ‣ Kernel: MultiOutputSpectralMixtureKernel\n ‣ Likelihood: GaussianLikelihood\n‣ Channels: 5\n‣ Parameters: 80\n‣ Training points: 1258\n‣ Iterations: 1000\n\n\n/Users/aveloz/miniconda3/lib/python3.9/site-packages/mogptk/model.py:384: UserWarning: Converting a tensor with requires_grad=True to a scalar may lead to unexpected behavior.\nConsider using tensor.detach() first. (Triggered internally at /Users/runner/work/pytorch/pytorch/pytorch/torch/csrc/autograd/generated/python_variable_methods.cpp:836.)\n return float(self.gpr.loss())\n\n\n 0/1000 0:00:00 loss= 1248.23 (warmup)\n 48/1000 0:00:10 loss= 1184.74\n 101/1000 0:00:20 loss= 1116.73\n 153/1000 0:00:30 loss= 1054.27\n 206/1000 0:00:40 loss= 988.854\n 258/1000 0:00:50 loss= 932.167\n 310/1000 0:01:00 loss= 862.731\n 360/1000 0:01:10 loss= 801.434\n 413/1000 0:01:20 loss= 738.048\n 465/1000 0:01:30 loss= 673.084\n 517/1000 0:01:40 loss= 615.362\n 566/1000 0:01:50 loss= 551.007\n 616/1000 0:02:00 loss= 487.771\n 667/1000 0:02:10 loss= 426.397\n 717/1000 0:02:20 loss= 363.946\n 764/1000 0:02:30 loss= 307.042\n 812/1000 0:02:40 loss= 271.866\n 863/1000 0:02:50 loss= 195.433\n 914/1000 0:03:00 loss= 142.252\n 965/1000 0:03:10 loss= 103.193\n 1000/1000 0:03:16 loss= 46.8325\nOptimization finished in 3 minutes 16 seconds\n\n\n\nXt, Mu, Lower, Upper = model.predict()\n\nfig, ax = plt.subplots(nrows=1, sharex=True, sharey=True)\nfor i in range(n_nodes):\n plt.plot(Xt[i], Mu[i] + y_offsets[i], alpha=0.4, color='b')\n plt.fill_between( np.squeeze(Xt[i]), Lower[i] + y_offsets[i], Upper[i] + y_offsets[i], alpha=0.4, color='b' )\n plt.plot(t, X[:,i] + y_offsets[i], alpha=0.4, color='r')\n t_test, x_test = channels[i].get_test_data()\n plt.scatter(t_test, x_test + y_offsets[i], color='green')\n\nax.set_yticks(y_offsets, [f\"node {i+1}\" for i in range(n_nodes)])\nax.spines['top'].set_visible(False)\nax.spines['right'].set_visible(False)\nax.invert_yaxis()\nax.set_xlim([0, 10])\nax.set_ylim([-5, 27])\nplt.xlabel(\"time\")\nplt.tight_layout()"
},
{
"objectID": "bme513/index.html",
"href": "bme513/index.html",
"title": "BME513 - Inteligencia Artificial para Salud",
"section": "",
"text": "Descripción. Este curso ofrece una introducción a los métodos de inteligencia artificial y aprendizaje automático aplicados a la salud e ingeniería biomédica. Se abordan técnicas de aprendizaje supervisado y no supervisado, redes neuronales profundas, modelos probabilísticos y causales, y aprendizaje por refuerzo. El curso enfatiza el análisis de datos médicos, sistemas de apoyo al diagnóstico, el procesamiento de lenguaje natural, señales e imágenes biomédicas y la toma de decisiones clínicas. También se presentan avances y aplicaciones recientes en medicina personalizada, salud digital e imagenología médica."
},
{
"objectID": "bme513/index.html#bibliografía-y-otros-recursos",
"href": "bme513/index.html#bibliografía-y-otros-recursos",
"title": "BME513 - Inteligencia Artificial para Salud",
"section": "Bibliografía y otros recursos",
"text": "Bibliografía y otros recursos\nAunque existen muchos recursos excelentes producidos por diversos investigadores en las últimas décadas, asignaremos lecturas de los siguientes libros:\n\nPattern Recognition and Machine Learning, Christopher Bishop (2006)."
},
{
"objectID": "bme513/index.html#integridad-académica",
"href": "bme513/index.html#integridad-académica",
"title": "BME513 - Inteligencia Artificial para Salud",
"section": "Integridad Académica",
"text": "Integridad Académica\nSe espera que los estudiantes actúen con honestidad e integridad. No mentir, hacer trampa ni plagiar en trabajos académicos o no académicos. Todo trabajo presentado debe ser propio, a menos que se permita expresamente la colaboración. Debe citar adecuadamente todas las fuentes utilizadas, incluyendo código tomado de recursos en línea. El material no citado o mal referenciado puede considerarse plagio."
},
{
"objectID": "bme513/index.html#uso-de-herramientas-de-inteligencia-artificial-ia",
"href": "bme513/index.html#uso-de-herramientas-de-inteligencia-artificial-ia",
"title": "BME513 - Inteligencia Artificial para Salud",
"section": "Uso de Herramientas de Inteligencia Artificial (IA)",
"text": "Uso de Herramientas de Inteligencia Artificial (IA)\nEl uso de herramientas de Inteligencia Artificial no está prohibido (¡broma!). De hecho, su utilización está permitida y fomentada. Sin embargo, es importante declarar de forma explícita cuándo y cómo se emplean estas herramientas en las tareas y trabajos del curso, especificando qué contenidos o códigos fueron generados mediante IA. Se requiere total transparencia para asegurar la integridad académica: omitir esta información puede considerarse una falta a las políticas del curso."
},
{
"objectID": "bme513/index.html#colaboración",
"href": "bme513/index.html#colaboración",
"title": "BME513 - Inteligencia Artificial para Salud",
"section": "Colaboración",
"text": "Colaboración\nSalvo que expresamente se indique trabajo en grupo, todas las tareas deben realizarse de forma individual. Se permite la discusión general con compañeros, pero no compartir respuestas detalladas ni código. Para proyectos en equipo, debe colaborar únicamente dentro de su grupo."
},
{
"objectID": "bme513/index.html#uso-de-código-y-recursos-online",
"href": "bme513/index.html#uso-de-código-y-recursos-online",
"title": "BME513 - Inteligencia Artificial para Salud",
"section": "Uso de código y recursos online",
"text": "Uso de código y recursos online\nPuede consultar y utilizar recursos en línea. Todo código o material tomado de fuentes externas debe ser citado correctamente."
},
{
"objectID": "bme513/index.html#entregas-tardías",
"href": "bme513/index.html#entregas-tardías",
"title": "BME513 - Inteligencia Artificial para Salud",
"section": "Entregas tardías",
"text": "Entregas tardías\nDispone de un total de 4 días de retraso que puede utilizar a gusto a lo largo del semestre en cualquiera de las evaluaciones del curso. Los días de retraso le permiten entregar laboratorios, tareas sin penalización. Retrasos superiores a 12 horas, se consideran como un día completo de retraso. Considere hacer uso de este beneficio en situaciones significativas o imprevistas. Si tiene problemas a largo plazo que afecten tu desempeño, se recomienda informar al profesor o jefe de carrera."
},
{
"objectID": "bme513/index.html#recalificaciones",
"href": "bme513/index.html#recalificaciones",
"title": "BME513 - Inteligencia Artificial para Salud",
"section": "Recalificaciones",
"text": "Recalificaciones\nLas solicitudes de revisión deben hacerse dentro de la semana posterior a la devolución de la calificación. Solo se considerarán solicitudes fundamentadas en base a la rúbrica proporcionada. Toda la pregunta será revisada nuevamente, lo que puede implicar aumento o disminución de puntos."
},
{
"objectID": "gp/gp01-regression-pytorch.html",
"href": "gp/gp01-regression-pytorch.html",
"title": "Basic GP Regression (Pytorch and GPyTorch)",
"section": "",
"text": "This notebook shows how to do Gaussian process regression:\n\ndefine a GP prior, 2) learn kernel hyperparameters by marginal likelihood,\nmake predictions, and 4) repeat the same using GPyTorch.\n\n\n!pip install \"gpytorch\"\n\n\nimport math\nimport os\nimport gpytorch\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport torch\nfrom scipy import optimize\nfrom scipy.spatial import distance_matrix\n\nplt.rcParams[\"figure.figsize\"] = (4, 3)\n\n# simple RBF kernel (squared‑exponential)\ndef rbf_kernel(X, Y, ls=1.0, amp=1.0):\n X = np.atleast_2d(X).reshape(-1, 1)\n Y = np.atleast_2d(Y).reshape(-1, 1)\n d2 = distance_matrix(X, Y) ** 2\n return amp**2 * np.exp(-0.5 * d2 / ls**2)\n\nGaussian Process Regression\nWe observe noisy data y(x) = f(x) + ε with ε ~ N(0, σ²).\nA GP prior f(x) ~ GP(0, k) with RBF kernel defines a distribution over functions.\nFor regression, the posterior over f and the predictive distribution are available in closed form.\nSynthetic data\n\ndef data_maker1(x, sig):\n x = np.asarray(x)\n return np.sin(x) + 0.5 * np.sin(4 * x) + np.random.randn(*x.shape) * sig\n\nsig = 0.25\ntrain_x = np.linspace(0, 5, 50)\ntest_x = np.linspace(0, 5, 500)\ntrain_y = data_maker1(train_x, sig=sig)\ntest_y = data_maker1(test_x, sig=0.0)\n\nplt.scatter(train_x, train_y)\nplt.plot(test_x, test_y)\nplt.xlabel(\"x\")\nplt.ylabel(\"Observations y\")\nplt.show()\n\n\n\n\n\n\n\n\nCircles are noisy observations, the blue curve is the underlying noise‑free function.\nPrior GP samples\n\nmean = np.zeros_like(test_x)\ncov = rbf_kernel(test_x, test_x, ls=0.2)\n\nprior_samples = np.random.multivariate_normal(mean=mean, cov=cov, size=5)\nplt.plot(test_x, prior_samples.T, color=\"black\", alpha=0.5)\nplt.plot(test_x, mean, linewidth=2.)\nstd = np.sqrt(np.diag(cov))\nplt.fill_between(test_x, mean - 2 * std, mean + 2 * std, alpha=0.25)\nplt.show()\n\n\n\n\n\n\n\n\nShort length‑scale gives very wiggly sample functions.\nHyperparameter learning (from scratch)\n\nell_est = 0.4\npost_sig_est = 0.5\n\ndef neg_MLL(pars):\n ell, noise = pars\n K = rbf_kernel(train_x, train_x, ls=ell)\n Ky = K + noise**2 * np.eye(*train_x.shape)\n L = np.linalg.cholesky(Ky)\n alpha = np.linalg.solve(L.T, np.linalg.solve(L, train_y))\n kernel_term = -0.5 * train_y @ alpha\n logdet = -np.sum(np.log(np.diag(L)))\n const = -0.5 * train_x.shape[0] * np.log(2 * np.pi)\n return -(kernel_term + logdet + const)\n\nres = optimize.minimize(\n neg_MLL,\n x0=np.array([ell_est, post_sig_est]),\n bounds=((0.01, 10.), (0.01, 10.))\n)\nell, post_sig_est = res.x\n\nprint(\"Learned length‑scale:\", ell)\nprint(\"Learned noise std:\", post_sig_est)\n\nLearned length‑scale: 0.5780687474139707\nLearned noise std: 0.22470850523850983\n\n\nNow we compute the posterior mean and covariance at test points.\n\nK_x_x = rbf_kernel(train_x, train_x, ls=ell)\nK_x_xstar = rbf_kernel(train_x, test_x, ls=ell)\nK_xstar_xstar = rbf_kernel(test_x, test_x, ls=ell)\n\nKy = K_x_x + post_sig_est**2 * np.eye(*train_x.shape)\nL = np.linalg.cholesky(Ky)\nalpha = np.linalg.solve(L.T, np.linalg.solve(L, train_y))\n\npost_mean = K_x_xstar.T @ alpha\nv = np.linalg.solve(L, K_x_xstar)\npost_cov = K_xstar_xstar - v.T @ v\n\npost_std = np.sqrt(np.diag(post_cov))\nlw_bd = post_mean - 2 * post_std\nup_bd = post_mean + 2 * post_std\n\nplt.scatter(train_x, train_y)\nplt.plot(test_x, test_y, linewidth=2.)\nplt.plot(test_x, post_mean, linewidth=2.)\nplt.fill_between(test_x, lw_bd, up_bd, alpha=0.25)\nplt.legend([\"True Function\", \"Predictive Mean\", \"Observed Data\", \"95% set (latent)\"])\nplt.show()\n\n\n\n\n\n\n\n\nThe posterior mean closely follows the true function.\nThe shaded band is a 95% credible set for the latent noise‑free function f(x).\nTo include observation noise in the band, add σ² on the diagonal:\n\nlw_bd_obs = post_mean - 2 * np.sqrt(post_std**2 + post_sig_est**2)\nup_bd_obs = post_mean + 2 * np.sqrt(post_std**2 + post_sig_est**2)\n\nPosterior samples\n\npost_samples = np.random.multivariate_normal(post_mean, post_cov, size=20)\nplt.scatter(train_x, train_y)\nplt.plot(test_x, test_y, linewidth=2.)\nplt.plot(test_x, post_mean, linewidth=2.)\nplt.plot(test_x, post_samples.T, color=\"gray\", alpha=0.25)\nplt.fill_between(test_x, lw_bd, up_bd, alpha=0.25)\nplt.legend([\"True Function\", \"Predictive Mean\", \"Observed Data\", \"Posterior Samples\"])\nplt.show()\n\n\n\n\n\n\n\n\nNext we reproduce the same regression using GPyTorch.\nGPyTorch implementation\n\ntrain_x_t = torch.tensor(train_x, dtype=torch.float32)\ntrain_y_t = torch.tensor(train_y, dtype=torch.float32)\ntest_x_t = torch.tensor(test_x, dtype=torch.float32)\ntest_y_t = torch.tensor(test_y, dtype=torch.float32)\n\nclass ExactGPModel(gpytorch.models.ExactGP):\n def __init__(self, train_x, train_y, likelihood):\n super().__init__(train_x, train_y, likelihood)\n self.mean_module = gpytorch.means.ZeroMean()\n self.covar_module = gpytorch.kernels.ScaleKernel(\n gpytorch.kernels.RBFKernel()\n )\n\n def forward(self, x):\n mean_x = self.mean_module(x)\n covar_x = self.covar_module(x)\n return gpytorch.distributions.MultivariateNormal(mean_x, covar_x)\n\nlikelihood = gpytorch.likelihoods.GaussianLikelihood()\nmodel = ExactGPModel(train_x_t, train_y_t, likelihood)\n\ntraining_iter = 50\nmodel.train()\nlikelihood.train()\noptimizer = torch.optim.Adam(model.parameters(), lr=0.1)\nmll = gpytorch.mlls.ExactMarginalLogLikelihood(likelihood, model)\n\nfor i in range(training_iter):\n optimizer.zero_grad()\n output = model(train_x_t)\n loss = -mll(output, train_y_t)\n loss.backward()\n if i % 10 == 0:\n print(\n f\"Iter {i+1:d}/{training_iter:d} - Loss: {loss.item():.3f} \"\n f\"squared lengthscale: \"\n f\"{model.covar_module.base_kernel.lengthscale.item():.3f} \"\n f\"noise variance: {model.likelihood.noise.item():.3f}\"\n )\n optimizer.step()\n\nIter 1/50 - Loss: 0.983 squared lengthscale: 0.693 noise variance: 0.693\nIter 11/50 - Loss: 0.695 squared lengthscale: 0.522 noise variance: 0.313\nIter 21/50 - Loss: 0.429 squared lengthscale: 0.549 noise variance: 0.127\nIter 31/50 - Loss: 0.304 squared lengthscale: 0.541 noise variance: 0.055\nIter 41/50 - Loss: 0.319 squared lengthscale: 0.545 noise variance: 0.038\n\n\n\nmodel.eval()\nlikelihood.eval()\nwith torch.no_grad():\n observed_pred = likelihood(model(test_x_t))\n lower, upper = observed_pred.confidence_region()\n f, ax = plt.subplots(1, 1, figsize=(4, 3))\n ax.scatter(train_x_t.numpy(), train_y_t.numpy())\n ax.plot(test_x_t.numpy(), test_y_t.numpy(), linewidth=2.)\n ax.plot(test_x_t.numpy(), observed_pred.mean.numpy(), linewidth=2.)\n ax.fill_between(test_x_t.numpy(), lower.numpy(), upper.numpy(), alpha=0.25)\n ax.set_ylim([-1.5, 1.5])\n ax.legend([\"True Function\", \"Predictive Mean\", \"Observed Data\",\n \"95% credible set (observations)\"])\n\n\n\n\n\n\n\n\nThe GPyTorch model recovers almost the same fit.\nHere the band is a 95% credible set for noisy observations (latent plus noise)."
},
{
"objectID": "gp/gp-2025.html",
"href": "gp/gp-2025.html",
"title": "Gaussian processes module",
"section": "",
"text": "Slides\nGaussian processes I Gaussian processes II\n\n\nHands-on\nGaussian Process Regression Gaussian Process Regression (Pytorch) Noise estimation example CO2 example, choosing a kernel Multi-output Gaussian Process (sensors network) Deep Gaussian Process\n\n\nResources\nRasmussen, Carl Edward. “Gaussian processes in machine learning.” Summer school on machine learning. Springer, Berlin, Heidelberg, 2003. Richard Turner lecture notes Mauricio Álvarez lecture notes Gaussian processes in Python - scikit-learn. Gaussian processes in Python - GPy. Gaussian processes in Python - Gpytorch. Gaussian process deconvolution"
},
{
"objectID": "gp/gp02-example-co2-sklearn.html",
"href": "gp/gp02-example-co2-sklearn.html",
"title": "Forecasting of CO2 level on Mona Loa dataset using Gaussian process regression (GPR)",
"section": "",
"text": "Taken from sklearn.\nThis example is based on Section 5.4.3 of “Gaussian Processes for Machine Learning” [1]_. It illustrates an example of complex kernel engineering and hyperparameter optimization using gradient ascent on the log-marginal-likelihood. The data consists of the monthly average atmospheric CO2 concentrations (in parts per million by volume (ppm)) collected at the Mauna Loa Observatory in Hawaii, between 1958 and 2001. The objective is to model the CO2 concentration as a function of the time \\(t\\) and extrapolate for years after 2001.\n.. rubric:: References\n.. [1] Rasmussen, Carl Edward. “Gaussian processes in machine learning.” Summer school on machine learning. Springer, Berlin, Heidelberg, 2003.\n!pip install polars\n\n\nCollecting polars\n\n Downloading polars-1.35.2-py3-none-any.whl.metadata (10 kB)\n\nCollecting polars-runtime-32==1.35.2 (from polars)\n\n Downloading polars_runtime_32-1.35.2-cp39-abi3-macosx_11_0_arm64.whl.metadata (1.5 kB)\n\nDownloading polars-1.35.2-py3-none-any.whl (783 kB)\n\n ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 783.6/783.6 kB 15.1 MB/s eta 0:00:00\n\nDownloading polars_runtime_32-1.35.2-cp39-abi3-macosx_11_0_arm64.whl (36.7 MB)\n\n ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 36.7/36.7 MB 22.2 MB/s eta 0:00:0000:0100:01\n\nInstalling collected packages: polars-runtime-32, polars\n\nSuccessfully installed polars-1.35.2 polars-runtime-32-1.35.2"
},
{
"objectID": "gp/gp02-example-co2-sklearn.html#build-the-dataset",
"href": "gp/gp02-example-co2-sklearn.html#build-the-dataset",
"title": "Forecasting of CO2 level on Mona Loa dataset using Gaussian process regression (GPR)",
"section": "Build the dataset",
"text": "Build the dataset\nWe will derive a dataset from the Mauna Loa Observatory that collected air samples. We are interested in estimating the concentration of CO2 and extrapolate it for further year. First, we load the original dataset available in OpenML as a pandas dataframe. This will be replaced with Polars once fetch_openml adds a native support for it.\n\nfrom sklearn.datasets import fetch_openml\n\nco2 = fetch_openml(data_id=41187, as_frame=True)\nco2.frame.head()\n\n\n\n\n\n\n\n\nyear\nmonth\nday\nweight\nflag\nstation\nco2\n\n\n\n\n0\n1958\n3\n29\n4\n0\nMLO\n316.1\n\n\n1\n1958\n4\n5\n6\n0\nMLO\n317.3\n\n\n2\n1958\n4\n12\n4\n0\nMLO\n317.6\n\n\n3\n1958\n4\n19\n6\n0\nMLO\n317.5\n\n\n4\n1958\n4\n26\n2\n0\nMLO\n316.4\n\n\n\n\n\n\n\nFirst, we process the original dataframe to create a date column and select it along with the CO2 column.\n\nimport polars as pl\n\nco2_data = pl.DataFrame(co2.frame[[\"year\", \"month\", \"day\", \"co2\"]]).select(\n pl.date(\"year\", \"month\", \"day\"), \"co2\"\n)\nco2_data.head()\n\n\nshape: (5, 2)\n\n\n\ndate\nco2\n\n\ndate\nf64\n\n\n\n\n1958-03-29\n316.1\n\n\n1958-04-05\n317.3\n\n\n1958-04-12\n317.6\n\n\n1958-04-19\n317.5\n\n\n1958-04-26\n316.4\n\n\n\n\n\n\n\nco2_data[\"date\"].min(), co2_data[\"date\"].max()\n\n(datetime.date(1958, 3, 29), datetime.date(2001, 12, 29))\n\n\nWe see that we get CO2 concentration for some days from March, 1958 to December, 2001. We can plot these raw information to have a better understanding.\n\nimport matplotlib.pyplot as plt\n\nplt.plot(co2_data[\"date\"], co2_data[\"co2\"])\nplt.xlabel(\"date\")\nplt.ylabel(\"CO$_2$ concentration (ppm)\")\n_ = plt.title(\"Raw air samples measurements from the Mauna Loa Observatory\")\n\n\n\n\n\n\n\n\nWe will preprocess the dataset by taking a monthly average and drop month for which no measurements were collected. Such a processing will have an smoothing effect on the data.\n\nco2_data = (\n co2_data.sort(by=\"date\")\n .group_by_dynamic(\"date\", every=\"1mo\")\n .agg(pl.col(\"co2\").mean())\n .drop_nulls()\n)\nplt.plot(co2_data[\"date\"], co2_data[\"co2\"])\nplt.xlabel(\"date\")\nplt.ylabel(\"Monthly average of CO$_2$ concentration (ppm)\")\n_ = plt.title(\n \"Monthly average of air samples measurements\\nfrom the Mauna Loa Observatory\"\n)\n\n\n\n\n\n\n\n\nThe idea in this example will be to predict the CO2 concentration in function of the date. We are as well interested in extrapolating for upcoming year after 2001.\nAs a first step, we will divide the data and the target to estimate. The data being a date, we will convert it into a numeric.\n\nX = co2_data.select(\n pl.col(\"date\").dt.year() + pl.col(\"date\").dt.month() / 12\n).to_numpy()\ny = co2_data[\"co2\"].to_numpy()"
},
{
"objectID": "gp/gp02-example-co2-sklearn.html#design-the-proper-kernel",
"href": "gp/gp02-example-co2-sklearn.html#design-the-proper-kernel",
"title": "Forecasting of CO2 level on Mona Loa dataset using Gaussian process regression (GPR)",
"section": "Design the proper kernel",
"text": "Design the proper kernel\nTo design the kernel to use with our Gaussian process, we can make some assumption regarding the data at hand. We observe that they have several characteristics: we see a long term rising trend, a pronounced seasonal variation and some smaller irregularities. We can use different appropriate kernel that would capture these features.\nFirst, the long term rising trend could be fitted using a radial basis function (RBF) kernel with a large length-scale parameter. The RBF kernel with a large length-scale enforces this component to be smooth. An trending increase is not enforced as to give a degree of freedom to our model. The specific length-scale and the amplitude are free hyperparameters.\n\nfrom sklearn.gaussian_process.kernels import RBF\n\nlong_term_trend_kernel = 50.0**2 * RBF(length_scale=50.0)\n\nThe seasonal variation is explained by the periodic exponential sine squared kernel with a fixed periodicity of 1 year. The length-scale of this periodic component, controlling its smoothness, is a free parameter. In order to allow decaying away from exact periodicity, the product with an RBF kernel is taken. The length-scale of this RBF component controls the decay time and is a further free parameter. This type of kernel is also known as locally periodic kernel.\n\nfrom sklearn.gaussian_process.kernels import ExpSineSquared\n\nseasonal_kernel = (\n 2.0**2\n * RBF(length_scale=100.0)\n * ExpSineSquared(length_scale=1.0, periodicity=1.0, periodicity_bounds=\"fixed\")\n)\n\nThe small irregularities are to be explained by a rational quadratic kernel component, whose length-scale and alpha parameter, which quantifies the diffuseness of the length-scales, are to be determined. A rational quadratic kernel is equivalent to an RBF kernel with several length-scale and will better accommodate the different irregularities.\n\nfrom sklearn.gaussian_process.kernels import RationalQuadratic\n\nirregularities_kernel = 0.5**2 * RationalQuadratic(length_scale=1.0, alpha=1.0)\n\nFinally, the noise in the dataset can be accounted with a kernel consisting of an RBF kernel contribution, which shall explain the correlated noise components such as local weather phenomena, and a white kernel contribution for the white noise. The relative amplitudes and the RBF’s length scale are further free parameters.\n\nfrom sklearn.gaussian_process.kernels import WhiteKernel\n\nnoise_kernel = 0.1**2 * RBF(length_scale=0.1) + WhiteKernel(\n noise_level=0.1**2, noise_level_bounds=(1e-5, 1e5)\n)\n\nThus, our final kernel is an addition of all previous kernel.\n\nco2_kernel = (\n long_term_trend_kernel + seasonal_kernel + irregularities_kernel + noise_kernel\n)\nco2_kernel\n\n50**2 * RBF(length_scale=50) + 2**2 * RBF(length_scale=100) * ExpSineSquared(length_scale=1, periodicity=1) + 0.5**2 * RationalQuadratic(alpha=1, length_scale=1) + 0.1**2 * RBF(length_scale=0.1) + WhiteKernel(noise_level=0.01)"
},
{
"objectID": "gp/gp02-example-co2-sklearn.html#model-fitting-and-extrapolation",
"href": "gp/gp02-example-co2-sklearn.html#model-fitting-and-extrapolation",
"title": "Forecasting of CO2 level on Mona Loa dataset using Gaussian process regression (GPR)",
"section": "Model fitting and extrapolation",
"text": "Model fitting and extrapolation\nNow, we are ready to use a Gaussian process regressor and fit the available data. To follow the example from the literature, we will subtract the mean from the target. We could have used normalize_y=True. However, doing so would have also scaled the target (dividing y by its standard deviation). Thus, the hyperparameters of the different kernel would have had different meaning since they would not have been expressed in ppm.\n\nfrom sklearn.gaussian_process import GaussianProcessRegressor\n\ny_mean = y.mean()\ngaussian_process = GaussianProcessRegressor(kernel=co2_kernel, normalize_y=False)\ngaussian_process.fit(X, y - y_mean)\n\nGaussianProcessRegressor(kernel=50**2 * RBF(length_scale=50) + 2**2 * RBF(length_scale=100) * ExpSineSquared(length_scale=1, periodicity=1) + 0.5**2 * RationalQuadratic(alpha=1, length_scale=1) + 0.1**2 * RBF(length_scale=0.1) + WhiteKernel(noise_level=0.01))In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.GaussianProcessRegressor?Documentation for GaussianProcessRegressoriFittedGaussianProcessRegressor(kernel=50**2 * RBF(length_scale=50) + 2**2 * RBF(length_scale=100) * ExpSineSquared(length_scale=1, periodicity=1) + 0.5**2 * RationalQuadratic(alpha=1, length_scale=1) + 0.1**2 * RBF(length_scale=0.1) + WhiteKernel(noise_level=0.01)) \n\n\nNow, we will use the Gaussian process to predict on:\n\ntraining data to inspect the goodness of fit;\nfuture data to see the extrapolation done by the model.\n\nThus, we create synthetic data from 1958 to the current month. In addition, we need to add the subtracted mean computed during training.\n\nimport datetime\n\nimport numpy as np\n\ntoday = datetime.datetime.now()\ncurrent_month = today.year + today.month / 12\nX_test = np.linspace(start=1958, stop=current_month, num=1_000).reshape(-1, 1)\nmean_y_pred, std_y_pred = gaussian_process.predict(X_test, return_std=True)\nmean_y_pred += y_mean\n\n\nplt.plot(X, y, color=\"black\", linestyle=\"dashed\", label=\"Measurements\")\nplt.plot(X_test, mean_y_pred, color=\"tab:blue\", alpha=0.4, label=\"Gaussian process\")\nplt.fill_between(\n X_test.ravel(),\n mean_y_pred - std_y_pred,\n mean_y_pred + std_y_pred,\n color=\"tab:blue\",\n alpha=0.2,\n)\nplt.legend()\nplt.xlabel(\"Year\")\nplt.ylabel(\"Monthly average of CO$_2$ concentration (ppm)\")\n_ = plt.title(\n \"Monthly average of air samples measurements\\nfrom the Mauna Loa Observatory\"\n)\n\n\n\n\n\n\n\n\nOur fitted model is capable to fit previous data properly and extrapolate to future year with confidence."
},
{
"objectID": "gp/gp02-example-co2-sklearn.html#interpretation-of-kernel-hyperparameters",
"href": "gp/gp02-example-co2-sklearn.html#interpretation-of-kernel-hyperparameters",
"title": "Forecasting of CO2 level on Mona Loa dataset using Gaussian process regression (GPR)",
"section": "Interpretation of kernel hyperparameters",
"text": "Interpretation of kernel hyperparameters\nNow, we can have a look at the hyperparameters of the kernel.\n\ngaussian_process.kernel_\n\n44.8**2 * RBF(length_scale=51.6) + 2.64**2 * RBF(length_scale=91.5) * ExpSineSquared(length_scale=1.48, periodicity=1) + 0.536**2 * RationalQuadratic(alpha=2.89, length_scale=0.968) + 0.188**2 * RBF(length_scale=0.122) + WhiteKernel(noise_level=0.0367)\n\n\nThus, most of the target signal, with the mean subtracted, is explained by a long-term rising trend for ~45 ppm and a length-scale of ~52 years. The periodic component has an amplitude of ~2.6ppm, a decay time of ~90 years and a length-scale of ~1.5. The long decay time indicates that we have a component very close to a seasonal periodicity. The correlated noise has an amplitude of ~0.2 ppm with a length scale of ~0.12 years and a white-noise contribution of ~0.04 ppm. Thus, the overall noise level is very small, indicating that the data can be very well explained by the model."
},
{
"objectID": "gp/gp01-regression.html",
"href": "gp/gp01-regression.html",
"title": "Gaussian Process Regression",
"section": "",
"text": "import numpy as np\nimport matplotlib.pyplot as plt\nfrom sklearn.gaussian_process import GaussianProcessRegressor\nfrom sklearn.gaussian_process.kernels import RBF, ConstantKernel, WhiteKernel\nimport seaborn as sns\nimport os\n\nplot_params = {'legend.fontsize': 18,\n 'figure.figsize': (8, 5),\n 'xtick.labelsize':'18',\n 'ytick.labelsize':'18',\n 'axes.titlesize':'24',\n 'axes.labelsize':'22'}\n\nplt.rcParams.update(plot_params)\nsns.set_style(\"whitegrid\")\n\ndef f(x):\n return np.sin(x) + 0.3 * np.cos(3 * x)\nx = np.linspace(-3, 3, 100)\n\nplt.figure()\nplt.plot(x, f(x), alpha=0.7)\nplt.xlabel('x')\nplt.ylabel('f(x)')\nplt.tight_layout()\n\nnp.random.seed(0)\n\n# training data\nX_train = np.linspace(-3, 3, 12)[:, None]\nX_train = np.array([-3, -1.9, 2])[:, None]\ny_train = f(X_train[:, 0]) + 0.1 * np.random.randn(len(X_train))\n\n# test grid\nX_test = np.linspace(-4, 4, 400)[:, None]\n\nplt.figure()\nplt.plot(X_train[:, 0], y_train, 'or', label='observations')\nplt.plot(X_test[:, 0], f(X_test[:, 0]), 'k--', label='ground truth')\nplt.xlabel('x')\nplt.ylabel('y')\nplt.legend()\nplt.tight_layout()\nfor n_samples in [1, 4]:\n idx_fig = 0\n for sigma_f in [1, 2, 3]:\n for length_scale in [0.1, 1, 3]:\n\n idx_fig+=1\n\n kernel = ConstantKernel(sigma_f, (1e-3, 1e3)) \\\n * RBF(length_scale=length_scale, length_scale_bounds=(1e-2, 1e2)) \\\n + WhiteKernel(noise_level=0.0, noise_level_bounds=(1e-10, 1e0))\n\n gp = GaussianProcessRegressor(\n kernel=kernel,\n alpha=0.0,\n optimizer=None, # <- disables LML optimization / 'fmin_l_bfgs_b'\n n_restarts_optimizer=5,\n normalize_y=False)\n\n # Prior mean/cov on test grid\n mu_prior, cov_prior = gp.predict(X_test, return_cov=True)\n # Draw prior samples\n prior_samps = np.random.multivariate_normal(mean=mu_prior.ravel(), cov=cov_prior, size=n_samples)\n\n plt.close('all')\n fig, axs = plt.subplots(1, 2, figsize=(12, 5), gridspec_kw={'width_ratios': [1, 2]})\n axs = axs.flatten()\n\n # Left: covariance matrix\n im = axs[0].imshow(cov_prior, origin=\"lower\", extent=[-4, 4, -4, 4], vmin=0.0, vmax=2.0)\n axs[0].set_xlabel(r'$x$')\n axs[0].set_ylabel(r\"$x^\\prime$\")\n axs[0].grid(False)\n axs[0].set_xlim([-4, 4])\n axs[0].set_ylim([-4, 4])\n fig.colorbar(im, ax=axs[0], fraction=0.046, pad=0.04)\n\n # Right: prior samples\n for i in range(n_samples):\n axs[1].plot(X_test[:, 0], prior_samps[i], alpha=0.7, lw=4)\n axs[1].set_xlabel('x')\n axs[1].set_ylabel('f(x)')\n axs[1].set_xlim([-4, 4])\n axs[1].set_ylim([-4, 4])\n\n plt.suptitle(f'$\\ell={length_scale}$, $\\sigma_f={sigma_f}$', fontsize=38)\n plt.tight_layout()\n # plt.savefig(os.path.join('.',f'fig-prior-rbf-nsamp{n_samples}-{idx_fig}.pdf'))\n plt.show()\nlength_scale = 1\nsigma_f = 1\n\nkernel = ConstantKernel(sigma_f, (1e-3, 1e3)) \\\n * RBF(length_scale=length_scale, length_scale_bounds=(1e-2, 1e2)) \\\n + WhiteKernel(noise_level=0.0, noise_level_bounds=(1e-10, 1e0))\n\ngp = GaussianProcessRegressor(\n kernel=kernel,\n alpha=0.0,\n optimizer=None, # <- disables LML optimization / 'fmin_l_bfgs_b'\n n_restarts_optimizer=5,\n normalize_y=False)\n\n# Prior mean/cov on test grid\nmu_prior, cov_prior = gp.predict(X_test, return_cov=True)\nstd_prior = np.sqrt(np.diag(cov_prior))\nn_samples = 3\n# Draw prior samples\nprior_samps = np.random.multivariate_normal(mean=mu_prior.ravel(), cov=cov_prior, size=n_samples)\n\n\nplt.close('all')\nfig, axs = plt.subplots(1, 2, figsize=(12, 5), gridspec_kw={'width_ratios': [1, 2]})\naxs = axs.flatten()\n\n# Left: covariance matrix\nim = axs[0].imshow(cov_prior, origin=\"lower\", extent=[-4, 4, -4, 4], vmin=0.0, vmax=2.0)\naxs[0].set_xlabel(r'$x$')\naxs[0].set_ylabel(r\"$x^\\prime$\")\naxs[0].grid(False)\naxs[0].set_xlim([-4, 4])\naxs[0].set_ylim([-4, 4])\nfig.colorbar(im, ax=axs[0], fraction=0.046, pad=0.04)\n\n# Right: prior samples\nfor i in range(n_samples):\n axs[1].plot(X_test[:, 0], prior_samps[i], alpha=0.7, lw=4)\naxs[1].set_xlabel('x')\naxs[1].set_ylabel('f(x)')\naxs[1].set_xlim([-4, 4])\naxs[1].set_ylim([-4, 4])\n\nplt.suptitle(f'$\\ell={length_scale}$, $\\sigma_f={sigma_f}$', fontsize=38)\nplt.tight_layout()\n# plt.savefig(os.path.join('.',f'fig-prior-rbf-with-moments.pdf'))\n\n# Right: prior samples\naxs[1].plot(X_test[:, 0], mu_prior, 'r', label='GP mean', lw=4)\naxs[1].fill_between(\n X_test[:, 0],\n mu_prior - 2 * std_prior,\n mu_prior + 2 * std_prior,\n color='r',\n alpha=0.2,\n linewidth=0,\n edgecolor='none',\n label='95% CI')\naxs[1].legend(loc=\"lower left\", ncols=2)\n# plt.savefig(os.path.join('.',f'fig-prior-rbf-with-moments-2.pdf'))\n\nplt.show()\ngp.fit(X_train, y_train)\n# Posterior mean/cov on test grid\nmu, cov = gp.predict(X_test, return_cov=True)\n\nn_samples = 3\n# Draw posterior samples\npost_samps = np.random.multivariate_normal(mean=mu.ravel(), cov=cov, size=n_samples)\nstd = np.sqrt(np.diag(cov))\n\n\nplt.close('all')\nfig, axs = plt.subplots(1, 2, figsize=(12, 5), gridspec_kw={'width_ratios': [1, 2]})\naxs = axs.flatten()\n\n# Left: covariance matrix\nim = axs[0].imshow(cov, origin=\"lower\", extent=[-4, 4, -4, 4], vmin=0.0, vmax=2.0)\naxs[0].set_xlabel(r'$x$')\naxs[0].set_ylabel(r\"$x^\\prime$\")\naxs[0].grid(False)\naxs[0].set_xlim([-4, 4])\naxs[0].set_ylim([-4, 4])\nfig.colorbar(im, ax=axs[0], fraction=0.046, pad=0.04)\n\n# Right: prior samples\nfor i in range(n_samples):\n axs[1].plot(X_test[:, 0], post_samps[i], alpha=0.7, lw=4)\naxs[1].set_xlabel('x')\naxs[1].set_ylabel('f(x)')\naxs[1].set_xlim([-4, 4])\naxs[1].set_ylim([-4, 4])\naxs[1].plot(X_test[:, 0], mu, 'r', label='GP mean', lw=4)\naxs[1].fill_between(\n X_test[:, 0],\n mu - 2 * std,\n mu + 2 * std,\n color='r',\n alpha=0.2,\n linewidth=0,\n edgecolor='none',\n label='95% CI')\naxs[1].scatter(np.squeeze(X_train), y_train, color=\"red\", zorder=10, s=60, label=\"Obs\")\naxs[1].legend(loc=\"lower left\", ncols=3)\n\n\nplt.suptitle(f'$\\ell={length_scale}$, $\\sigma_f={sigma_f}$', fontsize=38)\nplt.tight_layout()\n# plt.savefig(os.path.join('.',f'fig-post-rbf-with-moments.pdf'))\nplt.show()\n\n\n\n\n/Users/aveloz/miniconda3/lib/python3.9/site-packages/sklearn/gaussian_process/kernels.py:307: RuntimeWarning: divide by zero encountered in log\n return np.log(np.hstack(theta))"
},
{
"objectID": "gp/gp01-regression.html#dataset-and-gaussian-process-generation",
"href": "gp/gp01-regression.html#dataset-and-gaussian-process-generation",
"title": "Gaussian Process Regression",
"section": "Dataset and Gaussian process generation",
"text": "Dataset and Gaussian process generation\nWe will create a training dataset that we will use in the different sections.\n\nrng = np.random.RandomState(5)\nX_train = rng.uniform(0, 5, 10).reshape(-1, 1)\ny_train = np.sin((X_train[:, 0] - 2.5) ** 2)\nn_samples = 5\nX_train\n\narray([[1.10996586],\n [4.35366153],\n [1.03359578],\n [4.59305454],\n [2.44205594],\n [3.05871931],\n [3.82953928],\n [2.59208994],\n [1.48400251],\n [0.93860614]])\n\n\n\nRadial Basis Function kernel\n\nfrom sklearn.gaussian_process import GaussianProcessRegressor\nfrom sklearn.gaussian_process.kernels import RBF\n\nkernel = 1.0 * RBF(length_scale=0.1, length_scale_bounds=(1e-1, 10.0))\ngpr = GaussianProcessRegressor(kernel=kernel, random_state=0)\n\nfig, ax = plt.subplots(nrows=1, sharex=True, sharey=True, figsize=(7, 3))\n# plot prior\nplot_gpr_samples(gpr, n_samples=n_samples, ax=ax)\nhandles, labels = ax.get_legend_handles_labels()\nby_label = dict(zip(labels, handles))\nax.legend(by_label.values(), by_label.keys(), loc=\"upper center\", bbox_to_anchor=(0.5, 1.1), ncol=len(by_label), fontsize=12)\nax.set_xlim([0, 5])\nax.set_ylim([-4, 4])\nax.set_xlabel(\"x\", fontsize=18)\nax.set_ylabel(\"y\", fontsize=18)\nax.tick_params(axis='both', which='major', labelsize=16)\nax.spines['top'].set_visible(False)\nax.spines['right'].set_visible(False)\nplt.tight_layout()\n# plt.savefig(f'rbf-0.pdf')\n\nfor idx in range(X_train.shape[0]):\n fig, ax = plt.subplots(nrows=1, sharex=True, sharey=True, figsize=(7, 3))\n x_train_ = np.array(X_train[:idx+1, 0]).reshape(-1, 1)\n y_train_ = np.array(y_train[:idx+1]).reshape(-1, 1)\n gpr.fit(x_train_, y_train_)\n # plot posterior\n plot_gpr_samples(gpr, n_samples=n_samples, ax=ax)\n ax.scatter(np.squeeze(x_train_), y_train_, color=\"red\", zorder=10, label=\"Obs\")\n handles, labels = ax.get_legend_handles_labels()\n by_label = dict(zip(labels, handles))\n ax.legend(by_label.values(), by_label.keys(), loc=\"upper center\", bbox_to_anchor=(0.5, 1.3), ncol=len(by_label), fontsize=12)\n ax.set_xlim([0, 5])\n ax.set_ylim([-4, 4])\n ax.set_xlabel(\"x\", fontsize=18)\n ax.set_ylabel(\"y\", fontsize=18)\n ax.tick_params(axis='both', which='major', labelsize=16)\n ax.spines['top'].set_visible(False)\n ax.spines['right'].set_visible(False)\n plt.tight_layout()\n # plt.savefig(f'rbf-{idx+1}.pdf')\n\nplt.close(fig)\n\n/Users/aveloz/miniconda3/lib/python3.9/site-packages/sklearn/gaussian_process/kernels.py:442: ConvergenceWarning: The optimal value found for dimension 0 of parameter k2__length_scale is close to the specified lower bound 0.1. Decreasing the bound and calling fit again may find a better value.\n warnings.warn(\n/Users/aveloz/miniconda3/lib/python3.9/site-packages/sklearn/gaussian_process/kernels.py:442: ConvergenceWarning: The optimal value found for dimension 0 of parameter k2__length_scale is close to the specified lower bound 0.1. Decreasing the bound and calling fit again may find a better value.\n warnings.warn(\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nX_train.shape\n\n(10, 1)\n\n\n\nfrom sklearn.gaussian_process import GaussianProcessRegressor\nfrom sklearn.gaussian_process.kernels import RBF\n\nlength_scales = [0.05, 0.1, 0.25, 0.5, 1.0, 10]\nfig, ax = plt.subplots(nrows=len(length_scales), sharex=True, sharey=True, figsize=(7, 7))\nfor i, ls in enumerate(length_scales):\n kernel = 1.0 * RBF(length_scale=ls, length_scale_bounds=(1e-1, 10.0)) \n gpr = GaussianProcessRegressor(kernel=kernel, random_state=0)\n plot_gpr_samples(gpr, n_samples=n_samples, ax=ax[i]) # plot prior\n if i==0:\n handles, labels = ax[i].get_legend_handles_labels()\n by_label = dict(zip(labels, handles))\n ax[i].legend(by_label.values(), by_label.keys(), loc=\"upper center\", bbox_to_anchor=(0.5, 1.5), ncol=len(by_label), fontsize=14)\n ax[i].set_xlim([0, 5])\n ax[i].set_ylim([-4, 4])\n ax[i].tick_params(axis='both', which='major', labelsize=16)\n ax[i].set_ylabel(f\"$\\ell = {ls}$\", fontsize=18)\n ax[i].spines['top'].set_visible(False)\n ax[i].spines['right'].set_visible(False)\n if i == len(length_scales)-1:\n ax[i].set_xlabel(\"x\", fontsize=18)\nplt.tight_layout()\n# plt.savefig(f'rbf-panel-length-scales.pdf')\n\n\nsigmas = [0.1, 0.25, 0.5, 1.0, 3.0]\nfig, ax = plt.subplots(nrows=len(sigmas), sharex=True, sharey=True, figsize=(7, 7))\nfor i, sigma in enumerate(sigmas):\n ls = 0.1\n kernel = sigma * RBF(length_scale=ls, length_scale_bounds=(1e-1, 10.0)) # [web:4]\n gpr = GaussianProcessRegressor(kernel=kernel, random_state=0)\n plot_gpr_samples(gpr, n_samples=n_samples, ax=ax[i]) # plot prior\n if i==0:\n handles, labels = ax[i].get_legend_handles_labels()\n by_label = dict(zip(labels, handles))\n ax[i].legend(by_label.values(), by_label.keys(), loc=\"upper center\", bbox_to_anchor=(0.5, 1.5), ncol=len(by_label), fontsize=14)\n ax[i].set_xlim([0, 5])\n ax[i].set_ylim([-4, 4])\n ax[i].tick_params(axis='both', which='major', labelsize=16)\n ax[i].set_ylabel(f\"$\\sigma = {sigma}$\", fontsize=18)\n # ax[i].set_title(f\"$\\ell = {ls}$\", fontsize=18)\n ax[i].spines['top'].set_visible(False)\n ax[i].spines['right'].set_visible(False)\n if i == len(sigmas)-1:\n ax[i].set_xlabel(\"x\", fontsize=18)\nplt.tight_layout()\n# plt.savefig(f'rbf-panel-sigmas.pdf')\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n# Rational Quadratic kernel\nfrom sklearn.gaussian_process import GaussianProcessRegressor\nfrom sklearn.gaussian_process.kernels import RBF, RationalQuadratic, Matern, ExpSineSquared, ConstantKernel, DotProduct\n\nkernels = [(1.0 * RBF(length_scale=1.0, length_scale_bounds=(1e-1, 10.0)), 'kernel-rbf.pdf'),\n (1.0 * RationalQuadratic(length_scale=1.0, alpha=0.1, alpha_bounds=(1e-5, 1e15)), 'kernel-rationalquadratic.pdf'),\n (1.0 * Matern(length_scale=1.0, length_scale_bounds=(1e-1, 10.0), nu=1.5), 'kernel-matern.pdf'),\n # (1.0 * ExpSineSquared(length_scale=1.0, periodicity=3.0, length_scale_bounds=(0.1, 10.0), periodicity_bounds=(1.0, 10.0)), 'kernel-expsinesquared.pdf'),\n (ConstantKernel(0.1, (0.01, 10.0)) * (DotProduct(sigma_0=1.0, sigma_0_bounds=(0.1, 10.0)) ** 2), 'kernel-cte-dot.pdf')\n ]\n\n\nfor kernel, filename in kernels:\n\n gpr = GaussianProcessRegressor(kernel=kernel, random_state=0)\n\n fig, ax = plt.subplots(nrows=2, sharex=True, sharey=True, figsize=(10, 6))\n # plot prior\n plot_gpr_samples(gpr, n_samples=n_samples, ax=ax[0])\n handles, labels = ax[0].get_legend_handles_labels()\n by_label = dict(zip(labels, handles))\n ax[0].legend(by_label.values(), by_label.keys(), loc=\"upper center\", bbox_to_anchor=(0.5, 0.99), ncol=len(by_label), fontsize=14)\n ax[0].set_xlim([0, 5])\n ax[0].set_ylim([-4, 4])\n # ax[0].set_xlabel(\"x\", fontsize=18)\n ax[0].spines['top'].set_visible(False)\n ax[0].spines['right'].set_visible(False)\n ax[0].set_ylabel(\"y\", fontsize=18)\n ax[0].tick_params(axis='both', which='major', labelsize=16)\n\n x_train_ = np.array(X_train[:, 0]).reshape(-1, 1)\n y_train_ = np.array(y_train[:]).reshape(-1, 1)\n gpr.fit(x_train_, y_train_)\n # plot posterior\n plot_gpr_samples(gpr, n_samples=n_samples, ax=ax[1])\n ax[1].scatter(np.squeeze(x_train_), y_train_, color=\"red\", zorder=10, label=\"Observations\")\n handles, labels = ax[1].get_legend_handles_labels()\n by_label = dict(zip(labels, handles))\n ax[1].legend(by_label.values(), by_label.keys(), loc=\"upper center\", bbox_to_anchor=(0.5, 1.1), ncol=len(by_label), fontsize=14)\n ax[1].set_xlim([0, 5])\n ax[1].set_ylim([-4, 4])\n ax[1].set_xlabel(\"x\", fontsize=18)\n ax[1].set_ylabel(\"y\", fontsize=18)\n ax[1].tick_params(axis='both', which='major', labelsize=16)\n # ax.set_title(\"Samples from posterior distribution (RBF kernel)\", fontsize=18)\n ax[1].spines['top'].set_visible(False)\n ax[1].spines['right'].set_visible(False)\n\n plt.tight_layout()\n # plt.savefig(filename)\n\n\n/Users/aveloz/miniconda3/lib/python3.9/site-packages/sklearn/gaussian_process/_gpr.py:478: UserWarning: Predicted variances smaller than 0. Setting those variances to 0.\n warnings.warn(\n/Users/aveloz/miniconda3/lib/python3.9/site-packages/sklearn/gaussian_process/_gpr.py:523: RuntimeWarning: covariance is not positive-semidefinite.\n y_samples = rng.multivariate_normal(y_mean, y_cov, n_samples).T\n/Users/aveloz/miniconda3/lib/python3.9/site-packages/sklearn/gaussian_process/_gpr.py:660: ConvergenceWarning: lbfgs failed to converge (status=2):\nABNORMAL_TERMINATION_IN_LNSRCH.\n\nIncrease the number of iterations (max_iter) or scale the data as shown in:\n https://scikit-learn.org/stable/modules/preprocessing.html\n _check_optimize_result(\"lbfgs\", opt_res)"
},
{
"objectID": "bme423/ejemplos/difusion_lineal.html",
"href": "bme423/ejemplos/difusion_lineal.html",
"title": "Filtrado mediante la ecuación de difusión lineal",
"section": "",
"text": "from matplotlib import pyplot as plt\nimport os\nimport numpy as np\nfrom skimage import io\nfrom scipy.signal import convolve2d\n\n\ndef escalar_intensidades(img, scale=255):\n img = img - img.min()\n img = img / img.max()\n return scale * img\n\ndef gradient(f, kx, ky):\n gradx = convolve2d(f, kx, boundary='symm', mode='same')\n grady = convolve2d(f, ky, boundary='symm', mode='same')\n return gradx, grady\n\n# kernels para calcular gradientes\nkx = np.array([[-1, 0, 1], [-2, 0, 1], [-1, 0, 1]])\nky = np.array([[-1, -2, -1], [0, 0, 0], [1, 2, 1]])\n\n\npath = '.'\nfilename = 'lorenzo.jpg'\nimg = io.imread( os.path.join(path, filename) )\nimg = np.mean(img, axis=2)\nimg = escalar_intensidades(img)\n\n\nGradiente de una imagen\n\ngx, gy = gradient(img, kx, ky)\n\n\nfig, axs = plt.subplots(nrows=1, ncols=3, figsize=(10,3))\n\nim0 = axs[0].imshow(img, cmap='gray')\naxs[0].set_title(r'$f, r=['+f'{img.min()},{img.max()}'+']$')\naxs[0].axis('off')\nfig.colorbar(im0, ax=axs[0], fraction=0.046, pad=0.04)\n\nim1 = axs[1].imshow(gx, cmap='gray')\naxs[1].set_title(r'$\\nabla_{\\mathbf{x}} f$')\naxs[1].axis('off')\nfig.colorbar(im1, ax=axs[1], fraction=0.046, pad=0.04)\n\nim2 = axs[2].imshow(gy, cmap='gray')\naxs[2].set_title(r'$\\nabla_{\\mathbf{y}} f$')\naxs[2].axis('off')\nfig.colorbar(im2, ax=axs[2], fraction=0.046, pad=0.04)\n\nplt.show()\n\n\n\n\n\n\n\n\n\n\nEjemplo de implementación del filtro de difusión lineal\nEl siguiente programa implementa la solución numérica de la siguiente PDE:\n\\[\\frac{\\partial f}{\\partial t} = c \\frac{\\partial^2 f}{\\partial x^2} + c \\frac{\\partial^2 f}{\\partial y^2}\\]\n\nc = 0.02\nit_max = 10\ndt = 1\n\nfs = [np.copy(img)]\n\nfor it in range(1, it_max+1):\n print(f'iteración {it}')\n gx, gy = gradient(fs[it-1], kx, ky)\n g2x, _ = gradient(gx, kx, ky)\n _, g2y = gradient(gy, kx, ky)\n f_actual = fs[it-1] + dt*c*(g2x+g2y)\n fs.append( f_actual )\n\niteración 1\niteración 2\niteración 3\niteración 4\niteración 5\niteración 6\niteración 7\niteración 8\niteración 9\niteración 10\n\n\n\nfig, axs = plt.subplots(nrows=1, ncols=2, figsize=(10,6))\naxs[0].imshow(img, cmap='gray')\naxs[0].set_title(r'$f$')\naxs[0].axis('off')\naxs[1].imshow(fs[-1], cmap='gray')\naxs[1].set_title(r'$\\frac{\\partial f}{\\partial t} = c \\frac{\\partial^2 f}{\\partial x^2} + c\\frac{\\partial^2 f}{\\partial y^2}$')\naxs[1].axis('off')\nplt.show()"
},
{
"objectID": "bme423/ejemplos/cnn-01-conv.html",
"href": "bme423/ejemplos/cnn-01-conv.html",
"title": "Convolución en Keras",
"section": "",
"text": "Este notebook muestra la aplicación de convoluciones en imágenes.\n\nDescargas\nbee.png\n\n\nLectura y apertura de imágenes\nEl siguiente código permite leer una imagen, cargarla en un arreglo de numpy y mostrarla.\n\n%matplotlib inline\nimport matplotlib.pyplot as plt\nimport numpy as np\n\nfrom skimage.io import imread\nfrom skimage.transform import resize\n\n\nsample_image = imread(\"bee.png\").astype(\"float32\")\nprint(\"sample image shape: \", sample_image.shape)\n\nsize = sample_image.shape\n\nplt.imshow(sample_image.astype('uint8'));\n\nsample image shape: (600, 600, 3)\n\n\n\n\n\n\n\n\n\n\n\nFiltro de convolución\nEl objetivo de esta sección es utilizar TensorFlow / Keras para realizar convoluciones individuales sobre imágenes. En esta sección todavía no se entrena ningún modelo.\n\nimport tensorflow as tf\n\nprint(tf.__version__)\n\n2.16.2\n\n\n\nfrom tensorflow.keras.models import Sequential\nfrom tensorflow.keras.layers import Conv2D\n\n\nconv = Conv2D(filters=3, kernel_size=(5, 5), padding=\"same\")\n\n\nsample_image.shape\n\n(600, 600, 3)\n\n\n\nimg_in = np.expand_dims(sample_image, 0)\nimg_in.shape\n\n(1, 600, 600, 3)\n\n\nSi aplicamos esta convolución a esta imagen, ¿cuál será la forma del mapa de características generado?\nPistas:\n\nEn Keras padding=\"same\" significa que las convoluciones usan el relleno necesario para preservar la dimensión espacial de las imágenes o mapas de entrada.\n\nEn Keras, las convoluciones no tienen strides por defecto.\n\n¿Cuánto padding debe usar Keras en este caso particular para preservar las dimensiones espaciales?\n\n\nimg_out = conv(img_in)\nprint(type(img_out), img_out.shape)\n\n<class 'tensorflow.python.framework.ops.EagerTensor'> (1, 600, 600, 3)\n\n\nLa salida puede convertirse a un arreglo de numpy\n\nnp_img_out = img_out[0].numpy()\nprint(type(np_img_out))\n\n<class 'numpy.ndarray'>\n\n\n\nfig, (ax0, ax1) = plt.subplots(ncols=2, figsize=(10, 5))\nax0.imshow(sample_image.astype('uint8'))\nax1.imshow(np_img_out.astype('uint8'));\n\n\n\n\n\n\n\n\nLa salida tiene 3 canales, por lo tanto, también puede interpretarse como una imagen RGB con matplotlib. Sin embargo, es el resultado de un filtro convolucional aleatorio aplicado a la imagen original.\nVeamos los parámetros:\n\nconv.count_params()\n\n228\n\n\nPregunta: ¿Puedes calcular el número de parámetros entrenables a partir de los hiperparámetros de la capa?\nPistas:\n\nla imagen de entrada tiene 3 colores y un único kernel de convolución mezcla información de los tres canales de entrada para calcular su salida;\n\nuna capa convolucional genera muchos canales de salida a la vez: cada canal es el resultado de una operación de convolución distinta (también llamada unidad) de la capa;\n\nNo olvidar los sesgos/biases\n\n\nlen(conv.get_weights())\n\n2\n\n\n\nweights = conv.get_weights()[0]\nweights.shape\n\n(5, 5, 3, 3)\n\n\nCada uno de los 3 canales de salida es generado por un kernel de convolución distinto.\nCada kernel tiene dimensión 5x5 y opera sobre los 3 canales de entrada.\n\nbiases = conv.get_weights()[1]\nbiases.shape\n\n(3,)\n\n\nUn bias por canal de salida.\nPodemos construir un kernel nosotros mismos (“manualmente”).\n\ndef my_init(shape=(5, 5, 3, 3), dtype=None):\n array = np.zeros(shape=shape, dtype=\"float32\")\n array[:, :, 0, 0] = 1 / 25\n array[:, :, 1, 1] = 1 / 25\n array[:, :, 2, 2] = 1 / 25\n return array\n\n\nnp.transpose(my_init(), (2, 3, 0, 1))\n\narray([[[[0.04, 0.04, 0.04, 0.04, 0.04],\n [0.04, 0.04, 0.04, 0.04, 0.04],\n [0.04, 0.04, 0.04, 0.04, 0.04],\n [0.04, 0.04, 0.04, 0.04, 0.04],\n [0.04, 0.04, 0.04, 0.04, 0.04]],\n\n [[0. , 0. , 0. , 0. , 0. ],\n [0. , 0. , 0. , 0. , 0. ],\n [0. , 0. , 0. , 0. , 0. ],\n [0. , 0. , 0. , 0. , 0. ],\n [0. , 0. , 0. , 0. , 0. ]],\n\n [[0. , 0. , 0. , 0. , 0. ],\n [0. , 0. , 0. , 0. , 0. ],\n [0. , 0. , 0. , 0. , 0. ],\n [0. , 0. , 0. , 0. , 0. ],\n [0. , 0. , 0. , 0. , 0. ]]],\n\n\n [[[0. , 0. , 0. , 0. , 0. ],\n [0. , 0. , 0. , 0. , 0. ],\n [0. , 0. , 0. , 0. , 0. ],\n [0. , 0. , 0. , 0. , 0. ],\n [0. , 0. , 0. , 0. , 0. ]],\n\n [[0.04, 0.04, 0.04, 0.04, 0.04],\n [0.04, 0.04, 0.04, 0.04, 0.04],\n [0.04, 0.04, 0.04, 0.04, 0.04],\n [0.04, 0.04, 0.04, 0.04, 0.04],\n [0.04, 0.04, 0.04, 0.04, 0.04]],\n\n [[0. , 0. , 0. , 0. , 0. ],\n [0. , 0. , 0. , 0. , 0. ],\n [0. , 0. , 0. , 0. , 0. ],\n [0. , 0. , 0. , 0. , 0. ],\n [0. , 0. , 0. , 0. , 0. ]]],\n\n\n [[[0. , 0. , 0. , 0. , 0. ],\n [0. , 0. , 0. , 0. , 0. ],\n [0. , 0. , 0. , 0. , 0. ],\n [0. , 0. , 0. , 0. , 0. ],\n [0. , 0. , 0. , 0. , 0. ]],\n\n [[0. , 0. , 0. , 0. , 0. ],\n [0. , 0. , 0. , 0. , 0. ],\n [0. , 0. , 0. , 0. , 0. ],\n [0. , 0. , 0. , 0. , 0. ],\n [0. , 0. , 0. , 0. , 0. ]],\n\n [[0.04, 0.04, 0.04, 0.04, 0.04],\n [0.04, 0.04, 0.04, 0.04, 0.04],\n [0.04, 0.04, 0.04, 0.04, 0.04],\n [0.04, 0.04, 0.04, 0.04, 0.04],\n [0.04, 0.04, 0.04, 0.04, 0.04]]]], dtype=float32)\n\n\n\nconv = Conv2D(filters=3, kernel_size=(5, 5), padding=\"same\", kernel_initializer=my_init)\n\n\nfig, (ax0, ax1) = plt.subplots(ncols=2, figsize=(10, 5))\nax0.imshow(img_in[0].astype('uint8'))\n\nimg_out = conv(img_in)\nprint(img_out.shape)\nnp_img_out = img_out[0].numpy()\nax1.imshow(np_img_out.astype('uint8'));\n\n(1, 600, 600, 3)\n\n\n\n\n\n\n\n\n\n\nDefine una capa Conv2D con 3 filtros (5x5) que calculen la función identidad (preserven la imagen de entrada sin mezclar los colores).\n\nCambia el stride a 2. ¿Cuál es el tamaño de la imagen de salida?\n\nCambia el padding a VALID. ¿Qué se observa?\n\n\ndef my_init(shape=(5, 5, 3, 3), dtype=None):\n array = np.zeros(shape=shape, dtype=\"float32\")\n array[2, 2] = np.eye(3)\n return array\n\n\nconv_strides_same = Conv2D(filters=3, kernel_size=5, strides=2,\n padding=\"same\", kernel_initializer=my_init,\n input_shape=(None, None, 3))\n\nconv_strides_valid = Conv2D(filters=3, kernel_size=5, strides=2,\n padding=\"valid\", \n kernel_initializer=my_init)\n\nimg_in = np.expand_dims(sample_image, 0)\nimg_out_same = conv_strides_same(img_in)[0].numpy()\nimg_out_valid = conv_strides_valid(img_in)[0].numpy()\n\nprint(\"Shape of original image:\", sample_image.shape)\nprint(\"Shape of result with SAME padding:\", img_out_same.shape)\nprint(\"Shape of result with VALID padding:\", img_out_valid.shape)\n\nfig, (ax0, ax1, ax2) = plt.subplots(ncols=3, figsize=(12, 4))\nax0.imshow(img_in[0].astype(np.uint8))\nax1.imshow(img_out_same.astype(np.uint8))\nax2.imshow(img_out_valid.astype(np.uint8));\n\n/Users/aveloz/miniconda3/lib/python3.9/site-packages/keras/src/layers/convolutional/base_conv.py:107: UserWarning: Do not pass an `input_shape`/`input_dim` argument to a layer. When using Sequential models, prefer using an `Input(shape)` object as the first layer in the model instead.\n super().__init__(activity_regularizer=activity_regularizer, **kwargs)\n\n\nShape of original image: (600, 600, 3)\nShape of result with SAME padding: (300, 300, 3)\nShape of result with VALID padding: (298, 298, 3)\n\n\n\n\n\n\n\n\n\nEl stride de 2 divide el tamaño de la imagen a la mitad. En el caso de padding ‘VALID’, no agrega padding, por lo tanto el tamaño de la imagen de salida es el mismo que el tamaño original menos 2 debido al tamaño del kernel.\n\n\nDetección de bordes en imágenes en escala de grises\n\n# convert image to greyscale\ngrey_sample_image = sample_image.mean(axis=2)\n\n# add the channel dimension even if it's only one channel so\n# as to be consistent with Keras expectations.\ngrey_sample_image = grey_sample_image[:, :, np.newaxis]\n\n\n# matplotlib does not like the extra dim for the color channel\n# when plotting gray-level images. Let's use squeeze:\nplt.imshow(np.squeeze(grey_sample_image.astype(np.uint8)),\n cmap=plt.cm.gray);\n\n\n\n\n\n\n\n\n\ndef my_init(shape, dtype=None):\n array = np.array([\n [0.0, 0.2, 0.0],\n [0.0, -0.2, 0.0],\n [0.0, 0.0, 0.0],\n ], dtype=\"float32\")\n # adds two axis to match the required shape (3,3,1,1)\n return np.expand_dims(np.expand_dims(array,-1),-1)\n\n\nconv_edge = Conv2D(kernel_size=(3,3), filters=1,\n padding=\"same\", kernel_initializer=my_init,\n input_shape=(None, None, 1))\n\nimg_in = np.expand_dims(grey_sample_image, 0)\nimg_out = conv_edge(img_in).numpy()\n\nfig, (ax0, ax1) = plt.subplots(ncols=2, figsize=(10, 5))\nax0.imshow(np.squeeze(img_in[0]).astype(np.uint8),\n cmap=plt.cm.gray);\nax1.imshow(np.squeeze(img_out[0]).astype(np.uint8),\n cmap=plt.cm.gray);\n\n# vertical edge detection.\n# Many other kernels work, for example differences\n# of centered gaussians\n#\n# You may try with this filter as well\n# np.array([\n# [ 0.1, 0.2, 0.1],\n# [ 0.0, 0.0, 0.0],\n# [-0.1, -0.2, -0.1],\n# ], dtype=\"float32\")\n\n\n\n\n\n\n\n\n\n\nPooling y strides con convoluciones\n\nUsa MaxPool2D para aplicar un max pooling de 2x2 con strides de 2 a la imagen. ¿Cuál es el impacto en el tamaño de la imagen?\n\nUsa AvgPool2D para aplicar un average pooling.\n¿Es posible calcular un max pooling y un average pooling con kernels elegidos a mano?\n\nImplementa un average pooling de 3x3 con una convolución regular Conv2D, con strides, kernel y padding bien elegidos.\n\n\nfrom tensorflow.keras.layers import MaxPool2D, AvgPool2D\n\n\nmax_pool = MaxPool2D(2, strides=2)\nimg_in = np.expand_dims(sample_image, 0)\nimg_out = max_pool(img_in).numpy()\n\nprint(\"input shape:\", img_in.shape)\nprint(\"output shape:\", img_out.shape)\n\nfig, (ax0, ax1) = plt.subplots(ncols=2, figsize=(10, 5))\nax0.imshow(img_in[0].astype('uint8'))\nax1.imshow(img_out[0].astype('uint8'));\n\n# no es posible hacer un max pooling con kernels. Sí es posible hacer un average pooling.\n\ninput shape: (1, 600, 600, 3)\noutput shape: (1, 300, 300, 3)\n\n\n\n\n\n\n\n\n\n\navg_pool = AvgPool2D(3, strides=3, input_shape=(None, None, 3))\n\nimg_in = np.expand_dims(sample_image, 0)\nimg_out_avg_pool = avg_pool(img_in).numpy()\n\ndef my_init(shape=(3, 3, 3, 3), dtype=None):\n array = np.zeros(shape=shape, dtype=\"float32\")\n array[:, :, 0, 0] = 1 / 9.\n array[:, :, 1, 1] = 1 / 9.\n array[:, :, 2, 2] = 1 / 9.\n return array\n\nconv_avg = Conv2D(kernel_size=3, filters=3, strides=3,\n padding=\"valid\", \n kernel_initializer=my_init,\n input_shape=(None, None, 3))\n\nimg_out_conv = conv_avg(np.expand_dims(sample_image, 0)).numpy()\n\nprint(\"input shape:\", img_in.shape)\nprint(\"output avg pool shape:\", img_out_avg_pool.shape)\nprint(\"output conv shape:\", img_out_conv.shape)\n\nfig, (ax0, ax1, ax2) = plt.subplots(ncols=3, figsize=(10, 5))\nax0.imshow(img_in[0].astype('uint8'))\nax1.imshow(img_out_avg_pool[0].astype('uint8'))\nax2.imshow(img_out_conv[0].astype('uint8'));\n\nprint(\"Avg pool is similar to Conv ? -\", np.allclose(img_out_avg_pool, img_out_conv))\n\ninput shape: (1, 600, 600, 3)\noutput avg pool shape: (1, 200, 200, 3)\noutput conv shape: (1, 200, 200, 3)\nAvg pool is similar to Conv ? - True\n\n\n/Users/aveloz/miniconda3/lib/python3.9/site-packages/keras/src/layers/pooling/base_pooling.py:23: UserWarning: Do not pass an `input_shape`/`input_dim` argument to a layer. When using Sequential models, prefer using an `Input(shape)` object as the first layer in the model instead.\n super().__init__(name=name, **kwargs)"
},
{
"objectID": "bme423/ejemplos/cnn-02-pretr.html",
"href": "bme423/ejemplos/cnn-02-pretr.html",
"title": "Uso de un modelo CNN preentrenado en Keras",
"section": "",
"text": "Objetivos:\n\nCargar un modelo ResNet50 preentrenado desde Keras Zoo\n\nConstruir un modelo sin la última capa y calcular representaciones de imágenes\n\nExplorar la calidad de las representaciones con t-SNE\n\nReentrenar la última capa en un conjunto de datos de gatos vs. perros\n\n\n\nDescargas\nimages_pascalVOC.zip\nimg_emb.h5\n\n%matplotlib inline\n\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport os\nfrom zipfile import ZipFile\n\nif not os.path.exists(\"images_resize\"):\n print('Extracting image files...')\n zf = ZipFile('images_pascalVOC.zip')\n zf.extractall('.')\n\n\nfrom keras.applications.resnet50 import ResNet50\nfrom keras.models import Model\nfrom keras.preprocessing import image\n\nmodel = ResNet50(include_top=True, weights='imagenet')\n\n\nprint(model.summary())\n\nModel: \"resnet50\"\n\n\n\n┏━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┓\n┃ Layer (type) ┃ Output Shape ┃ Param # ┃ Connected to ┃\n┡━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━┩\n│ input_layer │ (None, 224, 224, │ 0 │ - │\n│ (InputLayer) │ 3) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv1_pad │ (None, 230, 230, │ 0 │ input_layer[0][0] │\n│ (ZeroPadding2D) │ 3) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv1_conv (Conv2D) │ (None, 112, 112, │ 9,472 │ conv1_pad[0][0] │\n│ │ 64) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv1_bn │ (None, 112, 112, │ 256 │ conv1_conv[0][0] │\n│ (BatchNormalizatio… │ 64) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv1_relu │ (None, 112, 112, │ 0 │ conv1_bn[0][0] │\n│ (Activation) │ 64) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ pool1_pad │ (None, 114, 114, │ 0 │ conv1_relu[0][0] │\n│ (ZeroPadding2D) │ 64) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ pool1_pool │ (None, 56, 56, │ 0 │ pool1_pad[0][0] │\n│ (MaxPooling2D) │ 64) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2_block1_1_conv │ (None, 56, 56, │ 4,160 │ pool1_pool[0][0] │\n│ (Conv2D) │ 64) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2_block1_1_bn │ (None, 56, 56, │ 256 │ conv2_block1_1_c… │\n│ (BatchNormalizatio… │ 64) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2_block1_1_relu │ (None, 56, 56, │ 0 │ conv2_block1_1_b… │\n│ (Activation) │ 64) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2_block1_2_conv │ (None, 56, 56, │ 36,928 │ conv2_block1_1_r… │\n│ (Conv2D) │ 64) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2_block1_2_bn │ (None, 56, 56, │ 256 │ conv2_block1_2_c… │\n│ (BatchNormalizatio… │ 64) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2_block1_2_relu │ (None, 56, 56, │ 0 │ conv2_block1_2_b… │\n│ (Activation) │ 64) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2_block1_0_conv │ (None, 56, 56, │ 16,640 │ pool1_pool[0][0] │\n│ (Conv2D) │ 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2_block1_3_conv │ (None, 56, 56, │ 16,640 │ conv2_block1_2_r… │\n│ (Conv2D) │ 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2_block1_0_bn │ (None, 56, 56, │ 1,024 │ conv2_block1_0_c… │\n│ (BatchNormalizatio… │ 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2_block1_3_bn │ (None, 56, 56, │ 1,024 │ conv2_block1_3_c… │\n│ (BatchNormalizatio… │ 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2_block1_add │ (None, 56, 56, │ 0 │ conv2_block1_0_b… │\n│ (Add) │ 256) │ │ conv2_block1_3_b… │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2_block1_out │ (None, 56, 56, │ 0 │ conv2_block1_add… │\n│ (Activation) │ 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2_block2_1_conv │ (None, 56, 56, │ 16,448 │ conv2_block1_out… │\n│ (Conv2D) │ 64) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2_block2_1_bn │ (None, 56, 56, │ 256 │ conv2_block2_1_c… │\n│ (BatchNormalizatio… │ 64) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2_block2_1_relu │ (None, 56, 56, │ 0 │ conv2_block2_1_b… │\n│ (Activation) │ 64) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2_block2_2_conv │ (None, 56, 56, │ 36,928 │ conv2_block2_1_r… │\n│ (Conv2D) │ 64) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2_block2_2_bn │ (None, 56, 56, │ 256 │ conv2_block2_2_c… │\n│ (BatchNormalizatio… │ 64) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2_block2_2_relu │ (None, 56, 56, │ 0 │ conv2_block2_2_b… │\n│ (Activation) │ 64) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2_block2_3_conv │ (None, 56, 56, │ 16,640 │ conv2_block2_2_r… │\n│ (Conv2D) │ 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2_block2_3_bn │ (None, 56, 56, │ 1,024 │ conv2_block2_3_c… │\n│ (BatchNormalizatio… │ 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2_block2_add │ (None, 56, 56, │ 0 │ conv2_block1_out… │\n│ (Add) │ 256) │ │ conv2_block2_3_b… │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2_block2_out │ (None, 56, 56, │ 0 │ conv2_block2_add… │\n│ (Activation) │ 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2_block3_1_conv │ (None, 56, 56, │ 16,448 │ conv2_block2_out… │\n│ (Conv2D) │ 64) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2_block3_1_bn │ (None, 56, 56, │ 256 │ conv2_block3_1_c… │\n│ (BatchNormalizatio… │ 64) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2_block3_1_relu │ (None, 56, 56, │ 0 │ conv2_block3_1_b… │\n│ (Activation) │ 64) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2_block3_2_conv │ (None, 56, 56, │ 36,928 │ conv2_block3_1_r… │\n│ (Conv2D) │ 64) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2_block3_2_bn │ (None, 56, 56, │ 256 │ conv2_block3_2_c… │\n│ (BatchNormalizatio… │ 64) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2_block3_2_relu │ (None, 56, 56, │ 0 │ conv2_block3_2_b… │\n│ (Activation) │ 64) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2_block3_3_conv │ (None, 56, 56, │ 16,640 │ conv2_block3_2_r… │\n│ (Conv2D) │ 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2_block3_3_bn │ (None, 56, 56, │ 1,024 │ conv2_block3_3_c… │\n│ (BatchNormalizatio… │ 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2_block3_add │ (None, 56, 56, │ 0 │ conv2_block2_out… │\n│ (Add) │ 256) │ │ conv2_block3_3_b… │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2_block3_out │ (None, 56, 56, │ 0 │ conv2_block3_add… │\n│ (Activation) │ 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block1_1_conv │ (None, 28, 28, │ 32,896 │ conv2_block3_out… │\n│ (Conv2D) │ 128) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block1_1_bn │ (None, 28, 28, │ 512 │ conv3_block1_1_c… │\n│ (BatchNormalizatio… │ 128) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block1_1_relu │ (None, 28, 28, │ 0 │ conv3_block1_1_b… │\n│ (Activation) │ 128) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block1_2_conv │ (None, 28, 28, │ 147,584 │ conv3_block1_1_r… │\n│ (Conv2D) │ 128) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block1_2_bn │ (None, 28, 28, │ 512 │ conv3_block1_2_c… │\n│ (BatchNormalizatio… │ 128) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block1_2_relu │ (None, 28, 28, │ 0 │ conv3_block1_2_b… │\n│ (Activation) │ 128) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block1_0_conv │ (None, 28, 28, │ 131,584 │ conv2_block3_out… │\n│ (Conv2D) │ 512) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block1_3_conv │ (None, 28, 28, │ 66,048 │ conv3_block1_2_r… │\n│ (Conv2D) │ 512) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block1_0_bn │ (None, 28, 28, │ 2,048 │ conv3_block1_0_c… │\n│ (BatchNormalizatio… │ 512) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block1_3_bn │ (None, 28, 28, │ 2,048 │ conv3_block1_3_c… │\n│ (BatchNormalizatio… │ 512) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block1_add │ (None, 28, 28, │ 0 │ conv3_block1_0_b… │\n│ (Add) │ 512) │ │ conv3_block1_3_b… │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block1_out │ (None, 28, 28, │ 0 │ conv3_block1_add… │\n│ (Activation) │ 512) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block2_1_conv │ (None, 28, 28, │ 65,664 │ conv3_block1_out… │\n│ (Conv2D) │ 128) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block2_1_bn │ (None, 28, 28, │ 512 │ conv3_block2_1_c… │\n│ (BatchNormalizatio… │ 128) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block2_1_relu │ (None, 28, 28, │ 0 │ conv3_block2_1_b… │\n│ (Activation) │ 128) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block2_2_conv │ (None, 28, 28, │ 147,584 │ conv3_block2_1_r… │\n│ (Conv2D) │ 128) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block2_2_bn │ (None, 28, 28, │ 512 │ conv3_block2_2_c… │\n│ (BatchNormalizatio… │ 128) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block2_2_relu │ (None, 28, 28, │ 0 │ conv3_block2_2_b… │\n│ (Activation) │ 128) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block2_3_conv │ (None, 28, 28, │ 66,048 │ conv3_block2_2_r… │\n│ (Conv2D) │ 512) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block2_3_bn │ (None, 28, 28, │ 2,048 │ conv3_block2_3_c… │\n│ (BatchNormalizatio… │ 512) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block2_add │ (None, 28, 28, │ 0 │ conv3_block1_out… │\n│ (Add) │ 512) │ │ conv3_block2_3_b… │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block2_out │ (None, 28, 28, │ 0 │ conv3_block2_add… │\n│ (Activation) │ 512) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block3_1_conv │ (None, 28, 28, │ 65,664 │ conv3_block2_out… │\n│ (Conv2D) │ 128) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block3_1_bn │ (None, 28, 28, │ 512 │ conv3_block3_1_c… │\n│ (BatchNormalizatio… │ 128) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block3_1_relu │ (None, 28, 28, │ 0 │ conv3_block3_1_b… │\n│ (Activation) │ 128) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block3_2_conv │ (None, 28, 28, │ 147,584 │ conv3_block3_1_r… │\n│ (Conv2D) │ 128) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block3_2_bn │ (None, 28, 28, │ 512 │ conv3_block3_2_c… │\n│ (BatchNormalizatio… │ 128) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block3_2_relu │ (None, 28, 28, │ 0 │ conv3_block3_2_b… │\n│ (Activation) │ 128) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block3_3_conv │ (None, 28, 28, │ 66,048 │ conv3_block3_2_r… │\n│ (Conv2D) │ 512) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block3_3_bn │ (None, 28, 28, │ 2,048 │ conv3_block3_3_c… │\n│ (BatchNormalizatio… │ 512) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block3_add │ (None, 28, 28, │ 0 │ conv3_block2_out… │\n│ (Add) │ 512) │ │ conv3_block3_3_b… │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block3_out │ (None, 28, 28, │ 0 │ conv3_block3_add… │\n│ (Activation) │ 512) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block4_1_conv │ (None, 28, 28, │ 65,664 │ conv3_block3_out… │\n│ (Conv2D) │ 128) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block4_1_bn │ (None, 28, 28, │ 512 │ conv3_block4_1_c… │\n│ (BatchNormalizatio… │ 128) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block4_1_relu │ (None, 28, 28, │ 0 │ conv3_block4_1_b… │\n│ (Activation) │ 128) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block4_2_conv │ (None, 28, 28, │ 147,584 │ conv3_block4_1_r… │\n│ (Conv2D) │ 128) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block4_2_bn │ (None, 28, 28, │ 512 │ conv3_block4_2_c… │\n│ (BatchNormalizatio… │ 128) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block4_2_relu │ (None, 28, 28, │ 0 │ conv3_block4_2_b… │\n│ (Activation) │ 128) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block4_3_conv │ (None, 28, 28, │ 66,048 │ conv3_block4_2_r… │\n│ (Conv2D) │ 512) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block4_3_bn │ (None, 28, 28, │ 2,048 │ conv3_block4_3_c… │\n│ (BatchNormalizatio… │ 512) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block4_add │ (None, 28, 28, │ 0 │ conv3_block3_out… │\n│ (Add) │ 512) │ │ conv3_block4_3_b… │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block4_out │ (None, 28, 28, │ 0 │ conv3_block4_add… │\n│ (Activation) │ 512) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block1_1_conv │ (None, 14, 14, │ 131,328 │ conv3_block4_out… │\n│ (Conv2D) │ 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block1_1_bn │ (None, 14, 14, │ 1,024 │ conv4_block1_1_c… │\n│ (BatchNormalizatio… │ 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block1_1_relu │ (None, 14, 14, │ 0 │ conv4_block1_1_b… │\n│ (Activation) │ 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block1_2_conv │ (None, 14, 14, │ 590,080 │ conv4_block1_1_r… │\n│ (Conv2D) │ 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block1_2_bn │ (None, 14, 14, │ 1,024 │ conv4_block1_2_c… │\n│ (BatchNormalizatio… │ 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block1_2_relu │ (None, 14, 14, │ 0 │ conv4_block1_2_b… │\n│ (Activation) │ 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block1_0_conv │ (None, 14, 14, │ 525,312 │ conv3_block4_out… │\n│ (Conv2D) │ 1024) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block1_3_conv │ (None, 14, 14, │ 263,168 │ conv4_block1_2_r… │\n│ (Conv2D) │ 1024) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block1_0_bn │ (None, 14, 14, │ 4,096 │ conv4_block1_0_c… │\n│ (BatchNormalizatio… │ 1024) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block1_3_bn │ (None, 14, 14, │ 4,096 │ conv4_block1_3_c… │\n│ (BatchNormalizatio… │ 1024) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block1_add │ (None, 14, 14, │ 0 │ conv4_block1_0_b… │\n│ (Add) │ 1024) │ │ conv4_block1_3_b… │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block1_out │ (None, 14, 14, │ 0 │ conv4_block1_add… │\n│ (Activation) │ 1024) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block2_1_conv │ (None, 14, 14, │ 262,400 │ conv4_block1_out… │\n│ (Conv2D) │ 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block2_1_bn │ (None, 14, 14, │ 1,024 │ conv4_block2_1_c… │\n│ (BatchNormalizatio… │ 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block2_1_relu │ (None, 14, 14, │ 0 │ conv4_block2_1_b… │\n│ (Activation) │ 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block2_2_conv │ (None, 14, 14, │ 590,080 │ conv4_block2_1_r… │\n│ (Conv2D) │ 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block2_2_bn │ (None, 14, 14, │ 1,024 │ conv4_block2_2_c… │\n│ (BatchNormalizatio… │ 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block2_2_relu │ (None, 14, 14, │ 0 │ conv4_block2_2_b… │\n│ (Activation) │ 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block2_3_conv │ (None, 14, 14, │ 263,168 │ conv4_block2_2_r… │\n│ (Conv2D) │ 1024) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block2_3_bn │ (None, 14, 14, │ 4,096 │ conv4_block2_3_c… │\n│ (BatchNormalizatio… │ 1024) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block2_add │ (None, 14, 14, │ 0 │ conv4_block1_out… │\n│ (Add) │ 1024) │ │ conv4_block2_3_b… │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block2_out │ (None, 14, 14, │ 0 │ conv4_block2_add… │\n│ (Activation) │ 1024) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block3_1_conv │ (None, 14, 14, │ 262,400 │ conv4_block2_out… │\n│ (Conv2D) │ 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block3_1_bn │ (None, 14, 14, │ 1,024 │ conv4_block3_1_c… │\n│ (BatchNormalizatio… │ 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block3_1_relu │ (None, 14, 14, │ 0 │ conv4_block3_1_b… │\n│ (Activation) │ 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block3_2_conv │ (None, 14, 14, │ 590,080 │ conv4_block3_1_r… │\n│ (Conv2D) │ 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block3_2_bn │ (None, 14, 14, │ 1,024 │ conv4_block3_2_c… │\n│ (BatchNormalizatio… │ 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block3_2_relu │ (None, 14, 14, │ 0 │ conv4_block3_2_b… │\n│ (Activation) │ 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block3_3_conv │ (None, 14, 14, │ 263,168 │ conv4_block3_2_r… │\n│ (Conv2D) │ 1024) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block3_3_bn │ (None, 14, 14, │ 4,096 │ conv4_block3_3_c… │\n│ (BatchNormalizatio… │ 1024) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block3_add │ (None, 14, 14, │ 0 │ conv4_block2_out… │\n│ (Add) │ 1024) │ │ conv4_block3_3_b… │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block3_out │ (None, 14, 14, │ 0 │ conv4_block3_add… │\n│ (Activation) │ 1024) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block4_1_conv │ (None, 14, 14, │ 262,400 │ conv4_block3_out… │\n│ (Conv2D) │ 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block4_1_bn │ (None, 14, 14, │ 1,024 │ conv4_block4_1_c… │\n│ (BatchNormalizatio… │ 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block4_1_relu │ (None, 14, 14, │ 0 │ conv4_block4_1_b… │\n│ (Activation) │ 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block4_2_conv │ (None, 14, 14, │ 590,080 │ conv4_block4_1_r… │\n│ (Conv2D) │ 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block4_2_bn │ (None, 14, 14, │ 1,024 │ conv4_block4_2_c… │\n│ (BatchNormalizatio… │ 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block4_2_relu │ (None, 14, 14, │ 0 │ conv4_block4_2_b… │\n│ (Activation) │ 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block4_3_conv │ (None, 14, 14, │ 263,168 │ conv4_block4_2_r… │\n│ (Conv2D) │ 1024) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block4_3_bn │ (None, 14, 14, │ 4,096 │ conv4_block4_3_c… │\n│ (BatchNormalizatio… │ 1024) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block4_add │ (None, 14, 14, │ 0 │ conv4_block3_out… │\n│ (Add) │ 1024) │ │ conv4_block4_3_b… │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block4_out │ (None, 14, 14, │ 0 │ conv4_block4_add… │\n│ (Activation) │ 1024) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block5_1_conv │ (None, 14, 14, │ 262,400 │ conv4_block4_out… │\n│ (Conv2D) │ 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block5_1_bn │ (None, 14, 14, │ 1,024 │ conv4_block5_1_c… │\n│ (BatchNormalizatio… │ 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block5_1_relu │ (None, 14, 14, │ 0 │ conv4_block5_1_b… │\n│ (Activation) │ 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block5_2_conv │ (None, 14, 14, │ 590,080 │ conv4_block5_1_r… │\n│ (Conv2D) │ 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block5_2_bn │ (None, 14, 14, │ 1,024 │ conv4_block5_2_c… │\n│ (BatchNormalizatio… │ 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block5_2_relu │ (None, 14, 14, │ 0 │ conv4_block5_2_b… │\n│ (Activation) │ 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block5_3_conv │ (None, 14, 14, │ 263,168 │ conv4_block5_2_r… │\n│ (Conv2D) │ 1024) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block5_3_bn │ (None, 14, 14, │ 4,096 │ conv4_block5_3_c… │\n│ (BatchNormalizatio… │ 1024) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block5_add │ (None, 14, 14, │ 0 │ conv4_block4_out… │\n│ (Add) │ 1024) │ │ conv4_block5_3_b… │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block5_out │ (None, 14, 14, │ 0 │ conv4_block5_add… │\n│ (Activation) │ 1024) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block6_1_conv │ (None, 14, 14, │ 262,400 │ conv4_block5_out… │\n│ (Conv2D) │ 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block6_1_bn │ (None, 14, 14, │ 1,024 │ conv4_block6_1_c… │\n│ (BatchNormalizatio… │ 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block6_1_relu │ (None, 14, 14, │ 0 │ conv4_block6_1_b… │\n│ (Activation) │ 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block6_2_conv │ (None, 14, 14, │ 590,080 │ conv4_block6_1_r… │\n│ (Conv2D) │ 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block6_2_bn │ (None, 14, 14, │ 1,024 │ conv4_block6_2_c… │\n│ (BatchNormalizatio… │ 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block6_2_relu │ (None, 14, 14, │ 0 │ conv4_block6_2_b… │\n│ (Activation) │ 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block6_3_conv │ (None, 14, 14, │ 263,168 │ conv4_block6_2_r… │\n│ (Conv2D) │ 1024) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block6_3_bn │ (None, 14, 14, │ 4,096 │ conv4_block6_3_c… │\n│ (BatchNormalizatio… │ 1024) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block6_add │ (None, 14, 14, │ 0 │ conv4_block5_out… │\n│ (Add) │ 1024) │ │ conv4_block6_3_b… │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block6_out │ (None, 14, 14, │ 0 │ conv4_block6_add… │\n│ (Activation) │ 1024) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv5_block1_1_conv │ (None, 7, 7, 512) │ 524,800 │ conv4_block6_out… │\n│ (Conv2D) │ │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv5_block1_1_bn │ (None, 7, 7, 512) │ 2,048 │ conv5_block1_1_c… │\n│ (BatchNormalizatio… │ │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv5_block1_1_relu │ (None, 7, 7, 512) │ 0 │ conv5_block1_1_b… │\n│ (Activation) │ │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv5_block1_2_conv │ (None, 7, 7, 512) │ 2,359,808 │ conv5_block1_1_r… │\n│ (Conv2D) │ │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv5_block1_2_bn │ (None, 7, 7, 512) │ 2,048 │ conv5_block1_2_c… │\n│ (BatchNormalizatio… │ │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv5_block1_2_relu │ (None, 7, 7, 512) │ 0 │ conv5_block1_2_b… │\n│ (Activation) │ │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv5_block1_0_conv │ (None, 7, 7, │ 2,099,200 │ conv4_block6_out… │\n│ (Conv2D) │ 2048) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv5_block1_3_conv │ (None, 7, 7, │ 1,050,624 │ conv5_block1_2_r… │\n│ (Conv2D) │ 2048) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv5_block1_0_bn │ (None, 7, 7, │ 8,192 │ conv5_block1_0_c… │\n│ (BatchNormalizatio… │ 2048) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv5_block1_3_bn │ (None, 7, 7, │ 8,192 │ conv5_block1_3_c… │\n│ (BatchNormalizatio… │ 2048) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv5_block1_add │ (None, 7, 7, │ 0 │ conv5_block1_0_b… │\n│ (Add) │ 2048) │ │ conv5_block1_3_b… │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv5_block1_out │ (None, 7, 7, │ 0 │ conv5_block1_add… │\n│ (Activation) │ 2048) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv5_block2_1_conv │ (None, 7, 7, 512) │ 1,049,088 │ conv5_block1_out… │\n│ (Conv2D) │ │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv5_block2_1_bn │ (None, 7, 7, 512) │ 2,048 │ conv5_block2_1_c… │\n│ (BatchNormalizatio… │ │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv5_block2_1_relu │ (None, 7, 7, 512) │ 0 │ conv5_block2_1_b… │\n│ (Activation) │ │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv5_block2_2_conv │ (None, 7, 7, 512) │ 2,359,808 │ conv5_block2_1_r… │\n│ (Conv2D) │ │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv5_block2_2_bn │ (None, 7, 7, 512) │ 2,048 │ conv5_block2_2_c… │\n│ (BatchNormalizatio… │ │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv5_block2_2_relu │ (None, 7, 7, 512) │ 0 │ conv5_block2_2_b… │\n│ (Activation) │ │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv5_block2_3_conv │ (None, 7, 7, │ 1,050,624 │ conv5_block2_2_r… │\n│ (Conv2D) │ 2048) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv5_block2_3_bn │ (None, 7, 7, │ 8,192 │ conv5_block2_3_c… │\n│ (BatchNormalizatio… │ 2048) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv5_block2_add │ (None, 7, 7, │ 0 │ conv5_block1_out… │\n│ (Add) │ 2048) │ │ conv5_block2_3_b… │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv5_block2_out │ (None, 7, 7, │ 0 │ conv5_block2_add… │\n│ (Activation) │ 2048) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv5_block3_1_conv │ (None, 7, 7, 512) │ 1,049,088 │ conv5_block2_out… │\n│ (Conv2D) │ │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv5_block3_1_bn │ (None, 7, 7, 512) │ 2,048 │ conv5_block3_1_c… │\n│ (BatchNormalizatio… │ │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv5_block3_1_relu │ (None, 7, 7, 512) │ 0 │ conv5_block3_1_b… │\n│ (Activation) │ │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv5_block3_2_conv │ (None, 7, 7, 512) │ 2,359,808 │ conv5_block3_1_r… │\n│ (Conv2D) │ │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv5_block3_2_bn │ (None, 7, 7, 512) │ 2,048 │ conv5_block3_2_c… │\n│ (BatchNormalizatio… │ │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv5_block3_2_relu │ (None, 7, 7, 512) │ 0 │ conv5_block3_2_b… │\n│ (Activation) │ │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv5_block3_3_conv │ (None, 7, 7, │ 1,050,624 │ conv5_block3_2_r… │\n│ (Conv2D) │ 2048) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv5_block3_3_bn │ (None, 7, 7, │ 8,192 │ conv5_block3_3_c… │\n│ (BatchNormalizatio… │ 2048) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv5_block3_add │ (None, 7, 7, │ 0 │ conv5_block2_out… │\n│ (Add) │ 2048) │ │ conv5_block3_3_b… │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv5_block3_out │ (None, 7, 7, │ 0 │ conv5_block3_add… │\n│ (Activation) │ 2048) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ avg_pool │ (None, 2048) │ 0 │ conv5_block3_out… │\n│ (GlobalAveragePool… │ │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ predictions (Dense) │ (None, 1000) │ 2,049,000 │ avg_pool[0][0] │\n└─────────────────────┴───────────────────┴────────────┴───────────────────┘\n\n\n\n Total params: 25,636,712 (97.80 MB)\n\n\n\n Trainable params: 25,583,592 (97.59 MB)\n\n\n\n Non-trainable params: 53,120 (207.50 KB)\n\n\n\nNone\n\n\n\n\nClasificación de una imagen\n\nAbrir una imagen, preprocesarla y construir un batch de 1 imagen\nUsar el modelo para clasificar esa imagen\nDecodificar las predicciones usando decode_predictions de Keras\n\n\nNotas:\n\nSe puede utilizar preprocess_input para el preprocesamiento de la imagen\n\nProbar el código con \"images_resize/000007.jpg\"\n\n\nimport numpy as np\nimport matplotlib.pyplot as plt\nfrom keras.applications.imagenet_utils import preprocess_input, decode_predictions\nfrom PIL import Image\nfrom imageio.v2 import imread\n\npath = \"images_resize/000007.jpg\"\n\n# Read image using imageio\nimg = imread(path)\nplt.imshow(img)\n\n# Resize image using PIL\nimg_pil = Image.fromarray(img)\nimg_resized = img_pil.resize((224, 224))\nimg = np.array(img_resized).astype(\"float32\")\n\n# Add a batch dimension\nimg_batch = preprocess_input(img[np.newaxis])\n\npredictions = model.predict(img_batch)\ndecoded_predictions = decode_predictions(predictions)\n\nfor s, name, score in decoded_predictions[0]:\n print(name, score)\n\n\n1/1 ━━━━━━━━━━━━━━━━━━━━ 1s 713ms/step\n\nconvertible 0.9606545\n\nbeach_wagon 0.014514458\n\nsports_car 0.011048748\n\ngrille 0.0050838953\n\ncar_wheel 0.0031563553\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nCálculo de la representación de una imagen\n\nfrom keras.applications.resnet50 import ResNet50\nfrom keras.models import Model\nfrom keras.preprocessing import image\n\nmodel = ResNet50(include_top=False, weights='imagenet')\ninput = model.input\noutput = model.output\nbase_model = Model(input, output)\n\n\nrepresentation = base_model.predict(img_batch)\nprint(\"shape of representation:\", representation.shape)\nprint(\"proportion of zero valued axis: %0.3f\" % np.mean(representation[0]==0))\n\n\n1/1 ━━━━━━━━━━━━━━━━━━━━ 1s 663ms/step\n\nshape of representation: (1, 7, 7, 2048)\n\nproportion of zero valued axis: 0.852\n\n\n\n\nCalcular las representaciones de todas las imágenes puede ser un proceso costoso. Normalmente, esto se realiza utilizando grandes batches en una GPU.\nPara la siguiente parte, utilizaremos representaciones precalculadas guardadas en formato h5. Esto se realiza utilizando el script process_images.py.\n\nimport os\npaths = [\"images_resize/\" + path for path in sorted(os.listdir(\"images_resize/\"))]\n\n\nimport h5py\n\n# Load pre-calculated representations\nh5f = h5py.File('img_emb.h5','r')\nout_tensors = h5f['img_emb'][:]\nh5f.close()\n\nLas representaciones son densas.\n\n# Proportion of zeros in the vector of the first image:\nprint(\"proportion of zeros (first image):\", np.mean(out_tensors[0] == 0.0))\n\n# Proportion of negative values in the full representation tensor\nprint(\"proportion of strictly negative values:\", np.mean(out_tensors < 0.0))\n\n# For all representations:\nplt.hist(np.mean(out_tensors == 0.0, axis=1))\nplt.title(\"Fraction of zero values per image vector\");\n\n# These 0 values come from the different ReLU units.\n# They propagate through the layers, and there can be many.\n# If a network has too many of them, a lot of computation\n# / memory is wasted.\n\nproportion of zeros (first image): 0.15380859375\nproportion of strictly negative values: 0.0\n\n\n\n\n\n\n\n\n\n\nfrom sklearn.manifold import TSNE\n\nimg_emb_tsne = TSNE(perplexity=30).fit_transform(out_tensors)\n\n\nimport matplotlib.pyplot as plt\n\nplt.figure(figsize=(10, 10))\nplt.scatter(img_emb_tsne[:, 0], img_emb_tsne[:, 1]);\nplt.xticks(()); plt.yticks(());\nplt.show()\n\n\n\n\n\n\n\n\nOtra visualización de los embeddings en el espacio generado con TSNE.\n\nimport matplotlib\nimport matplotlib.pyplot as plt\nfrom matplotlib.offsetbox import OffsetImage, AnnotationBbox\nfrom PIL import Image\nfrom imageio.v2 import imread\n\n\ndef imscatter(x, y, paths, ax=None, zoom=1, linewidth=0):\n if ax is None:\n ax = plt.gca()\n x, y = np.atleast_1d(x, y)\n artists = []\n for x0, y0, p in zip(x, y, paths):\n try:\n im = imread(p)\n except:\n print(p)\n continue\n # Resize image using PIL\n img_pil = Image.fromarray(im)\n img_resized = img_pil.resize((224, 224))\n im = np.array(img_resized)\n\n im = OffsetImage(im, zoom=zoom)\n ab = AnnotationBbox(im, (x0, y0), xycoords='data',\n frameon=True, pad=0.1, \n bboxprops=dict(edgecolor='red',\n linewidth=linewidth))\n artists.append(ax.add_artist(ab))\n ax.update_datalim(np.column_stack([x, y]))\n ax.autoscale()\n return artists\n\n\nfig, ax = plt.subplots(figsize=(50, 50))\nimscatter(img_emb_tsne[:, 0], img_emb_tsne[:, 1], paths, zoom=0.5, ax=ax)\nplt.savefig('tsne.png')\n\n\n\n\n\n\n\n\n\n\nBúsqueda de imágenes similares\n\ndef display(img):\n plt.figure()\n img = imread(img)\n plt.imshow(img)\n\n\nidx = 57\n\ndef most_similar(idx, top_n=5):\n dists = np.linalg.norm(out_tensors - out_tensors[idx], axis = 1)\n sorted_dists = np.argsort(dists)\n return sorted_dists[:top_n]\n\nsim = most_similar(idx)\n[display(paths[s]) for s in sim];\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nClasificación mediante Vecinos Más Cercanos\nUsando estas representaciones, es posible construir un clasificador de vecinos más cercanos. Sin embargo, las representaciones fueron aprendidas en ImageNet, que contiene imágenes centradas. Cuando introducimos imágenes de PascalVOC, se asemejan más a entradas plausibles de un sistema del mundo real.\nLa siguiente sección explora esta posibilidad calculando el histograma de similitudes entre una imagen y las demás.\n\nout_norms = np.linalg.norm(out_tensors, axis=1, keepdims=True)\nnormed_out_tensors = out_tensors / out_norms\n\n\nitem_idx = 208\ndists_to_item = np.linalg.norm(out_tensors - out_tensors[item_idx], axis=1)\ncos_to_item = np.dot(normed_out_tensors, normed_out_tensors[item_idx]) \nplt.hist(cos_to_item, bins=200)\ndisplay(paths[item_idx])\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nAl ver el histograma de similitudes anterior, se aprecia que no existe una separación clara de los límites entre clases.\nCon un conjunto de datos etiquetado, incluso con muy pocas etiquetas por clase, sería posible:\n- construir un modelo de k-Vecinos Más Cercanos,\n- construir un modelo de clasificación como una SVM u otro.\n\nitems = np.where(cos_to_item > 0.44)\nprint(items)\n[display(paths[s]) for s, _ in zip(items[0], range(10))];\n\n(array([ 4, 9, 12, 60, 82, 151, 170, 186, 187, 205, 208, 225, 252,\n 265, 274, 280, 310, 330, 331, 355, 385, 391, 397, 400, 420, 435,\n 474, 486, 490]),)"
},
{
"objectID": "bme423/projectos.html",
"href": "bme423/projectos.html",
"title": "Objetivos",
"section": "",
"text": "Al finalizar el semestre, será capaz de:\n\nComprender y aplicar los fundamentos teóricos y prácticos del procesamiento de imágenes médicas: Abordar desde la adquisición y representación de imágenes hasta el uso de técnicas de mejora y preprocesamiento, incluyendo operaciones puntuales y sobre histogramas, filtrado espacial, transformada de Fourier, filtrado mediante ecuaciones diferenciales y análisis del impacto del ruido y degradación en imágenes médicas.\nDiseñar, implementar y evaluar algoritmos de segmentación y análisis cuantitativo: Desarrollar métodos para aislar, identificar y medir estructuras anatómicas o patológicas en imágenes médicas, utilizando enfoques clásicos y avanzados que garanticen precisión y reproducibilidad.\nDesarrollar y evaluar algoritmos de reconocimiento de patrones y aprendizaje automático: Aplicar métodos de inteligencia artificial, aprendizaje supervisado (ANN, CNN), y diseño de pipelines automatizados para la clasificación y detección en imágenes médicas.\nAnalizar y ejecutar métodos de reconstrucción:: Implementar algoritmos para la reconstrucción volumétrica y bidimensional a partir de proyecciones, comprendiendo su aplicación en modalidades como tomografía.\nInterpretar especificaciones técnicas y parámetros: Analizar especificaciones críticas de equipos y softwares de procesamiento de imágenes médicas para seleccionar estrategias y herramientas apropiadas en aplicaciones clínicas.\nIntegrar conocimientos en proyectos aplicados: Planificar y ejecutar proyectos prácticos/laboratorios, documentando metódicamente los procedimientos, resultados y conclusiones, en concordancia con estándares académicos y éticos.\n\n\n\nLos proyectos deben desarrollarse durante el transcurso del semestre (no al final).\nAl final del semestre deberá hacer una presentación de 15 min, entregar un informe escrito y poner a disposición del curso un video explicativo del proyecto, el informe escrito y la implementación realizada.\nLos temas son a elección de los estudiantes.\n\n\nLa entrega de los temas de proyecto tiene como propósito verificar que el trabajo que será realizado posee la “dificultad apropiada”. Usted recibirá retroalimentación que le permitirá hacer los ajustes necesarios a su proyecto de tal manera de no resolver problemas muy simples o muy complejos.\nEn la fecha indicada debe entregar un documento de no más de dos páginas vía Aula Virtual con lo siguiente:\n\nTítulo del proyecto.\nDescripción. Esto incluye un breve contexto del tema a abordar de manera simple y concreta. Por ejemplo,\n\n“Se quiere detectar de manera automática la variable (…) en base a imágenes de (…). En la literatura se han alcanzado accuracies entre el 60-70% en el problema descrito”.\n\nProblema específico a abordar. Debe explicitar el objetivo del trabajo de manera simple y concreta. Por ejemplo,\n\n“Mi objetivo es superar las medidas de desempeño obtenidas en los artículos …”.\n“Varios artículos que resuelven el problema descrito emplean el modelo X. Mi objetivo es evaluar el modelo Y y comparar los resultados obtenidos al usar el enfoque tradicional”.\n“No existen implementaciones disponibles públicamente del método propuesto en el artículo X. Mi objetivo es implementar el método propuesto en ese artículo y reproducir los resultados obtenidos”.\n\nPunto de partida. Debe indicar si hay implementaciones disponibles de lo que usted propone desarrollar o si lo que propone hacer en este curso es la continuación de un proyecto desarrollado en otra asignatura. Debe establecer de manera clara la diferencia de lo que usted hará con lo hecho por otras personas o en su trabajo previo. Esta diferencia no necesariamente la tendrá clara en este momento, pero es algo que deberá indicar en la entrega parcial o final del proyecto.\nDataset(s). Breve descripción de los datos a utilizar, incluyendo enlaces a las bases de datos, etc.\nArtículo(s) relacionado(s). Mencione el o los artículos que de una u otra manera se relacionen con el proyecto que abordará.\n\nSi tiene más de una idea a desarrollar, debe hacer un documento por idea (no mezclar ideas de proyecto).\n\n\n\nLa entrega de los proyectos contempla lo siguiente:\n\nPresentación presencial. Tendrán una duración de 10-15 minutos.\nPresentación grabada. Todos los grupos deben grabar su presentación (duración máxima 15 minutos). Para la entrega de esto, no debe subir videos directamente al Aula Virtual, sino copiar un enlace en el informe escrito desde YouTube, Google Drive u otro mecanismo de su preferencia.\nImplementación. La implementación debe incluir todos los códigos fuente con un archivo explicativo sobre su uso. Puede subir los códigos directamente al Aula Virtual o puede copiar un enlace en el informe escrito desde GitHub, Google Drive u otro mecanismo de su preferencia.\n\nNo debe adjuntar los datos utilizados a menos que sea estrictamente necesario, para ejecutar un demo, por ejemplo.\nAsegúrese de configurar los permisos apropiados para acceder a los códigos en caso de usar Google Drive.\n\nInforme escrito. El informe escrito, posee un formato libre y debe incluir:\n\nTítulo del proyecto.\nNombre, apellido y carrera de los integrantes.\nEnlaces a la presentación grabada y al código con la implementación del proyecto (si corresponde).\nLa descripción del problema y datos utilizados.\nLa solución implementada, las métricas de desempeño y los experimentos realizados.\nEl análisis de los resultados y, si corresponde, la comparación con otros métodos.\n\nBibliografía relevante a su trabajo y las citas correspondientes.\n\n\n\n\nLos criterios de evaluación son los siguientes:\n\nClaridad del informe escrito y presentación (20 %).\n\nEl informe y la presentación son claros, bien redactados y estructurados.\nLas figuras son explicativas y nítidas.\nLos datos/problemas están bien explicados.\nSe presenta la bibliografía relevante y se cita apropiadamente.\n\nDescripción y calidad de la solución (40 %).\n\nLa solución está claramente explicada y se evidencia dominio de los elementos que componen la solución. Se incluyen ejemplos, diagramas o pseudocódigo si es necesario.\nLa justificación de la solución es clara y coherente con el problema descrito.\nLa descripción de la solución es completa.\nEl trabajo realizado refleja dedicación de un semestre.\n\nClaridad y pertinencia de la implementación (25 %).\n\nLa implementación es clara, bien organizada y adecuada al problema.\n\nExperimentación y análisis de los resultados (15 %).\n\nSe definen y reportan métricas de desempeño relevantes.\nEl análisis de resultados es claro, profundo y evidencia aporte propio."
},
{
"objectID": "bme423/projectos.html#proyectos",
"href": "bme423/projectos.html#proyectos",
"title": "Objetivos",
"section": "",
"text": "Los proyectos deben desarrollarse durante el transcurso del semestre (no al final).\nAl final del semestre deberá hacer una presentación de 15 min, entregar un informe escrito y poner a disposición del curso un video explicativo del proyecto, el informe escrito y la implementación realizada.\nLos temas son a elección de los estudiantes.\n\n\nLa entrega de los temas de proyecto tiene como propósito verificar que el trabajo que será realizado posee la “dificultad apropiada”. Usted recibirá retroalimentación que le permitirá hacer los ajustes necesarios a su proyecto de tal manera de no resolver problemas muy simples o muy complejos.\nEn la fecha indicada debe entregar un documento de no más de dos páginas vía Aula Virtual con lo siguiente:\n\nTítulo del proyecto.\nDescripción. Esto incluye un breve contexto del tema a abordar de manera simple y concreta. Por ejemplo,\n\n“Se quiere detectar de manera automática la variable (…) en base a imágenes de (…). En la literatura se han alcanzado accuracies entre el 60-70% en el problema descrito”.\n\nProblema específico a abordar. Debe explicitar el objetivo del trabajo de manera simple y concreta. Por ejemplo,\n\n“Mi objetivo es superar las medidas de desempeño obtenidas en los artículos …”.\n“Varios artículos que resuelven el problema descrito emplean el modelo X. Mi objetivo es evaluar el modelo Y y comparar los resultados obtenidos al usar el enfoque tradicional”.\n“No existen implementaciones disponibles públicamente del método propuesto en el artículo X. Mi objetivo es implementar el método propuesto en ese artículo y reproducir los resultados obtenidos”.\n\nPunto de partida. Debe indicar si hay implementaciones disponibles de lo que usted propone desarrollar o si lo que propone hacer en este curso es la continuación de un proyecto desarrollado en otra asignatura. Debe establecer de manera clara la diferencia de lo que usted hará con lo hecho por otras personas o en su trabajo previo. Esta diferencia no necesariamente la tendrá clara en este momento, pero es algo que deberá indicar en la entrega parcial o final del proyecto.\nDataset(s). Breve descripción de los datos a utilizar, incluyendo enlaces a las bases de datos, etc.\nArtículo(s) relacionado(s). Mencione el o los artículos que de una u otra manera se relacionen con el proyecto que abordará.\n\nSi tiene más de una idea a desarrollar, debe hacer un documento por idea (no mezclar ideas de proyecto).\n\n\n\nLa entrega de los proyectos contempla lo siguiente:\n\nPresentación presencial. Tendrán una duración de 10-15 minutos.\nPresentación grabada. Todos los grupos deben grabar su presentación (duración máxima 15 minutos). Para la entrega de esto, no debe subir videos directamente al Aula Virtual, sino copiar un enlace en el informe escrito desde YouTube, Google Drive u otro mecanismo de su preferencia.\nImplementación. La implementación debe incluir todos los códigos fuente con un archivo explicativo sobre su uso. Puede subir los códigos directamente al Aula Virtual o puede copiar un enlace en el informe escrito desde GitHub, Google Drive u otro mecanismo de su preferencia.\n\nNo debe adjuntar los datos utilizados a menos que sea estrictamente necesario, para ejecutar un demo, por ejemplo.\nAsegúrese de configurar los permisos apropiados para acceder a los códigos en caso de usar Google Drive.\n\nInforme escrito. El informe escrito, posee un formato libre y debe incluir:\n\nTítulo del proyecto.\nNombre, apellido y carrera de los integrantes.\nEnlaces a la presentación grabada y al código con la implementación del proyecto (si corresponde).\nLa descripción del problema y datos utilizados.\nLa solución implementada, las métricas de desempeño y los experimentos realizados.\nEl análisis de los resultados y, si corresponde, la comparación con otros métodos.\n\nBibliografía relevante a su trabajo y las citas correspondientes.\n\n\n\n\nLos criterios de evaluación son los siguientes:\n\nClaridad del informe escrito y presentación (20 %).\n\nEl informe y la presentación son claros, bien redactados y estructurados.\nLas figuras son explicativas y nítidas.\nLos datos/problemas están bien explicados.\nSe presenta la bibliografía relevante y se cita apropiadamente.\n\nDescripción y calidad de la solución (40 %).\n\nLa solución está claramente explicada y se evidencia dominio de los elementos que componen la solución. Se incluyen ejemplos, diagramas o pseudocódigo si es necesario.\nLa justificación de la solución es clara y coherente con el problema descrito.\nLa descripción de la solución es completa.\nEl trabajo realizado refleja dedicación de un semestre.\n\nClaridad y pertinencia de la implementación (25 %).\n\nLa implementación es clara, bien organizada y adecuada al problema.\n\nExperimentación y análisis de los resultados (15 %).\n\nSe definen y reportan métricas de desempeño relevantes.\nEl análisis de resultados es claro, profundo y evidencia aporte propio."
},
{
"objectID": "bme423/labs/lab4.html",
"href": "bme423/labs/lab4.html",
"title": "Laboratorio 4",
"section": "",
"text": "Implementar e evaluar el desempeño de una red neuronal U-net en el problema de segmentación de esclerosis múltiple.\nImplementar un programa que permita hacer la detección de objetos en imágenes usando modelos preentrenados. Ejemplo:"
},
{
"objectID": "bme423/labs/lab4.html#instrucciones-para-la-entrega.",
"href": "bme423/labs/lab4.html#instrucciones-para-la-entrega.",
"title": "Laboratorio 4",
"section": "Instrucciones para la entrega.",
"text": "Instrucciones para la entrega.\n\nSe puede trabajar en grupos de 2 personas máximo.\nEn la fecha correspondiente debe un jupyter por cada pregunta con las soluciones de los ejercicios propuestos. Exporte los jupyter notebooks al formato pdf con las salidas de las celdas visibles.\nLos archivos debe tener nombres con la estructura apellido1_apellido2_ej1_lab4.ipynb y apellido1_apellido2_ej1_lab4.pdf. Dentro del jupyter debe indicar nombre y apellido de los integrantes del grupo.\nNo respetar estas instrucciones significarán una penalización en su nota de 10 puntos."
},
{
"objectID": "bme423/labs/lab3.html#objetivos",
"href": "bme423/labs/lab3.html#objetivos",
"title": "Segmentación de imágenes",
"section": "Objetivos",
"text": "Objetivos\nLos objetivos de esta actividad son los siguientes:\n\nImplementar workflows que permitan segmentar estructuras de interés en imágenes médicas usando diferentes algoritmos.\nComparar distintas segmentaciones mediante métricas cuantitativas.\nAnalizar resultados en varios sujetos."
},
{
"objectID": "bme423/labs/lab3.html#datos",
"href": "bme423/labs/lab3.html#datos",
"title": "Segmentación de imágenes",
"section": "Datos",
"text": "Datos\nSe trabajará con datos de pacientes que sufren esclerosis múltiple: Open MS data"
},
{
"objectID": "bme423/labs/lab3.html#datos-1",
"href": "bme423/labs/lab3.html#datos-1",
"title": "Segmentación de imágenes",
"section": "Datos",
"text": "Datos\n\n\nPaciente 4 - Anatomía, slice 312\n\n\nPaciente 4 - Anatomía + Gold Standard, slice 312"
},
{
"objectID": "bme423/labs/lab3.html#actividad",
"href": "bme423/labs/lab3.html#actividad",
"title": "Segmentación de imágenes",
"section": "Actividad",
"text": "Actividad\n\nDesarrolle workflows para la segmentación de esclerosis múltiple usando los algoritmos: k-means, fuzzy k-means, mezclas gaussianas mediante EM y crecimiento de regiones (region growing).\nTodos los workflows deben considerar mejoras de contraste y filtros adecuados. Esta etapa puede ser común para todos los workflows.\nMejore los resultados obtenidos usando un MRF.\nCompare cuantitativamente los distintos workflows implementados. Analice los resultados."
},
{
"objectID": "bme423/labs/lab3.html#section",
"href": "bme423/labs/lab3.html#section",
"title": "Segmentación de imágenes",
"section": "",
"text": "Nota:\n\nPuede emplear las librerías que considere pertinentes para el desarrollo de los workflows. Explique el funcionamiento de todas las funciones utilizadas.\nEs necesario analizar el efecto de los principales parámetros de cada técnica de segmentación para una correcta comparación cuantitativa."
},
{
"objectID": "bme423/labs/lab3.html#instrucciones-para-la-entrega",
"href": "bme423/labs/lab3.html#instrucciones-para-la-entrega",
"title": "Segmentación de imágenes",
"section": "Instrucciones para la entrega",
"text": "Instrucciones para la entrega\n\napellido_nombre_l3.ipynb y apellido_nombre_l3.pdf\nMedio: Aula virtual\nLas versiones .pdf en las entregas corresponden a los archivos .ipynb con las salidas de las celdas visibles.\nNo respetar las instrucciones significará un descuento de 10 pts."
},
{
"objectID": "bambinos/mayas.html#introducción",
"href": "bambinos/mayas.html#introducción",
"title": "La economía Maya",
"section": "Introducción",
"text": "Introducción\n\n\n\n\n\nLa base de la economía maya fue la agricultura, especialmente el cultivo de maíz, calabaza, frijoles y chile.\nAdemás, complementaban su sustento con la caza, la pesca y la domesticación de abejas."
},
{
"objectID": "bambinos/mayas.html#agricultura-y-técnicas",
"href": "bambinos/mayas.html#agricultura-y-técnicas",
"title": "La economía Maya",
"section": "Agricultura y técnicas",
"text": "Agricultura y técnicas\n\n\n\nLos mayas usaban el sistema de milpa, que implicaba el cultivo rotativo y tala y roza para preparar la tierra.\nLa tierra era propiedad de las élites, pero trabajada por campesinos."
},
{
"objectID": "bambinos/mayas.html#comercio-y-trueque",
"href": "bambinos/mayas.html#comercio-y-trueque",
"title": "La economía Maya",
"section": "Comercio y trueque",
"text": "Comercio y trueque\n\n\n \n\n\nEl comercio maya se basaba en el intercambio de productos agrícolas, artesanías y minerales.\nUsaban el trueque y los granos de cacao como moneda.\nEl transporte se hacía a pie y en canoas."
},
{
"objectID": "bambinos/mayas.html#producción-artesanal-y-recursos",
"href": "bambinos/mayas.html#producción-artesanal-y-recursos",
"title": "La economía Maya",
"section": "Producción artesanal y recursos",
"text": "Producción artesanal y recursos\n\n\n\n\n\nLos mayas produjeron artesanías como tejidos, cerámica y objetos de jade y obsidiana.\nEl control de recursos como minas y sal fue clave para su economía."
},
{
"objectID": "ejemplos-ml/gp01-regression-pytorch.html",
"href": "ejemplos-ml/gp01-regression-pytorch.html",
"title": "Basic GP Regression (Pytorch and GPyTorch)",
"section": "",
"text": "This notebook shows how to do Gaussian process regression:\n\ndefine a GP prior, 2) learn kernel hyperparameters by marginal likelihood,\nmake predictions, and 4) repeat the same using GPyTorch.\n\n\n!pip install \"gpytorch\"\n\n\nimport math\nimport os\nimport gpytorch\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport torch\nfrom scipy import optimize\nfrom scipy.spatial import distance_matrix\n\nplt.rcParams[\"figure.figsize\"] = (4, 3)\n\n# simple RBF kernel (squared‑exponential)\ndef rbf_kernel(X, Y, ls=1.0, amp=1.0):\n X = np.atleast_2d(X).reshape(-1, 1)\n Y = np.atleast_2d(Y).reshape(-1, 1)\n d2 = distance_matrix(X, Y) ** 2\n return amp**2 * np.exp(-0.5 * d2 / ls**2)\n\nGaussian Process Regression\nWe observe noisy data y(x) = f(x) + ε with ε ~ N(0, σ²).\nA GP prior f(x) ~ GP(0, k) with RBF kernel defines a distribution over functions.\nFor regression, the posterior over f and the predictive distribution are available in closed form.\nSynthetic data\n\ndef data_maker1(x, sig):\n x = np.asarray(x)\n return np.sin(x) + 0.5 * np.sin(4 * x) + np.random.randn(*x.shape) * sig\n\nsig = 0.25\ntrain_x = np.linspace(0, 5, 50)\ntest_x = np.linspace(0, 5, 500)\ntrain_y = data_maker1(train_x, sig=sig)\ntest_y = data_maker1(test_x, sig=0.0)\n\nplt.scatter(train_x, train_y)\nplt.plot(test_x, test_y)\nplt.xlabel(\"x\")\nplt.ylabel(\"Observations y\")\nplt.show()\n\n\n\n\n\n\n\n\nCircles are noisy observations, the blue curve is the underlying noise‑free function.\nPrior GP samples\n\nmean = np.zeros_like(test_x)\ncov = rbf_kernel(test_x, test_x, ls=0.2)\n\nprior_samples = np.random.multivariate_normal(mean=mean, cov=cov, size=5)\nplt.plot(test_x, prior_samples.T, color=\"black\", alpha=0.5)\nplt.plot(test_x, mean, linewidth=2.)\nstd = np.sqrt(np.diag(cov))\nplt.fill_between(test_x, mean - 2 * std, mean + 2 * std, alpha=0.25)\nplt.show()\n\n\n\n\n\n\n\n\nShort length‑scale gives very wiggly sample functions.\nHyperparameter learning (from scratch)\n\nell_est = 0.4\npost_sig_est = 0.5\n\ndef neg_MLL(pars):\n ell, noise = pars\n K = rbf_kernel(train_x, train_x, ls=ell)\n Ky = K + noise**2 * np.eye(*train_x.shape)\n L = np.linalg.cholesky(Ky)\n alpha = np.linalg.solve(L.T, np.linalg.solve(L, train_y))\n kernel_term = -0.5 * train_y @ alpha\n logdet = -np.sum(np.log(np.diag(L)))\n const = -0.5 * train_x.shape[0] * np.log(2 * np.pi)\n return -(kernel_term + logdet + const)\n\nres = optimize.minimize(\n neg_MLL,\n x0=np.array([ell_est, post_sig_est]),\n bounds=((0.01, 10.), (0.01, 10.))\n)\nell, post_sig_est = res.x\n\nprint(\"Learned length‑scale:\", ell)\nprint(\"Learned noise std:\", post_sig_est)\n\nLearned length‑scale: 0.5780687474139707\nLearned noise std: 0.22470850523850983\n\n\nNow we compute the posterior mean and covariance at test points.\n\nK_x_x = rbf_kernel(train_x, train_x, ls=ell)\nK_x_xstar = rbf_kernel(train_x, test_x, ls=ell)\nK_xstar_xstar = rbf_kernel(test_x, test_x, ls=ell)\n\nKy = K_x_x + post_sig_est**2 * np.eye(*train_x.shape)\nL = np.linalg.cholesky(Ky)\nalpha = np.linalg.solve(L.T, np.linalg.solve(L, train_y))\n\npost_mean = K_x_xstar.T @ alpha\nv = np.linalg.solve(L, K_x_xstar)\npost_cov = K_xstar_xstar - v.T @ v\n\npost_std = np.sqrt(np.diag(post_cov))\nlw_bd = post_mean - 2 * post_std\nup_bd = post_mean + 2 * post_std\n\nplt.scatter(train_x, train_y)\nplt.plot(test_x, test_y, linewidth=2.)\nplt.plot(test_x, post_mean, linewidth=2.)\nplt.fill_between(test_x, lw_bd, up_bd, alpha=0.25)\nplt.legend([\"True Function\", \"Predictive Mean\", \"Observed Data\", \"95% set (latent)\"])\nplt.show()\n\n\n\n\n\n\n\n\nThe posterior mean closely follows the true function.\nThe shaded band is a 95% credible set for the latent noise‑free function f(x).\nTo include observation noise in the band, add σ² on the diagonal:\n\nlw_bd_obs = post_mean - 2 * np.sqrt(post_std**2 + post_sig_est**2)\nup_bd_obs = post_mean + 2 * np.sqrt(post_std**2 + post_sig_est**2)\n\nPosterior samples\n\npost_samples = np.random.multivariate_normal(post_mean, post_cov, size=20)\nplt.scatter(train_x, train_y)\nplt.plot(test_x, test_y, linewidth=2.)\nplt.plot(test_x, post_mean, linewidth=2.)\nplt.plot(test_x, post_samples.T, color=\"gray\", alpha=0.25)\nplt.fill_between(test_x, lw_bd, up_bd, alpha=0.25)\nplt.legend([\"True Function\", \"Predictive Mean\", \"Observed Data\", \"Posterior Samples\"])\nplt.show()\n\n\n\n\n\n\n\n\nNext we reproduce the same regression using GPyTorch.\nGPyTorch implementation\n\ntrain_x_t = torch.tensor(train_x, dtype=torch.float32)\ntrain_y_t = torch.tensor(train_y, dtype=torch.float32)\ntest_x_t = torch.tensor(test_x, dtype=torch.float32)\ntest_y_t = torch.tensor(test_y, dtype=torch.float32)\n\nclass ExactGPModel(gpytorch.models.ExactGP):\n def __init__(self, train_x, train_y, likelihood):\n super().__init__(train_x, train_y, likelihood)\n self.mean_module = gpytorch.means.ZeroMean()\n self.covar_module = gpytorch.kernels.ScaleKernel(\n gpytorch.kernels.RBFKernel()\n )\n\n def forward(self, x):\n mean_x = self.mean_module(x)\n covar_x = self.covar_module(x)\n return gpytorch.distributions.MultivariateNormal(mean_x, covar_x)\n\nlikelihood = gpytorch.likelihoods.GaussianLikelihood()\nmodel = ExactGPModel(train_x_t, train_y_t, likelihood)\n\ntraining_iter = 50\nmodel.train()\nlikelihood.train()\noptimizer = torch.optim.Adam(model.parameters(), lr=0.1)\nmll = gpytorch.mlls.ExactMarginalLogLikelihood(likelihood, model)\n\nfor i in range(training_iter):\n optimizer.zero_grad()\n output = model(train_x_t)\n loss = -mll(output, train_y_t)\n loss.backward()\n if i % 10 == 0:\n print(\n f\"Iter {i+1:d}/{training_iter:d} - Loss: {loss.item():.3f} \"\n f\"squared lengthscale: \"\n f\"{model.covar_module.base_kernel.lengthscale.item():.3f} \"\n f\"noise variance: {model.likelihood.noise.item():.3f}\"\n )\n optimizer.step()\n\nIter 1/50 - Loss: 0.983 squared lengthscale: 0.693 noise variance: 0.693\nIter 11/50 - Loss: 0.695 squared lengthscale: 0.522 noise variance: 0.313\nIter 21/50 - Loss: 0.429 squared lengthscale: 0.549 noise variance: 0.127\nIter 31/50 - Loss: 0.304 squared lengthscale: 0.541 noise variance: 0.055\nIter 41/50 - Loss: 0.319 squared lengthscale: 0.545 noise variance: 0.038\n\n\n\nmodel.eval()\nlikelihood.eval()\nwith torch.no_grad():\n observed_pred = likelihood(model(test_x_t))\n lower, upper = observed_pred.confidence_region()\n f, ax = plt.subplots(1, 1, figsize=(4, 3))\n ax.scatter(train_x_t.numpy(), train_y_t.numpy())\n ax.plot(test_x_t.numpy(), test_y_t.numpy(), linewidth=2.)\n ax.plot(test_x_t.numpy(), observed_pred.mean.numpy(), linewidth=2.)\n ax.fill_between(test_x_t.numpy(), lower.numpy(), upper.numpy(), alpha=0.25)\n ax.set_ylim([-1.5, 1.5])\n ax.legend([\"True Function\", \"Predictive Mean\", \"Observed Data\",\n \"95% credible set (observations)\"])\n\n\n\n\n\n\n\n\nThe GPyTorch model recovers almost the same fit.\nHere the band is a 95% credible set for noisy observations (latent plus noise)."
},
{
"objectID": "ejemplos-ml/gp02-example-noiseest-sklearn.html",
"href": "ejemplos-ml/gp02-example-noiseest-sklearn.html",
"title": "Ability of Gaussian process regression (GPR) to estimate data noise-level",
"section": "",
"text": "Taken from sklearn\nThis example shows the ability of the :class:~sklearn.gaussian_process.kernels.WhiteKernel to estimate the noise level in the data. Moreover, we show the importance of kernel hyperparameters initialization."
},
{
"objectID": "ejemplos-ml/gp02-example-noiseest-sklearn.html#data-generation",
"href": "ejemplos-ml/gp02-example-noiseest-sklearn.html#data-generation",
"title": "Ability of Gaussian process regression (GPR) to estimate data noise-level",
"section": "Data generation",
"text": "Data generation\nWe will work in a setting where X will contain a single feature. We create a function that will generate the target to be predicted. We will add an option to add some noise to the generated target.\n\nimport numpy as np\n\n\ndef target_generator(X, add_noise=False):\n target = 0.5 + np.sin(3 * X)\n if add_noise:\n rng = np.random.RandomState(1)\n target += rng.normal(0, 0.3, size=target.shape)\n return target.squeeze()\n\nLet’s have a look to the target generator where we will not add any noise to observe the signal that we would like to predict.\n\nX = np.linspace(0, 5, num=80).reshape(-1, 1)\ny = target_generator(X, add_noise=False)\n\n\nimport matplotlib.pyplot as plt\n\nplt.plot(X, y, label=\"Expected signal\")\nplt.legend()\nplt.xlabel(\"X\")\n_ = plt.ylabel(\"y\")\n\n\n\n\n\n\n\n\nThe target is transforming the input X using a sine function. Now, we will generate few noisy training samples. To illustrate the noise level, we will plot the true signal together with the noisy training samples.\n\nrng = np.random.RandomState(0)\nX_train = rng.uniform(0, 5, size=20).reshape(-1, 1)\ny_train = target_generator(X_train, add_noise=True)\n\n\nplt.plot(X, y, label=\"Expected signal\")\nplt.scatter(\n x=X_train[:, 0],\n y=y_train,\n color=\"black\",\n alpha=0.4,\n label=\"Observations\",\n)\nplt.legend()\nplt.xlabel(\"X\")\n_ = plt.ylabel(\"y\")"
},
{
"objectID": "ejemplos-ml/gp02-example-noiseest-sklearn.html#optimisation-of-kernel-hyperparameters-in-gpr",
"href": "ejemplos-ml/gp02-example-noiseest-sklearn.html#optimisation-of-kernel-hyperparameters-in-gpr",
"title": "Ability of Gaussian process regression (GPR) to estimate data noise-level",
"section": "Optimisation of kernel hyperparameters in GPR",
"text": "Optimisation of kernel hyperparameters in GPR\nNow, we will create a :class:~sklearn.gaussian_process.GaussianProcessRegressor using an additive kernel adding a :class:~sklearn.gaussian_process.kernels.RBF and :class:~sklearn.gaussian_process.kernels.WhiteKernel kernels. The :class:~sklearn.gaussian_process.kernels.WhiteKernel is a kernel that will able to estimate the amount of noise present in the data while the :class:~sklearn.gaussian_process.kernels.RBF will serve at fitting the non-linearity between the data and the target.\nHowever, we will show that the hyperparameter space contains several local minima. It will highlights the importance of initial hyperparameter values.\nWe will create a model using a kernel with a high noise level and a large length scale, which will explain all variations in the data by noise.\n\nfrom sklearn.gaussian_process import GaussianProcessRegressor\nfrom sklearn.gaussian_process.kernels import RBF, WhiteKernel\n\nkernel = 1.0 * RBF(length_scale=1e1, length_scale_bounds=(1e-2, 1e3)) + WhiteKernel(\n noise_level=1, noise_level_bounds=(1e-10, 1e1)\n)\ngpr = GaussianProcessRegressor(kernel=kernel, alpha=0.0)\ngpr.fit(X_train, y_train)\ny_mean, y_std = gpr.predict(X, return_std=True)\n\n/Users/aveloz/miniconda3/lib/python3.9/site-packages/sklearn/gaussian_process/kernels.py:452: ConvergenceWarning: The optimal value found for dimension 0 of parameter k1__k2__length_scale is close to the specified upper bound 1000.0. Increasing the bound and calling fit again may find a better value.\n warnings.warn(\n\n\n\nplt.plot(X, y, label=\"Expected signal\")\nplt.scatter(x=X_train[:, 0], y=y_train, color=\"black\", alpha=0.4, label=\"Observations\")\nplt.errorbar(X, y_mean, y_std, label=\"Posterior mean ± std\")\nplt.legend()\nplt.xlabel(\"X\")\nplt.ylabel(\"y\")\n_ = plt.title(\n (\n f\"Initial: {kernel}\\nOptimum: {gpr.kernel_}\\nLog-Marginal-Likelihood: \"\n f\"{gpr.log_marginal_likelihood(gpr.kernel_.theta)}\"\n ),\n fontsize=8,\n)\n\n\n\n\n\n\n\n\nWe see that the optimum kernel found still has a high noise level and an even larger length scale. The length scale reaches the maximum bound that we allowed for this parameter and we got a warning as a result.\nMore importantly, we observe that the model does not provide useful predictions: the mean prediction seems to be constant: it does not follow the expected noise-free signal.\nNow, we will initialize the :class:~sklearn.gaussian_process.kernels.RBF with a larger length_scale initial value and the :class:~sklearn.gaussian_process.kernels.WhiteKernel with a smaller initial noise level lower while keeping the parameter bounds unchanged.\n\nkernel = 1.0 * RBF(length_scale=1e-1, length_scale_bounds=(1e-2, 1e3)) + WhiteKernel(\n noise_level=1e-2, noise_level_bounds=(1e-10, 1e1)\n)\ngpr = GaussianProcessRegressor(kernel=kernel, alpha=0.0)\ngpr.fit(X_train, y_train)\ny_mean, y_std = gpr.predict(X, return_std=True)\n\n\nplt.plot(X, y, label=\"Expected signal\")\nplt.scatter(x=X_train[:, 0], y=y_train, color=\"black\", alpha=0.4, label=\"Observations\")\nplt.errorbar(X, y_mean, y_std, label=\"Posterior mean ± std\")\nplt.legend()\nplt.xlabel(\"X\")\nplt.ylabel(\"y\")\n_ = plt.title(\n (\n f\"Initial: {kernel}\\nOptimum: {gpr.kernel_}\\nLog-Marginal-Likelihood: \"\n f\"{gpr.log_marginal_likelihood(gpr.kernel_.theta)}\"\n ),\n fontsize=8,\n)\n\n\n\n\n\n\n\n\nFirst, we see that the model’s predictions are more precise than the previous model’s: this new model is able to estimate the noise-free functional relationship.\nLooking at the kernel hyperparameters, we see that the best combination found has a smaller noise level and shorter length scale than the first model.\nWe can inspect the negative Log-Marginal-Likelihood (LML) of :class:~sklearn.gaussian_process.GaussianProcessRegressor for different hyperparameters to get a sense of the local minima.\n\nfrom matplotlib.colors import LogNorm\n\nlength_scale = np.logspace(-2, 4, num=80)\nnoise_level = np.logspace(-2, 1, num=80)\nlength_scale_grid, noise_level_grid = np.meshgrid(length_scale, noise_level)\n\nlog_marginal_likelihood = [\n gpr.log_marginal_likelihood(theta=np.log([0.36, scale, noise]))\n for scale, noise in zip(length_scale_grid.ravel(), noise_level_grid.ravel())\n]\nlog_marginal_likelihood = np.reshape(log_marginal_likelihood, noise_level_grid.shape)\n\n\nvmin, vmax = (-log_marginal_likelihood).min(), 50\nlevel = np.around(np.logspace(np.log10(vmin), np.log10(vmax), num=20), decimals=1)\nplt.contour(\n length_scale_grid,\n noise_level_grid,\n -log_marginal_likelihood,\n levels=level,\n norm=LogNorm(vmin=vmin, vmax=vmax),\n)\nplt.colorbar()\nplt.xscale(\"log\")\nplt.yscale(\"log\")\nplt.xlabel(\"Length-scale\")\nplt.ylabel(\"Noise-level\")\nplt.title(\"Negative log-marginal-likelihood\")\nplt.show()\n\n\n\n\n\n\n\n\nWe see that there are two local minima that correspond to the combination of hyperparameters previously found. Depending on the initial values for the hyperparameters, the gradient-based optimization might or might not converge to the best model. It is thus important to repeat the optimization several times for different initializations. This can be done by setting the n_restarts_optimizer parameter of the :class:~sklearn.gaussian_process.GaussianProcessRegressor class.\nLet’s try again to fit our model with the bad initial values but this time with 10 random restarts.\n\nkernel = 1.0 * RBF(length_scale=1e1, length_scale_bounds=(1e-2, 1e3)) + WhiteKernel(\n noise_level=1, noise_level_bounds=(1e-10, 1e1)\n)\ngpr = GaussianProcessRegressor(\n kernel=kernel, alpha=0.0, n_restarts_optimizer=10, random_state=0\n)\ngpr.fit(X_train, y_train)\ny_mean, y_std = gpr.predict(X, return_std=True)\n\n\nplt.plot(X, y, label=\"Expected signal\")\nplt.scatter(x=X_train[:, 0], y=y_train, color=\"black\", alpha=0.4, label=\"Observations\")\nplt.errorbar(X, y_mean, y_std, label=\"Posterior mean ± std\")\nplt.legend()\nplt.xlabel(\"X\")\nplt.ylabel(\"y\")\n_ = plt.title(\n (\n f\"Initial: {kernel}\\nOptimum: {gpr.kernel_}\\nLog-Marginal-Likelihood: \"\n f\"{gpr.log_marginal_likelihood(gpr.kernel_.theta)}\"\n ),\n fontsize=8,\n)\n\n\n\n\n\n\n\n\nAs we hoped, random restarts allow the optimization to find the best set of hyperparameters despite the bad initial values."
},
{
"objectID": "ejemplos-ml/gp03-sensors-network.html",
"href": "ejemplos-ml/gp03-sensors-network.html",
"title": "Multi-output Gaussian Process (Sensor Network)",
"section": "",
"text": "import numpy as np\nimport matplotlib.pyplot as plt\nimport os\nimport pandas as pd\nimport mogptk\nimport torch\n\n\nplot_params = {'legend.fontsize': 18,\n 'figure.figsize': (15, 7),\n 'xtick.labelsize':'18',\n 'ytick.labelsize':'18',\n 'axes.titlesize':'24',\n 'axes.labelsize':'22'}\nplt.rcParams.update(plot_params)\n\n\nrng = np.random.default_rng(123)\n\nT = 500\nn_nodes = 5\n\nt = np.linspace(0, 10, T)\nt1_lost = np.linspace(4, 5, 100)\nX = np.zeros((T,n_nodes))\n\nX[:,0] = np.sin(t * (2 * np.pi)) + np.sin(t * (3 * np.pi))\nX[:,1] = np.sin((t-1) * (2 * np.pi)) + np.sin((t-1) * (3 * np.pi))\nX[:,2] = np.sin(t * (2 * np.pi)) + np.sin(t * (4 * np.pi))\nX[:,3] = np.sin((t-1) * (2 * np.pi)) + 0.5*np.sin((t-1) * (4 * np.pi))\nX[:,4] = 0.3*np.sin((t-1) * (2 * np.pi)) + 0.8*np.sin((t-1) * (8 * np.pi))\n\n\ntorch.manual_seed(1);\n\nT = 500\nn_nodes = 5\nt = np.linspace(0, 10, T)\nX = np.zeros((T, n_nodes))\nX[:, 0] = np.sin(t * (2 * np.pi)) + np.sin(t * (3 * np.pi))\nX[:, 1] = np.sin((t-1) * (2 * np.pi)) + np.sin((t-1) * (3 * np.pi))\nX[:, 2] = np.sin(t * (2 * np.pi)) + np.sin(t * (4 * np.pi))\nX[:, 3] = np.sin((t-1) * (2 * np.pi)) + 0.5*np.sin((t-1) * (4 * np.pi))\nX[:, 4] = 0.3*np.sin((t-1) * (2 * np.pi)) + 0.8*np.sin((t-1) * (8 * np.pi))\ncolumns = [f\"Node{i+1}\" for i in range(n_nodes)]\ndf_synth = pd.DataFrame(X, columns=columns)\ndf_synth['Time'] = t\ndf_synth = df_synth[['Time'] + columns]\ndataset = mogptk.LoadDataFrame(df_synth, x_col='Time', y_col=columns)\n\nfor channel in dataset:\n channel.remove_randomly(pct=0.4)\n\n# drop relative ranges to simulate sensor failure\ndataset[0].remove_relative_range(0.2, 0.3)\ndataset[1].remove_relative_range(0.8, 1.0)\ndataset[2].remove_relative_range(0.9, 1.0)\ndataset[3].remove_relative_range(0.8, 1.0)\ndataset[4].remove_relative_range(0.0, 0.2)\n\nchannels = []\nfor channel in dataset:\n channel.transform(mogptk.TransformDetrend(degree=1))\n channel.transform(mogptk.TransformStandard())\n channels.append(channel)\n\n# dataset.plot(transformed=True, figsize=(10,10));\nn_train = channels[0].get_train_data()[0].shape[0]\nn_test = channels[0].get_test_data()[0].shape[0]\nn_train+n_test\n\n500\n\n\n\noffset = 6.0\ny_offsets = np.arange(n_nodes) * offset\n\nfig, ax = plt.subplots(nrows=1, sharex=True, sharey=True)\nfor i in range(n_nodes):\n plt.plot(t, X[:,i] + y_offsets[i], alpha=0.4, color='r')\n\nax.set_yticks(y_offsets, [f\"node {i+1}\" for i in range(n_nodes)])\nax.spines['top'].set_visible(False)\nax.spines['right'].set_visible(False)\nax.invert_yaxis()\nax.set_xlim([0, 10])\nax.set_ylim([-5, 27])\nplt.xlabel(\"time\")\nplt.tight_layout()\n\nfig, ax = plt.subplots(nrows=1, sharex=True, sharey=True)\nfor i in range(n_nodes):\n plt.plot(t, X[:,i] + y_offsets[i], alpha=0.4, color='k')\n t_train, x_train = channels[i].get_train_data()\n plt.scatter(t_train, x_train + y_offsets[i], color='red')\n\nax.set_yticks(y_offsets, [f\"node {i+1}\" for i in range(n_nodes)])\nax.spines['top'].set_visible(False)\nax.spines['right'].set_visible(False)\nax.invert_yaxis()\nax.set_xlim([0, 10])\nax.set_ylim([-5, 27])\nplt.xlabel(\"time\")\nplt.tight_layout()\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nmodel = mogptk.MOSM(dataset, Q=3)\nmodel.init_parameters(method='BNSE')\n\nXt, Mu, Lower, Upper = model.predict()\n\nfig, ax = plt.subplots(nrows=1, sharex=True, sharey=True)\nfor i in range(n_nodes):\n plt.plot(Xt[i], Mu[i] + y_offsets[i], alpha=0.4, color='b')\n plt.fill_between( np.squeeze(Xt[i]), Lower[i] + y_offsets[i], Upper[i] + y_offsets[i], alpha=0.4, color='b' )\n plt.plot(t, X[:,i] + y_offsets[i], alpha=0.4, color='r')\n t_test, x_test = channels[i].get_test_data()\n plt.scatter(t_test, x_test + y_offsets[i], color='green')\n\nax.set_yticks(y_offsets, [f\"node {i+1}\" for i in range(n_nodes)])\nax.spines['top'].set_visible(False)\nax.spines['right'].set_visible(False)\nax.invert_yaxis()\nax.set_xlim([0, 10])\nax.set_ylim([-5, 27])\nplt.xlabel(\"time\")\nplt.tight_layout()\n\n\n\n\n\n\n\n\n\nmodel.train(method='Adam', lr=0.01, iters=1000, verbose=True);\n\nStarting optimization using Adam\n‣ Model: Exact\n ‣ Kernel: MultiOutputSpectralMixtureKernel\n ‣ Likelihood: GaussianLikelihood\n‣ Channels: 5\n‣ Parameters: 80\n‣ Training points: 1258\n‣ Iterations: 1000\n\n\n/Users/aveloz/miniconda3/lib/python3.9/site-packages/mogptk/model.py:384: UserWarning: Converting a tensor with requires_grad=True to a scalar may lead to unexpected behavior.\nConsider using tensor.detach() first. (Triggered internally at /Users/runner/work/pytorch/pytorch/pytorch/torch/csrc/autograd/generated/python_variable_methods.cpp:836.)\n return float(self.gpr.loss())\n\n\n 0/1000 0:00:00 loss= 1248.23 (warmup)\n 48/1000 0:00:10 loss= 1184.74\n 101/1000 0:00:20 loss= 1116.73\n 153/1000 0:00:30 loss= 1054.27\n 206/1000 0:00:40 loss= 988.854\n 258/1000 0:00:50 loss= 932.167\n 310/1000 0:01:00 loss= 862.731\n 360/1000 0:01:10 loss= 801.434\n 413/1000 0:01:20 loss= 738.048\n 465/1000 0:01:30 loss= 673.084\n 517/1000 0:01:40 loss= 615.362\n 566/1000 0:01:50 loss= 551.007\n 616/1000 0:02:00 loss= 487.771\n 667/1000 0:02:10 loss= 426.397\n 717/1000 0:02:20 loss= 363.946\n 764/1000 0:02:30 loss= 307.042\n 812/1000 0:02:40 loss= 271.866\n 863/1000 0:02:50 loss= 195.433\n 914/1000 0:03:00 loss= 142.252\n 965/1000 0:03:10 loss= 103.193\n 1000/1000 0:03:16 loss= 46.8325\nOptimization finished in 3 minutes 16 seconds\n\n\n\nXt, Mu, Lower, Upper = model.predict()\n\nfig, ax = plt.subplots(nrows=1, sharex=True, sharey=True)\nfor i in range(n_nodes):\n plt.plot(Xt[i], Mu[i] + y_offsets[i], alpha=0.4, color='b')\n plt.fill_between( np.squeeze(Xt[i]), Lower[i] + y_offsets[i], Upper[i] + y_offsets[i], alpha=0.4, color='b' )\n plt.plot(t, X[:,i] + y_offsets[i], alpha=0.4, color='r')\n t_test, x_test = channels[i].get_test_data()\n plt.scatter(t_test, x_test + y_offsets[i], color='green')\n\nax.set_yticks(y_offsets, [f\"node {i+1}\" for i in range(n_nodes)])\nax.spines['top'].set_visible(False)\nax.spines['right'].set_visible(False)\nax.invert_yaxis()\nax.set_xlim([0, 10])\nax.set_ylim([-5, 27])\nplt.xlabel(\"time\")\nplt.tight_layout()"
},
{
"objectID": "ejemplos-ml/gp01-regression.html",
"href": "ejemplos-ml/gp01-regression.html",
"title": "Gaussian Process Regression",
"section": "",
"text": "import numpy as np\nimport matplotlib.pyplot as plt\nfrom sklearn.gaussian_process import GaussianProcessRegressor\nfrom sklearn.gaussian_process.kernels import RBF, ConstantKernel, WhiteKernel\nimport seaborn as sns\nimport os\n\nplot_params = {'legend.fontsize': 18,\n 'figure.figsize': (8, 5),\n 'xtick.labelsize':'18',\n 'ytick.labelsize':'18',\n 'axes.titlesize':'24',\n 'axes.labelsize':'22'}\n\nplt.rcParams.update(plot_params)\nsns.set_style(\"whitegrid\")\n\ndef f(x):\n return np.sin(x) + 0.3 * np.cos(3 * x)\nx = np.linspace(-3, 3, 100)\n\nplt.figure()\nplt.plot(x, f(x), alpha=0.7)\nplt.xlabel('x')\nplt.ylabel('f(x)')\nplt.tight_layout()\n\nnp.random.seed(0)\n\n# training data\nX_train = np.linspace(-3, 3, 12)[:, None]\nX_train = np.array([-3, -1.9, 2])[:, None]\ny_train = f(X_train[:, 0]) + 0.1 * np.random.randn(len(X_train))\n\n# test grid\nX_test = np.linspace(-4, 4, 400)[:, None]\n\nplt.figure()\nplt.plot(X_train[:, 0], y_train, 'or', label='observations')\nplt.plot(X_test[:, 0], f(X_test[:, 0]), 'k--', label='ground truth')\nplt.xlabel('x')\nplt.ylabel('y')\nplt.legend()\nplt.tight_layout()\nfor n_samples in [1, 4]:\n idx_fig = 0\n for sigma_f in [1, 2, 3]:\n for length_scale in [0.1, 1, 3]:\n\n idx_fig+=1\n\n kernel = ConstantKernel(sigma_f, (1e-3, 1e3)) \\\n * RBF(length_scale=length_scale, length_scale_bounds=(1e-2, 1e2)) \\\n + WhiteKernel(noise_level=0.0, noise_level_bounds=(1e-10, 1e0))\n\n gp = GaussianProcessRegressor(\n kernel=kernel,\n alpha=0.0,\n optimizer=None, # <- disables LML optimization / 'fmin_l_bfgs_b'\n n_restarts_optimizer=5,\n normalize_y=False)\n\n # Prior mean/cov on test grid\n mu_prior, cov_prior = gp.predict(X_test, return_cov=True)\n # Draw prior samples\n prior_samps = np.random.multivariate_normal(mean=mu_prior.ravel(), cov=cov_prior, size=n_samples)\n\n plt.close('all')\n fig, axs = plt.subplots(1, 2, figsize=(12, 5), gridspec_kw={'width_ratios': [1, 2]})\n axs = axs.flatten()\n\n # Left: covariance matrix\n im = axs[0].imshow(cov_prior, origin=\"lower\", extent=[-4, 4, -4, 4], vmin=0.0, vmax=2.0)\n axs[0].set_xlabel(r'$x$')\n axs[0].set_ylabel(r\"$x^\\prime$\")\n axs[0].grid(False)\n axs[0].set_xlim([-4, 4])\n axs[0].set_ylim([-4, 4])\n fig.colorbar(im, ax=axs[0], fraction=0.046, pad=0.04)\n\n # Right: prior samples\n for i in range(n_samples):\n axs[1].plot(X_test[:, 0], prior_samps[i], alpha=0.7, lw=4)\n axs[1].set_xlabel('x')\n axs[1].set_ylabel('f(x)')\n axs[1].set_xlim([-4, 4])\n axs[1].set_ylim([-4, 4])\n\n plt.suptitle(f'$\\ell={length_scale}$, $\\sigma_f={sigma_f}$', fontsize=38)\n plt.tight_layout()\n # plt.savefig(os.path.join('.',f'fig-prior-rbf-nsamp{n_samples}-{idx_fig}.pdf'))\n plt.show()\nlength_scale = 1\nsigma_f = 1\n\nkernel = ConstantKernel(sigma_f, (1e-3, 1e3)) \\\n * RBF(length_scale=length_scale, length_scale_bounds=(1e-2, 1e2)) \\\n + WhiteKernel(noise_level=0.0, noise_level_bounds=(1e-10, 1e0))\n\ngp = GaussianProcessRegressor(\n kernel=kernel,\n alpha=0.0,\n optimizer=None, # <- disables LML optimization / 'fmin_l_bfgs_b'\n n_restarts_optimizer=5,\n normalize_y=False)\n\n# Prior mean/cov on test grid\nmu_prior, cov_prior = gp.predict(X_test, return_cov=True)\nstd_prior = np.sqrt(np.diag(cov_prior))\nn_samples = 3\n# Draw prior samples\nprior_samps = np.random.multivariate_normal(mean=mu_prior.ravel(), cov=cov_prior, size=n_samples)\n\n\nplt.close('all')\nfig, axs = plt.subplots(1, 2, figsize=(12, 5), gridspec_kw={'width_ratios': [1, 2]})\naxs = axs.flatten()\n\n# Left: covariance matrix\nim = axs[0].imshow(cov_prior, origin=\"lower\", extent=[-4, 4, -4, 4], vmin=0.0, vmax=2.0)\naxs[0].set_xlabel(r'$x$')\naxs[0].set_ylabel(r\"$x^\\prime$\")\naxs[0].grid(False)\naxs[0].set_xlim([-4, 4])\naxs[0].set_ylim([-4, 4])\nfig.colorbar(im, ax=axs[0], fraction=0.046, pad=0.04)\n\n# Right: prior samples\nfor i in range(n_samples):\n axs[1].plot(X_test[:, 0], prior_samps[i], alpha=0.7, lw=4)\naxs[1].set_xlabel('x')\naxs[1].set_ylabel('f(x)')\naxs[1].set_xlim([-4, 4])\naxs[1].set_ylim([-4, 4])\n\nplt.suptitle(f'$\\ell={length_scale}$, $\\sigma_f={sigma_f}$', fontsize=38)\nplt.tight_layout()\n# plt.savefig(os.path.join('.',f'fig-prior-rbf-with-moments.pdf'))\n\n# Right: prior samples\naxs[1].plot(X_test[:, 0], mu_prior, 'r', label='GP mean', lw=4)\naxs[1].fill_between(\n X_test[:, 0],\n mu_prior - 2 * std_prior,\n mu_prior + 2 * std_prior,\n color='r',\n alpha=0.2,\n linewidth=0,\n edgecolor='none',\n label='95% CI')\naxs[1].legend(loc=\"lower left\", ncols=2)\n# plt.savefig(os.path.join('.',f'fig-prior-rbf-with-moments-2.pdf'))\n\nplt.show()\ngp.fit(X_train, y_train)\n# Posterior mean/cov on test grid\nmu, cov = gp.predict(X_test, return_cov=True)\n\nn_samples = 3\n# Draw posterior samples\npost_samps = np.random.multivariate_normal(mean=mu.ravel(), cov=cov, size=n_samples)\nstd = np.sqrt(np.diag(cov))\n\n\nplt.close('all')\nfig, axs = plt.subplots(1, 2, figsize=(12, 5), gridspec_kw={'width_ratios': [1, 2]})\naxs = axs.flatten()\n\n# Left: covariance matrix\nim = axs[0].imshow(cov, origin=\"lower\", extent=[-4, 4, -4, 4], vmin=0.0, vmax=2.0)\naxs[0].set_xlabel(r'$x$')\naxs[0].set_ylabel(r\"$x^\\prime$\")\naxs[0].grid(False)\naxs[0].set_xlim([-4, 4])\naxs[0].set_ylim([-4, 4])\nfig.colorbar(im, ax=axs[0], fraction=0.046, pad=0.04)\n\n# Right: prior samples\nfor i in range(n_samples):\n axs[1].plot(X_test[:, 0], post_samps[i], alpha=0.7, lw=4)\naxs[1].set_xlabel('x')\naxs[1].set_ylabel('f(x)')\naxs[1].set_xlim([-4, 4])\naxs[1].set_ylim([-4, 4])\naxs[1].plot(X_test[:, 0], mu, 'r', label='GP mean', lw=4)\naxs[1].fill_between(\n X_test[:, 0],\n mu - 2 * std,\n mu + 2 * std,\n color='r',\n alpha=0.2,\n linewidth=0,\n edgecolor='none',\n label='95% CI')\naxs[1].scatter(np.squeeze(X_train), y_train, color=\"red\", zorder=10, s=60, label=\"Obs\")\naxs[1].legend(loc=\"lower left\", ncols=3)\n\n\nplt.suptitle(f'$\\ell={length_scale}$, $\\sigma_f={sigma_f}$', fontsize=38)\nplt.tight_layout()\n# plt.savefig(os.path.join('.',f'fig-post-rbf-with-moments.pdf'))\nplt.show()\n\n\n\n\n/Users/aveloz/miniconda3/lib/python3.9/site-packages/sklearn/gaussian_process/kernels.py:307: RuntimeWarning: divide by zero encountered in log\n return np.log(np.hstack(theta))"
},
{
"objectID": "ejemplos-ml/gp01-regression.html#dataset-and-gaussian-process-generation",
"href": "ejemplos-ml/gp01-regression.html#dataset-and-gaussian-process-generation",
"title": "Gaussian Process Regression",
"section": "Dataset and Gaussian process generation",
"text": "Dataset and Gaussian process generation\nWe will create a training dataset that we will use in the different sections.\n\nrng = np.random.RandomState(5)\nX_train = rng.uniform(0, 5, 10).reshape(-1, 1)\ny_train = np.sin((X_train[:, 0] - 2.5) ** 2)\nn_samples = 5\nX_train\n\narray([[1.10996586],\n [4.35366153],\n [1.03359578],\n [4.59305454],\n [2.44205594],\n [3.05871931],\n [3.82953928],\n [2.59208994],\n [1.48400251],\n [0.93860614]])\n\n\n\nRadial Basis Function kernel\n\nfrom sklearn.gaussian_process import GaussianProcessRegressor\nfrom sklearn.gaussian_process.kernels import RBF\n\nkernel = 1.0 * RBF(length_scale=0.1, length_scale_bounds=(1e-1, 10.0))\ngpr = GaussianProcessRegressor(kernel=kernel, random_state=0)\n\nfig, ax = plt.subplots(nrows=1, sharex=True, sharey=True, figsize=(7, 3))\n# plot prior\nplot_gpr_samples(gpr, n_samples=n_samples, ax=ax)\nhandles, labels = ax.get_legend_handles_labels()\nby_label = dict(zip(labels, handles))\nax.legend(by_label.values(), by_label.keys(), loc=\"upper center\", bbox_to_anchor=(0.5, 1.1), ncol=len(by_label), fontsize=12)\nax.set_xlim([0, 5])\nax.set_ylim([-4, 4])\nax.set_xlabel(\"x\", fontsize=18)\nax.set_ylabel(\"y\", fontsize=18)\nax.tick_params(axis='both', which='major', labelsize=16)\nax.spines['top'].set_visible(False)\nax.spines['right'].set_visible(False)\nplt.tight_layout()\n# plt.savefig(f'rbf-0.pdf')\n\nfor idx in range(X_train.shape[0]):\n fig, ax = plt.subplots(nrows=1, sharex=True, sharey=True, figsize=(7, 3))\n x_train_ = np.array(X_train[:idx+1, 0]).reshape(-1, 1)\n y_train_ = np.array(y_train[:idx+1]).reshape(-1, 1)\n gpr.fit(x_train_, y_train_)\n # plot posterior\n plot_gpr_samples(gpr, n_samples=n_samples, ax=ax)\n ax.scatter(np.squeeze(x_train_), y_train_, color=\"red\", zorder=10, label=\"Obs\")\n handles, labels = ax.get_legend_handles_labels()\n by_label = dict(zip(labels, handles))\n ax.legend(by_label.values(), by_label.keys(), loc=\"upper center\", bbox_to_anchor=(0.5, 1.3), ncol=len(by_label), fontsize=12)\n ax.set_xlim([0, 5])\n ax.set_ylim([-4, 4])\n ax.set_xlabel(\"x\", fontsize=18)\n ax.set_ylabel(\"y\", fontsize=18)\n ax.tick_params(axis='both', which='major', labelsize=16)\n ax.spines['top'].set_visible(False)\n ax.spines['right'].set_visible(False)\n plt.tight_layout()\n # plt.savefig(f'rbf-{idx+1}.pdf')\n\nplt.close(fig)\n\n/Users/aveloz/miniconda3/lib/python3.9/site-packages/sklearn/gaussian_process/kernels.py:442: ConvergenceWarning: The optimal value found for dimension 0 of parameter k2__length_scale is close to the specified lower bound 0.1. Decreasing the bound and calling fit again may find a better value.\n warnings.warn(\n/Users/aveloz/miniconda3/lib/python3.9/site-packages/sklearn/gaussian_process/kernels.py:442: ConvergenceWarning: The optimal value found for dimension 0 of parameter k2__length_scale is close to the specified lower bound 0.1. Decreasing the bound and calling fit again may find a better value.\n warnings.warn(\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nX_train.shape\n\n(10, 1)\n\n\n\nfrom sklearn.gaussian_process import GaussianProcessRegressor\nfrom sklearn.gaussian_process.kernels import RBF\n\nlength_scales = [0.05, 0.1, 0.25, 0.5, 1.0, 10]\nfig, ax = plt.subplots(nrows=len(length_scales), sharex=True, sharey=True, figsize=(7, 7))\nfor i, ls in enumerate(length_scales):\n kernel = 1.0 * RBF(length_scale=ls, length_scale_bounds=(1e-1, 10.0)) \n gpr = GaussianProcessRegressor(kernel=kernel, random_state=0)\n plot_gpr_samples(gpr, n_samples=n_samples, ax=ax[i]) # plot prior\n if i==0:\n handles, labels = ax[i].get_legend_handles_labels()\n by_label = dict(zip(labels, handles))\n ax[i].legend(by_label.values(), by_label.keys(), loc=\"upper center\", bbox_to_anchor=(0.5, 1.5), ncol=len(by_label), fontsize=14)\n ax[i].set_xlim([0, 5])\n ax[i].set_ylim([-4, 4])\n ax[i].tick_params(axis='both', which='major', labelsize=16)\n ax[i].set_ylabel(f\"$\\ell = {ls}$\", fontsize=18)\n ax[i].spines['top'].set_visible(False)\n ax[i].spines['right'].set_visible(False)\n if i == len(length_scales)-1:\n ax[i].set_xlabel(\"x\", fontsize=18)\nplt.tight_layout()\n# plt.savefig(f'rbf-panel-length-scales.pdf')\n\n\nsigmas = [0.1, 0.25, 0.5, 1.0, 3.0]\nfig, ax = plt.subplots(nrows=len(sigmas), sharex=True, sharey=True, figsize=(7, 7))\nfor i, sigma in enumerate(sigmas):\n ls = 0.1\n kernel = sigma * RBF(length_scale=ls, length_scale_bounds=(1e-1, 10.0)) # [web:4]\n gpr = GaussianProcessRegressor(kernel=kernel, random_state=0)\n plot_gpr_samples(gpr, n_samples=n_samples, ax=ax[i]) # plot prior\n if i==0:\n handles, labels = ax[i].get_legend_handles_labels()\n by_label = dict(zip(labels, handles))\n ax[i].legend(by_label.values(), by_label.keys(), loc=\"upper center\", bbox_to_anchor=(0.5, 1.5), ncol=len(by_label), fontsize=14)\n ax[i].set_xlim([0, 5])\n ax[i].set_ylim([-4, 4])\n ax[i].tick_params(axis='both', which='major', labelsize=16)\n ax[i].set_ylabel(f\"$\\sigma = {sigma}$\", fontsize=18)\n # ax[i].set_title(f\"$\\ell = {ls}$\", fontsize=18)\n ax[i].spines['top'].set_visible(False)\n ax[i].spines['right'].set_visible(False)\n if i == len(sigmas)-1:\n ax[i].set_xlabel(\"x\", fontsize=18)\nplt.tight_layout()\n# plt.savefig(f'rbf-panel-sigmas.pdf')\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n# Rational Quadratic kernel\nfrom sklearn.gaussian_process import GaussianProcessRegressor\nfrom sklearn.gaussian_process.kernels import RBF, RationalQuadratic, Matern, ExpSineSquared, ConstantKernel, DotProduct\n\nkernels = [(1.0 * RBF(length_scale=1.0, length_scale_bounds=(1e-1, 10.0)), 'kernel-rbf.pdf'),\n (1.0 * RationalQuadratic(length_scale=1.0, alpha=0.1, alpha_bounds=(1e-5, 1e15)), 'kernel-rationalquadratic.pdf'),\n (1.0 * Matern(length_scale=1.0, length_scale_bounds=(1e-1, 10.0), nu=1.5), 'kernel-matern.pdf'),\n # (1.0 * ExpSineSquared(length_scale=1.0, periodicity=3.0, length_scale_bounds=(0.1, 10.0), periodicity_bounds=(1.0, 10.0)), 'kernel-expsinesquared.pdf'),\n (ConstantKernel(0.1, (0.01, 10.0)) * (DotProduct(sigma_0=1.0, sigma_0_bounds=(0.1, 10.0)) ** 2), 'kernel-cte-dot.pdf')\n ]\n\n\nfor kernel, filename in kernels:\n\n gpr = GaussianProcessRegressor(kernel=kernel, random_state=0)\n\n fig, ax = plt.subplots(nrows=2, sharex=True, sharey=True, figsize=(10, 6))\n # plot prior\n plot_gpr_samples(gpr, n_samples=n_samples, ax=ax[0])\n handles, labels = ax[0].get_legend_handles_labels()\n by_label = dict(zip(labels, handles))\n ax[0].legend(by_label.values(), by_label.keys(), loc=\"upper center\", bbox_to_anchor=(0.5, 0.99), ncol=len(by_label), fontsize=14)\n ax[0].set_xlim([0, 5])\n ax[0].set_ylim([-4, 4])\n # ax[0].set_xlabel(\"x\", fontsize=18)\n ax[0].spines['top'].set_visible(False)\n ax[0].spines['right'].set_visible(False)\n ax[0].set_ylabel(\"y\", fontsize=18)\n ax[0].tick_params(axis='both', which='major', labelsize=16)\n\n x_train_ = np.array(X_train[:, 0]).reshape(-1, 1)\n y_train_ = np.array(y_train[:]).reshape(-1, 1)\n gpr.fit(x_train_, y_train_)\n # plot posterior\n plot_gpr_samples(gpr, n_samples=n_samples, ax=ax[1])\n ax[1].scatter(np.squeeze(x_train_), y_train_, color=\"red\", zorder=10, label=\"Observations\")\n handles, labels = ax[1].get_legend_handles_labels()\n by_label = dict(zip(labels, handles))\n ax[1].legend(by_label.values(), by_label.keys(), loc=\"upper center\", bbox_to_anchor=(0.5, 1.1), ncol=len(by_label), fontsize=14)\n ax[1].set_xlim([0, 5])\n ax[1].set_ylim([-4, 4])\n ax[1].set_xlabel(\"x\", fontsize=18)\n ax[1].set_ylabel(\"y\", fontsize=18)\n ax[1].tick_params(axis='both', which='major', labelsize=16)\n # ax.set_title(\"Samples from posterior distribution (RBF kernel)\", fontsize=18)\n ax[1].spines['top'].set_visible(False)\n ax[1].spines['right'].set_visible(False)\n\n plt.tight_layout()\n # plt.savefig(filename)\n\n\n/Users/aveloz/miniconda3/lib/python3.9/site-packages/sklearn/gaussian_process/_gpr.py:478: UserWarning: Predicted variances smaller than 0. Setting those variances to 0.\n warnings.warn(\n/Users/aveloz/miniconda3/lib/python3.9/site-packages/sklearn/gaussian_process/_gpr.py:523: RuntimeWarning: covariance is not positive-semidefinite.\n y_samples = rng.multivariate_normal(y_mean, y_cov, n_samples).T\n/Users/aveloz/miniconda3/lib/python3.9/site-packages/sklearn/gaussian_process/_gpr.py:660: ConvergenceWarning: lbfgs failed to converge (status=2):\nABNORMAL_TERMINATION_IN_LNSRCH.\n\nIncrease the number of iterations (max_iter) or scale the data as shown in:\n https://scikit-learn.org/stable/modules/preprocessing.html\n _check_optimize_result(\"lbfgs\", opt_res)"
},
{
"objectID": "ejemplos-ml/gp02-example-co2-sklearn.html",
"href": "ejemplos-ml/gp02-example-co2-sklearn.html",
"title": "Forecasting of CO2 level on Mona Loa dataset using Gaussian process regression (GPR)",
"section": "",
"text": "Taken from sklearn.\nThis example is based on Section 5.4.3 of “Gaussian Processes for Machine Learning” [1]_. It illustrates an example of complex kernel engineering and hyperparameter optimization using gradient ascent on the log-marginal-likelihood. The data consists of the monthly average atmospheric CO2 concentrations (in parts per million by volume (ppm)) collected at the Mauna Loa Observatory in Hawaii, between 1958 and 2001. The objective is to model the CO2 concentration as a function of the time \\(t\\) and extrapolate for years after 2001.\n.. rubric:: References\n.. [1] Rasmussen, Carl Edward. “Gaussian processes in machine learning.” Summer school on machine learning. Springer, Berlin, Heidelberg, 2003.\n!pip install polars\n\n\nCollecting polars\n\n Downloading polars-1.35.2-py3-none-any.whl.metadata (10 kB)\n\nCollecting polars-runtime-32==1.35.2 (from polars)\n\n Downloading polars_runtime_32-1.35.2-cp39-abi3-macosx_11_0_arm64.whl.metadata (1.5 kB)\n\nDownloading polars-1.35.2-py3-none-any.whl (783 kB)\n\n ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 783.6/783.6 kB 15.1 MB/s eta 0:00:00\n\nDownloading polars_runtime_32-1.35.2-cp39-abi3-macosx_11_0_arm64.whl (36.7 MB)\n\n ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 36.7/36.7 MB 22.2 MB/s eta 0:00:0000:0100:01\n\nInstalling collected packages: polars-runtime-32, polars\n\nSuccessfully installed polars-1.35.2 polars-runtime-32-1.35.2"
},
{
"objectID": "ejemplos-ml/gp02-example-co2-sklearn.html#build-the-dataset",
"href": "ejemplos-ml/gp02-example-co2-sklearn.html#build-the-dataset",
"title": "Forecasting of CO2 level on Mona Loa dataset using Gaussian process regression (GPR)",
"section": "Build the dataset",
"text": "Build the dataset\nWe will derive a dataset from the Mauna Loa Observatory that collected air samples. We are interested in estimating the concentration of CO2 and extrapolate it for further year. First, we load the original dataset available in OpenML as a pandas dataframe. This will be replaced with Polars once fetch_openml adds a native support for it.\n\nfrom sklearn.datasets import fetch_openml\n\nco2 = fetch_openml(data_id=41187, as_frame=True)\nco2.frame.head()\n\n\n\n\n\n\n\n\nyear\nmonth\nday\nweight\nflag\nstation\nco2\n\n\n\n\n0\n1958\n3\n29\n4\n0\nMLO\n316.1\n\n\n1\n1958\n4\n5\n6\n0\nMLO\n317.3\n\n\n2\n1958\n4\n12\n4\n0\nMLO\n317.6\n\n\n3\n1958\n4\n19\n6\n0\nMLO\n317.5\n\n\n4\n1958\n4\n26\n2\n0\nMLO\n316.4\n\n\n\n\n\n\n\nFirst, we process the original dataframe to create a date column and select it along with the CO2 column.\n\nimport polars as pl\n\nco2_data = pl.DataFrame(co2.frame[[\"year\", \"month\", \"day\", \"co2\"]]).select(\n pl.date(\"year\", \"month\", \"day\"), \"co2\"\n)\nco2_data.head()\n\n\nshape: (5, 2)\n\n\n\ndate\nco2\n\n\ndate\nf64\n\n\n\n\n1958-03-29\n316.1\n\n\n1958-04-05\n317.3\n\n\n1958-04-12\n317.6\n\n\n1958-04-19\n317.5\n\n\n1958-04-26\n316.4\n\n\n\n\n\n\n\nco2_data[\"date\"].min(), co2_data[\"date\"].max()\n\n(datetime.date(1958, 3, 29), datetime.date(2001, 12, 29))\n\n\nWe see that we get CO2 concentration for some days from March, 1958 to December, 2001. We can plot these raw information to have a better understanding.\n\nimport matplotlib.pyplot as plt\n\nplt.plot(co2_data[\"date\"], co2_data[\"co2\"])\nplt.xlabel(\"date\")\nplt.ylabel(\"CO$_2$ concentration (ppm)\")\n_ = plt.title(\"Raw air samples measurements from the Mauna Loa Observatory\")\n\n\n\n\n\n\n\n\nWe will preprocess the dataset by taking a monthly average and drop month for which no measurements were collected. Such a processing will have an smoothing effect on the data.\n\nco2_data = (\n co2_data.sort(by=\"date\")\n .group_by_dynamic(\"date\", every=\"1mo\")\n .agg(pl.col(\"co2\").mean())\n .drop_nulls()\n)\nplt.plot(co2_data[\"date\"], co2_data[\"co2\"])\nplt.xlabel(\"date\")\nplt.ylabel(\"Monthly average of CO$_2$ concentration (ppm)\")\n_ = plt.title(\n \"Monthly average of air samples measurements\\nfrom the Mauna Loa Observatory\"\n)\n\n\n\n\n\n\n\n\nThe idea in this example will be to predict the CO2 concentration in function of the date. We are as well interested in extrapolating for upcoming year after 2001.\nAs a first step, we will divide the data and the target to estimate. The data being a date, we will convert it into a numeric.\n\nX = co2_data.select(\n pl.col(\"date\").dt.year() + pl.col(\"date\").dt.month() / 12\n).to_numpy()\ny = co2_data[\"co2\"].to_numpy()"
},
{
"objectID": "ejemplos-ml/gp02-example-co2-sklearn.html#design-the-proper-kernel",
"href": "ejemplos-ml/gp02-example-co2-sklearn.html#design-the-proper-kernel",
"title": "Forecasting of CO2 level on Mona Loa dataset using Gaussian process regression (GPR)",
"section": "Design the proper kernel",
"text": "Design the proper kernel\nTo design the kernel to use with our Gaussian process, we can make some assumption regarding the data at hand. We observe that they have several characteristics: we see a long term rising trend, a pronounced seasonal variation and some smaller irregularities. We can use different appropriate kernel that would capture these features.\nFirst, the long term rising trend could be fitted using a radial basis function (RBF) kernel with a large length-scale parameter. The RBF kernel with a large length-scale enforces this component to be smooth. An trending increase is not enforced as to give a degree of freedom to our model. The specific length-scale and the amplitude are free hyperparameters.\n\nfrom sklearn.gaussian_process.kernels import RBF\n\nlong_term_trend_kernel = 50.0**2 * RBF(length_scale=50.0)\n\nThe seasonal variation is explained by the periodic exponential sine squared kernel with a fixed periodicity of 1 year. The length-scale of this periodic component, controlling its smoothness, is a free parameter. In order to allow decaying away from exact periodicity, the product with an RBF kernel is taken. The length-scale of this RBF component controls the decay time and is a further free parameter. This type of kernel is also known as locally periodic kernel.\n\nfrom sklearn.gaussian_process.kernels import ExpSineSquared\n\nseasonal_kernel = (\n 2.0**2\n * RBF(length_scale=100.0)\n * ExpSineSquared(length_scale=1.0, periodicity=1.0, periodicity_bounds=\"fixed\")\n)\n\nThe small irregularities are to be explained by a rational quadratic kernel component, whose length-scale and alpha parameter, which quantifies the diffuseness of the length-scales, are to be determined. A rational quadratic kernel is equivalent to an RBF kernel with several length-scale and will better accommodate the different irregularities.\n\nfrom sklearn.gaussian_process.kernels import RationalQuadratic\n\nirregularities_kernel = 0.5**2 * RationalQuadratic(length_scale=1.0, alpha=1.0)\n\nFinally, the noise in the dataset can be accounted with a kernel consisting of an RBF kernel contribution, which shall explain the correlated noise components such as local weather phenomena, and a white kernel contribution for the white noise. The relative amplitudes and the RBF’s length scale are further free parameters.\n\nfrom sklearn.gaussian_process.kernels import WhiteKernel\n\nnoise_kernel = 0.1**2 * RBF(length_scale=0.1) + WhiteKernel(\n noise_level=0.1**2, noise_level_bounds=(1e-5, 1e5)\n)\n\nThus, our final kernel is an addition of all previous kernel.\n\nco2_kernel = (\n long_term_trend_kernel + seasonal_kernel + irregularities_kernel + noise_kernel\n)\nco2_kernel\n\n50**2 * RBF(length_scale=50) + 2**2 * RBF(length_scale=100) * ExpSineSquared(length_scale=1, periodicity=1) + 0.5**2 * RationalQuadratic(alpha=1, length_scale=1) + 0.1**2 * RBF(length_scale=0.1) + WhiteKernel(noise_level=0.01)"
},
{
"objectID": "ejemplos-ml/gp02-example-co2-sklearn.html#model-fitting-and-extrapolation",
"href": "ejemplos-ml/gp02-example-co2-sklearn.html#model-fitting-and-extrapolation",
"title": "Forecasting of CO2 level on Mona Loa dataset using Gaussian process regression (GPR)",
"section": "Model fitting and extrapolation",
"text": "Model fitting and extrapolation\nNow, we are ready to use a Gaussian process regressor and fit the available data. To follow the example from the literature, we will subtract the mean from the target. We could have used normalize_y=True. However, doing so would have also scaled the target (dividing y by its standard deviation). Thus, the hyperparameters of the different kernel would have had different meaning since they would not have been expressed in ppm.\n\nfrom sklearn.gaussian_process import GaussianProcessRegressor\n\ny_mean = y.mean()\ngaussian_process = GaussianProcessRegressor(kernel=co2_kernel, normalize_y=False)\ngaussian_process.fit(X, y - y_mean)\n\nGaussianProcessRegressor(kernel=50**2 * RBF(length_scale=50) + 2**2 * RBF(length_scale=100) * ExpSineSquared(length_scale=1, periodicity=1) + 0.5**2 * RationalQuadratic(alpha=1, length_scale=1) + 0.1**2 * RBF(length_scale=0.1) + WhiteKernel(noise_level=0.01))In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.GaussianProcessRegressor?Documentation for GaussianProcessRegressoriFittedGaussianProcessRegressor(kernel=50**2 * RBF(length_scale=50) + 2**2 * RBF(length_scale=100) * ExpSineSquared(length_scale=1, periodicity=1) + 0.5**2 * RationalQuadratic(alpha=1, length_scale=1) + 0.1**2 * RBF(length_scale=0.1) + WhiteKernel(noise_level=0.01)) \n\n\nNow, we will use the Gaussian process to predict on:\n\ntraining data to inspect the goodness of fit;\nfuture data to see the extrapolation done by the model.\n\nThus, we create synthetic data from 1958 to the current month. In addition, we need to add the subtracted mean computed during training.\n\nimport datetime\n\nimport numpy as np\n\ntoday = datetime.datetime.now()\ncurrent_month = today.year + today.month / 12\nX_test = np.linspace(start=1958, stop=current_month, num=1_000).reshape(-1, 1)\nmean_y_pred, std_y_pred = gaussian_process.predict(X_test, return_std=True)\nmean_y_pred += y_mean\n\n\nplt.plot(X, y, color=\"black\", linestyle=\"dashed\", label=\"Measurements\")\nplt.plot(X_test, mean_y_pred, color=\"tab:blue\", alpha=0.4, label=\"Gaussian process\")\nplt.fill_between(\n X_test.ravel(),\n mean_y_pred - std_y_pred,\n mean_y_pred + std_y_pred,\n color=\"tab:blue\",\n alpha=0.2,\n)\nplt.legend()\nplt.xlabel(\"Year\")\nplt.ylabel(\"Monthly average of CO$_2$ concentration (ppm)\")\n_ = plt.title(\n \"Monthly average of air samples measurements\\nfrom the Mauna Loa Observatory\"\n)\n\n\n\n\n\n\n\n\nOur fitted model is capable to fit previous data properly and extrapolate to future year with confidence."
},
{
"objectID": "ejemplos-ml/gp02-example-co2-sklearn.html#interpretation-of-kernel-hyperparameters",
"href": "ejemplos-ml/gp02-example-co2-sklearn.html#interpretation-of-kernel-hyperparameters",
"title": "Forecasting of CO2 level on Mona Loa dataset using Gaussian process regression (GPR)",
"section": "Interpretation of kernel hyperparameters",
"text": "Interpretation of kernel hyperparameters\nNow, we can have a look at the hyperparameters of the kernel.\n\ngaussian_process.kernel_\n\n44.8**2 * RBF(length_scale=51.6) + 2.64**2 * RBF(length_scale=91.5) * ExpSineSquared(length_scale=1.48, periodicity=1) + 0.536**2 * RationalQuadratic(alpha=2.89, length_scale=0.968) + 0.188**2 * RBF(length_scale=0.122) + WhiteKernel(noise_level=0.0367)\n\n\nThus, most of the target signal, with the mean subtracted, is explained by a long-term rising trend for ~45 ppm and a length-scale of ~52 years. The periodic component has an amplitude of ~2.6ppm, a decay time of ~90 years and a length-scale of ~1.5. The long decay time indicates that we have a component very close to a seasonal periodicity. The correlated noise has an amplitude of ~0.2 ppm with a length scale of ~0.12 years and a white-noise contribution of ~0.04 ppm. Thus, the overall noise level is very small, indicating that the data can be very well explained by the model."
},
{
"objectID": "ejemplos-ml/gp04-deep_GPs.html",
"href": "ejemplos-ml/gp04-deep_GPs.html",
"title": "Deep Gaussian Processes",
"section": "",
"text": "Open In Colab"
},
{
"objectID": "ejemplos-ml/gp04-deep_GPs.html#getting-started",
"href": "ejemplos-ml/gp04-deep_GPs.html#getting-started",
"title": "Deep Gaussian Processes",
"section": "1. Getting started",
"text": "1. Getting started\nMake sure that you have the appropriate packages installed, including PyDeepGP: you can review the Getting Started page for detailed instructions.\nFirst, we will setup the notebook with libraries we are going to use. As in previous labs, we will use GPy.\n\n# %pip install numpy==1.26.4\n%pip install \"numpy<1.24\"\n\nRequirement already satisfied: numpy<1.24 in /Users/aveloz/miniconda3/lib/python3.9/site-packages (1.23.5)\nNote: you may need to restart the kernel to use updated packages.\n\n\n\n# Install prerequisite packages\n# !pip install git+https://github.com/connorfuhrman/paramz@connorfuhrman/np_type_alias_dep\n# !pip install git+https://github.com/m-lyon/GPy \n# !pip install git+https://github.com/m-lyon/climin\n# !pip install git+https://github.com/SheffieldML/PyDeepGP\n\n# %pip install gpy\n\n\n# Support for maths\nimport numpy as np\n# Plotting tools\nfrom matplotlib import pyplot as plt\n# we use the following for plotting figures in jupyter\n%matplotlib inline\n\nimport warnings\nwarnings.filterwarnings('ignore')\n\n# GPy: Gaussian processes library\nimport GPy\n\n# PyDeepGP: Deep Gaussian processes\nimport deepgp\n\nWe will use data from the winners of the Olympic men’s marathon, highlight limitations with standard GPs and demonstrate how we can make use of deep GPs for such a problem.\n\nimport pickle\nimport requests\n\nreq = requests.get('https://github.com/gpschool/labs/raw/2023/.resources/olympic_marathon_men')\ndata = pickle.loads(req.content)\n\nX, y = data['X'], data['Y'] # X represents the year, and y are the average pace of the winner\n\n\n# Set up our plotting environment\nplt.figure(figsize=(14, 6))\n\n# Plot the training data, the results of the gold medal winning time for the Olympic men's marathon\nplt.plot(X, y, \"kx\", mew=2)\n\n# Annotate plot\nplt.legend(labels=[\"winning time\"]), plt.xlim((1890, 2018))\nplt.xlabel(\"year\"), plt.ylabel(\"pace (minutes per kilometer)\")\nplt.title(\"Olympic men's marathon gold medal winning times from 1896 to 2012\");\n\n\n\n\n\n\n\n\nBy now, you should be familiar with fitting a GP using GPy. We will fit a standard RBF kernel. Note that we are using a Gaussian likelihood, and have a constant mean for our GP (to be optimised).\n\nm_full = GPy.models.GPRegression(\n X, y,\n mean_function=GPy.mappings.Constant(1,1),\n kernel=GPy.kern.RBF(1)\n)\n\nm_full.optimize(messages=False)\ndisplay(m_full)\n\n\n\n\nModel: GP regression\nObjective: 4.785438859622699\nNumber of Parameters: 4\nNumber of Optimization Parameters: 4\nUpdates: True\n\n\n\n\n\n\nGP_regression.\nvalue\nconstraints\npriors\n\n\nconstmap.C\n3.5882415421063345\n\n\n\n\nrbf.variance\n0.2796060152640848\n+ve\n\n\n\nrbf.lengthscale\n20.797074162386387\n+ve\n\n\n\nGaussian_noise.variance\n0.04190680752643112\n+ve\n\n\n\n\n\n\nThis is utility code from previous labs, adapted slightly so that it will work with deep GPs as well\n\ndef plot_gp(model, X, training_points=False):\n \"\"\" Plotting utility to plot a GP fit with 95% confidence interval \"\"\"\n # Plot 95% confidence interval\n m, _ = model.predict(X)\n lci, uci = model.predict_quantiles(\n X,\n (2.5, 97.5)\n )\n plt.fill_between(X[:,0], lci[:,0], uci[:,0], alpha=0.5)\n\n # Plot GP mean and initial training points\n plt.plot(X, m, \"-\")\n plt.legend(labels=[\"GP fit\"])\n\n plt.xlabel(\"x\"), plt.ylabel(\"f\")\n\n # Plot training points if included\n if training_points:\n X_, Y_ = model.X, model.Y\n plt.plot(X_, Y_, \"kx\", mew=2)\n plt.legend(labels=[\"GP fit\", \"sample points\"])\n\nWe can see that plotting the GP, we struggle to handle the outlier, giving an suboptimial fit.\n\nXnew = np.arange(1890,2019)[:, None] # predict winning pace every year between 1890 and 2018\n\nplt.figure(figsize=(14,6))\n# Plot the GP prediction of the latent function with training points\nplot_gp(m_full, Xnew, training_points=True)\n# Annotate plot\nplt.xlabel(\"year\"), plt.ylabel(\"pace (minutes per kilometer)\")\nplt.title(\"Exact GP fit of latent function $f$ describing marathon pace in min/km, assuming a Gaussian likelihood\");"
},
{
"objectID": "ejemplos-ml/gp04-deep_GPs.html#deep-gp-regression",
"href": "ejemplos-ml/gp04-deep_GPs.html#deep-gp-regression",
"title": "Deep Gaussian Processes",
"section": "2. Deep GP Regression",
"text": "2. Deep GP Regression\nAs we have seen before, the GP struggles to fit to the observations due to the presence of the outlier in 1904. Previously, in Lab 2, we modelled this with a non-Gaussian likelihood to give a heavy-tailed output using a Student’s T-distribution. An alternative way to deal with the non-Gaussian is to construct a hierarchical model: a deep GP with two layers.\n\\[\n y = f_1(f_2(x)),\\quad \\mathrm{where}\\ f_1\\sim \\mathcal{GP}\\ \\mathrm{and}\\ f_2 \\sim \\mathcal{GP}\n\\]\nWe are essentially constructing the function, \\[f : \\mathbf{x} \\underset{f_2}{\\mapsto} \\mathbf{z} \\underset{f_1}{\\mapsto}y,\\] where \\(\\mathbf{z}\\) is a latent variable in the hierarchical model. We can refer to \\(\\mathbf{z}\\) as a ‘layer’ in a deep model.\nWe will no construct our deep GP using pyDeepGP. We have one hidden variable (or layer), and will initialise our latent representations with principle component analysis (PCA).\nFor simplicity, we use the Gaussian RBF kernel for each layer, and have 1-D latent variables.\n\nnum_hidden = 1\nlatent_dim = 1\n\nkernels = [*[GPy.kern.RBF(latent_dim, ARD=True)]*num_hidden] # hidden kernels\nkernels.append(GPy.kern.RBF(X.shape[1])) # we append a kernel for the input layer\n\nm_deep = deepgp.DeepGP(\n # this describes the shapes of the inputs and outputs of our latent GPs\n [y.shape[1], *[latent_dim]*num_hidden, X.shape[1]],\n X = X, # training input\n Y = y, # training outout\n inits = [*['PCA']*num_hidden, 'PCA'], # initialise layers\n kernels = kernels,\n num_inducing = 50,\n back_constraint = False\n)\n\n\nm_deep.initialize_parameter()\ndisplay(m_deep)\n\n\n\n\nModel: deepgp\nObjective: 100.13067506795919\nNumber of Parameters: 260\nNumber of Optimization Parameters: 260\nUpdates: True\n\n\n\n\n\n\ndeepgp.\nvalue\nconstraints\npriors\n\n\nobslayer.inducing inputs\n(50, 1)\n\n\n\n\nobslayer.rbf.variance\n1.0\n+ve\n\n\n\nobslayer.rbf.lengthscale\n1.0\n+ve\n\n\n\nobslayer.Gaussian_noise.variance\n1.0\n+ve\n\n\n\nobslayer.Kuu_var\n(50,)\n+ve\n\n\n\nobslayer.latent space.mean\n(27, 1)\n\n\n\n\nobslayer.latent space.variance\n(27, 1)\n+ve\n\n\n\nlayer_1.inducing inputs\n(50, 1)\n\n\n\n\nlayer_1.rbf.variance\n1.0\n+ve\n\n\n\nlayer_1.rbf.lengthscale\n1.0\n+ve\n\n\n\nlayer_1.Gaussian_noise.variance\n0.01\n+ve\n\n\n\nlayer_1.Kuu_var\n(50,)\n+ve\n\n\n\n\n\n\n\nOptimising a Deep GP\nReflecting on the defined model, we can see that we have \\(260\\) parameters to optimise, including kernel and likelihood hyperparameters and inducing inputs and variables for each layer, as well as the latent parameters.\nYou may find that running the optimisation as is will cause a collapse of the Gaussian noise in each layer, causing failure of the optimiser. In the next cell, we construct a utility function to reset the variance to \\(1.0\\) to try and avoid this:\n\ndef optimise_dgp(model, messages=True):\n ''' Utility function for optimising deep GP by first\n reinitiailising the Gaussian noise at each layer\n (for reasons pertaining to stability)\n '''\n model.initialize_parameter()\n for layer in model.layers:\n layer.likelihood.variance.constrain_positive(warning=False)\n layer.likelihood.variance = 1. # small variance may cause collapse\n model.optimize(messages=messages, max_iters=10000)\n\nNow, let’s try optimising the deep GP. You may find that the optimisation fails with status Errorb'ABNORMAL_TERMINATION_IN_LNSRCH: just try rerunning the cell.\n\noptimise_dgp(m_deep, messages=True)\n\n\n\n\nWe can plot our deep GP in the same fit as before, by calling predict() and predict_quantiles() to obtain a moments and quantiles from the optimised deep GP in the observation domain:\n\nXnew = np.arange(1890,2019)[:, None] # predict winning pace every year between 1890 and 2018\n\nplt.figure(figsize=(14,6))\n\n# Plot the our deep GP prediction\nplot_gp(m_deep, Xnew, training_points=True)\n\n# Annotate plot\nplt.xlabel(\"year\"), plt.ylabel(\"pace (minutes per kilometer)\")\nplt.title(\"Deep GP with %d hidden layer(s) fit describing marathon pace in min/km\" % num_hidden);\n\n\n\n\n\n\n\n\n\n\nVisualising Mappings\nAs we can see, the deep GP performs much better than the standard GP fit. We may also find it interesting to look at both the individual functions mapping between layers.\nWe can visualise the latent mappings by propagating the input through layers – since each output is multivariate Gaussian by virtue of the mappings being GPs, we can plot the uncertainty of the latent functions at each layer.\n\ndef plot_dgp_layers(model, X, training_points=True, axsize=(14,6)):\n ''' Plot mappings between layers in a deep GP '''\n if not isinstance(model, deepgp.DeepGP):\n return plot_gp(model, X) # catch a batch GP\n\n num_layers = len(model.layers) # Get number of layers\n layer_input = X # The first input\n\n _, axs = plt.subplots(num_layers, 1, figsize=(axsize[0], axsize[1]*num_layers))\n\n # The layers in a deep GP are ordered from observation to input,\n # ... we will plot them from input to output, so reverse the layers\n layers = list(reversed(model.layers))\n for i, layer in enumerate(layers):\n # We get the mean and confidence intervals of the layer\n mu_i, _ = layer.predict(layer_input, include_likelihood=False)\n lci_i, uci_i = layer.predict_quantiles(layer_input, (2.5, 97.5))\n # Plot mean and 95% CI of latent function\n axs[i].plot(layer_input, mu_i)\n axs[i].fill_between(layer_input[:,0], lci_i[:,0], uci_i[:,0], alpha=0.5)\n # Annotate plot\n axs[i].set_ylabel(layer.name)\n axs[i].set_xlabel(layers[i-1].name if i > 0 else \"input\")\n axs[i].set_title(\"$f_%d$\" % (num_layers-i))\n # Set mean as input for next layer\n layer_input = np.linspace(*min(lci_i), *max(uci_i), num=100)[:,None]\n\n if training_points: # Plot propagated training points\n axs[i].plot(\n layer.X.mean.values if i > 0 else layer.X,\n layer.Y.mean.values if i < num_layers-1 else layer.Y,\n 'kx', mew=2\n )\n\nWe now plot our two GPs that form the hierarchical (deep) GP. The first maps the input domain to the first latent space, and the second maps from that latent space into space of our observation model.\n\\[y = f_1(f_2(x))\\]\n\nplot_dgp_layers(m_deep, Xnew, training_points=True, axsize=(14, 6))\n\n\n\n\n\n\n\n\n\n\nSampling\nAs with all models, we might want to sample from the posterior. We can do this with the mean and covariance of our GP layers, and use these to create random samples – by the nature of the model, each sample from the first layer forms the input to the second. You can see the code to perform this below:\n\ndef sample_dgp(model, X, num_samples=1, include_likelihood=True):\n ''' Sample from a hierarchical GP by propagating\n samples through layers\n '''\n samples = []\n jitter = 1e-5\n count, num_tries = 0, 100\n while len(samples) < num_samples:\n next_input = X\n if count > num_tries:\n print(\"failed to sample\")\n break\n try:\n count = count + 1\n for layer in reversed(model.layers):\n mu_k, sig_k = layer.predict(\n next_input, full_cov=True, include_likelihood=include_likelihood\n )\n sample_k = mu_k + np.linalg.cholesky(sig_k + jitter*np.eye(X.shape[0]))@np.random.randn(*X.shape)\n next_input = sample_k\n samples.append(sample_k)\n count = 0\n except:\n pass\n\n return samples if num_samples > 1 else samples[0]\n\n\n_, axs = plt.subplots(2,1, figsize=(14,12))\n\nsamples = sample_dgp(m_deep, Xnew, 10, include_likelihood=True)\nfor sample in samples:\n axs[0].plot(Xnew, sample, 'go', alpha=0.2)\naxs[0].plot(X, y, 'kx', mew=2)\naxs[0].set_title(\"observable samples\")\n\nsamples = sample_dgp(m_deep, Xnew, 100, include_likelihood=False)\nfor sample in samples:\n axs[1].plot(Xnew, sample, 'g-', alpha=0.1)\naxs[1].plot(X, y, 'kx', mew=2)\naxs[1].set_title(\"latent samples\")\n\n[(ax.set_xlabel(\"year\"), ax.set_ylabel(\"pace (minutes per kilometer)\")) for ax in axs];\n\n\n\n\n\n\n\n\n\n\nExercise:\nNow you have seen how we can fit a deep GP to data, and sample from the posterior. Using the following utility code snippets, construct a deep GP prior and same from it. Apply standard and deep GP regression to the model, and comment on the results.\n\ndef gp_prior_sample(x, kern=GPy.kern.RBF):\n ''' '''\n if not isinstance(kern, GPy.kern.Kern):\n kern = kern(x.shape[1], ARD=True)\n mu = np.zeros((x.shape[0]))\n C = kern.K(x,x)\n return np.random.multivariate_normal(mu, C, 1).T\n\ndef deepgp_prior_sample(x, kernels=[GPy.kern.RBF]):\n ''' Sample from hierarchical model: f = f1(f2(...fn(x)))\n where fi ~ GP(0,Ki) and Ki = kernels[i].K\n '''\n z = x\n for kern in reversed(kernels):\n z = gp_prior_sample(z, kern=kern)\n return z"
},
{
"objectID": "ejemplos-ml/gp04-deep_GPs.html#approximating-discontinuities",
"href": "ejemplos-ml/gp04-deep_GPs.html#approximating-discontinuities",
"title": "Deep Gaussian Processes",
"section": "3. Approximating Discontinuities",
"text": "3. Approximating Discontinuities\nOne of the benefits of deep Gaussian processes is that we can warp the latent GPs non-linearly, which helps model more complex structures, such as step discontinuties. In this section, we will show an example of how a deep GP can be used to model a rectangle function, and compare it to a standard GP.\nFirst, we will create some data from a rectangle function, with the upper and lower parts overlapping randomly:\n\ndef overlapping_rect(scale=1.):\n ''' Create a rectangle function with overlap in upper and lower layers'''\n x = np.linspace(0., 1., 400)\n y = np.hstack([np.zeros(100), np.random.choice([0., 1.], size=(50,)), np.ones(100), np.random.choice([0., 1.], size=(50,)), np.zeros(100)])\n return x[:,None], scale*y[:,None]\n\n# We generate and plot our data (not that there is no added noise)\nX, y = overlapping_rect()\n\nplt.figure(figsize=(14, 6))\nplt.plot(X, y, 'kx', alpha=0.5);\n\n\n\n\n\n\n\n\nAs we know from previous labs, fitting a GP to this will be difficult because of the inherent smoothness assumed. However, we will fit and plot one all the same, just for comparison:\n\nm_full = GPy.models.GPRegression(X, y, kernel=GPy.kern.RBF(1))\nm_full.optimize()\ndisplay(m_full)\n\n\n\n\nModel: GP regression\nObjective: 46.73756961394463\nNumber of Parameters: 3\nNumber of Optimization Parameters: 3\nUpdates: True\n\n\n\n\n\n\nGP_regression.\nvalue\nconstraints\npriors\n\n\nrbf.variance\n0.24121650210341336\n+ve\n\n\n\nrbf.lengthscale\n0.20363838808749113\n+ve\n\n\n\nGaussian_noise.variance\n0.0686572550818164\n+ve\n\n\n\n\n\n\n\nXnew = np.linspace(-0.2, 1.2, num=500)[:,None]\nplt.figure(figsize=(14,6))\nplot_gp(m_full, Xnew, training_points=True)\n\n\n\n\n\n\n\n\nAs we can see, the GP struggles with the discontinuties and gives us an overly uncertain, and smooth fit.\nWe will now try a simple 3-layer deep GP, \\(y = f_1(f_2(f_3(x)))\\), with RBF kernels at each layer.\n\nnum_hidden = 2\n\nm_deep = deepgp.DeepGP(\n [y.shape[1], *[1]*num_hidden, X.shape[1]],\n X = X,\n Y = y,\n init = [*['PCA']*num_hidden, 'PCA'],\n kernels = [*[GPy.kern.RBF(1, ARD=True)]*num_hidden, GPy.kern.RBF(1)],\n num_inducing = 50,\n back_constraint=False\n)\noptimise_dgp(m_deep)\n\n\n\n\nWe plot the fit now, and as we can see, the is close to the observations, with the greatest uncertainty occuring in the overlapping discontinuties.\n\nplt.figure(figsize=(14,6))\nplot_gp(m_deep, Xnew, training_points=True)\n\n\n\n\n\n\n\n\nWe can look at the samples from the posterior, of both simulated observations and of the latent GPs. We can see that while the samples are not tightly fit to 0 or 1, we observe a reasonable behaviour representing the rectangle function (which we have treated as continuous). Notably, if we look to the edges of the plot, where we are sampling at input from which we have no observations, the behaviour is modelling the step functionality as a possibility.\n\n_, axs = plt.subplots(2,1, figsize=(14,12))\n\nsamples = sample_dgp(m_deep, Xnew, 10, include_likelihood=True)\nfor sample in samples:\n axs[0].plot(Xnew, sample, 'go', alpha=0.2)\naxs[0].plot(X, y, 'kx', mew=2)\naxs[0].set_title(\"observable samples\")\n\nsamples = sample_dgp(m_deep, Xnew, 100, include_likelihood=False)\nfor sample in samples:\n axs[1].plot(Xnew, sample, 'g-', alpha=0.1)\naxs[1].plot(X, y, 'kx', mew=2)\naxs[1].set_title(\"latent samples\")\n\n[(ax.set_xlabel(\"x\"), ax.set_ylabel(\"y\")) for ax in axs];\n\n\n\n\n\n\n\n\n\n\nCredit\nThis notebook was written by Wil Ward, based on documentation of PyDeepGP and talks by Neil Lawrence."
},
{
"objectID": "bambinos/corazon.html#posizione-e-dimensione-del-cuore",
"href": "bambinos/corazon.html#posizione-e-dimensione-del-cuore",
"title": "Il cuore",
"section": "Posizione e dimensione del cuore",
"text": "Posizione e dimensione del cuore"
},
{
"objectID": "bambinos/corazon.html#trasporto-di-nutrienti-e-ossigeno",
"href": "bambinos/corazon.html#trasporto-di-nutrienti-e-ossigeno",
"title": "Il cuore",
"section": "Trasporto di nutrienti e ossigeno",
"text": "Trasporto di nutrienti e ossigeno"
},
{
"objectID": "bambinos/corazon.html#atri-ventricoli-e-valvole",
"href": "bambinos/corazon.html#atri-ventricoli-e-valvole",
"title": "Il cuore",
"section": "Atri, ventricoli e valvole",
"text": "Atri, ventricoli e valvole"
},
{
"objectID": "bambinos/corazon.html#cura-del-cuore",
"href": "bambinos/corazon.html#cura-del-cuore",
"title": "Il cuore",
"section": "Cura del cuore",
"text": "Cura del cuore"
},
{
"objectID": "bambinos/corazon.html#section",
"href": "bambinos/corazon.html#section",
"title": "Il cuore",
"section": "",
"text": "Grazie per la sua attenzione."
},
{
"objectID": "bme423/labs/lab1.html#objetivos",
"href": "bme423/labs/lab1.html#objetivos",
"title": "Manipulación de imágenes, DICOM y color",
"section": "Objetivos",
"text": "Objetivos\nLos objetivos de esta actividad son los siguientes:\n\nFamiliarizarse con las bibliotecas NumPy, SciPy, y Matplotlib.\nFamiliarizarse con el manejo básico de imágenes digitales.\nFamiliarizarse con el estándar DICOM, utilizado para transmitir, almacenar, recuperar, imprimir, procesar y mostrar información relativa a las imágenes médicas.\nAprender a utilizar la biblioteca pydicom."
},
{
"objectID": "bme423/labs/lab1.html#actividades",
"href": "bme423/labs/lab1.html#actividades",
"title": "Manipulación de imágenes, DICOM y color",
"section": "Actividades",
"text": "Actividades\n\nTrabajo complementario (opcional)\nDICOM\nMejora de contraste\nFiltrado espacial\nVisualización de mapas de activación\nInstrucciones para la entrega"
},
{
"objectID": "bme423/labs/lab1.html#trabajo-complementario-1",
"href": "bme423/labs/lab1.html#trabajo-complementario-1",
"title": "Manipulación de imágenes, DICOM y color",
"section": "1. Trabajo complementario",
"text": "1. Trabajo complementario\n\nInstale la plataforma de desarrollo Anaconda, disponible de forma gratuita en LINK. También puede usar Google Colab o Visual Studio Code.\nEstudie y haga los ejercicios de las siguientes secciones del documento “Scipy Lecture Notes”:\n\nSección 1.4. NumPy: creating and manipulating numerical data.\nSección 1.5. Matplotlib: plotting.\nSecciones 1.6.1, 1.6.3, 1.6.5, 1.6.6 y 1.6.10. Scipy : high-level scientific computing."
},
{
"objectID": "bme423/labs/lab1.html#trabajo-complementario-2",
"href": "bme423/labs/lab1.html#trabajo-complementario-2",
"title": "Manipulación de imágenes, DICOM y color",
"section": "1. Trabajo complementario",
"text": "1. Trabajo complementario\n\nLeer el siguiente material de referencia:\n\nWhy Does the DICOM Standard Exist?\nParte 1 “Introduction and Overview” del estándar DICOM.\nDocumentación de la biblioteca PyDicom."
},
{
"objectID": "bme423/labs/lab1.html#dicom-1",
"href": "bme423/labs/lab1.html#dicom-1",
"title": "Manipulación de imágenes, DICOM y color",
"section": "2. DICOM",
"text": "2. DICOM\n\nSe trabajará con dos conjunto de datos.\n\ndata1: imágenes de CT de distintos pacientes.\ndata2: Imágenes de CT de cortes de un mismo paciente.\n\nLos datos están disponibles en Github.\n\n!git clone https://github.com/aavelozb/bme423-data.git\n!unzip bme423-data/data1.zip -d bme423-data/\n!unzip bme423-data/data2.zip -d bme423-data/"
},
{
"objectID": "bme423/labs/lab1.html#dicom---actividades",
"href": "bme423/labs/lab1.html#dicom---actividades",
"title": "Manipulación de imágenes, DICOM y color",
"section": "2. DICOM - actividades",
"text": "2. DICOM - actividades\n\nDesarrolle un programa que genere un archivo CSV con los nombres y fechas de nacimiento de los pacientes de las imágenes contenidas en el directorio data1.\nDesarrolle un programa que muestre en una sola figura todas las imágenes del directorio data1. Cada imagen debe estar identificada por el nombre del paciente.\nDesarrolle un programa que anonimice todas las imágenes del directorio data1.\nImplemente un programa que permita visualizar un corte coronal y sagital de las imágenes del directorio data2."
},
{
"objectID": "bme423/labs/lab1.html#dicom---actividades-1",
"href": "bme423/labs/lab1.html#dicom---actividades-1",
"title": "Manipulación de imágenes, DICOM y color",
"section": "2. DICOM - actividades",
"text": "2. DICOM - actividades\n\nImplemente un programa que permita visualizar un corte oblicuo coronal-sagital de las imágenes del directorio data2.\nEl proceso de downsampling consiste en re-muestrear una imagen. La forma más simple de realizar este proceso es conservar uno de cada \\(n \\in \\mathbb{N}\\) píxeles de la imagen.\n\n\nRealice el proceso de downsampling de la imagen p5.dcm, conservando uno de cada 2, 3 y 4 píxeles.\nMuestre la imagen original y las de tamaño reducido. Analice las diferencias entre éstas."
},
{
"objectID": "bme423/labs/lab1.html#dicom---actividades-2",
"href": "bme423/labs/lab1.html#dicom---actividades-2",
"title": "Manipulación de imágenes, DICOM y color",
"section": "2. DICOM - actividades",
"text": "2. DICOM - actividades\n\nVisualice las imágenes del directorio data2 usando widgets de Matplotlib, o ipywidgets."
},
{
"objectID": "bme423/labs/lab1.html#contraste---actividades",
"href": "bme423/labs/lab1.html#contraste---actividades",
"title": "Manipulación de imágenes, DICOM y color",
"section": "3. Contraste - actividades",
"text": "3. Contraste - actividades\n\nAgregue opciones a un widget para aplicar operaciones de mejora de contraste, en base a la transformación \\(\\gamma\\) (Ec. 3.2-3, sección 3.2.3, página 110) y usando una función de transformación definida por tramos (Figura 3.10(a), página 116).\nGenere situaciones que permitan apreciar en qué situaciones el contraste mejora, versus cuándo empeora. Se recomienda usar los histogramas de las imágenes resultantes, junto a los histogramas de las imágenes de entrada para su explicación."
},
{
"objectID": "bme423/labs/lab1.html#contraste---actividades-1",
"href": "bme423/labs/lab1.html#contraste---actividades-1",
"title": "Manipulación de imágenes, DICOM y color",
"section": "3. Contraste - actividades",
"text": "3. Contraste - actividades\n\nImplemente la ecualización (Ec. 3.3-8, página 126) y especificación de histogramas (Ec. 3.3-12, página 130). Explique los resultados (no es necesario usar widgets)."
},
{
"objectID": "bme423/labs/lab1.html#filtrado-espacial---actividades",
"href": "bme423/labs/lab1.html#filtrado-espacial---actividades",
"title": "Manipulación de imágenes, DICOM y color",
"section": "4. Filtrado espacial - actividades",
"text": "4. Filtrado espacial - actividades\n\nImplemente la operación de convolución (sección 3.4.2, página 148, ecuación 3.4-1).\nUsando su implementación de la convolución:\n\n\nImplemente los filtros de suavizado, incluyendo el filtro Gaussiano, (sección 3.5.1, página 152) y agudizado (sección 3.6, página 157).\nAplique estos filtros al volumen de CT de una misma persona (data2). Aplique la convolución en 2D y luego en 3D.\nCompare con el resultado obtenido usando la función \\(\\texttt{scipy.ndimage.convolve}\\) (para un filtro)."
},
{
"objectID": "bme423/labs/lab1.html#section",
"href": "bme423/labs/lab1.html#section",
"title": "Manipulación de imágenes, DICOM y color",
"section": "",
"text": "Ayuda: La siguiente sentencia permite construir la versión rellenada con ceros de la imagen:\npad_len = (mask.shape[0] - 1) // 2\nimg_padded = np.pad(img, ((pad_len, pad_len), (pad_len, pad_len)),\n 'constant', constant_values=0)\ndonde \\(\\texttt{mask}\\) contiene la máscara del filtro (se asume que es cuadrada, con largo impar), e \\(\\texttt{img}\\) es la imagen original."
},
{
"objectID": "bme423/labs/lab1.html#filtrado-espacial---actividades-1",
"href": "bme423/labs/lab1.html#filtrado-espacial---actividades-1",
"title": "Manipulación de imágenes, DICOM y color",
"section": "4. Filtrado espacial - actividades",
"text": "4. Filtrado espacial - actividades\n\nAplique los filtros de suavizado, filtros de agudizado y operaciones de mejora de contraste de manera combinada en la imagen xray.dcm.\n\n\nExplique la pertinencia de los pasos aplicados y cuantifique la mejora en la calidad de la imagen a medida que aplica los pasos considerados.\nUse el ejemplo de la sección 3.7 (pág. 169) como inspiración.\n\n\nResuelva el mismo problema de la pregunta anterior para el caso 3D con el volumen data2."
},
{
"objectID": "bme423/labs/lab1.html#filtrado-espacial---actividades-2",
"href": "bme423/labs/lab1.html#filtrado-espacial---actividades-2",
"title": "Manipulación de imágenes, DICOM y color",
"section": "4. Filtrado espacial - actividades",
"text": "4. Filtrado espacial - actividades\nNota: La operación de convolución, los filtros, y los métodos de mejora de contraste debe implementarlos Ud., sin utilizar librerías específicas de procesamiento de imágenes."
},
{
"objectID": "bme423/labs/lab1.html#visualización-de-mapas-de-activación---actividades",
"href": "bme423/labs/lab1.html#visualización-de-mapas-de-activación---actividades",
"title": "Manipulación de imágenes, DICOM y color",
"section": "5. Visualización de mapas de activación - actividades",
"text": "5. Visualización de mapas de activación - actividades\n\nDesarrolle un programa que permita visualizar un mapa como el siguiente:\n\n\n\n\n\n\nDispone de los archivos anat.nii, zmap_voice.nii.gz y zmap_nonvoice.nii.gz.\nNote que los archivos están en formato .nii, los cuales pueden ser leídos usando la librería \\(\\texttt{nibabel}\\)."
},
{
"objectID": "bme423/labs/lab1.html#section-1",
"href": "bme423/labs/lab1.html#section-1",
"title": "Manipulación de imágenes, DICOM y color",
"section": "",
"text": "Entregas:\n\n\n\napellido_nombre_l1e1.ipynb y apellido_nombre_l1e1.pdf\n\nFecha: hoy\nRespuestas desde la 1 hasta la 7.\nMedio: Aula virtual\n\n\n\n\napellido_nombre_l1e2.ipynb y apellido_nombre_l1e2.pdf\n\nFecha: 10/09/2025\nRespuestas desde la 8 en adelante.\nMedio: Aula virtual\n\n\n\nLas versiones \\(\\texttt{.pdf}\\) en las entregas corresponden a los archivos \\(\\texttt{.ipynb}\\) con las salidas de las celdas visibles.\nNo respetar las instrucciones significará un descuento de 10 pts."
},
{
"objectID": "bme423/labs/lab2.html#objetivos",
"href": "bme423/labs/lab2.html#objetivos",
"title": "Contraste y filtrado",
"section": "Objetivos",
"text": "Objetivos\nLos objetivos de esta actividad son los siguientes:\n\nImplementar un pipeline de procesamiento para mejorar la calidad de imágenes médicas.\nComparar distintas opciones de mejora de contraste / filtros mediante métricas cuantitativas.\nAnalizar resultados en varios sujetos."
},
{
"objectID": "bme423/labs/lab2.html#datos",
"href": "bme423/labs/lab2.html#datos",
"title": "Contraste y filtrado",
"section": "Datos",
"text": "Datos\nSe trabajará con datos de pacientes que sufren esclerosis múltiple: Open MS data"
},
{
"objectID": "bme423/labs/lab2.html#datos-1",
"href": "bme423/labs/lab2.html#datos-1",
"title": "Contraste y filtrado",
"section": "Datos",
"text": "Datos\n\n\nPaciente 4 - Anatomía, slice 312\n\n\nPaciente 4 - Anatomía + Gold Standard, slice 312"
},
{
"objectID": "bme423/labs/lab2.html#actividad-1",
"href": "bme423/labs/lab2.html#actividad-1",
"title": "Contraste y filtrado",
"section": "Actividad 1",
"text": "Actividad 1\nImplementar el filtro de difusión anisotrópica en 3D y aplicarlo a uno de los pacientes (sin el uso de librerías)."
},
{
"objectID": "bme423/labs/lab2.html#actividad-2",
"href": "bme423/labs/lab2.html#actividad-2",
"title": "Contraste y filtrado",
"section": "Actividad 2",
"text": "Actividad 2\n\nImplementar pipelines para diferentes opciones de filtrado y mejora de contraste vistas en clases, con el propósito de mejorar la calidad de las imágenes disponibles.\nComparar cuantitativamente estos pipelines y elija el mejor.\n\nSe pueden usar librerías, como scikit-image, simpleITK, etc., para la convolución, fft 2D y difusión anisotrópica.\nDebe considerar los parámetros de las diferentes técnicas para su comparación.\nDebe considerar las particularidades propias de la esclerosis múltiple."
},
{
"objectID": "bme423/labs/lab2.html#instrucciones-para-la-entrega",
"href": "bme423/labs/lab2.html#instrucciones-para-la-entrega",
"title": "Contraste y filtrado",
"section": "Instrucciones para la entrega",
"text": "Instrucciones para la entrega\n\napellido_nombre_l2.ipynb y apellido_nombre_l2.pdf\nMedio: Aula virtual\nLas versiones .pdf en las entregas corresponden a los archivos .ipynb con las salidas de las celdas visibles.\nNo respetar las instrucciones significará un descuento de 10 pts."
},
{
"objectID": "bme423/labs/jp-corazon.html#objetivos",
"href": "bme423/labs/jp-corazon.html#objetivos",
"title": "Manipulación de imágenes, DICOM y color",
"section": "Objetivos",
"text": "Objetivos\nLos objetivos de esta actividad son los siguientes:\n\nFamiliarizarse con las bibliotecas NumPy, SciPy, y Matplotlib.\nFamiliarizarse con el manejo básico de imágenes digitales.\nFamiliarizarse con el estándar DICOM, utilizado para transmitir, almacenar, recuperar, imprimir, procesar y mostrar información relativa a las imágenes médicas.\nAprender a utilizar la biblioteca pydicom."
},
{
"objectID": "bme423/labs/jp-corazon.html#actividades",
"href": "bme423/labs/jp-corazon.html#actividades",
"title": "Manipulación de imágenes, DICOM y color",
"section": "Actividades",
"text": "Actividades\n\nTrabajo complementario (opcional)\nDICOM\nMejora de contraste\nFiltrado espacial\nVisualización de mapas de activación\nInstrucciones para la entrega"
},
{
"objectID": "bme423/labs/jp-corazon.html#trabajo-complementario-1",
"href": "bme423/labs/jp-corazon.html#trabajo-complementario-1",
"title": "Manipulación de imágenes, DICOM y color",
"section": "1. Trabajo complementario",
"text": "1. Trabajo complementario\n\nInstale la plataforma de desarrollo Anaconda, disponible de forma gratuita en LINK. También puede usar Google Colab o Visual Studio Code.\nEstudie y haga los ejercicios de las siguientes secciones del documento “Scipy Lecture Notes”:\n\nSección 1.4. NumPy: creating and manipulating numerical data.\nSección 1.5. Matplotlib: plotting.\nSecciones 1.6.1, 1.6.3, 1.6.5, 1.6.6 y 1.6.10. Scipy : high-level scientific computing."
},
{
"objectID": "bme423/labs/jp-corazon.html#trabajo-complementario-2",
"href": "bme423/labs/jp-corazon.html#trabajo-complementario-2",
"title": "Manipulación de imágenes, DICOM y color",
"section": "1. Trabajo complementario",
"text": "1. Trabajo complementario\n\nLeer el siguiente material de referencia:\n\nWhy Does the DICOM Standard Exist?\nParte 1 “Introduction and Overview” del estándar DICOM.\nDocumentación de la biblioteca PyDicom."
},
{
"objectID": "bme423/labs/jp-corazon.html#dicom-1",
"href": "bme423/labs/jp-corazon.html#dicom-1",
"title": "Manipulación de imágenes, DICOM y color",
"section": "2. DICOM",
"text": "2. DICOM\n\nSe trabajará con dos conjunto de datos.\n\ndata1: imágenes de CT de distintos pacientes.\ndata2: Imágenes de CT de cortes de un mismo paciente.\n\nLos datos están disponibles en Github.\n\n!git clone https://github.com/aavelozb/bme423-data.git\n!unzip bme423-data/data1.zip -d bme423-data/\n!unzip bme423-data/data2.zip -d bme423-data/"
},
{
"objectID": "bme423/labs/jp-corazon.html#dicom---actividades",
"href": "bme423/labs/jp-corazon.html#dicom---actividades",
"title": "Manipulación de imágenes, DICOM y color",
"section": "2. DICOM - actividades",
"text": "2. DICOM - actividades\n\nDesarrolle un programa que genere un archivo CSV con los nombres y fechas de nacimiento de los pacientes de las imágenes contenidas en el directorio data1.\nDesarrolle un programa que muestre en una sola figura todas las imágenes del directorio data1. Cada imagen debe estar identificada por el nombre del paciente.\nDesarrolle un programa que anonimice todas las imágenes del directorio data1.\nImplemente un programa que permita visualizar un corte coronal y sagital de las imágenes del directorio data2."
},
{
"objectID": "bme423/labs/jp-corazon.html#dicom---actividades-1",
"href": "bme423/labs/jp-corazon.html#dicom---actividades-1",
"title": "Manipulación de imágenes, DICOM y color",
"section": "2. DICOM - actividades",
"text": "2. DICOM - actividades\n\nImplemente un programa que permita visualizar un corte oblicuo coronal-sagital de las imágenes del directorio data2.\nEl proceso de downsampling consiste en re-muestrear una imagen. La forma más simple de realizar este proceso es conservar uno de cada \\(n \\in \\mathbb{N}\\) píxeles de la imagen.\n\n\nRealice el proceso de downsampling de la imagen p5.dcm, conservando uno de cada 2, 3 y 4 píxeles.\nMuestre la imagen original y las de tamaño reducido. Analice las diferencias entre éstas."
},
{
"objectID": "bme423/labs/jp-corazon.html#dicom---actividades-2",
"href": "bme423/labs/jp-corazon.html#dicom---actividades-2",
"title": "Manipulación de imágenes, DICOM y color",
"section": "2. DICOM - actividades",
"text": "2. DICOM - actividades\n\nVisualice las imágenes del directorio data2 usando widgets de Matplotlib, o ipywidgets."
},
{
"objectID": "bme423/labs/jp-corazon.html#contraste---actividades",
"href": "bme423/labs/jp-corazon.html#contraste---actividades",
"title": "Manipulación de imágenes, DICOM y color",
"section": "3. Contraste - actividades",
"text": "3. Contraste - actividades\n\nAgregue opciones a un widget para aplicar operaciones de mejora de contraste, en base a la transformación \\(\\gamma\\) (Ec. 3.2-3, sección 3.2.3, página 110) y usando una función de transformación definida por tramos (Figura 3.10(a), página 116).\nGenere situaciones que permitan apreciar en qué situaciones el contraste mejora, versus cuándo empeora. Se recomienda usar los histogramas de las imágenes resultantes, junto a los histogramas de las imágenes de entrada para su explicación."
},
{
"objectID": "bme423/labs/jp-corazon.html#contraste---actividades-1",
"href": "bme423/labs/jp-corazon.html#contraste---actividades-1",
"title": "Manipulación de imágenes, DICOM y color",
"section": "3. Contraste - actividades",
"text": "3. Contraste - actividades\n\nImplemente la ecualización (Ec. 3.3-8, página 126) y especificación de histogramas (Ec. 3.3-12, página 130). Explique los resultados (no es necesario usar widgets)."
},
{
"objectID": "bme423/labs/jp-corazon.html#filtrado-espacial---actividades",
"href": "bme423/labs/jp-corazon.html#filtrado-espacial---actividades",
"title": "Manipulación de imágenes, DICOM y color",
"section": "4. Filtrado espacial - actividades",
"text": "4. Filtrado espacial - actividades\n\nImplemente la operación de convolución (sección 3.4.2, página 148, ecuación 3.4-1).\nUsando su implementación de la convolución:\n\n\nImplemente los filtros de suavizado, incluyendo el filtro Gaussiano, (sección 3.5.1, página 152) y agudizado (sección 3.6, página 157).\nAplique estos filtros al volumen de CT de una misma persona (data2). Aplique la convolución en 2D y luego en 3D.\nCompare con el resultado obtenido usando la función \\(\\texttt{scipy.ndimage.convolve}\\) (para un filtro)."
},
{
"objectID": "bme423/labs/jp-corazon.html#section",
"href": "bme423/labs/jp-corazon.html#section",
"title": "Manipulación de imágenes, DICOM y color",
"section": "",
"text": "Ayuda: La siguiente sentencia permite construir la versión rellenada con ceros de la imagen:\npad_len = (mask.shape[0] - 1) // 2\nimg_padded = np.pad(img, ((pad_len, pad_len), (pad_len, pad_len)),\n 'constant', constant_values=0)\ndonde \\(\\texttt{mask}\\) contiene la máscara del filtro (se asume que es cuadrada, con largo impar), e \\(\\texttt{img}\\) es la imagen original."
},
{
"objectID": "bme423/labs/jp-corazon.html#filtrado-espacial---actividades-1",
"href": "bme423/labs/jp-corazon.html#filtrado-espacial---actividades-1",
"title": "Manipulación de imágenes, DICOM y color",
"section": "4. Filtrado espacial - actividades",
"text": "4. Filtrado espacial - actividades\n\nAplique los filtros de suavizado, filtros de agudizado y operaciones de mejora de contraste de manera combinada en la imagen xray.dcm.\n\n\nExplique la pertinencia de los pasos aplicados y cuantifique la mejora en la calidad de la imagen a medida que aplica los pasos considerados.\nUse el ejemplo de la sección 3.7 (pág. 169) como inspiración.\n\n\nResuelva el mismo problema de la pregunta anterior para el caso 3D con el volumen data2."
},
{
"objectID": "bme423/labs/jp-corazon.html#filtrado-espacial---actividades-2",
"href": "bme423/labs/jp-corazon.html#filtrado-espacial---actividades-2",
"title": "Manipulación de imágenes, DICOM y color",
"section": "4. Filtrado espacial - actividades",
"text": "4. Filtrado espacial - actividades\nNota: La operación de convolución, los filtros, y los métodos de mejora de contraste debe implementarlos Ud., sin utilizar librerías específicas de procesamiento de imágenes."
},
{
"objectID": "bme423/labs/jp-corazon.html#visualización-de-mapas-de-activación---actividades",
"href": "bme423/labs/jp-corazon.html#visualización-de-mapas-de-activación---actividades",
"title": "Manipulación de imágenes, DICOM y color",
"section": "5. Visualización de mapas de activación - actividades",
"text": "5. Visualización de mapas de activación - actividades\n\nDesarrolle un programa que permita visualizar un mapa como el siguiente:\n\n\n\n\n\n\nDispone de los archivos anat.nii, zmap_voice.nii.gz y zmap_nonvoice.nii.gz.\nNote que los archivos están en formato .nii, los cuales pueden ser leídos usando la librería \\(\\texttt{nibabel}\\)."
},
{
"objectID": "bme423/labs/jp-corazon.html#section-1",
"href": "bme423/labs/jp-corazon.html#section-1",
"title": "Manipulación de imágenes, DICOM y color",
"section": "",
"text": "Entregas:\n\n\n\napellido_nombre_l1e1.ipynb y apellido_nombre_l1e1.pdf\n\nFecha: hoy\nRespuestas desde la 1 hasta la 7.\nMedio: Aula virtual\n\n\n\n\napellido_nombre_l1e2.ipynb y apellido_nombre_l1e2.pdf\n\nFecha: 10/09/2025\nRespuestas desde la 8 en adelante.\nMedio: Aula virtual\n\n\n\nLas versiones \\(\\texttt{.pdf}\\) en las entregas corresponden a los archivos \\(\\texttt{.ipynb}\\) con las salidas de las celdas visibles.\nNo respetar las instrucciones significará un descuento de 10 pts."
},
{
"objectID": "bme423/index.html",
"href": "bme423/index.html",
"title": "BME423 - Procesamiento de imágenes médicas",
"section": "",
"text": "Día\nHora\nLugar\n\n\n\n\nCátedra\nViernes\n10:15 - 13:30\n202 (Hucke)\n\n\nLab\nMiércoles\n14:30 - 17:45\nLab. 302 (Hucke)\n\n\n\nProfesor: Dr. Alejandro Veloz (email: alejandro.veloz@uv.cl) Ayudante:"
},
{
"objectID": "bme423/index.html#fechas-de-las-pruebas",
"href": "bme423/index.html#fechas-de-las-pruebas",
"title": "BME423 - Procesamiento de imágenes médicas",
"section": "Fechas de las pruebas",
"text": "Fechas de las pruebas\n02-10. Prueba 1. 13-11. Prueba 2. 11-12. Prueba 3."
},
{
"objectID": "bme423/index.html#laboratorios-1",
"href": "bme423/index.html#laboratorios-1",
"title": "BME423 - Procesamiento de imágenes médicas",
"section": "Laboratorios",
"text": "Laboratorios\nLa asistencia a laboratorio es obligatoria. Sin perjuicio de lo anterior, en el transcurso del semestre podrá ausentarse a 3 sesiones de laboratorio sin necesidad de presentar justificación. Esto no incluye a las sesiones que dan inicio a una nueva actividad del laboratorio.\nLas notas de los laboratorios contemplarán los siguientes aspectos:\n\nSeguimiento de instrucciones de entrega.\nEntrega de parte del trabajo solicitado al finalizar los laboratorios (cada laboratorio indicará qué es lo que debe entregarse).\nContenido de las respuestas a las preguntas formuladas."
},
{
"objectID": "bme423/index.html#fechas-importantes",
"href": "bme423/index.html#fechas-importantes",
"title": "BME423 - Procesamiento de imágenes médicas",
"section": "Fechas importantes",
"text": "Fechas importantes\n28-08. Entrega de temas de proyecto. 13-11. Presentación avance. 04-12. Prueba. 11-12. Entrega proyectos."
},
{
"objectID": "bme423/index.html#laboratorios-2",
"href": "bme423/index.html#laboratorios-2",
"title": "BME423 - Procesamiento de imágenes médicas",
"section": "Laboratorios",
"text": "Laboratorios\nLa asistencia a laboratorio es obligatoria. Sin perjuicio de lo anterior, en el transcurso del semestre podrá ausentarse a 3 sesiones de laboratorio sin necesidad de presentar justificación. Esto no incluye a las sesiones que dan inicio a una nueva actividad del laboratorio.\nLas notas de los laboratorios contemplarán los siguientes aspectos:\n\nSeguimiento de instrucciones de entrega.\nEntrega de parte del trabajo solicitado al finalizar los laboratorios (cada laboratorio indicará qué es lo que debe entregarse).\nContenido de las respuestas a las preguntas formuladas."
},
{
"objectID": "bme423/index.html#proyectos",
"href": "bme423/index.html#proyectos",
"title": "BME423 - Procesamiento de imágenes médicas",
"section": "Proyectos",
"text": "Proyectos\nLos proyectos deben desarrollarse durante el transcurso del semestre (no al final).\nAl final del semestre deberá hacer una presentación de 15 min, entregar un informe escrito y poner a disposición del curso un video explicativo del proyecto, el informe escrito y la implementación realizada.\nLos temas son a elección de los estudiantes.\n\nDefinición de los temas de proyecto.\nLa entrega de los temas de proyecto tiene como propósito verificar que el trabajo que será realizado posee la “dificultad apropiada”. Usted recibirá retroalimentación que le permitirá hacer los ajustes necesarios a su proyecto de tal manera de no resolver problemas muy simples o muy complejos.\nEn la fecha indicada debe entregar un documento de no más de dos páginas vía Aula Virtual con lo siguiente:\n\nTítulo del proyecto.\nDescripción. Esto incluye un breve contexto del tema a abordar de manera simple y concreta. Por ejemplo,\n\n“Se quiere detectar de manera automática la variable (…) en base a imágenes de (…). En la literatura se han alcanzado accuracies entre el 60-70% en el problema descrito”.\n\nProblema específico a abordar. Debe explicitar el objetivo del trabajo de manera simple y concreta. Por ejemplo,\n\n“Mi objetivo es superar las medidas de desempeño obtenidas en los artículos …”.\n“Varios artículos que resuelven el problema descrito emplean el modelo X. Mi objetivo es evaluar el modelo Y y comparar los resultados obtenidos al usar el enfoque tradicional”.\n“No existen implementaciones disponibles públicamente del método propuesto en el artículo X. Mi objetivo es implementar el método propuesto en ese artículo y reproducir los resultados obtenidos”.\n\nPunto de partida. Debe indicar si hay implementaciones disponibles de lo que usted propone desarrollar o si lo que propone hacer en este curso es la continuación de un proyecto desarrollado en otra asignatura. Debe establecer de manera clara la diferencia de lo que usted hará con lo hecho por otras personas o en su trabajo previo. Esta diferencia no necesariamente la tendrá clara en este momento, pero es algo que deberá indicar en la entrega parcial o final del proyecto.\nDataset(s). Breve descripción de los datos a utilizar, incluyendo enlaces a las bases de datos, etc.\nArtículo(s) relacionado(s). Mencione el o los artículos que de una u otra manera se relacionen con el proyecto que abordará.\n\nSi tiene más de una idea a desarrollar, debe hacer un documento por idea (no mezclar ideas de proyecto).\n\n\nProductos a entregar en los proyectos.\nLa entrega de los proyectos contempla lo siguiente:\n\nPresentación presencial. Tendrán una duración de 10-15 minutos.\nPresentación grabada. Todos los grupos deben grabar su presentación (duración máxima 15 minutos). Para la entrega de esto, no debe subir videos directamente al Aula Virtual, sino copiar un enlace en el informe escrito desde YouTube, Google Drive u otro mecanismo de su preferencia.\nImplementación. La implementación debe incluir todos los códigos fuente con un archivo explicativo sobre su uso. Puede subir los códigos directamente al Aula Virtual o puede copiar un enlace en el informe escrito desde GitHub, Google Drive u otro mecanismo de su preferencia.\n\nNo debe adjuntar los datos utilizados a menos que sea estrictamente necesario, para ejecutar un demo, por ejemplo.\nAsegúrese de configurar los permisos apropiados para acceder a los códigos en caso de usar Google Drive.\n\nInforme escrito. El informe escrito, posee un formato libre y debe incluir:\n\nTítulo del proyecto.\nNombre, apellido y carrera de los integrantes.\nEnlaces a la presentación grabada y al código con la implementación del proyecto (si corresponde).\nLa descripción del problema y datos utilizados.\nLa solución implementada, las métricas de desempeño y los experimentos realizados.\nEl análisis de los resultados y, si corresponde, la comparación con otros métodos.\n\nBibliografía relevante a su trabajo y las citas correspondientes.\n\n\n\nCriterios de evaluación.\nLos criterios de evaluación son los siguientes:\n\nClaridad del informe escrito y presentación (20 %).\n\nEl informe y la presentación son claros, bien redactados y estructurados.\nLas figuras son explicativas y nítidas.\nLos datos/problemas están bien explicados.\nSe presenta la bibliografía relevante y se cita apropiadamente.\n\nDescripción y calidad de la solución (40 %).\n\nLa solución está claramente explicada y se evidencia dominio de los elementos que componen la solución. Se incluyen ejemplos, diagramas o pseudocódigo si es necesario.\nLa justificación de la solución es clara y coherente con el problema descrito.\nLa descripción de la solución es completa.\nEl trabajo realizado refleja dedicación de un semestre.\n\nClaridad y pertinencia de la implementación (25 %).\n\nLa implementación es clara, bien organizada y adecuada al problema.\n\nExperimentación y análisis de los resultados (15 %).\n\nSe definen y reportan métricas de desempeño relevantes.\nEl análisis de resultados es claro, profundo y evidencia aporte propio."
},
{
"objectID": "bme423/index.html#integridad-académica",
"href": "bme423/index.html#integridad-académica",
"title": "BME423 - Procesamiento de imágenes médicas",
"section": "Integridad Académica",
"text": "Integridad Académica\nSe espera que los estudiantes actúen con honestidad e integridad. No mentir, hacer trampa ni plagiar en trabajos académicos o no académicos. Todo trabajo presentado debe ser propio, a menos que se permita expresamente la colaboración. Debe citar adecuadamente todas las fuentes utilizadas, incluyendo código tomado de recursos en línea. El material no citado o mal referenciado puede considerarse plagio."
},
{
"objectID": "bme423/index.html#uso-de-herramientas-de-inteligencia-artificial-ia",
"href": "bme423/index.html#uso-de-herramientas-de-inteligencia-artificial-ia",
"title": "BME423 - Procesamiento de imágenes médicas",
"section": "Uso de Herramientas de Inteligencia Artificial (IA)",
"text": "Uso de Herramientas de Inteligencia Artificial (IA)\nEl uso de herramientas y recursos de IA está permitido y se fomenta. Sin embargo, se debe explicitar cuándo y cómo se usan estas herramientas en las tareas y trabajos relacionados con el curso. Debe especificar qué contenidos y/o códigos son generados con IA. Se espera total transparencia para mantener la integridad académica: no revelar el uso de IA puede considerarse una violación de las políticas del curso."
},
{
"objectID": "bme423/index.html#colaboración",
"href": "bme423/index.html#colaboración",
"title": "BME423 - Procesamiento de imágenes médicas",
"section": "Colaboración",
"text": "Colaboración\nSalvo que expresamente se indique trabajo en grupo, todas las tareas deben realizarse de forma individual. Se permite la discusión general con compañeros, pero no compartir respuestas detalladas ni código. Para proyectos en equipo, debe colaborar únicamente dentro de su grupo."
},
{
"objectID": "bme423/index.html#uso-de-código-y-recursos-online",
"href": "bme423/index.html#uso-de-código-y-recursos-online",
"title": "BME423 - Procesamiento de imágenes médicas",
"section": "Uso de código y recursos online",
"text": "Uso de código y recursos online\nPuede consultar y utilizar recursos en línea. Todo código o material tomado de fuentes externas debe ser citado correctamente."
},
{
"objectID": "bme423/index.html#entregas-tardias",
"href": "bme423/index.html#entregas-tardias",
"title": "BME423 - Procesamiento de imágenes médicas",
"section": "Entregas tardías",
"text": "Entregas tardías\nDispone de un total de 4 días de retraso que puede utilizar a gusto a lo largo del semestre en cualquiera de las evaluaciones del curso. Los días de retraso le permiten entregar laboratorios, tareas sin penalización. Retrasos superiores a 12 horas, se consideran como un día completo de retraso. Considere hacer uso de este beneficio en situaciones significativas o imprevistas. Si tiene problemas a largo plazo que afecten tu desempeño, se recomienda informar al profesor o jefe de carrera."
},
{
"objectID": "bme423/index.html#recalificaciones",
"href": "bme423/index.html#recalificaciones",
"title": "BME423 - Procesamiento de imágenes médicas",
"section": "Recalificaciones",
"text": "Recalificaciones\nLas solicitudes de revisión deben hacerse dentro de la semana posterior a la devolución de la calificación. Solo se considerarán solicitudes fundamentadas en base a la rúbrica proporcionada. Toda la pregunta será revisada nuevamente, lo que puede implicar aumento o disminución de puntos."
},
{
"objectID": "bme423/ejemplos/cnn-04-fullycnn.html",
"href": "bme423/ejemplos/cnn-04-fullycnn.html",
"title": "Fully CNNs",
"section": "",
"text": "Objetivos:\n- Cargar un modelo de CNN preentrenado en ImageNet\n- Transformar la red en una Red Fully Convolucional\n- Aplicar la red para realizar una segmentación débil en imágenes\nArchivos requeridos:\nweights_dense.h5\ndog.jpg\nmeta_clsloc.mat\n\n%matplotlib inline\nimport warnings\n\nimport numpy as np\nimport matplotlib.pyplot as plt\n\nnp.random.seed(1)\n\n\n# Load a pre-trained ResNet50\n# We use include_top = False for now,\n# as we'll import output Dense Layer later\n\nimport tensorflow as tf\nfrom tensorflow.keras.applications.resnet50 import ResNet50\nbase_model = ResNet50(include_top=False)\n\nprint(base_model.output_shape)\n\n(None, None, None, 2048)\n\n\n\nprint(base_model.summary())\n\nModel: \"resnet50\"\n\n\n\n┏━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┓\n┃ Layer (type) ┃ Output Shape ┃ Param # ┃ Connected to ┃\n┡━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━┩\n│ input_layer │ (None, None, │ 0 │ - │\n│ (InputLayer) │ None, 3) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv1_pad │ (None, None, │ 0 │ input_layer[0][0] │\n│ (ZeroPadding2D) │ None, 3) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv1_conv (Conv2D) │ (None, None, │ 9,472 │ conv1_pad[0][0] │\n│ │ None, 64) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv1_bn │ (None, None, │ 256 │ conv1_conv[0][0] │\n│ (BatchNormalizatio… │ None, 64) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv1_relu │ (None, None, │ 0 │ conv1_bn[0][0] │\n│ (Activation) │ None, 64) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ pool1_pad │ (None, None, │ 0 │ conv1_relu[0][0] │\n│ (ZeroPadding2D) │ None, 64) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ pool1_pool │ (None, None, │ 0 │ pool1_pad[0][0] │\n│ (MaxPooling2D) │ None, 64) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2_block1_1_conv │ (None, None, │ 4,160 │ pool1_pool[0][0] │\n│ (Conv2D) │ None, 64) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2_block1_1_bn │ (None, None, │ 256 │ conv2_block1_1_c… │\n│ (BatchNormalizatio… │ None, 64) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2_block1_1_relu │ (None, None, │ 0 │ conv2_block1_1_b… │\n│ (Activation) │ None, 64) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2_block1_2_conv │ (None, None, │ 36,928 │ conv2_block1_1_r… │\n│ (Conv2D) │ None, 64) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2_block1_2_bn │ (None, None, │ 256 │ conv2_block1_2_c… │\n│ (BatchNormalizatio… │ None, 64) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2_block1_2_relu │ (None, None, │ 0 │ conv2_block1_2_b… │\n│ (Activation) │ None, 64) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2_block1_0_conv │ (None, None, │ 16,640 │ pool1_pool[0][0] │\n│ (Conv2D) │ None, 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2_block1_3_conv │ (None, None, │ 16,640 │ conv2_block1_2_r… │\n│ (Conv2D) │ None, 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2_block1_0_bn │ (None, None, │ 1,024 │ conv2_block1_0_c… │\n│ (BatchNormalizatio… │ None, 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2_block1_3_bn │ (None, None, │ 1,024 │ conv2_block1_3_c… │\n│ (BatchNormalizatio… │ None, 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2_block1_add │ (None, None, │ 0 │ conv2_block1_0_b… │\n│ (Add) │ None, 256) │ │ conv2_block1_3_b… │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2_block1_out │ (None, None, │ 0 │ conv2_block1_add… │\n│ (Activation) │ None, 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2_block2_1_conv │ (None, None, │ 16,448 │ conv2_block1_out… │\n│ (Conv2D) │ None, 64) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2_block2_1_bn │ (None, None, │ 256 │ conv2_block2_1_c… │\n│ (BatchNormalizatio… │ None, 64) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2_block2_1_relu │ (None, None, │ 0 │ conv2_block2_1_b… │\n│ (Activation) │ None, 64) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2_block2_2_conv │ (None, None, │ 36,928 │ conv2_block2_1_r… │\n│ (Conv2D) │ None, 64) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2_block2_2_bn │ (None, None, │ 256 │ conv2_block2_2_c… │\n│ (BatchNormalizatio… │ None, 64) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2_block2_2_relu │ (None, None, │ 0 │ conv2_block2_2_b… │\n│ (Activation) │ None, 64) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2_block2_3_conv │ (None, None, │ 16,640 │ conv2_block2_2_r… │\n│ (Conv2D) │ None, 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2_block2_3_bn │ (None, None, │ 1,024 │ conv2_block2_3_c… │\n│ (BatchNormalizatio… │ None, 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2_block2_add │ (None, None, │ 0 │ conv2_block1_out… │\n│ (Add) │ None, 256) │ │ conv2_block2_3_b… │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2_block2_out │ (None, None, │ 0 │ conv2_block2_add… │\n│ (Activation) │ None, 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2_block3_1_conv │ (None, None, │ 16,448 │ conv2_block2_out… │\n│ (Conv2D) │ None, 64) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2_block3_1_bn │ (None, None, │ 256 │ conv2_block3_1_c… │\n│ (BatchNormalizatio… │ None, 64) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2_block3_1_relu │ (None, None, │ 0 │ conv2_block3_1_b… │\n│ (Activation) │ None, 64) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2_block3_2_conv │ (None, None, │ 36,928 │ conv2_block3_1_r… │\n│ (Conv2D) │ None, 64) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2_block3_2_bn │ (None, None, │ 256 │ conv2_block3_2_c… │\n│ (BatchNormalizatio… │ None, 64) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2_block3_2_relu │ (None, None, │ 0 │ conv2_block3_2_b… │\n│ (Activation) │ None, 64) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2_block3_3_conv │ (None, None, │ 16,640 │ conv2_block3_2_r… │\n│ (Conv2D) │ None, 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2_block3_3_bn │ (None, None, │ 1,024 │ conv2_block3_3_c… │\n│ (BatchNormalizatio… │ None, 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2_block3_add │ (None, None, │ 0 │ conv2_block2_out… │\n│ (Add) │ None, 256) │ │ conv2_block3_3_b… │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2_block3_out │ (None, None, │ 0 │ conv2_block3_add… │\n│ (Activation) │ None, 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block1_1_conv │ (None, None, │ 32,896 │ conv2_block3_out… │\n│ (Conv2D) │ None, 128) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block1_1_bn │ (None, None, │ 512 │ conv3_block1_1_c… │\n│ (BatchNormalizatio… │ None, 128) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block1_1_relu │ (None, None, │ 0 │ conv3_block1_1_b… │\n│ (Activation) │ None, 128) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block1_2_conv │ (None, None, │ 147,584 │ conv3_block1_1_r… │\n│ (Conv2D) │ None, 128) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block1_2_bn │ (None, None, │ 512 │ conv3_block1_2_c… │\n│ (BatchNormalizatio… │ None, 128) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block1_2_relu │ (None, None, │ 0 │ conv3_block1_2_b… │\n│ (Activation) │ None, 128) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block1_0_conv │ (None, None, │ 131,584 │ conv2_block3_out… │\n│ (Conv2D) │ None, 512) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block1_3_conv │ (None, None, │ 66,048 │ conv3_block1_2_r… │\n│ (Conv2D) │ None, 512) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block1_0_bn │ (None, None, │ 2,048 │ conv3_block1_0_c… │\n│ (BatchNormalizatio… │ None, 512) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block1_3_bn │ (None, None, │ 2,048 │ conv3_block1_3_c… │\n│ (BatchNormalizatio… │ None, 512) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block1_add │ (None, None, │ 0 │ conv3_block1_0_b… │\n│ (Add) │ None, 512) │ │ conv3_block1_3_b… │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block1_out │ (None, None, │ 0 │ conv3_block1_add… │\n│ (Activation) │ None, 512) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block2_1_conv │ (None, None, │ 65,664 │ conv3_block1_out… │\n│ (Conv2D) │ None, 128) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block2_1_bn │ (None, None, │ 512 │ conv3_block2_1_c… │\n│ (BatchNormalizatio… │ None, 128) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block2_1_relu │ (None, None, │ 0 │ conv3_block2_1_b… │\n│ (Activation) │ None, 128) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block2_2_conv │ (None, None, │ 147,584 │ conv3_block2_1_r… │\n│ (Conv2D) │ None, 128) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block2_2_bn │ (None, None, │ 512 │ conv3_block2_2_c… │\n│ (BatchNormalizatio… │ None, 128) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block2_2_relu │ (None, None, │ 0 │ conv3_block2_2_b… │\n│ (Activation) │ None, 128) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block2_3_conv │ (None, None, │ 66,048 │ conv3_block2_2_r… │\n│ (Conv2D) │ None, 512) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block2_3_bn │ (None, None, │ 2,048 │ conv3_block2_3_c… │\n│ (BatchNormalizatio… │ None, 512) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block2_add │ (None, None, │ 0 │ conv3_block1_out… │\n│ (Add) │ None, 512) │ │ conv3_block2_3_b… │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block2_out │ (None, None, │ 0 │ conv3_block2_add… │\n│ (Activation) │ None, 512) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block3_1_conv │ (None, None, │ 65,664 │ conv3_block2_out… │\n│ (Conv2D) │ None, 128) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block3_1_bn │ (None, None, │ 512 │ conv3_block3_1_c… │\n│ (BatchNormalizatio… │ None, 128) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block3_1_relu │ (None, None, │ 0 │ conv3_block3_1_b… │\n│ (Activation) │ None, 128) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block3_2_conv │ (None, None, │ 147,584 │ conv3_block3_1_r… │\n│ (Conv2D) │ None, 128) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block3_2_bn │ (None, None, │ 512 │ conv3_block3_2_c… │\n│ (BatchNormalizatio… │ None, 128) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block3_2_relu │ (None, None, │ 0 │ conv3_block3_2_b… │\n│ (Activation) │ None, 128) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block3_3_conv │ (None, None, │ 66,048 │ conv3_block3_2_r… │\n│ (Conv2D) │ None, 512) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block3_3_bn │ (None, None, │ 2,048 │ conv3_block3_3_c… │\n│ (BatchNormalizatio… │ None, 512) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block3_add │ (None, None, │ 0 │ conv3_block2_out… │\n│ (Add) │ None, 512) │ │ conv3_block3_3_b… │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block3_out │ (None, None, │ 0 │ conv3_block3_add… │\n│ (Activation) │ None, 512) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block4_1_conv │ (None, None, │ 65,664 │ conv3_block3_out… │\n│ (Conv2D) │ None, 128) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block4_1_bn │ (None, None, │ 512 │ conv3_block4_1_c… │\n│ (BatchNormalizatio… │ None, 128) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block4_1_relu │ (None, None, │ 0 │ conv3_block4_1_b… │\n│ (Activation) │ None, 128) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block4_2_conv │ (None, None, │ 147,584 │ conv3_block4_1_r… │\n│ (Conv2D) │ None, 128) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block4_2_bn │ (None, None, │ 512 │ conv3_block4_2_c… │\n│ (BatchNormalizatio… │ None, 128) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block4_2_relu │ (None, None, │ 0 │ conv3_block4_2_b… │\n│ (Activation) │ None, 128) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block4_3_conv │ (None, None, │ 66,048 │ conv3_block4_2_r… │\n│ (Conv2D) │ None, 512) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block4_3_bn │ (None, None, │ 2,048 │ conv3_block4_3_c… │\n│ (BatchNormalizatio… │ None, 512) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block4_add │ (None, None, │ 0 │ conv3_block3_out… │\n│ (Add) │ None, 512) │ │ conv3_block4_3_b… │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv3_block4_out │ (None, None, │ 0 │ conv3_block4_add… │\n│ (Activation) │ None, 512) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block1_1_conv │ (None, None, │ 131,328 │ conv3_block4_out… │\n│ (Conv2D) │ None, 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block1_1_bn │ (None, None, │ 1,024 │ conv4_block1_1_c… │\n│ (BatchNormalizatio… │ None, 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block1_1_relu │ (None, None, │ 0 │ conv4_block1_1_b… │\n│ (Activation) │ None, 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block1_2_conv │ (None, None, │ 590,080 │ conv4_block1_1_r… │\n│ (Conv2D) │ None, 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block1_2_bn │ (None, None, │ 1,024 │ conv4_block1_2_c… │\n│ (BatchNormalizatio… │ None, 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block1_2_relu │ (None, None, │ 0 │ conv4_block1_2_b… │\n│ (Activation) │ None, 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block1_0_conv │ (None, None, │ 525,312 │ conv3_block4_out… │\n│ (Conv2D) │ None, 1024) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block1_3_conv │ (None, None, │ 263,168 │ conv4_block1_2_r… │\n│ (Conv2D) │ None, 1024) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block1_0_bn │ (None, None, │ 4,096 │ conv4_block1_0_c… │\n│ (BatchNormalizatio… │ None, 1024) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block1_3_bn │ (None, None, │ 4,096 │ conv4_block1_3_c… │\n│ (BatchNormalizatio… │ None, 1024) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block1_add │ (None, None, │ 0 │ conv4_block1_0_b… │\n│ (Add) │ None, 1024) │ │ conv4_block1_3_b… │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block1_out │ (None, None, │ 0 │ conv4_block1_add… │\n│ (Activation) │ None, 1024) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block2_1_conv │ (None, None, │ 262,400 │ conv4_block1_out… │\n│ (Conv2D) │ None, 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block2_1_bn │ (None, None, │ 1,024 │ conv4_block2_1_c… │\n│ (BatchNormalizatio… │ None, 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block2_1_relu │ (None, None, │ 0 │ conv4_block2_1_b… │\n│ (Activation) │ None, 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block2_2_conv │ (None, None, │ 590,080 │ conv4_block2_1_r… │\n│ (Conv2D) │ None, 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block2_2_bn │ (None, None, │ 1,024 │ conv4_block2_2_c… │\n│ (BatchNormalizatio… │ None, 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block2_2_relu │ (None, None, │ 0 │ conv4_block2_2_b… │\n│ (Activation) │ None, 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block2_3_conv │ (None, None, │ 263,168 │ conv4_block2_2_r… │\n│ (Conv2D) │ None, 1024) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block2_3_bn │ (None, None, │ 4,096 │ conv4_block2_3_c… │\n│ (BatchNormalizatio… │ None, 1024) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block2_add │ (None, None, │ 0 │ conv4_block1_out… │\n│ (Add) │ None, 1024) │ │ conv4_block2_3_b… │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block2_out │ (None, None, │ 0 │ conv4_block2_add… │\n│ (Activation) │ None, 1024) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block3_1_conv │ (None, None, │ 262,400 │ conv4_block2_out… │\n│ (Conv2D) │ None, 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block3_1_bn │ (None, None, │ 1,024 │ conv4_block3_1_c… │\n│ (BatchNormalizatio… │ None, 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block3_1_relu │ (None, None, │ 0 │ conv4_block3_1_b… │\n│ (Activation) │ None, 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block3_2_conv │ (None, None, │ 590,080 │ conv4_block3_1_r… │\n│ (Conv2D) │ None, 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block3_2_bn │ (None, None, │ 1,024 │ conv4_block3_2_c… │\n│ (BatchNormalizatio… │ None, 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block3_2_relu │ (None, None, │ 0 │ conv4_block3_2_b… │\n│ (Activation) │ None, 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block3_3_conv │ (None, None, │ 263,168 │ conv4_block3_2_r… │\n│ (Conv2D) │ None, 1024) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block3_3_bn │ (None, None, │ 4,096 │ conv4_block3_3_c… │\n│ (BatchNormalizatio… │ None, 1024) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block3_add │ (None, None, │ 0 │ conv4_block2_out… │\n│ (Add) │ None, 1024) │ │ conv4_block3_3_b… │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block3_out │ (None, None, │ 0 │ conv4_block3_add… │\n│ (Activation) │ None, 1024) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block4_1_conv │ (None, None, │ 262,400 │ conv4_block3_out… │\n│ (Conv2D) │ None, 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block4_1_bn │ (None, None, │ 1,024 │ conv4_block4_1_c… │\n│ (BatchNormalizatio… │ None, 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block4_1_relu │ (None, None, │ 0 │ conv4_block4_1_b… │\n│ (Activation) │ None, 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block4_2_conv │ (None, None, │ 590,080 │ conv4_block4_1_r… │\n│ (Conv2D) │ None, 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block4_2_bn │ (None, None, │ 1,024 │ conv4_block4_2_c… │\n│ (BatchNormalizatio… │ None, 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block4_2_relu │ (None, None, │ 0 │ conv4_block4_2_b… │\n│ (Activation) │ None, 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block4_3_conv │ (None, None, │ 263,168 │ conv4_block4_2_r… │\n│ (Conv2D) │ None, 1024) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block4_3_bn │ (None, None, │ 4,096 │ conv4_block4_3_c… │\n│ (BatchNormalizatio… │ None, 1024) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block4_add │ (None, None, │ 0 │ conv4_block3_out… │\n│ (Add) │ None, 1024) │ │ conv4_block4_3_b… │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block4_out │ (None, None, │ 0 │ conv4_block4_add… │\n│ (Activation) │ None, 1024) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block5_1_conv │ (None, None, │ 262,400 │ conv4_block4_out… │\n│ (Conv2D) │ None, 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block5_1_bn │ (None, None, │ 1,024 │ conv4_block5_1_c… │\n│ (BatchNormalizatio… │ None, 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block5_1_relu │ (None, None, │ 0 │ conv4_block5_1_b… │\n│ (Activation) │ None, 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block5_2_conv │ (None, None, │ 590,080 │ conv4_block5_1_r… │\n│ (Conv2D) │ None, 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block5_2_bn │ (None, None, │ 1,024 │ conv4_block5_2_c… │\n│ (BatchNormalizatio… │ None, 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block5_2_relu │ (None, None, │ 0 │ conv4_block5_2_b… │\n│ (Activation) │ None, 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block5_3_conv │ (None, None, │ 263,168 │ conv4_block5_2_r… │\n│ (Conv2D) │ None, 1024) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block5_3_bn │ (None, None, │ 4,096 │ conv4_block5_3_c… │\n│ (BatchNormalizatio… │ None, 1024) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block5_add │ (None, None, │ 0 │ conv4_block4_out… │\n│ (Add) │ None, 1024) │ │ conv4_block5_3_b… │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block5_out │ (None, None, │ 0 │ conv4_block5_add… │\n│ (Activation) │ None, 1024) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block6_1_conv │ (None, None, │ 262,400 │ conv4_block5_out… │\n│ (Conv2D) │ None, 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block6_1_bn │ (None, None, │ 1,024 │ conv4_block6_1_c… │\n│ (BatchNormalizatio… │ None, 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block6_1_relu │ (None, None, │ 0 │ conv4_block6_1_b… │\n│ (Activation) │ None, 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block6_2_conv │ (None, None, │ 590,080 │ conv4_block6_1_r… │\n│ (Conv2D) │ None, 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block6_2_bn │ (None, None, │ 1,024 │ conv4_block6_2_c… │\n│ (BatchNormalizatio… │ None, 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block6_2_relu │ (None, None, │ 0 │ conv4_block6_2_b… │\n│ (Activation) │ None, 256) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block6_3_conv │ (None, None, │ 263,168 │ conv4_block6_2_r… │\n│ (Conv2D) │ None, 1024) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block6_3_bn │ (None, None, │ 4,096 │ conv4_block6_3_c… │\n│ (BatchNormalizatio… │ None, 1024) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block6_add │ (None, None, │ 0 │ conv4_block5_out… │\n│ (Add) │ None, 1024) │ │ conv4_block6_3_b… │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv4_block6_out │ (None, None, │ 0 │ conv4_block6_add… │\n│ (Activation) │ None, 1024) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv5_block1_1_conv │ (None, None, │ 524,800 │ conv4_block6_out… │\n│ (Conv2D) │ None, 512) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv5_block1_1_bn │ (None, None, │ 2,048 │ conv5_block1_1_c… │\n│ (BatchNormalizatio… │ None, 512) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv5_block1_1_relu │ (None, None, │ 0 │ conv5_block1_1_b… │\n│ (Activation) │ None, 512) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv5_block1_2_conv │ (None, None, │ 2,359,808 │ conv5_block1_1_r… │\n│ (Conv2D) │ None, 512) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv5_block1_2_bn │ (None, None, │ 2,048 │ conv5_block1_2_c… │\n│ (BatchNormalizatio… │ None, 512) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv5_block1_2_relu │ (None, None, │ 0 │ conv5_block1_2_b… │\n│ (Activation) │ None, 512) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv5_block1_0_conv │ (None, None, │ 2,099,200 │ conv4_block6_out… │\n│ (Conv2D) │ None, 2048) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv5_block1_3_conv │ (None, None, │ 1,050,624 │ conv5_block1_2_r… │\n│ (Conv2D) │ None, 2048) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv5_block1_0_bn │ (None, None, │ 8,192 │ conv5_block1_0_c… │\n│ (BatchNormalizatio… │ None, 2048) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv5_block1_3_bn │ (None, None, │ 8,192 │ conv5_block1_3_c… │\n│ (BatchNormalizatio… │ None, 2048) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv5_block1_add │ (None, None, │ 0 │ conv5_block1_0_b… │\n│ (Add) │ None, 2048) │ │ conv5_block1_3_b… │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv5_block1_out │ (None, None, │ 0 │ conv5_block1_add… │\n│ (Activation) │ None, 2048) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv5_block2_1_conv │ (None, None, │ 1,049,088 │ conv5_block1_out… │\n│ (Conv2D) │ None, 512) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv5_block2_1_bn │ (None, None, │ 2,048 │ conv5_block2_1_c… │\n│ (BatchNormalizatio… │ None, 512) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv5_block2_1_relu │ (None, None, │ 0 │ conv5_block2_1_b… │\n│ (Activation) │ None, 512) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv5_block2_2_conv │ (None, None, │ 2,359,808 │ conv5_block2_1_r… │\n│ (Conv2D) │ None, 512) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv5_block2_2_bn │ (None, None, │ 2,048 │ conv5_block2_2_c… │\n│ (BatchNormalizatio… │ None, 512) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv5_block2_2_relu │ (None, None, │ 0 │ conv5_block2_2_b… │\n│ (Activation) │ None, 512) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv5_block2_3_conv │ (None, None, │ 1,050,624 │ conv5_block2_2_r… │\n│ (Conv2D) │ None, 2048) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv5_block2_3_bn │ (None, None, │ 8,192 │ conv5_block2_3_c… │\n│ (BatchNormalizatio… │ None, 2048) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv5_block2_add │ (None, None, │ 0 │ conv5_block1_out… │\n│ (Add) │ None, 2048) │ │ conv5_block2_3_b… │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv5_block2_out │ (None, None, │ 0 │ conv5_block2_add… │\n│ (Activation) │ None, 2048) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv5_block3_1_conv │ (None, None, │ 1,049,088 │ conv5_block2_out… │\n│ (Conv2D) │ None, 512) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv5_block3_1_bn │ (None, None, │ 2,048 │ conv5_block3_1_c… │\n│ (BatchNormalizatio… │ None, 512) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv5_block3_1_relu │ (None, None, │ 0 │ conv5_block3_1_b… │\n│ (Activation) │ None, 512) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv5_block3_2_conv │ (None, None, │ 2,359,808 │ conv5_block3_1_r… │\n│ (Conv2D) │ None, 512) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv5_block3_2_bn │ (None, None, │ 2,048 │ conv5_block3_2_c… │\n│ (BatchNormalizatio… │ None, 512) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv5_block3_2_relu │ (None, None, │ 0 │ conv5_block3_2_b… │\n│ (Activation) │ None, 512) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv5_block3_3_conv │ (None, None, │ 1,050,624 │ conv5_block3_2_r… │\n│ (Conv2D) │ None, 2048) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv5_block3_3_bn │ (None, None, │ 8,192 │ conv5_block3_3_c… │\n│ (BatchNormalizatio… │ None, 2048) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv5_block3_add │ (None, None, │ 0 │ conv5_block2_out… │\n│ (Add) │ None, 2048) │ │ conv5_block3_3_b… │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv5_block3_out │ (None, None, │ 0 │ conv5_block3_add… │\n│ (Activation) │ None, 2048) │ │ │\n└─────────────────────┴───────────────────┴────────────┴───────────────────┘\n\n\n\n Total params: 23,587,712 (89.98 MB)\n\n\n\n Trainable params: 23,534,592 (89.78 MB)\n\n\n\n Non-trainable params: 53,120 (207.50 KB)\n\n\n\nNone\n\n\n\nres5c = base_model.layers[-1]\ntype(res5c)\n\nkeras.src.layers.activations.activation.Activation\n\n\n\nres5c\n\n<Activation name=conv5_block3_out, built=True>\n\n\n\nResNet totalmente convolucional\n\nA la salida del bloque residual res5c, la ResNet genera un tensor de forma \\(W \\times H \\times 2048\\).\n\nPara la entrada predeterminada de ImageNet, \\(224 \\times 224\\), el tamaño de salida es \\(7 \\times 7 \\times 2048\\).\n\n\nResNet layers\nLa cabeza de ResNet después del modelo base es la siguiente:\nx = base_model.output\nx = GlobalAveragePooling2D()(x)\nx = Dense(1000)(x)\nx = Softmax()(x)\nhttps://github.com/keras-team/keras-applications/blob/master/keras_applications/resnet50.py\n\n\nEn esta versión\n\nQueremos recuperar la información de las etiquetas, que está almacenada en la capa Dense. Cargaremos estos pesos después.\n\nCambiaremos la capa Dense a una capa Convolution2D para conservar la información espacial, con una salida de \\(W \\times H \\times 1000\\).\n\nPodemos usar un tamaño de kernel de (1, 1) para esa nueva capa Convolution2D con el fin de mantener la organización espacial de la capa anterior sin cambios (esto se llama pointwise convolution).\n\nQueremos aplicar un softmax solo en la última dimensión para preservar la información espacial \\(W \\times H\\).\n\n\n\nSoftmax\nPara aplicar softmax sólo a la última dimensión de un tensor:\n\nfrom tensorflow.keras import layers\n\n# A custom layer in Keras must implement the four following methods:\nclass SoftmaxMap(layers.Layer):\n # Init function\n def __init__(self, axis=-1, **kwargs):\n self.axis = axis\n super(SoftmaxMap, self).__init__(**kwargs)\n\n # There's no parameter, so we don't need this one\n def build(self, input_shape):\n pass\n\n # This is the layer we're interested in: \n # very similar to the regular softmax but note the additional\n # that we accept x.shape == (batch_size, w, h, n_classes)\n # which is not the case in Keras by default.\n # Note also that we substract the logits by their maximum to\n # make the softmax numerically stable.\n def call(self, x, mask=None):\n e = tf.exp(x - tf.math.reduce_max(x, axis=self.axis, keepdims=True))\n s = tf.math.reduce_sum(e, axis=self.axis, keepdims=True)\n return e / s\n\n # The output shape is the same as the input shape\n def get_output_shape_for(self, input_shape):\n return input_shape\n\nVerifiquemos si podemos usar esta capa para normalizar las probabilidades de las clases de algunas predicciones espaciales aleatorias:\n\nn_samples, w, h, n_classes = 10, 3, 4, 5\nrandom_data = np.random.randn(n_samples, w, h, n_classes).astype(\"float32\")\nrandom_data.shape\n\n(10, 3, 4, 5)\n\n\n\nrandom_data[0].sum(axis=-1)\n\narray([[ 0.27685624, -1.248265 , -0.17073488, -1.5251491 ],\n [ 2.3490455 , -1.4799201 , -3.292039 , 1.5062871 ],\n [-0.08336051, 2.3915372 , -1.7528347 , 3.5274372 ]],\n dtype=float32)\n\n\nFunción SoftmaxMap:\n\nsoftmaxMap = SoftmaxMap()\nsoftmax_mapped_data = softmaxMap(random_data).numpy()\nsoftmax_mapped_data.shape\n\n(10, 3, 4, 5)\n\n\nTodos los valores están en [0, 1]:\n\nsoftmax_mapped_data[0]\n\narray([[[0.56862915, 0.06077185, 0.06606976, 0.0383178 , 0.2662114 ],\n [0.01185074, 0.6777243 , 0.05529718, 0.16287254, 0.09225518],\n [0.48184162, 0.01423021, 0.08089001, 0.07605473, 0.3469834 ],\n [0.07524366, 0.19022258, 0.09395019, 0.23576528, 0.4048183 ]],\n\n [[0.03309341, 0.31252265, 0.24507003, 0.16442387, 0.24489003],\n [0.11887496, 0.20828551, 0.09239109, 0.180172 , 0.40027645],\n [0.19135876, 0.25699514, 0.19221951, 0.1641212 , 0.19530542],\n [0.09936516, 0.03292248, 0.1272154 , 0.52914804, 0.21134888]],\n\n [[0.10071651, 0.05022516, 0.05779989, 0.6628838 , 0.12837464],\n [0.04103367, 0.09390692, 0.6337432 , 0.08749201, 0.1438242 ],\n [0.34717003, 0.18080053, 0.08203337, 0.1813269 , 0.20866917],\n [0.17282423, 0.22243509, 0.24389896, 0.12789878, 0.23294285]]],\n dtype=float32)\n\n\nLa última dimensión suma app uno. Podemos usarla como probabilidad de una clase:\n\nsoftmax_mapped_data[0].sum(axis=-1)\n\narray([[0.99999994, 0.99999994, 1. , 1. ],\n [1. , 1. , 1. , 1. ],\n [1. , 1. , 1. , 0.9999999 ]], dtype=float32)\n\n\nNote que el canal más activado para cada ubicación espacial sigue siendo el mismo antes y después del mapa softmax. El orden de las activaciones se conserva ya que softmax es una función monótona (cuando se considera elemento por elemento):\n\nrandom_data[0].argmax(axis=-1)\n\narray([[0, 1, 0, 4],\n [1, 4, 1, 3],\n [3, 2, 0, 2]])\n\n\n\nsoftmax_mapped_data[0].argmax(axis=-1)\n\narray([[0, 1, 0, 4],\n [1, 4, 1, 3],\n [3, 2, 0, 2]])\n\n\n\n\nEjercicio\n\nCuál es la forma del kernel de convolución que queremos aplicar para reemplazar la capa Dense?\n\nConstruir el modelo totalmente convolucional como se describió arriba. Queremos que la salida preserve las dimensiones espaciales pero que produzca 1000 canales (un canal por clase).\n\nPuedes inspeccionar los últimos elementos de base_model.layers para encontrar qué capa eliminar.\n\nPuedes usar la capa Keras Convolution2D(output_channels, filter_w, filter_h) y nuestro SotfmaxMap para normalizar el resultado como probabilidades por clase.\n\nPor ahora, ignora los pesos de la(s) nueva(s) capa(s) (déjalos inicializados de forma aleatoria): solo concéntrate en construir la arquitectura correcta con la forma de salida adecuada.\n\n\nfrom tensorflow.keras.layers import Convolution2D\nfrom tensorflow.keras.models import Model\n\ninput = base_model.input\n\n# Take the output of the last layer of the convnet\n# layer:\nx = base_model.layers[-1].output\n\n# A 1x1 convolution, with 1000 output channels, one per class\nx = Convolution2D(1000, (1, 1), name='conv1000')(x)\n\n# Softmax on last axis of tensor to normalize the class\n# predictions in each spatial area\noutput = SoftmaxMap(axis=-1)(x)\n\nfully_conv_ResNet = Model(inputs=input, outputs=output)\n\n# A 1x1 convolution applies a Dense to each spatial grid location\n\nDatos aleatorios para verificar que es posible ejecutar un forward pass en una imagen RGB aleatoria:\n\nprediction_maps = fully_conv_ResNet(np.random.randn(1, 200, 300, 3)).numpy()\nprediction_maps.shape\n\n(1, 7, 10, 1000)\n\n\nLas probabilidades de clases deben sumar uno en cada áreas de la imagen de salida:\n\nprediction_maps.sum(axis=-1)\n\narray([[[1. , 1. , 0.99999994, 1. , 1. ,\n 1.0000001 , 1. , 0.9999999 , 1.0000001 , 1. ],\n [1. , 1. , 1. , 0.99999994, 1. ,\n 1. , 1. , 1.0000001 , 0.99999994, 1. ],\n [0.99999994, 1. , 0.99999994, 1.0000001 , 1. ,\n 1. , 1. , 1. , 0.9999999 , 1.0000001 ],\n [0.9999999 , 0.9999999 , 0.99999994, 1. , 1. ,\n 1. , 1. , 1. , 0.99999994, 1. ],\n [1.0000002 , 0.99999994, 1. , 1. , 0.9999999 ,\n 1. , 1. , 1. , 1. , 1. ],\n [0.99999994, 1. , 1.0000001 , 1.0000001 , 1. ,\n 1. , 1. , 0.99999994, 1. , 1. ],\n [1. , 1. , 1. , 0.99999994, 0.99999994,\n 1.0000001 , 0.99999994, 1. , 1.0000001 , 0.9999999 ]]],\n dtype=float32)\n\n\n\n\n\nPesos de la capa Densa\n\nLos pesos de la capa Densa de ResNet50 están en weights_dense.h5\nNuestra última capa es conv de 1x1 en vez de una fully connected\n\n\nimport h5py\n\nwith h5py.File('weights_dense.h5', 'r') as h5f:\n w = h5f['w'][:]\n b = h5f['b'][:]\n\n\nlast_layer = fully_conv_ResNet.layers[-2]\n\nprint(\"Loaded weight shape:\", w.shape)\nprint(\"Last conv layer weights shape:\", last_layer.get_weights()[0].shape)\n\nLoaded weight shape: (2048, 1000)\nLast conv layer weights shape: (1, 1, 2048, 1000)\n\n\n\n# reshape the weights\nw_reshaped = w.reshape((1, 1, 2048, 1000))\n\n# set the conv layer weights\nlast_layer.set_weights([w_reshaped, b])\n\n\n\nForward pass\nSe reformatea la entrada a un tamaño dado y luego se usa el método model.predict para calcular la salida\n\nfrom tensorflow.keras.applications.imagenet_utils import preprocess_input\nfrom skimage.io import imread\nfrom skimage.transform import resize\n\ndef forward_pass_resize(img_path, img_size):\n img_raw = imread(img_path)\n print(\"Image shape before resizing: %s\" % (img_raw.shape,))\n img = resize(img_raw, img_size, mode='reflect', preserve_range=True)\n img = preprocess_input(img[np.newaxis])\n print(\"Image batch size shape before forward pass:\", img.shape)\n prediction_map = fully_conv_ResNet(img).numpy()\n return prediction_map\n\n\noutput = forward_pass_resize(\"dog.jpg\", (800, 600))\nprint(\"prediction map shape\", output.shape)\n\nImage shape before resizing: (1600, 2560, 3)\nImage batch size shape before forward pass: (1, 800, 600, 3)\nprediction map shape (1, 25, 19, 1000)\n\n\n\n\nClases relacionadas a perros\nImageNet utiliza una ontología de conceptos, de la cual se derivan las clases. Un synset corresponde a un nodo en la ontología.\nPor ejemplo, todas las especies de perros son hijos del synset n02084071 (Perro, perro doméstico, Canis familiaris):\n\n# #### Helper tool from convnets-keras github\nimport numpy as np\nfrom scipy.io import loadmat\n\nsynsets = loadmat(\"meta_clsloc.mat\")[\"synsets\"][0]\nSYNSET_LIMIT = 1000\n\n# Create mappings between ids and sorted indices\nsorted_synsets = sorted([(int(s[0].item()), s[1][0]) for s in synsets[:SYNSET_LIMIT]], key=lambda x: x[1])\nid2idx = {id_: i for i, (id_, _) in enumerate(sorted_synsets)}\nidx2id = {i: id_ for id_, i in id2idx.items()}\n\ndef dfs(id_, out=None):\n if out is None: out = []\n id_ = id_ if isinstance(id_, int) else next(int(s[0].item()) for s in synsets if s[1][0] == id_)\n out.append(id_)\n for c in synsets[id_-1][5][0]: dfs(int(c), out)\n return out\n\ndef synset_to_dfs_ids(synset):\n return [id2idx[x] for x in dfs(synset) if x in id2idx]\n\ndef id_to_synset(idx): return synsets[idx2id[idx]-1][1][0]\ndef id_to_words(idx): return synsets[idx2id[idx]-1][2][0]\n\ndef pprint_output(out, n=10):\n for u in out.argsort()[::-1][:n]:\n print(f\"{round(100*out[u],2):.2f} : {id_to_words(u)}\")\n\n\nsynset = \"n02084071\" # synset de dogs\nids = synset_to_dfs_ids(synset)\nprint(\"All dog classes ids (%d):\" % len(ids))\nprint(ids)\n\nAll dog classes ids (118):\n[251, 268, 256, 253, 255, 254, 257, 159, 211, 210, 212, 214, 213, 216, 215, 219, 220, 221, 217, 218, 207, 209, 206, 205, 208, 193, 202, 194, 191, 204, 187, 203, 185, 192, 183, 199, 195, 181, 184, 201, 186, 200, 182, 188, 189, 190, 197, 196, 198, 179, 180, 177, 178, 175, 163, 174, 176, 160, 162, 161, 164, 168, 173, 170, 169, 165, 166, 167, 172, 171, 264, 263, 266, 265, 267, 262, 246, 242, 243, 248, 247, 229, 233, 234, 228, 231, 232, 230, 227, 226, 235, 225, 224, 223, 222, 236, 252, 237, 250, 249, 241, 239, 238, 240, 244, 245, 259, 261, 260, 258, 154, 153, 158, 152, 155, 151, 157, 156]\n\n\n\nfor dog_id in ids[:10]:\n print(id_to_words(dog_id))\nprint('...')\n\ndalmatian, coach dog, carriage dog\nMexican hairless\nNewfoundland, Newfoundland dog\nbasenji\nLeonberg\npug, pug-dog\nGreat Pyrenees\nRhodesian ridgeback\nvizsla, Hungarian pointer\nGerman short-haired pointer\n...\n\n\n\n\nMapa de calor de la clase “dog”\nLa siguiente función construye un mapa de calor a partir de un forward pass. Suma la representación de todos los ids correspondientes a un synset.\n\ndef build_heatmap(prediction_map, synset):\n class_ids = synset_to_dfs_ids(synset)\n class_ids = np.array([id_ for id_ in class_ids if id_ is not None])\n each_dog_proba_map = prediction_map[0, :, :, class_ids]\n # this style of indexing a tensor by an other array has the following shape effect:\n # (H, W, 1000) indexed by (118) ==> (118, H, W)\n any_dog_proba_map = each_dog_proba_map.sum(axis=0)\n print(\"size of heatmap: \" + str(any_dog_proba_map.shape))\n return any_dog_proba_map\n\n\ndef display_img_and_heatmap(img_path, heatmap):\n dog = imread(img_path)\n plt.figure(figsize=(12, 8))\n plt.subplot(1, 2, 1)\n plt.imshow(dog)\n plt.axis('off')\n plt.subplot(1, 2, 2)\n plt.imshow(heatmap, interpolation='nearest', cmap=\"viridis\")\n plt.axis('off')\n\n\n¿Cuál es el tamaño del mapa de calor comparado con la imagen de entrada?\nConstruir 3 o 4 mapas de calor de perro a partir de \"dog.jpg\", con los siguientes tamaños:\n\n(200, 320)\n(400, 640)\n(800, 1280)\n(1600, 2560) (opcional)\n\n\nPuede graficar un mapa de calor usando la función display_img_and_heatmap mostrada arriba. También puedes reutilizar forward_pass_resize para calcular los propios mapas de clase.\n\n# dog synset\ns = \"n02084071\"\n\nprobas_1 = forward_pass_resize(\"dog.jpg\", (200, 320))\nheatmap_1 = build_heatmap(probas_1, synset=s)\ndisplay_img_and_heatmap(\"dog.jpg\", heatmap_1)\n\nprobas_2 = forward_pass_resize(\"dog.jpg\", (400, 640))\nheatmap_2 = build_heatmap(probas_2, synset=s)\ndisplay_img_and_heatmap(\"dog.jpg\", heatmap_2)\n\nprobas_3 = forward_pass_resize(\"dog.jpg\", (800, 1280))\nheatmap_3 = build_heatmap(probas_3, synset=s)\ndisplay_img_and_heatmap(\"dog.jpg\", heatmap_3)\n\nImage shape before resizing: (1600, 2560, 3)\nImage batch size shape before forward pass: (1, 200, 320, 3)\nsize of heatmap: (7, 10)\nImage shape before resizing: (1600, 2560, 3)\nImage batch size shape before forward pass: (1, 400, 640, 3)\nsize of heatmap: (13, 20)\nImage shape before resizing: (1600, 2560, 3)\nImage batch size shape before forward pass: (1, 800, 1280, 3)\nsize of heatmap: (25, 40)\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nCombinando los 3 mapas de calor\nAl combinar los mapas de calor a diferentes escalas, obtenemos una información mucho mejor sobre la ubicación del perro.\n\nCombina los tres mapas de calor redimensionándolos a una forma similar y promediándolos.\n\nUna norma geométrica funcionará mejor que el promedio estándar\n\n\nfrom skimage.transform import resize\n\nheatmap_1_r = resize(heatmap_1, (50,80), mode='reflect',\n preserve_range=True, anti_aliasing=True)\nheatmap_2_r = resize(heatmap_2, (50,80), mode='reflect',\n preserve_range=True, anti_aliasing=True)\nheatmap_3_r = resize(heatmap_3, (50,80), mode='reflect',\n preserve_range=True, anti_aliasing=True)\n\n\nheatmap_geom_avg = np.power(heatmap_1_r * heatmap_2_r * heatmap_3_r, 0.333)\ndisplay_img_and_heatmap(\"dog.jpg\", heatmap_geom_avg)"
},
{
"objectID": "bme423/ejemplos/cnn-05-cnn-class-loc.html",
"href": "bme423/ejemplos/cnn-05-cnn-class-loc.html",
"title": "Clasificación y localización",
"section": "",
"text": "VOCdevkit.zip\ndog.jpg\n\nfrom __future__ import division\nimport numpy as np\nimport xml.etree.ElementTree as etree\nimport os\nimport os.path as op\n\n# Parse the xml annotation file and retrieve the path to each image,\n# its size and annotations\ndef extract_xml_annotation(filename):\n z = etree.parse(filename)\n objects = z.findall(\"./object\")\n size = (int(z.find(\".//width\").text), int(z.find(\".//height\").text))\n fname = z.find(\"./filename\").text\n dicts = [{obj.find(\"name\").text:[int(obj.find(\"bndbox/xmin\").text), \n int(obj.find(\"bndbox/ymin\").text), \n int(obj.find(\"bndbox/xmax\").text), \n int(obj.find(\"bndbox/ymax\").text)]} \n for obj in objects]\n return {\"size\": size, \"filename\": fname, \"objects\": dicts}\n\n\n# Filters annotations keeping only those we are interested in\n# We only keep images in which there is a single item\nannotations = []\n\nfilters = [\"dog\", \"cat\", \"bus\", \"car\", \"aeroplane\"]\nidx2labels = {k: v for k, v in enumerate(filters)}\nlabels2idx = {v: k for k, v in idx2labels.items()}\n\nannotation_folder = op.join(\"VOCdevkit\", \"VOC2007\", \"Annotations\")\nfor filename in sorted(os.listdir(annotation_folder)):\n annotation = extract_xml_annotation(op.join(annotation_folder, filename))\n\n new_objects = []\n for obj in annotation[\"objects\"]:\n # keep only labels we're interested in\n if list(obj.keys())[0] in filters:\n new_objects.append(obj)\n\n # Keep only if there's a single object in the image\n if len(new_objects) == 1:\n annotation[\"class\"] = list(new_objects[0].keys())[0]\n annotation[\"bbox\"] = list(new_objects[0].values())[0]\n annotation.pop(\"objects\")\n annotations.append(annotation)\n\n\nprint(\"Number of images with annotations:\", len(annotations))\nprint(\"Contents of annotation[0]:\\n\", annotations[0])\nprint(\"Correspondence between indices and labels:\\n\", idx2labels)\n\nNumber of images with annotations: 1264\nContents of annotation[0]:\n {'size': (500, 333), 'filename': '000007.jpg', 'class': 'car', 'bbox': [141, 50, 500, 330]}\nCorrespondence between indices and labels:\n {0: 'dog', 1: 'cat', 2: 'bus', 3: 'car', 4: 'aeroplane'}"
},
{
"objectID": "bme423/ejemplos/cnn-05-cnn-class-loc.html#embeddings",
"href": "bme423/ejemplos/cnn-05-cnn-class-loc.html#embeddings",
"title": "Clasificación y localización",
"section": "Embeddings",
"text": "Embeddings\n\n# %load solutions/load_pretrained.py\nfrom keras.applications.resnet50 import ResNet50\nfrom keras.models import Model\n\nmodel = ResNet50(include_top=False)\ninput = model.input\n\n# Remove the average pooling layer\noutput = model.layers[-2].output\nheadless_conv = Model(inputs=input, outputs=output)\n\n\nfrom PIL import Image\nfrom imageio.v2 import imread\n\nfrom keras.applications.imagenet_utils import preprocess_input\n\ndef predict_batch(model, img_batch_path, img_size=None):\n img_list = []\n\n for im_path in img_batch_path:\n img = imread(im_path)\n if img_size:\n img_pil = Image.fromarray(img)\n img_resized = img_pil.resize(img_size)\n img = np.array(img_resized).astype(\"float32\")\n\n img = img.astype('float32')\n img_list.append(img)\n try:\n img_batch = np.stack(img_list, axis=0)\n except:\n raise ValueError(\n 'when both img_size and crop_size are None, all images '\n 'in image_paths must have the same shapes.')\n\n return model.predict(preprocess_input(img_batch))\n\n\noutput = predict_batch(headless_conv, [\"dog.jpg\"], (1000, 224))\nprint(\"output shape\", output.shape)\n\n\n1/1 ━━━━━━━━━━━━━━━━━━━━ 1s 934ms/step\n\noutput shape (1, 7, 32, 2048)\n\n\n\n\nThe output size is (batch_size, 1000/32 = 32, 224/32 = 7, 2048)\n\nCalcular las representaciones en todas las imágenes\n\nimport h5py\n\n# Load pre-calculated representations\nh5f = h5py.File(op.join(\"VOCdevkit\", \"voc_representations.h5\"),'r')\nreprs = h5f['reprs'][:]\nh5f.close()"
},
{
"objectID": "bme423/ejemplos/cnn-05-cnn-class-loc.html#ground-truth",
"href": "bme423/ejemplos/cnn-05-cnn-class-loc.html#ground-truth",
"title": "Clasificación y localización",
"section": "Ground truth",
"text": "Ground truth\n\nimg_resize = 224\nnum_classes = len(labels2idx.keys())\n\n\ndef tensorize_ground_truth(annotations):\n all_boxes = []\n all_cls = []\n for idx, annotation in enumerate(annotations):\n # Build a one-hot encoding of the class\n cls = np.zeros((num_classes))\n cls_idx = labels2idx[annotation[\"class\"]]\n cls[cls_idx] = 1.0\n \n coords = annotation[\"bbox\"]\n size = annotation[\"size\"]\n # resize the image\n x1, y1, x2, y2 = (coords[0] * img_resize / size[0],\n coords[1] * img_resize / size[1], \n coords[2] * img_resize / size[0],\n coords[3] * img_resize / size[1])\n \n # compute center of the box and its height and width\n cx, cy = ((x2 + x1) / 2, (y2 + y1) / 2)\n w = x2 - x1\n h = y2 - y1\n boxes = np.array([cx, cy, w, h])\n all_boxes.append(boxes)\n all_cls.append(cls)\n\n # stack everything into two big np tensors\n return np.vstack(all_cls), np.vstack(all_boxes)\n\n\nclasses, boxes = tensorize_ground_truth(annotations)\n\n\nprint(\"Classes and boxes shapes:\", classes.shape, boxes.shape)\n\nClasses and boxes shapes: (1264, 5) (1264, 4)\n\n\n\nprint(\"First 2 classes labels:\\n\")\nprint(classes[0:2])\n\nFirst 2 classes labels:\n\n[[0. 0. 0. 1. 0.]\n [0. 0. 0. 1. 0.]]\n\n\n\nprint(\"First 2 boxes coordinates:\\n\")\nprint(boxes[0:2])\n\nFirst 2 boxes coordinates:\n\n[[143.584 127.80780781 160.832 188.34834835]\n [113.568 123.43543544 87.36 116.37237237]]\n\n\n\ndef interpret_output(cls, boxes, img_size=(500, 333)):\n cls_idx = np.argmax(cls)\n confidence = cls[cls_idx]\n classname = idx2labels[cls_idx]\n cx, cy = boxes[0], boxes[1]\n w, h = boxes[2], boxes[3]\n \n small_box = [max(0, cx - w / 2), max(0, cy - h / 2), \n min(img_resize, cx + w / 2), min(img_resize, cy + h / 2)]\n \n fullsize_box = [int(small_box[0] * img_size[0] / img_resize), \n int(small_box[1] * img_size[1] / img_resize),\n int(small_box[2] * img_size[0] / img_resize), \n int(small_box[3] * img_size[1] / img_resize)]\n output = {\"class\": classname, \"confidence\":confidence, \"bbox\": fullsize_box}\n return output\n\n\nimg_idx = 1\n\nprint(\"Original annotation:\\n\")\nprint(annotations[img_idx])\n\nOriginal annotation:\n\n{'size': (500, 333), 'filename': '000012.jpg', 'class': 'car', 'bbox': [156, 97, 351, 270]}\n\n\n\nprint(\"Interpreted output:\\n\")\nprint(interpret_output(classes[img_idx], boxes[img_idx],\n img_size=annotations[img_idx][\"size\"]))\n\nInterpreted output:\n\n{'class': 'car', 'confidence': 1.0, 'bbox': [156, 97, 351, 270]}\n\n\n\nIntersection over Union\n\ndef iou(boxA, boxB):\n # find the intersecting box coordinates\n x0 = max(boxA[0], boxB[0])\n y0 = max(boxA[1], boxB[1])\n x1 = min(boxA[2], boxB[2])\n y1 = min(boxA[3], boxB[3])\n \n # compute the area of intersection rectangle\n inter_area = max(x1 - x0, 0) * max(y1 - y0, 0) + 1\n\n # compute the area of each box\n boxA_area = (boxA[2] - boxA[0] + 1) * (boxA[3] - boxA[1] + 1)\n boxB_area = (boxB[2] - boxB[0] + 1) * (boxB[3] - boxB[1] + 1)\n \n # compute the intersection over union by taking the intersection\n # area and dividing it by the sum of areas - the interesection area \n return inter_area / float(boxA_area + boxB_area - inter_area)\n\n\niou([47, 35, 147, 101], [1, 124, 496, 235])\n\n1.604672807214609e-05\n\n\n\nimg_idx = 1\noriginal = annotations[img_idx]\ninterpreted = interpret_output(classes[img_idx], boxes[img_idx],\n img_size=annotations[img_idx][\"size\"])\n\nprint(\"iou:\", iou(original[\"bbox\"], interpreted[\"bbox\"]))\n\niou: 0.9786493385936412\n\n\n\n\nModelo de clasificación y localización\n\nfrom keras.losses import mean_squared_error, categorical_crossentropy\nfrom keras.layers import Input, Convolution2D, Dropout, GlobalAveragePooling2D\nfrom keras.layers import Flatten, Dense, GlobalMaxPooling2D\nfrom keras.models import Model\n\n\ndef classif_and_loc_avg_model(num_classes):\n \"\"\"model that averages all the spatial information\n \n The goal of this model it to show that it's a very bad idea to\n destroy the spatial information with GlobalAveragePooling2D layer\n if our goal is to do object localization.\n \"\"\"\n model_input = Input(shape=(7, 7, 2048))\n x = GlobalAveragePooling2D()(model_input)\n x = Dropout(0.2)(x)\n head_classes = Dense(num_classes, activation=\"softmax\", name=\"head_classes\")(x)\n head_boxes = Dense(4, name=\"head_boxes\")(x)\n \n model = Model(inputs=model_input, outputs=[head_classes, head_boxes],\n name=\"resnet_loc\")\n model.compile(optimizer=\"adam\", loss=[categorical_crossentropy, \"mse\"],\n loss_weights=[1., 0.01]) \n return model\n\n\nmodel = classif_and_loc_avg_model(num_classes)\n\n\nnum = 64\ninputs = reprs[0:num]\nout_cls, out_boxes = classes[0:num], boxes[0:num]\n\nprint(\"input batch shape:\", inputs.shape)\nprint(\"ground truth batch shapes:\", out_cls.shape, out_boxes.shape)\n\ninput batch shape: (64, 7, 7, 2048)\nground truth batch shapes: (64, 5) (64, 4)\n\n\n\nout_cls.mean(axis=0)\n\narray([0.265625, 0.1875 , 0.03125 , 0.453125, 0.0625 ])\n\n\n\nout = model.predict(inputs)\nprint(\"model output shapes:\", out[0].shape, out[1].shape)\n\n\n2/2 ━━━━━━━━━━━━━━━━━━━━ 0s 11ms/step\n\nmodel output shapes: (64, 5) (64, 4)\n\n\n\n\n\nhistory = model.fit(inputs, [out_cls, out_boxes],\n batch_size=10, epochs=100)\n\n\nEpoch 1/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 4ms/step - head_boxes_loss: 17972.5195 - head_classes_loss: 2.1833 - loss: 182.5903 \n\nEpoch 2/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 15940.1348 - head_classes_loss: 1.3818 - loss: 161.1863 \n\nEpoch 3/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 14151.4932 - head_classes_loss: 0.5389 - loss: 142.8707 \n\nEpoch 4/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 13744.4951 - head_classes_loss: 0.3754 - loss: 137.9574 \n\nEpoch 5/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 5ms/step - head_boxes_loss: 13268.7100 - head_classes_loss: 0.2007 - loss: 133.1759 \n\nEpoch 6/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 12060.4863 - head_classes_loss: 0.0992 - loss: 120.4861 \n\nEpoch 7/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 11131.0781 - head_classes_loss: 0.0663 - loss: 111.1454 \n\nEpoch 8/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 10234.7588 - head_classes_loss: 0.0559 - loss: 102.0231 \n\nEpoch 9/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 9230.1514 - head_classes_loss: 0.0458 - loss: 92.6901 \n\nEpoch 10/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 8009.4800 - head_classes_loss: 0.0317 - loss: 80.1446 \n\nEpoch 11/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 8036.9961 - head_classes_loss: 0.0411 - loss: 80.3372 \n\nEpoch 12/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 7061.5000 - head_classes_loss: 0.0239 - loss: 70.8101 \n\nEpoch 13/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 6943.0713 - head_classes_loss: 0.0229 - loss: 69.3297 \n\nEpoch 14/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 6638.4497 - head_classes_loss: 0.0237 - loss: 66.1968 \n\nEpoch 15/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 5773.5840 - head_classes_loss: 0.0242 - loss: 57.0677 \n\nEpoch 16/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 5067.9219 - head_classes_loss: 0.0258 - loss: 50.6844 \n\nEpoch 17/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 4919.1699 - head_classes_loss: 0.0153 - loss: 49.0794 \n\nEpoch 18/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 4850.7412 - head_classes_loss: 0.0180 - loss: 48.7978 \n\nEpoch 19/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 4630.3965 - head_classes_loss: 0.0127 - loss: 46.5497 \n\nEpoch 20/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 4ms/step - head_boxes_loss: 4313.4844 - head_classes_loss: 0.0159 - loss: 43.2661 \n\nEpoch 21/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 3805.2886 - head_classes_loss: 0.0154 - loss: 37.6120 \n\nEpoch 22/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 3984.5269 - head_classes_loss: 0.0139 - loss: 39.8876 \n\nEpoch 23/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 3827.4724 - head_classes_loss: 0.0130 - loss: 37.9763 \n\nEpoch 24/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 10ms/step - head_boxes_loss: 3859.0188 - head_classes_loss: 0.0118 - loss: 38.5174\n\nEpoch 25/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 3778.6074 - head_classes_loss: 0.0080 - loss: 38.0217 \n\nEpoch 26/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 2922.7329 - head_classes_loss: 0.0096 - loss: 29.1933 \n\nEpoch 27/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 3021.8337 - head_classes_loss: 0.0064 - loss: 29.9597 \n\nEpoch 28/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 3382.9001 - head_classes_loss: 0.0087 - loss: 34.1091 \n\nEpoch 29/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 2941.6494 - head_classes_loss: 0.0084 - loss: 29.6819 \n\nEpoch 30/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 2856.4614 - head_classes_loss: 0.0095 - loss: 28.5830 \n\nEpoch 31/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 2759.3818 - head_classes_loss: 0.0066 - loss: 27.3447 \n\nEpoch 32/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 2930.5884 - head_classes_loss: 0.0050 - loss: 29.4397 \n\nEpoch 33/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 2698.9763 - head_classes_loss: 0.0068 - loss: 27.4157 \n\nEpoch 34/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 2685.6758 - head_classes_loss: 0.0087 - loss: 26.4414 \n\nEpoch 35/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 2446.5513 - head_classes_loss: 0.0056 - loss: 24.3928 \n\nEpoch 36/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 2645.4763 - head_classes_loss: 0.0054 - loss: 26.5532 \n\nEpoch 37/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 2422.2097 - head_classes_loss: 0.0058 - loss: 24.3874 \n\nEpoch 38/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 2431.1492 - head_classes_loss: 0.0044 - loss: 24.2241 \n\nEpoch 39/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 2248.5698 - head_classes_loss: 0.0055 - loss: 22.6144 \n\nEpoch 40/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 2283.1755 - head_classes_loss: 0.0046 - loss: 22.6371 \n\nEpoch 41/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 2298.8870 - head_classes_loss: 0.0049 - loss: 23.2539 \n\nEpoch 42/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 2435.0852 - head_classes_loss: 0.0042 - loss: 24.4689 \n\nEpoch 43/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 2441.0625 - head_classes_loss: 0.0044 - loss: 24.3910 \n\nEpoch 44/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 2311.7266 - head_classes_loss: 0.0053 - loss: 22.9973 \n\nEpoch 45/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 2372.1787 - head_classes_loss: 0.0048 - loss: 23.5092 \n\nEpoch 46/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 2228.9111 - head_classes_loss: 0.0045 - loss: 22.3401 \n\nEpoch 47/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 2020.0719 - head_classes_loss: 0.0038 - loss: 20.1627 \n\nEpoch 48/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 2291.6567 - head_classes_loss: 0.0042 - loss: 23.0159 \n\nEpoch 49/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 2125.6689 - head_classes_loss: 0.0051 - loss: 21.4342 \n\nEpoch 50/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 1988.7704 - head_classes_loss: 0.0045 - loss: 19.6816 \n\nEpoch 51/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 2048.7256 - head_classes_loss: 0.0043 - loss: 20.6911 \n\nEpoch 52/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 2033.0394 - head_classes_loss: 0.0061 - loss: 20.2451 \n\nEpoch 53/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 2001.8275 - head_classes_loss: 0.0032 - loss: 19.9809 \n\nEpoch 54/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 2207.7148 - head_classes_loss: 0.0035 - loss: 22.2814 \n\nEpoch 55/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 1918.1088 - head_classes_loss: 0.0025 - loss: 18.9470 \n\nEpoch 56/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 2190.1042 - head_classes_loss: 0.0034 - loss: 22.0774 \n\nEpoch 57/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 1955.4595 - head_classes_loss: 0.0024 - loss: 19.4009 \n\nEpoch 58/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 1981.0059 - head_classes_loss: 0.0041 - loss: 19.7037 \n\nEpoch 59/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 1986.1055 - head_classes_loss: 0.0023 - loss: 20.0243 \n\nEpoch 60/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 1817.0448 - head_classes_loss: 0.0034 - loss: 18.2813 \n\nEpoch 61/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 1675.4432 - head_classes_loss: 0.0024 - loss: 16.7537\n\nEpoch 62/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 1883.2296 - head_classes_loss: 0.0028 - loss: 18.9159 \n\nEpoch 63/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 1998.4353 - head_classes_loss: 0.0027 - loss: 19.7077 \n\nEpoch 64/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 1791.3716 - head_classes_loss: 0.0023 - loss: 17.9422 \n\nEpoch 65/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 4ms/step - head_boxes_loss: 1808.9841 - head_classes_loss: 0.0023 - loss: 18.0037 \n\nEpoch 66/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 4ms/step - head_boxes_loss: 1825.4220 - head_classes_loss: 0.0048 - loss: 17.9281 \n\nEpoch 67/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 4ms/step - head_boxes_loss: 1742.1736 - head_classes_loss: 0.0026 - loss: 17.4203 \n\nEpoch 68/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 2069.6509 - head_classes_loss: 0.0023 - loss: 20.7654 \n\nEpoch 69/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 4ms/step - head_boxes_loss: 1805.4827 - head_classes_loss: 0.0029 - loss: 18.1471 \n\nEpoch 70/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 4ms/step - head_boxes_loss: 1798.4182 - head_classes_loss: 0.0022 - loss: 17.9621 \n\nEpoch 71/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 7ms/step - head_boxes_loss: 1766.0226 - head_classes_loss: 0.0024 - loss: 17.7009 \n\nEpoch 72/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 1883.0762 - head_classes_loss: 0.0026 - loss: 18.9359 \n\nEpoch 73/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 1692.3936 - head_classes_loss: 0.0025 - loss: 17.0519 \n\nEpoch 74/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 1779.0175 - head_classes_loss: 0.0040 - loss: 17.8345 \n\nEpoch 75/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 1678.3625 - head_classes_loss: 0.0019 - loss: 16.7768 \n\nEpoch 76/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 4ms/step - head_boxes_loss: 1808.9407 - head_classes_loss: 0.0030 - loss: 18.2231 \n\nEpoch 77/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 4ms/step - head_boxes_loss: 1615.5199 - head_classes_loss: 0.0026 - loss: 16.0924 \n\nEpoch 78/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 4ms/step - head_boxes_loss: 1499.8060 - head_classes_loss: 0.0024 - loss: 15.0986 \n\nEpoch 79/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 4ms/step - head_boxes_loss: 1561.9724 - head_classes_loss: 0.0021 - loss: 15.7328 \n\nEpoch 80/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 4ms/step - head_boxes_loss: 1619.8292 - head_classes_loss: 0.0020 - loss: 16.2815 \n\nEpoch 81/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 5ms/step - head_boxes_loss: 1753.1555 - head_classes_loss: 0.0021 - loss: 17.5438 \n\nEpoch 82/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 1509.0085 - head_classes_loss: 0.0019 - loss: 15.2850 \n\nEpoch 83/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 4ms/step - head_boxes_loss: 1738.1558 - head_classes_loss: 0.0022 - loss: 17.3382 \n\nEpoch 84/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 1580.9921 - head_classes_loss: 0.0022 - loss: 15.9418 \n\nEpoch 85/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 1659.5834 - head_classes_loss: 0.0017 - loss: 16.7462 \n\nEpoch 86/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 1620.8119 - head_classes_loss: 0.0018 - loss: 16.3729 \n\nEpoch 87/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 4ms/step - head_boxes_loss: 1570.1206 - head_classes_loss: 0.0015 - loss: 15.5894 \n\nEpoch 88/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 1589.4634 - head_classes_loss: 0.0021 - loss: 15.8076 \n\nEpoch 89/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 4ms/step - head_boxes_loss: 1429.0085 - head_classes_loss: 0.0016 - loss: 14.3042 \n\nEpoch 90/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 5ms/step - head_boxes_loss: 1571.0714 - head_classes_loss: 0.0017 - loss: 15.7220 \n\nEpoch 91/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 4ms/step - head_boxes_loss: 1388.4607 - head_classes_loss: 0.0020 - loss: 13.8351 \n\nEpoch 92/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 4ms/step - head_boxes_loss: 1449.2737 - head_classes_loss: 0.0013 - loss: 14.4236 \n\nEpoch 93/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 1397.3894 - head_classes_loss: 0.0016 - loss: 13.8752 \n\nEpoch 94/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 1495.3950 - head_classes_loss: 0.0017 - loss: 14.9094 \n\nEpoch 95/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 1388.0986 - head_classes_loss: 0.0017 - loss: 13.8051 \n\nEpoch 96/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 1432.1313 - head_classes_loss: 0.0015 - loss: 14.3608 \n\nEpoch 97/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 1447.3666 - head_classes_loss: 0.0011 - loss: 14.6846 \n\nEpoch 98/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - head_boxes_loss: 1397.3793 - head_classes_loss: 0.0019 - loss: 14.0035 \n\nEpoch 99/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 4ms/step - head_boxes_loss: 1473.4706 - head_classes_loss: 0.0014 - loss: 14.9420 \n\nEpoch 100/100\n\n7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 6ms/step - head_boxes_loss: 1479.7235 - head_classes_loss: 0.0016 - loss: 14.7976 \n\n\n\n\n\nimport matplotlib.pyplot as plt\nplt.plot(np.log(history.history[\"head_boxes_loss\"]), label=\"boxes_loss\")\nplt.plot(np.log(history.history[\"head_classes_loss\"]), label=\"classes_loss\")\nplt.plot(np.log(history.history[\"loss\"]), label=\"loss\")\nplt.legend(loc=\"upper left\")\nplt.xlabel(\"Epochs\")\nplt.ylabel(\"Loss\")\nplt.show()\n\n\n\n\n\n\n\n\n\n\nImágenes y bounding boxes\n\n%matplotlib inline\nimport matplotlib.pyplot as plt\n\ndef patch(axis, bbox, display_txt, color):\n coords = (bbox[0], bbox[1]), bbox[2]-bbox[0]+1, bbox[3]-bbox[1]+1\n axis.add_patch(plt.Rectangle(*coords, fill=False, edgecolor=color, linewidth=2))\n axis.text(bbox[0], bbox[1], display_txt, bbox={'facecolor':color, 'alpha':0.5})\n \ndef plot_annotations(img_path, annotation=None, ground_truth=None):\n img = imread(img_path)\n plt.imshow(img)\n current_axis = plt.gca()\n if ground_truth:\n text = \"gt \" + ground_truth[\"class\"]\n patch(current_axis, ground_truth[\"bbox\"], text, \"red\")\n if annotation:\n conf = '{:0.2f} '.format(annotation['confidence'])\n text = conf + annotation[\"class\"]\n patch(current_axis, annotation[\"bbox\"], text, \"blue\")\n plt.axis('off')\n plt.show()\n\ndef display(index, ground_truth=True):\n res = model.predict(reprs[index][np.newaxis,])\n output = interpret_output(res[0][0], res[1][0], img_size=annotations[index][\"size\"])\n plot_annotations(\"VOCdevkit/VOC2007/JPEGImages/\" + annotations[index][\"filename\"], \n output, annotations[index] if ground_truth else None)\n\n\ndisplay(13)\n\n\n1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 47ms/step\n\n\n\n\n\n\n\n\n\n\n\n\ndisplay(194)\n\n\n1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 21ms/step\n\n\n\n\n\n\n\n\n\n\n\n\n# Compute class accuracy, iou average and global accuracy\ndef accuracy_and_iou(preds, trues, threshold=0.5):\n sum_valid, sum_accurate, sum_iou = 0, 0, 0\n num = len(preds)\n for pred, true in zip(preds, trues):\n iou_value = iou(pred[\"bbox\"], true[\"bbox\"])\n if pred[\"class\"] == true[\"class\"] and iou_value > threshold:\n sum_valid = sum_valid + 1\n sum_iou = sum_iou + iou_value\n if pred[\"class\"] == true[\"class\"]:\n sum_accurate = sum_accurate + 1\n return sum_accurate / num, sum_iou / num, sum_valid / num\n\n\n# Compute the previous function on the whole train / test set\ndef compute_acc(train=True):\n if train:\n beg, end = 0, (9 * len(annotations) // 10)\n split_name = \"train\"\n else:\n beg, end = (9 * len(annotations)) // 10, len(annotations) \n split_name = \"test\"\n res = model.predict(reprs[beg:end])\n outputs = []\n for index, (classes, boxes) in enumerate(zip(res[0], res[1])):\n output = interpret_output(classes, boxes,\n img_size=annotations[index][\"size\"])\n outputs.append(output)\n \n acc, iou, valid = accuracy_and_iou(outputs, annotations[beg:end],\n threshold=0.5)\n \n print('{} acc: {:0.3f}, mean iou: {:0.3f}, acc_valid: {:0.3f}'.format(\n split_name, acc, iou, valid) )\n\n\ncompute_acc(train=True)\ncompute_acc(train=False)\n\n\n36/36 ━━━━━━━━━━━━━━━━━━━━ 0s 4ms/step\n\ntrain acc: 0.821, mean iou: 0.367, acc_valid: 0.250\n\n4/4 ━━━━━━━━━━━━━━━━━━━━ 0s 4ms/step \n\ntest acc: 0.803, mean iou: 0.306, acc_valid: 0.173\n\n\n\n\n\n\nTraining\n\n# Keep last examples for test\ntest_num = reprs.shape[0] // 10\ntrain_num = reprs.shape[0] - test_num\ntest_inputs = reprs[train_num:]\ntest_cls, test_boxes = classes[train_num:], boxes[train_num:]\nprint(train_num)\n\n1138\n\n\n\nmodel = classif_and_loc_avg_model(num_classes)\n\n\n# Keep last examples for test\ntest_num = reprs.shape[0] // 10\ntrain_num = reprs.shape[0] - test_num\ntest_inputs = reprs[train_num:]\ntest_cls, test_boxes = classes[train_num:], boxes[train_num:]\nprint(train_num)\n\nbatch_size = 32\ninputs = reprs[0:train_num]\nout_cls, out_boxes = classes[0:train_num], boxes[0:train_num]\n\nprint(inputs.shape, out_cls.shape, out_boxes.shape)\nprint(test_inputs.shape, test_cls.shape, test_boxes.shape)\n\nhistory = model.fit(inputs, y=[out_cls, out_boxes], \n validation_data=(test_inputs, [test_cls, test_boxes]), \n batch_size=batch_size, epochs=10, verbose=2)\n\n1138\n(1138, 7, 7, 2048) (1138, 5) (1138, 4)\n(126, 7, 7, 2048) (126, 5) (126, 4)\nEpoch 1/10\n36/36 - 1s - 15ms/step - head_boxes_loss: 14378.6738 - head_classes_loss: 0.7973 - loss: 144.9700 - val_head_boxes_loss: 11651.1797 - val_head_classes_loss: 0.2991 - val_loss: 116.8985\nEpoch 2/10\n36/36 - 0s - 3ms/step - head_boxes_loss: 9247.6719 - head_classes_loss: 0.2699 - loss: 93.2352 - val_head_boxes_loss: 7589.5547 - val_head_classes_loss: 0.2247 - val_loss: 76.2045\nEpoch 3/10\n36/36 - 0s - 3ms/step - head_boxes_loss: 6129.0264 - head_classes_loss: 0.1975 - loss: 61.5965 - val_head_boxes_loss: 5228.7178 - val_head_classes_loss: 0.2733 - val_loss: 52.6217\nEpoch 4/10\n36/36 - 0s - 3ms/step - head_boxes_loss: 4372.4243 - head_classes_loss: 0.1528 - loss: 43.9875 - val_head_boxes_loss: 3972.6484 - val_head_classes_loss: 0.1984 - val_loss: 39.9542\nEpoch 5/10\n36/36 - 0s - 3ms/step - head_boxes_loss: 3488.2505 - head_classes_loss: 0.1165 - loss: 34.9518 - val_head_boxes_loss: 3369.6165 - val_head_classes_loss: 0.2144 - val_loss: 33.9110\nEpoch 6/10\n36/36 - 0s - 3ms/step - head_boxes_loss: 3026.0381 - head_classes_loss: 0.0977 - loss: 30.4518 - val_head_boxes_loss: 3077.6650 - val_head_classes_loss: 0.1713 - val_loss: 30.9241\nEpoch 7/10\n36/36 - 0s - 3ms/step - head_boxes_loss: 2837.5276 - head_classes_loss: 0.0812 - loss: 28.4066 - val_head_boxes_loss: 2931.5464 - val_head_classes_loss: 0.1833 - val_loss: 29.4579\nEpoch 8/10\n36/36 - 0s - 3ms/step - head_boxes_loss: 2705.0649 - head_classes_loss: 0.0714 - loss: 27.2259 - val_head_boxes_loss: 2843.6616 - val_head_classes_loss: 0.2011 - val_loss: 28.5867\nEpoch 9/10\n36/36 - 0s - 3ms/step - head_boxes_loss: 2630.8835 - head_classes_loss: 0.0607 - loss: 26.3297 - val_head_boxes_loss: 2775.7207 - val_head_classes_loss: 0.2042 - val_loss: 27.9032\nEpoch 10/10\n36/36 - 0s - 3ms/step - head_boxes_loss: 2562.8142 - head_classes_loss: 0.0564 - loss: 25.6258 - val_head_boxes_loss: 2714.5698 - val_head_classes_loss: 0.1737 - val_loss: 27.2560\n\n\n\ncompute_acc(train=True)\ncompute_acc(train=False)\n\n\n36/36 ━━━━━━━━━━━━━━━━━━━━ 0s 2ms/step\n\ntrain acc: 0.998, mean iou: 0.338, acc_valid: 0.198\n\n4/4 ━━━━━━━━━━━━━━━━━━━━ 0s 4ms/step \n\ntest acc: 0.937, mean iou: 0.290, acc_valid: 0.134\n\n\n\n\n\n\nMejor modelo\n\n# test acc: 0.898, mean iou: 0.457, acc_valid: 0.496\n\ndef classif_and_loc(num_classes):\n model_input = Input(shape=(7,7,2048))\n x = GlobalAveragePooling2D()(model_input)\n \n x = Dropout(0.2)(x)\n head_classes = Dense(num_classes, activation=\"softmax\", name=\"head_classes\")(x)\n \n y = Convolution2D(4, 1, 1, activation='relu', name='hidden_conv')(model_input)\n y = Flatten()(y)\n y = Dropout(0.2)(y)\n head_boxes = Dense(4, name=\"head_boxes\")(y)\n \n model = Model(model_input, outputs = [head_classes, head_boxes], name=\"resnet_loc\")\n model.compile(optimizer=\"adam\", loss=['categorical_crossentropy', \"mse\"], \n loss_weights=[1., 1/(224*224)]) \n return model\n\nmodel = classif_and_loc(5)\n\nhistory = model.fit(x = inputs, y=[out_cls, out_boxes], \n validation_data=(test_inputs, [test_cls, test_boxes]), \n batch_size=batch_size, epochs=30, verbose=2)\n\ncompute_acc(train=True)\ncompute_acc(train=False)\n\n\nEpoch 1/30\n\n36/36 - 1s - 19ms/step - head_boxes_loss: 9403.3945 - head_classes_loss: 0.6515 - loss: 0.8438 - val_head_boxes_loss: 3573.7976 - val_head_classes_loss: 0.3122 - val_loss: 0.3848\n\nEpoch 2/30\n\n36/36 - 0s - 5ms/step - head_boxes_loss: 2991.4478 - head_classes_loss: 0.2400 - loss: 0.3018 - val_head_boxes_loss: 2547.3743 - val_head_classes_loss: 0.1948 - val_loss: 0.2470\n\nEpoch 3/30\n\n36/36 - 0s - 5ms/step - head_boxes_loss: 2383.2554 - head_classes_loss: 0.1812 - loss: 0.2287 - val_head_boxes_loss: 2224.8140 - val_head_classes_loss: 0.2158 - val_loss: 0.2618\n\nEpoch 4/30\n\n36/36 - 0s - 5ms/step - head_boxes_loss: 2036.2715 - head_classes_loss: 0.1440 - loss: 0.1845 - val_head_boxes_loss: 1992.4321 - val_head_classes_loss: 0.2149 - val_loss: 0.2566\n\nEpoch 5/30\n\n36/36 - 0s - 5ms/step - head_boxes_loss: 1775.3939 - head_classes_loss: 0.1170 - loss: 0.1534 - val_head_boxes_loss: 1828.7864 - val_head_classes_loss: 0.1908 - val_loss: 0.2290\n\nEpoch 6/30\n\n36/36 - 0s - 5ms/step - head_boxes_loss: 1575.1567 - head_classes_loss: 0.0870 - loss: 0.1190 - val_head_boxes_loss: 1704.3774 - val_head_classes_loss: 0.1965 - val_loss: 0.2323\n\nEpoch 7/30\n\n36/36 - 0s - 5ms/step - head_boxes_loss: 1437.5016 - head_classes_loss: 0.0802 - loss: 0.1084 - val_head_boxes_loss: 1624.1078 - val_head_classes_loss: 0.1735 - val_loss: 0.2075\n\nEpoch 8/30\n\n36/36 - 0s - 5ms/step - head_boxes_loss: 1282.5614 - head_classes_loss: 0.0686 - loss: 0.0945 - val_head_boxes_loss: 1492.1785 - val_head_classes_loss: 0.2291 - val_loss: 0.2612\n\nEpoch 9/30\n\n36/36 - 0s - 5ms/step - head_boxes_loss: 1148.7317 - head_classes_loss: 0.0574 - loss: 0.0805 - val_head_boxes_loss: 1441.3212 - val_head_classes_loss: 0.2023 - val_loss: 0.2330\n\nEpoch 10/30\n\n36/36 - 0s - 5ms/step - head_boxes_loss: 1053.6012 - head_classes_loss: 0.0534 - loss: 0.0740 - val_head_boxes_loss: 1389.9946 - val_head_classes_loss: 0.1791 - val_loss: 0.2086\n\nEpoch 11/30\n\n36/36 - 0s - 5ms/step - head_boxes_loss: 996.6545 - head_classes_loss: 0.0448 - loss: 0.0649 - val_head_boxes_loss: 1327.2693 - val_head_classes_loss: 0.2130 - val_loss: 0.2417\n\nEpoch 12/30\n\n36/36 - 0s - 6ms/step - head_boxes_loss: 948.8165 - head_classes_loss: 0.0439 - loss: 0.0631 - val_head_boxes_loss: 1324.2382 - val_head_classes_loss: 0.2131 - val_loss: 0.2413\n\nEpoch 13/30\n\n36/36 - 0s - 5ms/step - head_boxes_loss: 885.9665 - head_classes_loss: 0.0352 - loss: 0.0517 - val_head_boxes_loss: 1290.5995 - val_head_classes_loss: 0.1920 - val_loss: 0.2196\n\nEpoch 14/30\n\n36/36 - 0s - 5ms/step - head_boxes_loss: 852.6992 - head_classes_loss: 0.0325 - loss: 0.0496 - val_head_boxes_loss: 1272.4675 - val_head_classes_loss: 0.1906 - val_loss: 0.2181\n\nEpoch 15/30\n\n36/36 - 0s - 5ms/step - head_boxes_loss: 831.9149 - head_classes_loss: 0.0307 - loss: 0.0475 - val_head_boxes_loss: 1278.3333 - val_head_classes_loss: 0.1908 - val_loss: 0.2182\n\nEpoch 16/30\n\n36/36 - 0s - 5ms/step - head_boxes_loss: 786.9148 - head_classes_loss: 0.0267 - loss: 0.0425 - val_head_boxes_loss: 1233.1768 - val_head_classes_loss: 0.1967 - val_loss: 0.2235\n\nEpoch 17/30\n\n36/36 - 0s - 5ms/step - head_boxes_loss: 769.9054 - head_classes_loss: 0.0242 - loss: 0.0395 - val_head_boxes_loss: 1218.7672 - val_head_classes_loss: 0.1882 - val_loss: 0.2146\n\nEpoch 18/30\n\n36/36 - 0s - 5ms/step - head_boxes_loss: 743.8181 - head_classes_loss: 0.0233 - loss: 0.0382 - val_head_boxes_loss: 1212.9133 - val_head_classes_loss: 0.1841 - val_loss: 0.2103\n\nEpoch 19/30\n\n36/36 - 0s - 5ms/step - head_boxes_loss: 715.8613 - head_classes_loss: 0.0257 - loss: 0.0392 - val_head_boxes_loss: 1196.8138 - val_head_classes_loss: 0.1816 - val_loss: 0.2074\n\nEpoch 20/30\n\n36/36 - 0s - 5ms/step - head_boxes_loss: 684.8339 - head_classes_loss: 0.0208 - loss: 0.0344 - val_head_boxes_loss: 1195.8585 - val_head_classes_loss: 0.2040 - val_loss: 0.2304\n\nEpoch 21/30\n\n36/36 - 0s - 5ms/step - head_boxes_loss: 667.8189 - head_classes_loss: 0.0168 - loss: 0.0300 - val_head_boxes_loss: 1174.8939 - val_head_classes_loss: 0.2020 - val_loss: 0.2278\n\nEpoch 22/30\n\n36/36 - 0s - 5ms/step - head_boxes_loss: 636.8113 - head_classes_loss: 0.0180 - loss: 0.0307 - val_head_boxes_loss: 1177.9949 - val_head_classes_loss: 0.1946 - val_loss: 0.2205\n\nEpoch 23/30\n\n36/36 - 0s - 5ms/step - head_boxes_loss: 631.2306 - head_classes_loss: 0.0176 - loss: 0.0302 - val_head_boxes_loss: 1158.8527 - val_head_classes_loss: 0.1911 - val_loss: 0.2164\n\nEpoch 24/30\n\n36/36 - 0s - 5ms/step - head_boxes_loss: 610.6813 - head_classes_loss: 0.0184 - loss: 0.0306 - val_head_boxes_loss: 1152.8240 - val_head_classes_loss: 0.2200 - val_loss: 0.2457\n\nEpoch 25/30\n\n36/36 - 0s - 5ms/step - head_boxes_loss: 593.0518 - head_classes_loss: 0.0135 - loss: 0.0253 - val_head_boxes_loss: 1157.3673 - val_head_classes_loss: 0.1970 - val_loss: 0.2224\n\nEpoch 26/30\n\n36/36 - 0s - 5ms/step - head_boxes_loss: 580.4446 - head_classes_loss: 0.0142 - loss: 0.0259 - val_head_boxes_loss: 1146.5696 - val_head_classes_loss: 0.2056 - val_loss: 0.2309\n\nEpoch 27/30\n\n36/36 - 0s - 5ms/step - head_boxes_loss: 569.8855 - head_classes_loss: 0.0146 - loss: 0.0260 - val_head_boxes_loss: 1136.2690 - val_head_classes_loss: 0.2177 - val_loss: 0.2428\n\nEpoch 28/30\n\n36/36 - 0s - 5ms/step - head_boxes_loss: 556.0013 - head_classes_loss: 0.0117 - loss: 0.0230 - val_head_boxes_loss: 1125.7990 - val_head_classes_loss: 0.1967 - val_loss: 0.2215\n\nEpoch 29/30\n\n36/36 - 0s - 5ms/step - head_boxes_loss: 537.1777 - head_classes_loss: 0.0133 - loss: 0.0241 - val_head_boxes_loss: 1135.8713 - val_head_classes_loss: 0.2026 - val_loss: 0.2277\n\nEpoch 30/30\n\n36/36 - 0s - 5ms/step - head_boxes_loss: 521.7027 - head_classes_loss: 0.0128 - loss: 0.0233 - val_head_boxes_loss: 1138.2365 - val_head_classes_loss: 0.2193 - val_loss: 0.2445\n\n36/36 ━━━━━━━━━━━━━━━━━━━━ 0s 2ms/step\n\ntrain acc: 1.000, mean iou: 0.613, acc_valid: 0.755\n\n4/4 ━━━━━━━━━━━━━━━━━━━━ 0s 5ms/step \n\ntest acc: 0.921, mean iou: 0.428, acc_valid: 0.441\n\n\n\n\n\ndisplay(1242)\n\n\n1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 17ms/step"
},
{
"objectID": "bme423/ejemplos/cnn-03-design.html",
"href": "bme423/ejemplos/cnn-03-design.html",
"title": "Diseño de CNNs",
"section": "",
"text": "Diseñaremos nuestra propia ConvNet y veremos algunas aplicaciones existentes.\nTambién exploraremos los tres métodos diferentes para definir un modelo en Keras:"
},
{
"objectID": "bme423/ejemplos/cnn-03-design.html#lenet",
"href": "bme423/ejemplos/cnn-03-design.html#lenet",
"title": "Diseño de CNNs",
"section": "1. LeNet",
"text": "1. LeNet\nYann Le Cun in 1998 (paper url).\n\n\n\nlenet archi\n\n\n\nfrom tensorflow.keras.models import Sequential\nfrom tensorflow.keras.layers import AvgPool2D, Conv2D, MaxPool2D, Dense, Flatten\nfrom tensorflow.keras import optimizers\n\nlenet = Sequential(name=\"LeNet-5\")\n\nlenet.add(Conv2D(6, kernel_size=(5, 5), activation=\"tanh\", padding=\"same\", name=\"C1\"))\nlenet.add(MaxPool2D(pool_size=(2, 2), name=\"S2\"))\nlenet.add(Conv2D(16, kernel_size=(5, 5), activation='tanh', name=\"C3\"))\nlenet.add(AvgPool2D(pool_size=(2, 2), name=\"S4\"))\nlenet.add(Conv2D(120, kernel_size=(5, 5), activation='tanh', name=\"C5\"))\nlenet.add(Flatten())\nlenet.add(Dense(84, activation='tanh', name=\"F6\"))\nlenet.add(Dense(10, activation='softmax'))\n\nlenet.summary()\n\nModel: \"LeNet-5\"\n\n\n\n┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓\n┃ Layer (type) ┃ Output Shape ┃ Param # ┃\n┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩\n│ C1 (Conv2D) │ ? │ 0 (unbuilt) │\n├─────────────────────────────────┼────────────────────────┼───────────────┤\n│ S2 (MaxPooling2D) │ ? │ 0 │\n├─────────────────────────────────┼────────────────────────┼───────────────┤\n│ C3 (Conv2D) │ ? │ 0 (unbuilt) │\n├─────────────────────────────────┼────────────────────────┼───────────────┤\n│ S4 (AveragePooling2D) │ ? │ 0 │\n├─────────────────────────────────┼────────────────────────┼───────────────┤\n│ C5 (Conv2D) │ ? │ 0 (unbuilt) │\n├─────────────────────────────────┼────────────────────────┼───────────────┤\n│ flatten (Flatten) │ ? │ 0 (unbuilt) │\n├─────────────────────────────────┼────────────────────────┼───────────────┤\n│ F6 (Dense) │ ? │ 0 (unbuilt) │\n├─────────────────────────────────┼────────────────────────┼───────────────┤\n│ dense (Dense) │ ? │ 0 (unbuilt) │\n└─────────────────────────────────┴────────────────────────┴───────────────┘\n\n\n\n Total params: 0 (0.00 B)\n\n\n\n Trainable params: 0 (0.00 B)\n\n\n\n Non-trainable params: 0 (0.00 B)\n\n\n\n\nn_epochs = 5\nbatch_size = 256\n\nlenet.compile(\n optimizer=optimizers.SGD(learning_rate=0.1),\n loss=\"sparse_categorical_crossentropy\",\n metrics=[\"accuracy\"]\n)\n\nlenet.fit(\n x_train, y_train,\n epochs=n_epochs,\n batch_size=batch_size,\n validation_data=(x_val, y_val)\n)\n\n\nEpoch 1/5\n\n196/196 ━━━━━━━━━━━━━━━━━━━━ 4s 21ms/step - accuracy: 0.7120 - loss: 1.0518 - val_accuracy: 0.9033 - val_loss: 0.3154\n\nEpoch 2/5\n\n196/196 ━━━━━━━━━━━━━━━━━━━━ 4s 20ms/step - accuracy: 0.9145 - loss: 0.2941 - val_accuracy: 0.9298 - val_loss: 0.2256\n\nEpoch 3/5\n\n196/196 ━━━━━━━━━━━━━━━━━━━━ 4s 20ms/step - accuracy: 0.9368 - loss: 0.2104 - val_accuracy: 0.9449 - val_loss: 0.1762\n\nEpoch 4/5\n\n196/196 ━━━━━━━━━━━━━━━━━━━━ 4s 20ms/step - accuracy: 0.9507 - loss: 0.1629 - val_accuracy: 0.9581 - val_loss: 0.1363\n\nEpoch 5/5\n\n196/196 ━━━━━━━━━━━━━━━━━━━━ 4s 20ms/step - accuracy: 0.9612 - loss: 0.1321 - val_accuracy: 0.9677 - val_loss: 0.1136\n\n\n\n\n<keras.src.callbacks.history.History at 0x3217e1ca0>\n\n\n\nlenet.evaluate(x_test, y_test, verbose=0)\n\n[0.10733101516962051, 0.9675999879837036]\n\n\nAunque LeNet fue definido inicialmente usando tanh o sigmoid, esas funciones de activación ahora se usan muy poco. Ambas se saturan con valores muy pequeños o muy grandes, lo que hace que su gradiente sea casi nulo.\nActualmente, la mayoría de las redes utilizan ReLU como función de activación en las capas ocultas, o alguna de sus variantes (https://keras.io/layers/advanced-activations/)."
},
{
"objectID": "bme423/ejemplos/cnn-03-design.html#inception",
"href": "bme423/ejemplos/cnn-03-design.html#inception",
"title": "Diseño de CNNs",
"section": "2. Inception",
"text": "2. Inception\nSzegedy et al. (paper url).\n\n\n\ninception archi\n\n\nEjemplo usando la API Functional:\na = Input(shape=(32,))\nb = Dense(32)(a)\nmodel = Model(inputs=a, outputs=b)\n\nfrom tensorflow.keras.layers import Concatenate, Flatten, Input\nfrom tensorflow.keras.models import Model\n\n\ndef inception_layer(tensor, n_filters):\n branch1x1 = Conv2D(n_filters, kernel_size=(1, 1), activation=\"relu\", padding=\"same\")(tensor)\n branch5x5 = Conv2D(n_filters, kernel_size=(5, 5), activation=\"relu\", padding=\"same\")(tensor)\n branch3x3 = Conv2D(n_filters, kernel_size=(3, 3), activation=\"relu\", padding=\"same\")(tensor)\n\n branch_pool = MaxPool2D(pool_size=(3, 3), strides=(1, 1), padding=\"same\")(tensor)\n\n output = Concatenate(axis=-1)(\n [branch1x1, branch5x5, branch3x3, branch_pool]\n )\n return output\n\n\ninput_tensor = Input(shape=input_shape)\nx = Conv2D(16, kernel_size=(5, 5), padding=\"same\")(input_tensor)\nx = inception_layer(x, 32)\nx = Flatten()(x)\noutput_tensor = Dense(10, activation=\"softmax\")(x)\n\nmini_inception = Model(inputs=input_tensor, outputs=output_tensor)\n\nmini_inception.summary()\n\nModel: \"functional_1\"\n\n\n\n┏━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┓\n┃ Layer (type) ┃ Output Shape ┃ Param # ┃ Connected to ┃\n┡━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━┩\n│ input_layer_1 │ (None, 28, 28, 1) │ 0 │ - │\n│ (InputLayer) │ │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2d (Conv2D) │ (None, 28, 28, │ 416 │ input_layer_1[0]… │\n│ │ 16) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2d_1 (Conv2D) │ (None, 28, 28, │ 544 │ conv2d[0][0] │\n│ │ 32) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2d_2 (Conv2D) │ (None, 28, 28, │ 12,832 │ conv2d[0][0] │\n│ │ 32) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ conv2d_3 (Conv2D) │ (None, 28, 28, │ 4,640 │ conv2d[0][0] │\n│ │ 32) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ max_pooling2d │ (None, 28, 28, │ 0 │ conv2d[0][0] │\n│ (MaxPooling2D) │ 16) │ │ │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ concatenate │ (None, 28, 28, │ 0 │ conv2d_1[0][0], │\n│ (Concatenate) │ 112) │ │ conv2d_2[0][0], │\n│ │ │ │ conv2d_3[0][0], │\n│ │ │ │ max_pooling2d[0]… │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ flatten_1 (Flatten) │ (None, 87808) │ 0 │ concatenate[0][0] │\n├─────────────────────┼───────────────────┼────────────┼───────────────────┤\n│ dense_1 (Dense) │ (None, 10) │ 878,090 │ flatten_1[0][0] │\n└─────────────────────┴───────────────────┴────────────┴───────────────────┘\n\n\n\n Total params: 896,522 (3.42 MB)\n\n\n\n Trainable params: 896,522 (3.42 MB)\n\n\n\n Non-trainable params: 0 (0.00 B)\n\n\n\n\nn_epochs = 5\nbatch_size = 256\n\nmini_inception.compile(\n optimizer=optimizers.SGD(learning_rate=0.1),\n loss=\"sparse_categorical_crossentropy\",\n metrics=[\"accuracy\"]\n)\n\nmini_inception.fit(\n x_train, y_train,\n epochs=n_epochs,\n batch_size=batch_size,\n validation_data=(x_val, y_val)\n)\n\nmini_inception.evaluate(x_test, y_test, verbose=0)\n\n\nEpoch 1/5\n\n196/196 ━━━━━━━━━━━━━━━━━━━━ 39s 197ms/step - accuracy: 0.8029 - loss: 0.6269 - val_accuracy: 0.9546 - val_loss: 0.1553\n\nEpoch 2/5\n\n196/196 ━━━━━━━━━━━━━━━━━━━━ 38s 191ms/step - accuracy: 0.9704 - loss: 0.1030 - val_accuracy: 0.9732 - val_loss: 0.0860\n\nEpoch 3/5\n\n196/196 ━━━━━━━━━━━━━━━━━━━━ 40s 206ms/step - accuracy: 0.9815 - loss: 0.0657 - val_accuracy: 0.9798 - val_loss: 0.0681\n\nEpoch 4/5\n\n196/196 ━━━━━━━━━━━━━━━━━━━━ 38s 192ms/step - accuracy: 0.9844 - loss: 0.0513 - val_accuracy: 0.9815 - val_loss: 0.0610\n\nEpoch 5/5\n\n196/196 ━━━━━━━━━━━━━━━━━━━━ 38s 193ms/step - accuracy: 0.9877 - loss: 0.0416 - val_accuracy: 0.9811 - val_loss: 0.0632\n\n\n\n\n[0.05889404937624931, 0.9814000129699707]"
},
{
"objectID": "bme423/ejemplos/cnn-03-design.html#resnet",
"href": "bme423/ejemplos/cnn-03-design.html#resnet",
"title": "Diseño de CNNs",
"section": "3. ResNet",
"text": "3. ResNet\nLos modelos ResNet (Residual Networks) fueron introducidos por He et al. en 2015 (paper url). Ellos descubrieron que añadir más capas mejoraba el rendimiento, pero resultaba difícil retropropagar los gradientes hasta las primeras capas.\nUn truco para permitir que los gradientes fluyan más fácilmente es utilizar conexiones de cortocircuito (shortcut connections) que dejan el tensor de entrada sin modificar (también conocidas como residuales).\n\n\n\nresnet archi\n\n\nEjemplo usando la API orientada a objetos:\nclass MyModel(Model):\n def __init__(self):\n self.classifier = Dense(10, activation=\"softmax\")\n \n def call(self, inputs):\n return self.classifier(inputs)\n\nfrom tensorflow.keras.layers import Add, Layer, Activation\n\nclass ResidualBlock(Layer):\n def __init__(self, n_filters):\n super().__init__(name=\"ResidualBlock\")\n\n self.conv1 = Conv2D(n_filters, kernel_size=(3, 3), activation=\"relu\", padding=\"same\")\n self.conv2 = Conv2D(n_filters, kernel_size=(3, 3), padding=\"same\")\n self.add = Add()\n self.last_relu = Activation(\"relu\")\n\n def call(self, inputs):\n x = self.conv1(inputs)\n x = self.conv2(inputs)\n\n y = self.add([x, inputs])\n y = self.last_relu(y)\n\n return y\n\n\nclass MiniResNet(Model):\n def __init__(self, n_filters):\n super().__init__()\n\n self.conv = Conv2D(n_filters, kernel_size=(5, 5), padding=\"same\")\n self.block = ResidualBlock(n_filters)\n self.flatten = Flatten()\n self.classifier = Dense(10, activation=\"softmax\")\n\n def call(self, inputs):\n x = self.conv(inputs)\n x = self.block(x)\n x = self.flatten(x)\n y = self.classifier(x)\n\n return y\n\n\nmini_resnet = MiniResNet(32)\n# mini_resnet.build((None, *input_shape))\nmini_resnet.summary()\n\nModel: \"mini_res_net\"\n\n\n\n┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓\n┃ Layer (type) ┃ Output Shape ┃ Param # ┃\n┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩\n│ conv2d_4 (Conv2D) │ ? │ 0 (unbuilt) │\n├─────────────────────────────────┼────────────────────────┼───────────────┤\n│ ResidualBlock (ResidualBlock) │ ? │ 0 (unbuilt) │\n├─────────────────────────────────┼────────────────────────┼───────────────┤\n│ flatten_2 (Flatten) │ ? │ 0 (unbuilt) │\n├─────────────────────────────────┼────────────────────────┼───────────────┤\n│ dense_2 (Dense) │ ? │ 0 (unbuilt) │\n└─────────────────────────────────┴────────────────────────┴───────────────┘\n\n\n\n Total params: 0 (0.00 B)\n\n\n\n Trainable params: 0 (0.00 B)\n\n\n\n Non-trainable params: 0 (0.00 B)\n\n\n\n\nn_epochs = 5\nbatch_size = 256\n\nmini_resnet.compile(\n optimizer=optimizers.SGD(learning_rate=0.1),\n loss=\"sparse_categorical_crossentropy\",\n metrics=[\"accuracy\"]\n)\n\nmini_resnet.fit(\n x_train, y_train,\n epochs=n_epochs,\n batch_size=batch_size,\n validation_data=(x_val, y_val)\n)\n\nmini_resnet.evaluate(x_test, y_test, verbose=0)\n\nEpoch 1/5\n\n\n/Users/aveloz/miniconda3/lib/python3.9/site-packages/keras/src/optimizers/base_optimizer.py:774: UserWarning: Gradients do not exist for variables ['mini_res_net/ResidualBlock/conv2d_5/kernel', 'mini_res_net/ResidualBlock/conv2d_5/bias'] when minimizing the loss. If using `model.compile()`, did you forget to provide a `loss` argument?\n warnings.warn(\n\n\n\n196/196 ━━━━━━━━━━━━━━━━━━━━ 16s 81ms/step - accuracy: 0.7973 - loss: 0.7147 - val_accuracy: 0.9618 - val_loss: 0.1397\n\nEpoch 2/5\n\n196/196 ━━━━━━━━━━━━━━━━━━━━ 16s 79ms/step - accuracy: 0.9665 - loss: 0.1171 - val_accuracy: 0.9213 - val_loss: 0.2453\n\nEpoch 3/5\n\n196/196 ━━━━━━━━━━━━━━━━━━━━ 16s 81ms/step - accuracy: 0.9712 - loss: 0.0945 - val_accuracy: 0.9679 - val_loss: 0.1019\n\nEpoch 4/5\n\n196/196 ━━━━━━━━━━━━━━━━━━━━ 15s 79ms/step - accuracy: 0.9788 - loss: 0.0716 - val_accuracy: 0.9684 - val_loss: 0.1025\n\nEpoch 5/5\n\n196/196 ━━━━━━━━━━━━━━━━━━━━ 15s 79ms/step - accuracy: 0.9829 - loss: 0.0592 - val_accuracy: 0.9723 - val_loss: 0.0942\n\n\n\n\n[0.08727332949638367, 0.9731000065803528]"
},
{
"objectID": "bme423/ejemplos/cnn-03-design.html#batch-normalization",
"href": "bme423/ejemplos/cnn-03-design.html#batch-normalization",
"title": "Diseño de CNNs",
"section": "4. Batch Normalization",
"text": "4. Batch Normalization\nBatch Normalization no es una arquitectura, es una capa. En el artículo de Ioffe et al. in 2015 (paper url) se señala:\n\nTraining Deep Neural Networks is complicated by the fact that the distribution of each layer’s inputs changes during training, as the parameters of the previous layers change. This slows down the training by requiring lower learningrates and careful parameter initialization, and makes it notoriously hard to train models with saturating nonlinearities. We refer to this phenomenon as internal covariate shift, and address the problem by normalizing layer inputs.\n\nEl resultado es que las CNNs que se entrenan con BatchNorm convergen más rápido con resultados mejores. Actualmente, todas o casi todas usan alguna forma de BatchNorm. Ver el artículo.\nUn bloque clásico es:\n\nclass ConvBlock(Layer):\n def __init__(n_filters, kernel_size):\n super().__init__()\n \n self.conv = Conv2D(n_filters, kernel_size=kernel_size, use_bias=False)\n self.bn = BatchNormalization(axis=3)\n self.activation = Activation(\"relu\")\n \n def call(self, inputs):\n return self.activation(\n self.bn(self.conv(inputs))\n )"
},
{
"objectID": "bme423/ejemplos/cnn-03-design.html#convoluciones-separables",
"href": "bme423/ejemplos/cnn-03-design.html#convoluciones-separables",
"title": "Diseño de CNNs",
"section": "5. Convoluciones separables",
"text": "5. Convoluciones separables\nLas CNNs suelen tener muchos parámetros debido a su gran profundidad. Un truco para reducir el número de parámetros con una pérdida mínima en el rendimiento es usar convolución separable.\nLa convolución estándar tiene muchos parámetros (aunque sigue siendo mucho menos que una capa densa):\n\n\n\nconv\n\n\n\nconv_model = Sequential(name=\"Conv Model\")\nconv_model.add(Conv2D(8, kernel_size=(3, 3), use_bias=False))\n\nCuántos parámetros?\n\nconv_model.build((None, *input_shape))\nconv_model.summary()\n\nModel: \"Conv Model\"\n\n\n\n┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓\n┃ Layer (type) ┃ Output Shape ┃ Param # ┃\n┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩\n│ conv2d_7 (Conv2D) │ (None, 26, 26, 8) │ 72 │\n└─────────────────────────────────┴────────────────────────┴───────────────┘\n\n\n\n Total params: 72 (288.00 B)\n\n\n\n Trainable params: 72 (288.00 B)\n\n\n\n Non-trainable params: 0 (0.00 B)\n\n\n\nLas convoluciones separables consisten en dos tipos de convolución:\n\nUna convolución depthwise: se crea un único kernel por canal de entrada, por lo que se afecta la información espacial, pero no se comparte información entre canales.\n\n\n\n\ndepthwise conv\n\n\n\nUna convolución pointwise: es una convolución habitual con un kernel de tamaño (1, 1). Aquí, la información espacial no se ve afectada, pero sí se comparte información entre los canales.\n\n\n\n\npointwise conv\n\n\n\nfrom tensorflow.keras.layers import DepthwiseConv2D\n\nseparable_model = Sequential(name=\"Separable Model\")\nseparable_model.add(DepthwiseConv2D(kernel_size=(3, 3), use_bias=False))\nseparable_model.add(Conv2D(8, kernel_size=(1, 1), use_bias=False))\n\n\nCuantos parámetros tienen las convoluciones Depthwise y Pointwise?\n\n\nseparable_model.build((None, *input_shape))\nseparable_model.summary()\n\nModel: \"Separable Model\"\n\n\n\n┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓\n┃ Layer (type) ┃ Output Shape ┃ Param # ┃\n┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩\n│ depthwise_conv2d │ (None, 26, 26, 1) │ 9 │\n│ (DepthwiseConv2D) │ │ │\n├─────────────────────────────────┼────────────────────────┼───────────────┤\n│ conv2d_8 (Conv2D) │ (None, 26, 26, 8) │ 8 │\n└─────────────────────────────────┴────────────────────────┴───────────────┘\n\n\n\n Total params: 17 (68.00 B)\n\n\n\n Trainable params: 17 (68.00 B)\n\n\n\n Non-trainable params: 0 (0.00 B)"
},
{
"objectID": "gp/gp03-sensors-network.html",
"href": "gp/gp03-sensors-network.html",
"title": "Multi-output Gaussian Process (Sensor Network)",
"section": "",
"text": "import numpy as np\nimport matplotlib.pyplot as plt\nimport os\nimport pandas as pd\nimport mogptk\nimport torch\n\n\nplot_params = {'legend.fontsize': 18,\n 'figure.figsize': (15, 7),\n 'xtick.labelsize':'18',\n 'ytick.labelsize':'18',\n 'axes.titlesize':'24',\n 'axes.labelsize':'22'}\nplt.rcParams.update(plot_params)\n\n\nrng = np.random.default_rng(123)\n\nT = 500\nn_nodes = 5\n\nt = np.linspace(0, 10, T)\nt1_lost = np.linspace(4, 5, 100)\nX = np.zeros((T,n_nodes))\n\nX[:,0] = np.sin(t * (2 * np.pi)) + np.sin(t * (3 * np.pi))\nX[:,1] = np.sin((t-1) * (2 * np.pi)) + np.sin((t-1) * (3 * np.pi))\nX[:,2] = np.sin(t * (2 * np.pi)) + np.sin(t * (4 * np.pi))\nX[:,3] = np.sin((t-1) * (2 * np.pi)) + 0.5*np.sin((t-1) * (4 * np.pi))\nX[:,4] = 0.3*np.sin((t-1) * (2 * np.pi)) + 0.8*np.sin((t-1) * (8 * np.pi))\n\n\ntorch.manual_seed(1);\n\nT = 500\nn_nodes = 5\nt = np.linspace(0, 10, T)\nX = np.zeros((T, n_nodes))\nX[:, 0] = np.sin(t * (2 * np.pi)) + np.sin(t * (3 * np.pi))\nX[:, 1] = np.sin((t-1) * (2 * np.pi)) + np.sin((t-1) * (3 * np.pi))\nX[:, 2] = np.sin(t * (2 * np.pi)) + np.sin(t * (4 * np.pi))\nX[:, 3] = np.sin((t-1) * (2 * np.pi)) + 0.5*np.sin((t-1) * (4 * np.pi))\nX[:, 4] = 0.3*np.sin((t-1) * (2 * np.pi)) + 0.8*np.sin((t-1) * (8 * np.pi))\ncolumns = [f\"Node{i+1}\" for i in range(n_nodes)]\ndf_synth = pd.DataFrame(X, columns=columns)\ndf_synth['Time'] = t\ndf_synth = df_synth[['Time'] + columns]\ndataset = mogptk.LoadDataFrame(df_synth, x_col='Time', y_col=columns)\n\nfor channel in dataset:\n channel.remove_randomly(pct=0.4)\n\n# drop relative ranges to simulate sensor failure\ndataset[0].remove_relative_range(0.2, 0.3)\ndataset[1].remove_relative_range(0.8, 1.0)\ndataset[2].remove_relative_range(0.9, 1.0)\ndataset[3].remove_relative_range(0.8, 1.0)\ndataset[4].remove_relative_range(0.0, 0.2)\n\nchannels = []\nfor channel in dataset:\n channel.transform(mogptk.TransformDetrend(degree=1))\n channel.transform(mogptk.TransformStandard())\n channels.append(channel)\n\n# dataset.plot(transformed=True, figsize=(10,10));\nn_train = channels[0].get_train_data()[0].shape[0]\nn_test = channels[0].get_test_data()[0].shape[0]\nn_train+n_test\n\n500\n\n\n\noffset = 6.0\ny_offsets = np.arange(n_nodes) * offset\n\nfig, ax = plt.subplots(nrows=1, sharex=True, sharey=True)\nfor i in range(n_nodes):\n plt.plot(t, X[:,i] + y_offsets[i], alpha=0.4, color='r')\n\nax.set_yticks(y_offsets, [f\"node {i+1}\" for i in range(n_nodes)])\nax.spines['top'].set_visible(False)\nax.spines['right'].set_visible(False)\nax.invert_yaxis()\nax.set_xlim([0, 10])\nax.set_ylim([-5, 27])\nplt.xlabel(\"time\")\nplt.tight_layout()\n\nfig, ax = plt.subplots(nrows=1, sharex=True, sharey=True)\nfor i in range(n_nodes):\n plt.plot(t, X[:,i] + y_offsets[i], alpha=0.4, color='k')\n t_train, x_train = channels[i].get_train_data()\n plt.scatter(t_train, x_train + y_offsets[i], color='red')\n\nax.set_yticks(y_offsets, [f\"node {i+1}\" for i in range(n_nodes)])\nax.spines['top'].set_visible(False)\nax.spines['right'].set_visible(False)\nax.invert_yaxis()\nax.set_xlim([0, 10])\nax.set_ylim([-5, 27])\nplt.xlabel(\"time\")\nplt.tight_layout()\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nmodel = mogptk.MOSM(dataset, Q=3)\nmodel.init_parameters(method='BNSE')\n\nXt, Mu, Lower, Upper = model.predict()\n\nfig, ax = plt.subplots(nrows=1, sharex=True, sharey=True)\nfor i in range(n_nodes):\n plt.plot(Xt[i], Mu[i] + y_offsets[i], alpha=0.4, color='b')\n plt.fill_between( np.squeeze(Xt[i]), Lower[i] + y_offsets[i], Upper[i] + y_offsets[i], alpha=0.4, color='b' )\n plt.plot(t, X[:,i] + y_offsets[i], alpha=0.4, color='r')\n t_test, x_test = channels[i].get_test_data()\n plt.scatter(t_test, x_test + y_offsets[i], color='green')\n\nax.set_yticks(y_offsets, [f\"node {i+1}\" for i in range(n_nodes)])\nax.spines['top'].set_visible(False)\nax.spines['right'].set_visible(False)\nax.invert_yaxis()\nax.set_xlim([0, 10])\nax.set_ylim([-5, 27])\nplt.xlabel(\"time\")\nplt.tight_layout()\n\n\n\n\n\n\n\n\n\nmodel.train(method='Adam', lr=0.01, iters=1000, verbose=True);\n\nStarting optimization using Adam\n‣ Model: Exact\n ‣ Kernel: MultiOutputSpectralMixtureKernel\n ‣ Likelihood: GaussianLikelihood\n‣ Channels: 5\n‣ Parameters: 80\n‣ Training points: 1258\n‣ Iterations: 1000\n\n\n/Users/aveloz/miniconda3/lib/python3.9/site-packages/mogptk/model.py:384: UserWarning: Converting a tensor with requires_grad=True to a scalar may lead to unexpected behavior.\nConsider using tensor.detach() first. (Triggered internally at /Users/runner/work/pytorch/pytorch/pytorch/torch/csrc/autograd/generated/python_variable_methods.cpp:836.)\n return float(self.gpr.loss())\n\n\n 0/1000 0:00:00 loss= 1248.23 (warmup)\n 48/1000 0:00:10 loss= 1184.74\n 101/1000 0:00:20 loss= 1116.73\n 153/1000 0:00:30 loss= 1054.27\n 206/1000 0:00:40 loss= 988.854\n 258/1000 0:00:50 loss= 932.167\n 310/1000 0:01:00 loss= 862.731\n 360/1000 0:01:10 loss= 801.434\n 413/1000 0:01:20 loss= 738.048\n 465/1000 0:01:30 loss= 673.084\n 517/1000 0:01:40 loss= 615.362\n 566/1000 0:01:50 loss= 551.007\n 616/1000 0:02:00 loss= 487.771\n 667/1000 0:02:10 loss= 426.397\n 717/1000 0:02:20 loss= 363.946\n 764/1000 0:02:30 loss= 307.042\n 812/1000 0:02:40 loss= 271.866\n 863/1000 0:02:50 loss= 195.433\n 914/1000 0:03:00 loss= 142.252\n 965/1000 0:03:10 loss= 103.193\n 1000/1000 0:03:16 loss= 46.8325\nOptimization finished in 3 minutes 16 seconds\n\n\n\nXt, Mu, Lower, Upper = model.predict()\n\nfig, ax = plt.subplots(nrows=1, sharex=True, sharey=True)\nfor i in range(n_nodes):\n plt.plot(Xt[i], Mu[i] + y_offsets[i], alpha=0.4, color='b')\n plt.fill_between( np.squeeze(Xt[i]), Lower[i] + y_offsets[i], Upper[i] + y_offsets[i], alpha=0.4, color='b' )\n plt.plot(t, X[:,i] + y_offsets[i], alpha=0.4, color='r')\n t_test, x_test = channels[i].get_test_data()\n plt.scatter(t_test, x_test + y_offsets[i], color='green')\n\nax.set_yticks(y_offsets, [f\"node {i+1}\" for i in range(n_nodes)])\nax.spines['top'].set_visible(False)\nax.spines['right'].set_visible(False)\nax.invert_yaxis()\nax.set_xlim([0, 10])\nax.set_ylim([-5, 27])\nplt.xlabel(\"time\")\nplt.tight_layout()"
},
{
"objectID": "gp/gp02-example-noiseest-sklearn.html",
"href": "gp/gp02-example-noiseest-sklearn.html",
"title": "Ability of Gaussian process regression (GPR) to estimate data noise-level",
"section": "",
"text": "Taken from sklearn\nThis example shows the ability of the :class:~sklearn.gaussian_process.kernels.WhiteKernel to estimate the noise level in the data. Moreover, we show the importance of kernel hyperparameters initialization."
},
{
"objectID": "gp/gp02-example-noiseest-sklearn.html#data-generation",
"href": "gp/gp02-example-noiseest-sklearn.html#data-generation",
"title": "Ability of Gaussian process regression (GPR) to estimate data noise-level",
"section": "Data generation",
"text": "Data generation\nWe will work in a setting where X will contain a single feature. We create a function that will generate the target to be predicted. We will add an option to add some noise to the generated target.\n\nimport numpy as np\n\n\ndef target_generator(X, add_noise=False):\n target = 0.5 + np.sin(3 * X)\n if add_noise:\n rng = np.random.RandomState(1)\n target += rng.normal(0, 0.3, size=target.shape)\n return target.squeeze()\n\nLet’s have a look to the target generator where we will not add any noise to observe the signal that we would like to predict.\n\nX = np.linspace(0, 5, num=80).reshape(-1, 1)\ny = target_generator(X, add_noise=False)\n\n\nimport matplotlib.pyplot as plt\n\nplt.plot(X, y, label=\"Expected signal\")\nplt.legend()\nplt.xlabel(\"X\")\n_ = plt.ylabel(\"y\")\n\n\n\n\n\n\n\n\nThe target is transforming the input X using a sine function. Now, we will generate few noisy training samples. To illustrate the noise level, we will plot the true signal together with the noisy training samples.\n\nrng = np.random.RandomState(0)\nX_train = rng.uniform(0, 5, size=20).reshape(-1, 1)\ny_train = target_generator(X_train, add_noise=True)\n\n\nplt.plot(X, y, label=\"Expected signal\")\nplt.scatter(\n x=X_train[:, 0],\n y=y_train,\n color=\"black\",\n alpha=0.4,\n label=\"Observations\",\n)\nplt.legend()\nplt.xlabel(\"X\")\n_ = plt.ylabel(\"y\")"
},
{
"objectID": "gp/gp02-example-noiseest-sklearn.html#optimisation-of-kernel-hyperparameters-in-gpr",
"href": "gp/gp02-example-noiseest-sklearn.html#optimisation-of-kernel-hyperparameters-in-gpr",
"title": "Ability of Gaussian process regression (GPR) to estimate data noise-level",
"section": "Optimisation of kernel hyperparameters in GPR",
"text": "Optimisation of kernel hyperparameters in GPR\nNow, we will create a :class:~sklearn.gaussian_process.GaussianProcessRegressor using an additive kernel adding a :class:~sklearn.gaussian_process.kernels.RBF and :class:~sklearn.gaussian_process.kernels.WhiteKernel kernels. The :class:~sklearn.gaussian_process.kernels.WhiteKernel is a kernel that will able to estimate the amount of noise present in the data while the :class:~sklearn.gaussian_process.kernels.RBF will serve at fitting the non-linearity between the data and the target.\nHowever, we will show that the hyperparameter space contains several local minima. It will highlights the importance of initial hyperparameter values.\nWe will create a model using a kernel with a high noise level and a large length scale, which will explain all variations in the data by noise.\n\nfrom sklearn.gaussian_process import GaussianProcessRegressor\nfrom sklearn.gaussian_process.kernels import RBF, WhiteKernel\n\nkernel = 1.0 * RBF(length_scale=1e1, length_scale_bounds=(1e-2, 1e3)) + WhiteKernel(\n noise_level=1, noise_level_bounds=(1e-10, 1e1)\n)\ngpr = GaussianProcessRegressor(kernel=kernel, alpha=0.0)\ngpr.fit(X_train, y_train)\ny_mean, y_std = gpr.predict(X, return_std=True)\n\n/Users/aveloz/miniconda3/lib/python3.9/site-packages/sklearn/gaussian_process/kernels.py:452: ConvergenceWarning: The optimal value found for dimension 0 of parameter k1__k2__length_scale is close to the specified upper bound 1000.0. Increasing the bound and calling fit again may find a better value.\n warnings.warn(\n\n\n\nplt.plot(X, y, label=\"Expected signal\")\nplt.scatter(x=X_train[:, 0], y=y_train, color=\"black\", alpha=0.4, label=\"Observations\")\nplt.errorbar(X, y_mean, y_std, label=\"Posterior mean ± std\")\nplt.legend()\nplt.xlabel(\"X\")\nplt.ylabel(\"y\")\n_ = plt.title(\n (\n f\"Initial: {kernel}\\nOptimum: {gpr.kernel_}\\nLog-Marginal-Likelihood: \"\n f\"{gpr.log_marginal_likelihood(gpr.kernel_.theta)}\"\n ),\n fontsize=8,\n)\n\n\n\n\n\n\n\n\nWe see that the optimum kernel found still has a high noise level and an even larger length scale. The length scale reaches the maximum bound that we allowed for this parameter and we got a warning as a result.\nMore importantly, we observe that the model does not provide useful predictions: the mean prediction seems to be constant: it does not follow the expected noise-free signal.\nNow, we will initialize the :class:~sklearn.gaussian_process.kernels.RBF with a larger length_scale initial value and the :class:~sklearn.gaussian_process.kernels.WhiteKernel with a smaller initial noise level lower while keeping the parameter bounds unchanged.\n\nkernel = 1.0 * RBF(length_scale=1e-1, length_scale_bounds=(1e-2, 1e3)) + WhiteKernel(\n noise_level=1e-2, noise_level_bounds=(1e-10, 1e1)\n)\ngpr = GaussianProcessRegressor(kernel=kernel, alpha=0.0)\ngpr.fit(X_train, y_train)\ny_mean, y_std = gpr.predict(X, return_std=True)\n\n\nplt.plot(X, y, label=\"Expected signal\")\nplt.scatter(x=X_train[:, 0], y=y_train, color=\"black\", alpha=0.4, label=\"Observations\")\nplt.errorbar(X, y_mean, y_std, label=\"Posterior mean ± std\")\nplt.legend()\nplt.xlabel(\"X\")\nplt.ylabel(\"y\")\n_ = plt.title(\n (\n f\"Initial: {kernel}\\nOptimum: {gpr.kernel_}\\nLog-Marginal-Likelihood: \"\n f\"{gpr.log_marginal_likelihood(gpr.kernel_.theta)}\"\n ),\n fontsize=8,\n)\n\n\n\n\n\n\n\n\nFirst, we see that the model’s predictions are more precise than the previous model’s: this new model is able to estimate the noise-free functional relationship.\nLooking at the kernel hyperparameters, we see that the best combination found has a smaller noise level and shorter length scale than the first model.\nWe can inspect the negative Log-Marginal-Likelihood (LML) of :class:~sklearn.gaussian_process.GaussianProcessRegressor for different hyperparameters to get a sense of the local minima.\n\nfrom matplotlib.colors import LogNorm\n\nlength_scale = np.logspace(-2, 4, num=80)\nnoise_level = np.logspace(-2, 1, num=80)\nlength_scale_grid, noise_level_grid = np.meshgrid(length_scale, noise_level)\n\nlog_marginal_likelihood = [\n gpr.log_marginal_likelihood(theta=np.log([0.36, scale, noise]))\n for scale, noise in zip(length_scale_grid.ravel(), noise_level_grid.ravel())\n]\nlog_marginal_likelihood = np.reshape(log_marginal_likelihood, noise_level_grid.shape)\n\n\nvmin, vmax = (-log_marginal_likelihood).min(), 50\nlevel = np.around(np.logspace(np.log10(vmin), np.log10(vmax), num=20), decimals=1)\nplt.contour(\n length_scale_grid,\n noise_level_grid,\n -log_marginal_likelihood,\n levels=level,\n norm=LogNorm(vmin=vmin, vmax=vmax),\n)\nplt.colorbar()\nplt.xscale(\"log\")\nplt.yscale(\"log\")\nplt.xlabel(\"Length-scale\")\nplt.ylabel(\"Noise-level\")\nplt.title(\"Negative log-marginal-likelihood\")\nplt.show()\n\n\n\n\n\n\n\n\nWe see that there are two local minima that correspond to the combination of hyperparameters previously found. Depending on the initial values for the hyperparameters, the gradient-based optimization might or might not converge to the best model. It is thus important to repeat the optimization several times for different initializations. This can be done by setting the n_restarts_optimizer parameter of the :class:~sklearn.gaussian_process.GaussianProcessRegressor class.\nLet’s try again to fit our model with the bad initial values but this time with 10 random restarts.\n\nkernel = 1.0 * RBF(length_scale=1e1, length_scale_bounds=(1e-2, 1e3)) + WhiteKernel(\n noise_level=1, noise_level_bounds=(1e-10, 1e1)\n)\ngpr = GaussianProcessRegressor(\n kernel=kernel, alpha=0.0, n_restarts_optimizer=10, random_state=0\n)\ngpr.fit(X_train, y_train)\ny_mean, y_std = gpr.predict(X, return_std=True)\n\n\nplt.plot(X, y, label=\"Expected signal\")\nplt.scatter(x=X_train[:, 0], y=y_train, color=\"black\", alpha=0.4, label=\"Observations\")\nplt.errorbar(X, y_mean, y_std, label=\"Posterior mean ± std\")\nplt.legend()\nplt.xlabel(\"X\")\nplt.ylabel(\"y\")\n_ = plt.title(\n (\n f\"Initial: {kernel}\\nOptimum: {gpr.kernel_}\\nLog-Marginal-Likelihood: \"\n f\"{gpr.log_marginal_likelihood(gpr.kernel_.theta)}\"\n ),\n fontsize=8,\n)\n\n\n\n\n\n\n\n\nAs we hoped, random restarts allow the optimization to find the best set of hyperparameters despite the bad initial values."
},
{
"objectID": "gp/gp04-deep_GPs.html",
"href": "gp/gp04-deep_GPs.html",
"title": "Deep Gaussian Processes",
"section": "",
"text": "Open In Colab"
},
{
"objectID": "gp/gp04-deep_GPs.html#getting-started",
"href": "gp/gp04-deep_GPs.html#getting-started",
"title": "Deep Gaussian Processes",
"section": "1. Getting started",
"text": "1. Getting started\nMake sure that you have the appropriate packages installed, including PyDeepGP: you can review the Getting Started page for detailed instructions.\nFirst, we will setup the notebook with libraries we are going to use. As in previous labs, we will use GPy.\n\n# %pip install numpy==1.26.4\n%pip install \"numpy<1.24\"\n\nRequirement already satisfied: numpy<1.24 in /Users/aveloz/miniconda3/lib/python3.9/site-packages (1.23.5)\nNote: you may need to restart the kernel to use updated packages.\n\n\n\n# Install prerequisite packages\n# !pip install git+https://github.com/connorfuhrman/paramz@connorfuhrman/np_type_alias_dep\n# !pip install git+https://github.com/m-lyon/GPy \n# !pip install git+https://github.com/m-lyon/climin\n# !pip install git+https://github.com/SheffieldML/PyDeepGP\n\n# %pip install gpy\n\n\n# Support for maths\nimport numpy as np\n# Plotting tools\nfrom matplotlib import pyplot as plt\n# we use the following for plotting figures in jupyter\n%matplotlib inline\n\nimport warnings\nwarnings.filterwarnings('ignore')\n\n# GPy: Gaussian processes library\nimport GPy\n\n# PyDeepGP: Deep Gaussian processes\nimport deepgp\n\nWe will use data from the winners of the Olympic men’s marathon, highlight limitations with standard GPs and demonstrate how we can make use of deep GPs for such a problem.\n\nimport pickle\nimport requests\n\nreq = requests.get('https://github.com/gpschool/labs/raw/2023/.resources/olympic_marathon_men')\ndata = pickle.loads(req.content)\n\nX, y = data['X'], data['Y'] # X represents the year, and y are the average pace of the winner\n\n\n# Set up our plotting environment\nplt.figure(figsize=(14, 6))\n\n# Plot the training data, the results of the gold medal winning time for the Olympic men's marathon\nplt.plot(X, y, \"kx\", mew=2)\n\n# Annotate plot\nplt.legend(labels=[\"winning time\"]), plt.xlim((1890, 2018))\nplt.xlabel(\"year\"), plt.ylabel(\"pace (minutes per kilometer)\")\nplt.title(\"Olympic men's marathon gold medal winning times from 1896 to 2012\");\n\n\n\n\n\n\n\n\nBy now, you should be familiar with fitting a GP using GPy. We will fit a standard RBF kernel. Note that we are using a Gaussian likelihood, and have a constant mean for our GP (to be optimised).\n\nm_full = GPy.models.GPRegression(\n X, y,\n mean_function=GPy.mappings.Constant(1,1),\n kernel=GPy.kern.RBF(1)\n)\n\nm_full.optimize(messages=False)\ndisplay(m_full)\n\n\n\n\nModel: GP regression\nObjective: 4.785438859622699\nNumber of Parameters: 4\nNumber of Optimization Parameters: 4\nUpdates: True\n\n\n\n\n\n\nGP_regression.\nvalue\nconstraints\npriors\n\n\nconstmap.C\n3.5882415421063345\n\n\n\n\nrbf.variance\n0.2796060152640848\n+ve\n\n\n\nrbf.lengthscale\n20.797074162386387\n+ve\n\n\n\nGaussian_noise.variance\n0.04190680752643112\n+ve\n\n\n\n\n\n\nThis is utility code from previous labs, adapted slightly so that it will work with deep GPs as well\n\ndef plot_gp(model, X, training_points=False):\n \"\"\" Plotting utility to plot a GP fit with 95% confidence interval \"\"\"\n # Plot 95% confidence interval\n m, _ = model.predict(X)\n lci, uci = model.predict_quantiles(\n X,\n (2.5, 97.5)\n )\n plt.fill_between(X[:,0], lci[:,0], uci[:,0], alpha=0.5)\n\n # Plot GP mean and initial training points\n plt.plot(X, m, \"-\")\n plt.legend(labels=[\"GP fit\"])\n\n plt.xlabel(\"x\"), plt.ylabel(\"f\")\n\n # Plot training points if included\n if training_points:\n X_, Y_ = model.X, model.Y\n plt.plot(X_, Y_, \"kx\", mew=2)\n plt.legend(labels=[\"GP fit\", \"sample points\"])\n\nWe can see that plotting the GP, we struggle to handle the outlier, giving an suboptimial fit.\n\nXnew = np.arange(1890,2019)[:, None] # predict winning pace every year between 1890 and 2018\n\nplt.figure(figsize=(14,6))\n# Plot the GP prediction of the latent function with training points\nplot_gp(m_full, Xnew, training_points=True)\n# Annotate plot\nplt.xlabel(\"year\"), plt.ylabel(\"pace (minutes per kilometer)\")\nplt.title(\"Exact GP fit of latent function $f$ describing marathon pace in min/km, assuming a Gaussian likelihood\");"
},
{
"objectID": "gp/gp04-deep_GPs.html#deep-gp-regression",
"href": "gp/gp04-deep_GPs.html#deep-gp-regression",
"title": "Deep Gaussian Processes",
"section": "2. Deep GP Regression",