-
Notifications
You must be signed in to change notification settings - Fork 36
/
Copy pathDeepLearning-Introduccion-practica-con-Keras-PRIMERA-PARTE.txt
1543 lines (961 loc) · 199 KB
/
DeepLearning-Introduccion-practica-con-Keras-PRIMERA-PARTE.txt
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
Prologo
En 1953, Isaac Asimov publico Segunda Fundacion, el tercer libro de la saga de la Fundacion (o el decimotercero segun otras fuentes, este es un tema de debate). En Segunda Fundacion aparece por primera vez Arkady Darell, uno de los principales personajes de la parte final de la saga. En su primera escena, Arkady, que tiene 14 anos, esta haciendo sus tareas escolares. En concreto, una redaccion que lleva por titulo ?El Futuro del Plan Sheldon?. Para hacer la redaccion, Arkady esta utilizando un ?transcriptor?,un dispositivo que convierte su voz en palabras escritas. Este tipo de dispositivo, que para Isaac Asimov era ciencia ficcion en 1953, lo tenemos al alcance de la mano en la mayoria de nuestros smartphones, y el Deep Learning es uno de los responsables de que ya tengamos este tipo de aplicaciones, siendo la tecnologia otro de ellos.En la actualidad disponemos de GPUs (Graphics Processor Units), que solo cuestan alrededor de 100 euros, que estarian en la lista del Top500 hace unos pocos anos (compitiendo con maquinas que costaron millones de dolares). Las GPUs estaban pensadas para facilitar la programacion de videojuegos, pero una combinacion de pequenos cambios (shaders unificados, memoria compartida, instrucciones de acceso a memoria, Tensor Cores? quiza no sean tan pequenos!), y la aparicion de nuevas herramientas de programacion (CUDA, OpenCL, OpenACC), han facilitado el uso eficiente de GPUs en aplicaciones de proposito general, entre ellas Deep Learning. Ademas, teniendo en cuenta que cada ano se venden mas de 1?000 millones de smartphones (todos llevan una GPU), y que el negocio de los videojuegos es muy atractivo, tenemos garantizado que la mejora tecnologica de las GPUs va a continuar durante mucho tiempo.
Conozco a Jordi desde hace mas de 30 anos; siempre ha estado muy preocupado por los ultimos avances tecnologicos, no solo en nuestra area de conocimiento (Arquitectura y Tecnologia de Computadores), sino en temas mas amplios que podriamos englobar en lo que se conoce en el mundo anglosajon como Computer Science. Jordi esta pensando en la investigacion, pero tambien en transferir esos conocimientos a nuestros estudiantes (este, y no otro, es el fin ultimo de la investigacion en la universidad). Teniendo en cuenta esto, no es de extranar que se haya embarcado en publicar una serie de libros dedicados a Deep Learning. Estas herramientas estan cambiando la forma de encarar los problemas de computacion y estan abriendo el espectro de que cosas puede hacer un computador.
Y que nos depara el futuro? Para estar mejor informados, podemos empezar leyendo este libro, pero en los proximos anos vamos a tener una serie de aplicaciones revolucionarias muy relacionados con Deep Learning: coches autonomos, tratamiento de lenguaje natural, traduccion automatica?
Quien lo va a tener dificil seran los escritores de ciencia ficcion, a quienes se les complica el imaginar nuevos dispositivos que no hayan sido ya disenados por ingenieros actuales.
Agustin Fernandez
Vicerrector de Transformacion Digital
de la Universitat PolitŠcnica de Catalunya (UPC)
Prefacio: la pasion de ensenar
Education is the most powerful weapon which you can use to change the world.
Nelson Mandela
Una actividad que realmente me estimula en estos momentos es contribuir a ser una chispa que despierte las mentes, por asi decirlo, con el fin de estar preparados para los cambios que se nos avecinan en nuestra sociedad a raiz del impacto de tecnologias como la inteligencia artificial en general y Deep Learning en particular.
Siempre me ha interesado la tecnologia de proxima generacion y su impacto, y por ello desde hace un tiempo ha captado mi interes la inteligencia artificial y su relacion con tecnologias como Cloud Computing, Big Data o la supercomputacion (high performance computing), areas en las que llevo investigando e impartiendo docencia desde hace 30 anos.
Sin duda, los avances tecnologicos en inteligencia artificial, junto con el resto de tecnologias mencionadas, ya estan aqui; eso nos permite construir una sociedad que mejora la vida de las personas, aunque tambien es cierto que la perspectiva del futuro cercano de estas tecnologias presenta alguna que otra incertidumbre.
Sin embargo, estoy convencido de que podemos conseguir, a medida que nos vayamos encontrando con nuevos problemas debido a estas nuevas tecnologias, encontrar como sociedad sus soluciones. Para ello, es clave que todos y cada uno de los que ya trabajamos en el mundo tecnologico consigamos una mejor comprension de estos nuevos temas que estan revolucionando la informatica y podamos darle el uso correcto, ademas de saber explicarlos.
Esta obra es la primera parte del libro Deep Learning - Introduccion practica con Keras que estoy escribiendo durante el tiempo libre que me deja mi actividad academica y de investigacion. Mi ilusion era poder terminar la obra entera antes de verano, pero debo ser realista y aceptar que no podra ser asi, y sin duda necesitare muchisimas mas horas (meses :) ) para poder terminarla.
Pero como ya esta finalizada la primera mitad del libro, siendo esta la parte mas basica del tema (la que yo llamo Hello world!) y la estoy usando para dar soporte a mis clases en la Facultat d Inform…tica de Barcelona de la Universitat Politecnica de Catalunya Barcelona Tech (UPC), he decidido avanzar su publicacion de forma abierta en mi pagina web personal www.JordiTorres.Barcelona/DeepLearning para ofrecer a la comunidad interesada un primer contacto con esta tecnologia y permitirle iniciarse por su cuenta en la programacion de Deep Learning sin tener que esperar a tener la obra completa. Si el lector prefiere acceder a este contenido en formato ebook o papel, puede obtenerlo en sus portales de compra.
Como reza el titulo, este libro que estoy preparando solo pretende ser una introduccion practica a Deep Learning, una de las areas mas activas actualmente en el ambito de la inteligencia artificial, no un tratado exhaustivo sobre el tema, pues esta dirigido a un lector que dispone de conocimientos en programacion pero que aun no ha tenido la oportunidad de iniciarse a estos nuevos conceptos claves en la informatica, y quiere descubrir algunos de los aspectos mas de vanguardia de esta tecnologia.
Ya les avanzo que el libro sera una invitacion a usar el teclado de su ordenador mientras va aprendiendo: nosotros lo llamamos learn by doing, y mi experiencia como profesor en la UPC me indica que es una aproximacion que funciona muy bien entre ingenieros e ingenieras que tratan de iniciarse en un nuevo tema.
Por esta razon, el libro tendra un caracter eminentemente practico, y por ello se reducira todo lo posible la parte teorico-matematica, aunque es estrictamente necesario recurrir a ciertos detalles teoricos para ofrecer un conocimiento solido al lector. Esto conlleva que en sus paginas se iran intercalando conocimientos teoricos y practicos, complementarios en el proceso de aprendizaje.
Espero con ello aportar mi granito de arena en este mundo de la formacion que tanto me apasiona; deseo tambien que sirva de guia a cualquier navegante interesado en empezar su aventura en este campo tan interesante.
Dejenme decirles: gracias por estar leyendo este libro! El simple hecho me reconforta y justifica mi esfuerzo en escribirlo. Aquellos que me conocen saben que la docencia (y la formacion en general) es una de mis pasiones, y me mantiene con vigor y energia. Como me recuerda a veces mi querida madre, cuando era pequeno decia que de mayor queria ensenar, ser maestro. Pues aqui me tienen, Sueno cumplido!
Jordi Torres i Vinals, a 27 de mayo de 2018.
Si el lector o lectora requiere contactar con el autor en relacion al contenido de este libro o quiere hacerle llegar sus comentarios puede hacerlo a traves del correo electronico [email protected]
Acerca de este libro
En este libro el lector encontrara una guia para adentrarse de manera practica a Deep Learning con la ayuda de la libreria Keras, la cual aprendera a usar con el objetivo de desarrollar y evaluar modelos Deep Learning. Aunque Deep Learning se sustenta en fascinantes matematicas, estas no son estrictamente necesarias para poder iniciarse, ni siquiera para crear proyectos que generen valor a la empresa gracias a librerias Python como Keras.
Por ello, este libro se centrara en temas practicos y concretos para descubrir al lector el apasionante mundo que se abre con el uso de Deep Learning, teniendo siempre en mente que solo podremos examinar una pequena parte, pues es imposible mostrar su alcance total en un unico libro; tan solo mantenerse al dia de las ultimas investigaciones, tecnologias o herramientas que van apareciendo es casi mision imposible, o como diria un amigo ingles, ?like drinking from a fire hose?, como beber de una manguera contra incendios.
A quien va dirigido el libro
Esta es una obra introductoria, ideada inicialmente para dar soporte a mi docencia en la UPC a alumnos y alumnas de ingenieria informatica pero con pocos o ningun conocimiento de Machine Learning. Pero a su vez, este libro puede ser tambien util a ingenieros e ingenieras que ya dejaron las aulas y se encuentran trabajando pero requieren, o simplemente les apetece, aprender sobre este tema.
Por ello el libro esta escrito en forma de ?distancia corta?, por asi decirlo, con el lector, como si estuvieramos en una de mis clases en la UPC. Para facilitarlo, introducire los conocimientos y conceptos en forma lineal, intentando involucrar al lector al requerirle que este en todo momento con el teclado delante y probando lo que le voy contando.
No obstante, esta no es una obra para todo el mundo, y es importante que el lector calibre bien sus expectativas; aqui no va a encontrarse explicaciones sobre la teoria fundamental de redes neuronales artificiales, ni se ofrecen detalles de como funcionan internamente los algoritmos relacionados con el tema. Por tanto, no es recomendable a quienes ya esten programando redes neuronales en algun otro entorno que no sea Keras, y si fuese esta libreria su campo de interes, quiza este es un camino demasiado largo para conocerla.
Organizacion del libro
El libro se organiza en capitulos que deben ser leidos en orden, ya que van guiando al lector y lo introducen gradualmente a los conocimientos imprescindibles para seguir los ejemplos practicos, intentando ir al grano y ser lo mas conciso posible. Al ser un libro introductorio, considero que es mucho mas util este enfoque que no uno mas formal. A pesar de todo, he intentado que el indice del libro exprese un mapa razonablemente ordenado de los principales conceptos del area.
El borrador del libro completo esta compuesto en estos momentos por ocho capitulos que mezclan el contenido teorico y practico, creando un viaje donde se repasan conceptos de las tres familias de arquitecturas de redes neuronales con las que el lector acabara estando familiarizado: redes neuronales densamente conectadas (densely connected networks), redes neuronales convolucionales (convolutional neural networks) y, finalmente, redes neuronales recurrentes (recurrent neural networks).
Para ser una herramienta de soporte adaptada a mi docencia, la organizacion del libro esta concebida para intentar equilibrar la carga de trabajo que se requiere para aprender los conceptos teoricos y practicos que se proponen en cada capitulo. En alguno de ellos se dedica mas tiempo a ?teoria? y en algun otro a ?practica?, pero la idea es que en global queden compensados.
El libro contiene claramente dos partes: una mas basica, que sigue la formula del libro que escribi sobre TensorFlow, Hello World en TensorFlow, en enero del 2016 y que tuvo gran aceptacion. Por tanto, he decidido seguir parcialmente su planteamiento. Esta es la parte que encontraran en este avance de publicacion de la primera mitad del libro.
Antes de empezar con el primer capitulo me he permitido introducir como empece a investigar en este tema y el porque considero que el desencadenante principal de esta resurreccion de la inteligencia artificial se debe a la supercomputacion.
El primer capitulo contiene una motivacion al tema y las instrucciones para preparar el entorno de trabajo para poder seguir los detalles de codigo que se iran presentando a continuacion.
En el segundo capitulo, a partir de un caso de estudio, se explican los conceptos basicos de una red neuronal. Luego introducimos las redes neuronales densamente conectadas y mostramos su implementacion con Keras.
En el tercer capitulo presentamos como se realiza el proceso de aprendizaje de una red neuronal, adentrandonos en algunos de sus componentes mas importantes. La segunda parte del capitulo invita al lector a que practique los conocimientos adquiridos con TensorFlow playground.
En el capitulo cuarto, ya preparado el lector con una base importante de como son las redes neuronales, presentamos e implementamos las redes neuronales convolucionales, una de las familias de redes neuronales mas populares en estos momentos.
La segunda parte del libro abarca una introduccion a todos los conceptos que actualmente se tratan en Deep Learning para que el lector al acabar el libro completo tenga una vision general del tema y pueda empezar por su cuenta a profundizar en aquellos aspectos que crea que le aportan mas valor. Espero que esta parte de la obra pueda ver la luz en pocos meses. Por favor, crucen los dedos conmigo!.
En estos momentos, el borrador del quinto capitulo describe como se pueden obtener los datos y como se preprocesan, con especial atencion en el caso de ser texto cuando se quiere entrenar una red neuronal. A continuacion analizamos desde un punto de vista absolutamente practico como puede ser la prevencion del sobreajuste (overfitting) de los modelos a los datos.
El capitulo sexto lo centraremos en uno de los problemas mas habituales en Deep Learning en el mundo real, como es el no tener suficientes datos para entrenar nuestras redes. Se explicaran varias tecnicas frecuentemente utilizadas en estos momentos en proyectos reales (transfer learning, data augmentation, etc.).
En el septimo capitulo se introducen las redes neuronales recurrentes, que a pesar de tener requerimientos de computacion importantes se estan popularizando mucho en la industria.
Y, finalmente, en el capitulo octavo vamos a presentar la API funcional de Keras que permite implementar arquitecturas mas complejas, e introducimos algunas de las que actualmente gozan de gran populariodad, como las GAN entre otras.
El libro acaba con una clausura donde me permitire hacer unas reflexiones sobre el tema y su impacto. En esta edicion de la primera parte del libro he incluido una version preliminar de esta clausura.
Este libro va acompanado de un repositorio de codigo en el GitHub donde el lector puede encontrar los ejemplos presentados en el mismo. Muchos de los ejemplos usados estan inspirados en los que Fran‡ois Chollet ha compartido en el GitHub de su ultimo libro, Deep Learning with Python1. Gracias, Fran‡ois!
Requisitos para seguir el libro
Como hemos mencionado con frecuencia, esta obra pretende ser una introduccion; por ello, no es necesario que el lector sea un experto en Python, solo ha de tener, evidentemente, conocimientos de programacion e interes en aprender por su cuenta detalles del lenguaje cuando no los entienda.
Tampoco se necesita ser un experto en Machine Learning, pero esta claro que puede ser muy util conocer unos primeros conceptos sobre el tema. Solo se suponen los conocimientos basicos en matematicas de cualquier estudiante (de bachillerato de la rama cientifico-tecnica). A partir de ellos, a lo largo de los capitulos se repasan muy brevemente los conceptos mas importantes de Machine Learning que se puedan requerir.
Asumimos que el lector, antes de empezar a leer, tiene instalado Python y el paquete de Keras en su ordenador, portatil o su instancia de maquina virtual en Cloud. Es importante remarcar que todos los codigos que se proponen al lector en esta primera parte del libro para que los pruebe en su ordenador pueden ser ejecutados en una plataforma que solo tenga CPU; no es un requisito tener una GPU2. Pero si que es cierto que en la version final del libro se propondran codigos que requieren entrenamientos de redes que en plataformas con solo CPU pueden tardar horas. En este caso, y si el lector le apetece, les propondremos que cancelen el proceso de calculo de aprendizaje de los parametros y sigan las instrucciones para descargar los resultados (de una version ya entrenada) de una ejecucion que hemos realizado nosotros con la ayuda de una GPU y que contendra los mismos valores que el lector llegaria a conseguir en su ordenador.
Pero lo mas importante, en cuanto a prerrequisitos, es tener interes por aprender!
Por que Keras?
Keras3 es la libreria recomendada para beginners, puesto que su curva de aprendizaje es muy suave en comparacion con otras, a la vez que es, sin duda, una de las herramientas para implementar redes neuronales de mayor popularidad en el momento despues de TensorFlow.
Keras es una libreria de Python que proporciona, de una manera sencilla, la creacion de una gran gama de modelos deÿDeep Learning usando como backend otras librerias como TensorFlow, Theano o CNTK. Fue desarrollado y es mantenido porÿFran‡ois Chollet4, ingeniero de Google, y su codigo ha sido liberado bajo la licencia permisiva del MIT.
Personalmente, valoro la austeridad y simplicidad que presenta este modelo de programacion, sin adornos y maximizando la legibilidad; permite expresar redes neuronales de una manera muy modular, considerando un modelo como una secuencia (o un grafo si se trata de modelos mas avanzados que trataremos en el capitulo 8). Por ultimo, pero no menos importante, creo que es un gran acierto haberse decantado por usar el lenguaje de programacion Python; por todo ello, he considerado usar Keras en este libro.
Keras en estos momentos se encuentra incluido en Tensorflow, pero ademas se puede usar como una libreria de Python. Para iniciarse en el tema considero que esta segunda opcion es la mas adecuada y para ello mi propuesta sera usar Jupyter5, puesto que es un entorno de desarrollo muy extendido y muy facil de usar. Mas adelante presentaremos como poder poner a punto nuestro entorno de trabajo.
Introduccion: la supercomputacion, corazon de Deep Learning
Seguramente, a estas alturas algunos lectores ya se han planteado la pregunta: por que un investigador en supercomputacion se ha puesto a investigar Deep Learning?
En realidad, hace anos que empece a interesarme por como la supercomputacion podia contribuir a mejorar los metodos de Machine Learning; entonces, en 2006, empece a codirigir tesis doctorales con un gran amigo y catedratico del departamento de Computer Science de la UPC, Ricard Gavald…6 , experto en Machine Learning y Data Mining.
Pero no fue hasta el septiembre del 2013, momento en el que ya disponia de una base relativamente solida de conocimiento sobre Machine Learning, que empece a centrar mi interes en Deep Learning, cuando, gracias al investigador de nuestro departamento Computer Architecture de la UPC Jordi Nin7, cayo en mis manos el articulo Building High-level Features Using Large Scale Unsupervised Learning8, escrito por investigadores de Google. En este articulo presentado en el congreso International Conference in Machine Learning del ano anterior, los autores explicaban como entrenaron un modelo Deep Learning en un cluster de 1?000 maquinas con 16?000 cores. Me alegre muchisimo de ver como la supercomputacion permitia acelerar este tipo de aplicaciones, como escribi en mi blog9 unos meses mas tarde, justificando las razones que llevaron al grupo a anadir este foco en su roadmap de investigacion.
Gracias a la ley de Moore10, en el ano 2012, cuando estos investigadores de Google escribieron este articulo, disponiamos de supercomputadores que permitian resolver problemas que hubieran sido intratables unos pocos anos antes debido a la capacidad de computacion. Por ejemplo, el computador al que yo tenia acceso en el ano 1982, donde ejecute mi primer programa con tarjetas perforadas, era un Fujitsu que permitia ejecutar algo mas de un millon de operaciones por segundo. 30 anos despues, en el 2012, el supercomputador Marenostrum que teniamos por aquel entonces en el Barcelona Supercomputer Center?Centro Nacional de Supercomputacion11 (BSC), era solo 1?000?000?000 veces mas rapido que el ordenador en el que yo empece.
Con la actualizacion de aquel ano, el supercomputador MareNostrum presentaba un rendimiento maximo teorico de 1,1 Petaflops (1?100?000?000?000?000 operaciones de coma flotante por segundo12). Lo conseguia con 3?056 servidores con un total de 48?896 cores y 115?000 Gibabytes de memoria principal total albergados en 36 racks. Por aquel entonces el supercomputador Marenostrum estaba considerado como uno de los mas rapidos del mundo, concretamente en la posicion trigesimosexta, en la lista TOP50013, que se actualiza cada medio ano y ordena los 500 supercomputadores mas potentes del mundo. Adjunta pueden ver una fotografia donde se observan los racks de computacion del Marenostrum que se albergaban en la capilla de Torres Girona del campus nord de la UPC en Barcelona14.
La primera GPU en la competicion Imagenet
Fue entonces cuando empece a tomar conciencia de la aplicabilidad de la supercomputacion a esta nueva area de investigacion; al empezar a buscar articulos de investigacion sobre el tema, descubri la existencia de la competicion de Imagenet y de los resultados del equipo de la universidad de Toronto en la competicion el ano 201215. La competicion ImageNet (Large Scale Visual Recognition Challenge16) se realizaba desde el 2010, y por aquel entonces se habia convertido en un referente en la comunidad de vision por computador para el reconocimiento de objetos a gran escala. En 2012 Alex Krizhevsky, Ilya Sutskever y Geoffrey E. Hilton emplearon por primera vez aceleradores hardware GPU (graphical processing units)17, usados ya en ese momento en los centros de supercomputacion como el nuestro en Barcelona para aumentar la velocidad de ejecucion de aplicaciones que requieren realizar muchos calculos.
Por ejemplo, en aquella epoca el BSC disponia ya de un supercomputador llamado MinoTauro, de 128 nodos Bull505, equipados con 2 procesadores Intel y 2 GPUs Tesla M2090 de NVIDIA cada uno de ellos. Con un rendimiento pico de 186 Teraflops18, puesto en marcha en septiembre del ano 2011 (como curiosidad, en aquel entonces fue considerado como el supercomputador con mayor eficiencia energetica de Europa segun la lista Green50019).
Hasta el 2012, el incremento de capacidad de computacion que cada ano conseguiamos de los ordenadores era gracias a la mejora de la CPU. Sin embargo, desde entonces el incremento de capacidad de computacion para Deep Learning no ha sido solo gracias a ellas, sino tambien a los nuevos sistemas masivamente paralelos basados en aceleradores GPU, que resultan decenas de veces mas eficientes que las CPU tradicionales.
Las GPU se desarrollaron originalmente para acelerar el juego 3D que requiere el uso repetido de procesos matematicos que incluyen distintos calculos sobre matrices. Inicialmente, companias como NVIDIA y AMD desarrollaron estos chips rapidos y masivamente paralelos para tarjetas graficas dedicadas a videojuegos: pronto se vio que las GPU utiles para juegos 3D. Eran muy adecuadas tambien para acelerar calculos sobre matrices numericas; por ello, este hardware en realidad beneficio a la comunidad cientifica, y en el 2007 NVIDIA lanzo el lenguaje de programacion CUDA20 para poder programar sus GPU. Gracias a ello, centros de investigacion en supercomputacion como el BSC empezaron a usar clusters de GPU para acelerar aplicaciones numericas.
Pero como veremos en este libro, las redes neuronales artificiales basicamente realizan operaciones matriciales que son tambien altamente paralelizables. Y esto es lo que hizo en 2012 el equipo de Alex Krizhevsky: entreno su algoritmo Deep Learning AlexNet con GPU. Desde entonces se empezaron a usar las GPU para esta competicion, y en estos momentos todos los grupos que investigan en Deep Learning estan usando este hardware o alternativas equivalentes que han aparecido recientemente.
Crecimiento exponencial de la capacidad de computacion como motor del Deep Learning
Ya he dicho que el hito del equipo de Krizhevsky fue un punto de inflexion importante en el campo de Deep Learning, y desde entonces se han ido sucediendo resultados espectaculares, uno tras otro, con un crecimiento exponencial de resultados cada vez mas sorprendentes.
Pero yo creo que la investigacion en este campo ha estado guiada en gran parte por los hallazgos experimentales mas que por la teoria, en el sentido de que estos avances espectaculares en el area a partir del 2012 solo han sido posibles gracias a que la computacion que se requeria para poderlos llevar a cabo estaba disponible; de esta manera, los investigadores de este campo han podido poner a prueba y ampliar viejas ideas, a la vez que han avanzado con nuevas que requerian muchos recursos de computacion.
Recientemente OpenAI21 ha publicado en su blog un estudio22 que corrobora precisamente esta vision que estoy defendiendo. Concretamente, presentan un analisis en el que se confirma que, desde 2012, la cantidad de computacion disponible para generar modelos de inteligencia artificial ha aumentado exponencialmente a la vez que afirman que las mejoras en la capacidad de calculo han sido un componente clave del progreso de la inteligencia artificial.
En este mismo articulo presentan una grafica23 impresionante para sintetizar los resultados de su analisis:
La grafica muestra la cantidad total de calculos, en Petaflop por dia, que se han utilizado para entrenar redes neuronales que, como comentaremos mas adelante, tienen nombre propio y son referentes en la comunidad de Deep Learning. Recordemos que un ?petaflop / s-day?, el eje vertical del grafico que esta en escala logaritmica, equivale a realizar 1?000?000?000?000?000 operaciones de redes neuronales por segundo durante un dia (s-day), o un total de aproximadamente 100?000?000?000?000?000?000 operaciones, independientemente de la precision numerica (lo que hace que "FLOP" sea un termino quizas impreciso en este articulo, a mi entender).
Aceleracion de Deep Learning con sistemas paralelos
Las tareas de entrenar redes Deep Learning requieren una gran cantidad de computacion y, a menudo, tambien necesitan el mismo tipo de operaciones matriciales que las aplicaciones intensivas en calculo numerico, lo que las hace similares a las aplicaciones tradicionales de supercomputacion. Por lo tanto, las aplicaciones Deep Learning funcionan muy bien en sistemas de computacion que usan aceleradores como GPU o field-programmable gate arrays (FPGA), que se han utilizado en el campo HPC durante mas de una decada dentro de los muros de los centros de supercomputacion. Esos dispositivos se enfocan en el rendimiento computacional al especializar su arquitectura en utilizar el alto paralelismo de datos en las cargas de trabajo HPC. Y precisamente estas tecnicas se pueden usar tambien para acelerar los algoritmos de aprendizaje automatico de Deep Learning.
Por ello, a partir del 2012 y hasta el 2014, los investigadores en Deep Learning empezaron a usar sistemas con GPU. La ventaja, ademas, es que estos algoritmos de aprendizaje escalaban perfectamente cuando podiamos poner mas de una GPU en un nodo. La siguiente grafica, extraida de uno de nuestros articulos de investigacion24, muestra como aumentando el numero de GPU se puede acelerar el proceso de aprendizaje:
Aceleracion de Deep Learning con sistemas distribuidos
La gran capacidad de computacional disponible permitio a la comunidad Deep Learning avanzar y poder disenar redes neuronales cada vez mas y mas complejas, volviendo a requerir mas capacidad de computacion que la que podia ofrecer un servidor con multiples GPU. Por ello a partir del 2014 para acelerar aun mas el calculo requerido, este se empezo a distribuir entre multiples maquinas con varias GPU conectadas por una red. Esa solucion habia sido, nuevamente, adoptada y muy conocida anteriormente en la comunidad de investigadores en supercomputacion, especificamente en la interconexion de maquinas mediante redes opticas con baja latencia, que permitian hacer esto de manera muy eficiente.
En la siguiente grafica se muestra como se puede acelerar el mismo algoritmo anterior con varias maquinas que cada una tiene 4 GPU25:
Tambien librerias del estandar de pasos de mensaje como Message Passing Interface (MPI26), usadas en la comunidad cientifica de supercomputacion desde hace decenios, se estan ahora usando en Deep Learning distribuido.
Aceleracion del Deep Learning con hardware especializado
Pero a partir de 2016, ademas de todas las anteriores innovaciones en supercomputacion, empezaron a aparecer chips de procesado especialmente pensados para algoritmos Deep Learning. Por ejemplo, en 2016 Google anuncio que habia construido un procesador dedicado llamado Tensor Processing Unit (TPU)27. Desde entonces Google ya ha desarrollado 3 versiones de TPU, la ultima presentada en su conferencia IO28, donde afirmaron que es 8 veces mas potentes que la version anterior. Ademas, ahora ya no solo la arquitectura es especifica para entrenar redes neuronales, sino tambien para la etapa de inferencia.
En la siguiente grafica obtenida del blog de Google Cloud29 podemos ver una comparativa de predicciones por segundo que se obtienen en una escala logaritmica para los tres diferentes tipos de arquitectura.
La aceleracion de Deep Learning con hardware especializado no ha hecho mas que empezar tanto para la etapa de entrenamiento como la etapa de inferencia si tenemos en cuenta que estan apareciendo numerosas empresas que estan disenando y empezando a producir chips especificos para inteligencia artificial30. Veremos grandes avances en breve, estoy seguro.
Una nueva generacion de supercomputadores disenados para Deep Learning e Inteligencia Artificial
Y ahora estamos ante la convergencia de las tecnologias de inteligencia artificial y la supercomputacion que pronto formara parte de la oferta que ofreceran las empresas proveedoras de sistemas informaticos al mundo industrial y empresarial.
Un ejemplo de lo que estara dentro de un tiempo en el mercado es una parte del actual supercomputador Marenostrum del Barcelona Supercomputing Center (BSC). MareNostrum es el nombre generico que utiliza el BSC para referirse a las diferentes actualizaciones de su supercomputador mas emblematico y el mas potente de Espana, y hasta hoy se han instalado cuatro versiones desde 200431. En estos momentos el Marenustrum es el supercomputador mas heterogeneo del mundo, con todo tipo de hardware experimental disponible en el mercado, puesto que su proposito es que sirva de plataforma de experimentacion para disenar futuros supercomputadores.
Esto se concreta en que la capacidad de calculo del MareNostrum 4 actual esta repartida en dos partes totalmente diferenciadas: un bloque de proposito general y un bloque de tecnologias emergentes. El bloque de tecnologias emergentes esta formado por clusteres de tres tecnologias diferentes que se iran incorporando y actualizando a medida que esten disponibles. Se trata de tecnologias que actualmente se estan desarrollando en Estados Unidos y Japon para acelerar la llegada de la nueva generacion de supercomputadores pre-exascala.
Una de ellas esta basada en el sistema IBM disenado especialmente para aplicaciones Deep Learning e inteligencia artificial32; IBM ha creado todo el stack de software necesario para ello. En el momento de escribir este libro ya se dispone del hardware y en breve se instalara33 el paquete de software PowerAI34, que convertira este hardware de supercomputacion en una maquina especialmente destinada a la inteligencia artficial. A traves de este software estaran disponibles para los investigadores de redes neuronales los principales frameworks de Deep Learning como TensorFlow (y Keras, incluido en el paquete de Tensorflow), Caffe, Chainer, Torch y Theano.
En cuanto al hardware, esta parte del Marenostrum consta de dos nodos de acceso y un cluster de 52 nodos basado en IBM Power 9 y NVIDIA V100 con sistema operativo Linux y interconectados por una red infiniband a 100 Gigabits por segundo. Cada nodo esta equipado con 2 procesadores IBM POWER9 que disponen de 20 cores fisicos cada uno y con 512GB de memoria. Cada uno de estos procesadores POWER9 estan conectados a dos GPU NVIDIA V100 (Volta) con 16GB de memoria, en total 4 GPU por nodo.
Las nuevas GPU NVIDIA V100 son las GPU mas avanzada hasta el momento35 para acelerar aplicaciones de inteligencia artificial que equivalen a 100 CPUs segun NVIDIA36. Esto lo consiguen emparejando sus CUDA cores con 640 tensor core, que no tenian la familia anterior de GPU Pascal. Los tensor core estan especificamente disenados para multiplicar dos matrices de 4?4 elementos en formato de coma flotante y permite tambien la acumulacion de una tercera matriz, pudiendo asi ejecutar de manera muy rapida las operaciones basicas de redes neuronales tanto en la fase de inferencia como de la de entrenamiento.
Ademas, esta nueva version de GPU actualiza el bus con el sistema NVLINK 2.037 que permite un alto ancho de banda con seis links que pueden llegar a trasferir 50GBytes por segundo. Aunque tradicionalmente el bus NVLINK estaba originalmente pensado para conectar las GPUs, esta version permite conectar tambien GPU y CPU. Otro elemento importante es el acceso a la memoria, que ha mejorado respecto a las versiones anteriores y permite anchos de banda de hasta 900 GigaBytes por segundo.
Les describo todo este detalle para que no les sorprenda que con solo 3 racks del Marenostrum actual (los de que se ven en la fotografia) se disponga de 1,5 Petaflops de rendimiento maximo teorico, mucho mas que los 1,1 Petaflops que tenia en el 2012 el Marenostrum 3 en 36 racks (foto anterior).
En resumen, no queria darles una clase de arquitectura de computadores, pero si explicar con ejemplos reales y cercanos a nosotros que la capacidad de computacion esta evolucionado de forma exponencial y ha permitido, como decia antes, probar nuevas ideas o ampliar las viejas, pues muchos de los avances en el area de Deep Learning des del 2012 ha estado guiados por los hallazgos experimentales con estos supercomputadores.
Sin embargo, sin ninguna duda otros factores han contribuido a desencadenar el resurgimiento de la inteligencia artificial, es cierto que no se debe solo a la supercomputacion. A todos nos viene a la cabeza el fenomeno del Big Data. Pero hay otros que quizas al lector no le sea tan familiar; en el siguiente capitulo presentaremos algunos de ellos.
PRIMERA PARTE: Hello World!
1 Ante una nueva tecnologia disruptiva
Se esta considerando la inteligencia artificial como la nueva revolucion industrial, corazon de lo que algunos llaman industria 4.0. Pues bien, Deep Learning es el motor de este proceso y en los siguientes capitulos hablaremos extensamente de ello. Pero en este vamos primero a situar el tema, ver porque la inteligencia artificial esta ya aqui y por que ha venido para quedarse.
1.1 La inteligencia artificial esta cambiando nuestras vidas
Nos encontramos ante vertiginosos avances en la calidad y prestaciones de una amplia gama de tecnologias cotidianas: en el caso del reconocimiento de voz, la transcripcion de voz a texto ha experimentado avances increibles, y ya esta disponible en diferentes dispositivos. Estamos interactuando cada vez mas con nuestros ordenadores (y todo tipo de dispositivo) simplemente hablando con ellos.
Tambien ha habido avances espectaculares en el procesamiento del lenguaje natural. Por ejemplo, simplemente haciendo clic en el simbolo de micro de Google Translate, el sistema transcribira a otro idioma lo que esta dictando. Google Translate ya permite convertir oraciones de una lengua a otra en 32 pares de idiomas, y ofrece traduccion de texto para mas de 100.
A su vez, los avances en la vision por computador tambien son enormes: ahora nuestros ordenadores, por ejemplo, pueden reconocer imagenes y generar descripciones textuales de su contenido en segundos.
Estas tres areas son cruciales para dar rienda suelta a las mejoras en robotica, drones o automoviles sin conductor, estando la inteligencia artificial en el corazon de toda esta innovacion tecnologica, que ultimamente avanza tan rapidamente gracias a Deep Learning.
Y todo ello a pesar de que la inteligencia artificial todavia no se ha desplegado ampliamente y es dificil hacerse una idea del gran impacto que tendra, al igual que en 1995 lo era el imaginarse el impacto futuro de internet. En aquel entonces, la mayoria de la gente no veia como internet era relevante para ellos y como iba a cambiar sus vidas.
Personas como Sundar Pichai, CEO de Google dicen que ?el impacto de la inteligencia artificial en la historia de la humanidad es comparable con la electricidad y el fuego38?. Para el, la inteligencia artificial es una de las cosas mas importantes en las que la humanidad esta trabajando y que al igual que la gente aprendio a utilizar el fuego para los beneficios de la humanidad, tambien necesito superar sus desventajas.
Quiero creerme que Pichai es muy optimista respecto a la inteligencia artificial y que esta convencido que podria usarse para ayudar a resolver algunos de los retos que tenemos la humanidad encima de la mesa. Quizas esta comparativa es una exageracion, eso solo lo sabremos con el tiempo; pero yo de ustedes le tendria puesto el ojo a la inteligencia artificial, porque algo esta cambiando, y a todos nos conviene estar atentos a lo que se avecina.
1.2 Inteligencia artificial, Machine Learning y Deep Learning
Creo que antes de continuar estaria bien que concretaramos un poco que entendemos por inteligencia artificial, Machine Learning y Deep Learning, tres terminos que apareceran muy a menudo a lo largo del libro.
Inteligencia artificial
A que nos referimos cuando hablamos de inteligencia artificial? Una extensa y precisa definicion (y descripcion de sus ambitos) se encuentra en el libro de Stuart Rusell39 y Peter Norvig40ÿtituladoÿArtificial Intelligence, a modern approach41,ÿel texto sobre inteligencia artificial mas popular en el mundo universitario y, sin duda para mi, el mejor punto de partida para tener una vision global del tema. Pero intentando hacer una aproximacion mas generalista (proposito de este libro), podriamos aceptar una definicion simple en la que por inteligencia artificial nos referimos a aquella inteligencia que muestran las maquinas, en contraste con la inteligencia natural de los humanos. En este sentido, una posible definicion concisa y general de inteligencia artificial podria ser el esfuerzo para automatizar tareas intelectuales normalmente realizadas por humanos.
Como tal, el area de inteligencia artificial (Artificial Intelligence en ingles) es un campo muy amplio que abarca muchas areas del conocimiento relacionadas con el aprendizaje automatico; incluso se incluyen muchos mas enfoques no siempre catalogados como aprendizaje automatico por mis colegas universitarios expertos en el tema. Ademas, a lo largo del tiempo, a medida que los computadores han sido cada vez mas capaces de ?hacer cosas?, se han ido cambiando las tareas o tecnologias consideradas como ?inteligentes?.
Esto explica el porque desde los anos 50, la inteligencia artificial ha experimentado varias oleadas de optimismo, seguidas por la decepcion y la perdida de financiacion e interes (epocas conocidas como AI winter42), seguidas de nuevos enfoques, exito y financiacion. Ademas, durante la mayor parte de su historia, la investigacion en inteligencia artificial se ha dividido en subcampos basados en consideraciones tecnicas o herramientas matematicas concretas y con comunidades de investigacion que no se comunicaban suficientemente entre si.
Machine Learning
Como deciamos en el anterior apartado, avances como el reconocimiento de voz, el procesado de lenguaje natural o la vision por computador son cruciales para desencadenar mejoras en robotica, drones, coches que se conducen solos, entre muchas otras areas que estan cambiando el futuro proximo. Muchos de estos avances han sido posibles gracias a una familia de tecnicas conocida popularmente como Deep Learning, del que hablaremos extensamente. Pero antes creo que es interesante para hacernos una imagen global correcta especificar que Deep Learning es una subparte de una de las areas de la inteligencia artificial conocida como Machine Learning.
Machine Learning, en general traducido al castellano como ?aprendizaje automatico? (aunque yo voy a mantener su nombre en ingles en este libro), es en si mismo un gran campo de investigacion y desarrollo. En concreto, Machine Learning se podria definir como el subcampo de la inteligencia artificial que proporciona a los ordenadores la capacidad de aprender sin ser explicitamente programados, es decir, sin que necesiten que el programador indique las reglas que debe seguir para lograr su tarea sino que las hace automaticamente.
Generalizando, podemos decir que Machine Learning consiste en desarrollar para cada problema un ?algoritmo? de prediccion para un caso de uso particular. Estos algoritmos aprenden de los datos con el fin de encontrar patrones o tendencias para comprender que nos dicen los datos y de esta manera construir un modelo para predecir y clasificar los elementos.
Dada la madurez del area de investigacion en Machine Learning, existen muchos enfoques bien establecidos para el aprendizaje automatico por parte de maquinas. Cada uno de ellos utiliza una estructura algoritmica diferente para optimizar las predicciones basadas en los datos recibidos. Machine Learning es un amplio campo con una compleja taxonomia de algoritmos que se agrupan, en general, en tres grandes categorias: aprendizaje supervisado, aprendizaje no supervisado y Reinforcement Learning.
Nos referimos a que el ?aprendizaje es supervisado? cuando los datos que usamos para el entrenamiento incluyen la solucion deseada, llamada ?etiqueta? (label). Algunos de los algoritmos mas populares de Machine Learning en esta categoria son la regresion lineal, la regresion logistica, support vector machines, decision trees, random forest y redes neuronales.
En cambio, cuando nos referimos a un ?aprendizaje no supervisado? los datos de entrenamiento no incluyen las etiquetas, y sera el algoritmo el que intentara clasificar la informacion por si mismo. Algunos de los algoritmos mas conocidos de esta categoria son clustering (K-means) o principal component analysis (PCA).
Tambien hablamos de Reinforcement Learning (o ?aprendizaje por refuerzo?, traduccion de algunos autores) cuando el modelo se implementa en forma de un agente que debera explorar un espacio desconocido y determinar las acciones a llevar a cabo mediante prueba y error: aprendera por si mismo gracias a las recompensas y penalizaciones que obtiene de sus acciones. El agente debe crear la mejor estrategia posible (politicas) para obtener la mayor recompensa en tiempo y forma. Este aprendizaje permite ser combinado con otros tipos, y esta ahora mismo muy de moda puesto que el mundo real presenta muchos de estos escenarios.
Terminologia basica de Machine Learning
En este punto vamos a avanzar terminologia basica de Machine Learning que nos permitira mantener un guion de presentacion de los conceptos de Deep Learning de manera mas comoda y gradual a lo largo del libro.
En general nos decantamos por usar el termino en ingles, aunque en los casos en que la traduccion facilite la comprension del texto usaremos las diversas opciones que se indicaran a continuacion.
En Machine Learning nos referimos a label (que tambien traduciremos por ?etiqueta?) a lo que estamos intentando predecir con un modelo. En cambio, a una variable de entrada la llamaremos feature (lo traduciremos como ?caracteristica? o ?variable? de un ejemplo o dato de entrada).
Un modelo (model en ingles) define la relacion entre features y labels y tiene dos fases claramente diferenciadas para el tema que nos ocupa:
* Fase de training (que traduciremos tambien por ?entrenamiento?o ?aprendizaje?), que es cuando se crea o se ?aprende? el modelo, mostrandole los ejemplos de entrada que se tienen etiquetados; de esta manera se consigue que el modelo aprenda iterativamente las relaciones entre las features y labels de los ejemplos.
* Fase de inference (que traduciremos por ?inferencia? o ?prediccion?), que se refiere al proceso de hacer predicciones mediante la aplicacion del modelo ya entrenado a ejemplos no etiquetados.
Consideremos un ejemplo simple de modelo que expresa una relacion lineal entre features y labels. El modelo podria expresarse de la siguiente forma:
y=wx+b
Donde:
* y es la label o etiqueta de un ejemplo de entrada.
* x la feature de ese ejemplo de entrada.
* w es la pendiente de la recta y que en general le llamaremos ?peso? (o weight en ingles) y es uno de los dos parametros que se tienen que aprender el modelo durante el proceso de entrenamiento para poder usarlo luego para inferencia.
* b es el punto de interseccion de la recta en el eje y que llamamos ?sesgo? (o bias en ingles). Este es el otro de los parametros que deben ser aprendidos por el modelo.
Aunque en este modelo simple que hemos representado solo tenemos una feature de entrada, en el caso de Deep Learning veremos que tenemos muchas variables de entrada, cada una con su peso wi. Por ejemplo, un modelo basado en tres features (x1, x2, x3) puede expresarse de la siguiente manera:
y= w1x1+ w2x2+w3x3+b
O, de manera mas general, se puede expresar como:
que expresa el sumatorio del producto escalar entre los dos vectores (X y W) y luego suma el sesgo.
El parametro sesgo b, para facilitar la formulacion, a veces se expresa como el parametro w0 (asumiendo una entrada adicional fija de x0=1).
En la fase de entrenamiento de un modelo se aprenden los valores ideales para los parametros del modelo (los pesos wi y el sesgo b). En el aprendizaje supervisado, la manera de conseguirlo es aplicar un algoritmo de aprendizaje automatico que obtenga el valor de estos parametros examinando muchos ejemplos etiquetados e intentar determinar unos valores para estos parametros del modelo que minimicen lo que llamamos loss (hay traducciones como ?error? en castellano).
Como veremos a lo largo del libro, la loss es un concepto central en Deep Learning que representa la penalizacion de una mala prediccion. Es decir, la loss es un numero que indica cuan mala ha sido una prediccion en un ejemplo concreto (si la prediccion del modelo es perfecta, la loss es cero). Para determinar este valor, como veremos mas adelante, en el proceso de entrenamiento aparecera el concepto de funcion de loss, y que de momento podemos ver como la funcion matematica que agrega las loss individuales obtenidas de los ejemplos de entrada al modelo.
En este contexto, por ahora podemos considerar que la fase de entrenamiento de un modelo consiste basicamente en ajustar los parametros (los pesos wi y el sesgo b) de tal manera que el resultado de la funcion de loss retorna el valor minimo posible.
Finalmente, nos queda avanzar el concepto de overfitting (al que tambien referenciaremos por su traduccion de ?sobreajuste?) de un modelo, que se produce cuando el modelo obtenido se ajusta tanto a los ejemplos etiquetados de entrada que no puede realizar las predicciones correctas como en ejemplos de datos nuevos que nunca ha visto antes.
Redes neuronales artificiales y Deep Learning
Un caso especial de algoritmos de Machine Learning son las redes neuronales artificiales. Si les ayuda, para visualizar su estructura pueden considerar que los algoritmos son similares a las neuronas humanas y su capacidad para la obtencion de resultados, como habran oido en alguna ocasion, aunque en la actualidad creo que poco tiene que ver.
En el caso concreto de Deep Learning (que en castellano se traduce a veces como ?aprendizaje profundo?, aunque usare la version en ingles), las estructuras algoritmicas antes mencionadas permiten modelos que estan compuestos de multiples capas de procesamiento para aprender representaciones de datos, con multiples niveles de abstraccion que realizan una serie de transformaciones lineales y no lineales que a partir de los datos de entrada generen una salida proxima a la esperada (label). El aprendizaje supervisado, en este caso, consiste en obtener los parametros de esas transformaciones (los pesos wi y el sesgo b), y consigue que esas transformaciones sean optimas, es decir, que la salida producida y la esperada difieran muy poco.
Una aproximacion grafica simple a una red neuronal Deep Learning es
En concreto, aqui representamos una red neuronal artificial con 3 capas: una de entrada (input layer) que recibe los datos de entrada y una de salida (output layer) que devuelve la prediccion realizada. Las capas que tenemos en medio se llaman capas ocultas (hidden layers) y podemos tener muchas, cada una con distinta cantidad de neuronas. Veremos mas adelante que las neuronas, representadas por los circulos, estaran interconectadas unas con otras de diferente manera entre las neuronas de las distintas capas.
En general, hoy en dia estamos manejando redes neuronales artificiales con muchisimas capas, que literalmente estan apiladas una encima de la otra; de aqui el concepto de deep (profundidad de la red), donde cada una de ellas esta a su vez compuesta por muchisimas neuronas, cada una con sus parametros (los pesos wi y el sesgo b) que, a su vez, realizan una transformacion simple de los datos que reciben de neuronas de la capa anterior para pasarlos a las de la capa posterior. La union de todas permite descubrir patrones complejos.
Como veremos en detalle mas adelante, los avances en Deep Learning han mejorado drasticamente el estado de la tecnica en reconocimiento de voz, reconocimiento de objetos visuales, deteccion de objetos y muchos otros dominios, siendo una de las tecnicas que han puesto la inteligencia artificial en el foco de interes de las empresas y de aqui el gran interes que ahora mismo suscitan.
Pero aunque Deep Learning a menudo se presenta envuelto de una cierta mistica, con referencias a algoritmos que ?funcionan como el cerebro?, que ?piensan? o ?entienden?, a mi entender la realidad aun dista bastante de este sueno de ciencia ficcion. Ademas, creo que sus conceptos basicos pueden ser explicados de manera relativamente facil a lectores con una base de conocimiento en informatica y sobre todo ganas de aprender, siendo este el proposito de este libro.
Antes de acabar, me gustaria dar una magnitud del problema que conlleva programar en estos momentos los algoritmos de Deep Learning: diferentes capas sirven para diferentes propositos, y cada parametro e hiperparametro importa mucho en el resultado final; esto lo hace extremadamente complicado a la hora de intentar afinar la programacion de un modelo de red neuronal, pareciendo mas un arte que una ciencia para los que se adentran por primera vez en el area. Pero esto no implica que sea algo misterioso, si bien es cierto que queda mucho por investigar, sino que simplemente hace falta muchas horas de aprendizaje y practica.
La siguiente figura resume visualmente la idea intuitiva de que Deep Learning es solo una parte de la inteligencia artificial, aunque en estos momentos quizas es la mas dinamica y la que esta haciendo realmente vibrar a la comunidad cientifica. Y de la misma manera que antes les mencionaba la obra de Stuart Rusell y Peter Novig como libro base de inteligencia artificial, para Deep Learning nos encontramos con un excelente libro, titulado Deep Learning43, realizado por Ian Goodfellow, Yoshua Bengio y Aaron Corville que es el ?campamento base? en estos momentos para el aprendizaje del tema en mas profundidad.
1.3 Por que ahora?
En tan solo diez anos44, cuatro de las cinco empresas mas grandes del mundo por capitalizacion de mercado han cambiado: Exxon Mobil, General Electric, Citigroup y Shell Oil estan fuera y Apple, Alphabet (la compania matriz de Google), Amazon y Facebook han tomado su lugar. Solo Microsoft mantiene su posicion. Ya se han percatado que todas ellas dominan la nueva era digital en que nos encontramos inmersos. Estamos hablando de empresas que basan su poderio en inteligencia artificial en general, y en particular Deep Learning.ÿ
John McCarthy acuno el termino inteligencia artificial en la decada de los 50 y fue uno de los padres fundadores de la inteligencia artificial junto con Marvin Minsky. Tambien en 1958 Frank Rosenblatt construyo un prototipo de red neuronal, que llamo el Perceptron. Ademas, las ideas clave de las redes neuronales Deep Learning para la vision por computador ya se conocian en 1989; tambien los algoritmos fundamentales de Deep Learning para series temporales como LSTM (que trataremos mas adelante), ya fueron desarrollados en 1997, por poner algunos ejemplos. Entonces, por que este boom de la inteligencia artificial?
Sin duda, la computacion disponible ha sido el principal desencadenante, como ya hemos presentado anteriormente. Sin embargo, otros factores han contribuido a desencadenar el potencial de la inteligencia artificial y las tecnologias relacionadas. A continuacion vamos a hablar de algunos de ellos.
Los datos, el combustible para la inteligencia artificial
La inteligencia artificial requiere grandes conjuntos de datos para el entrenamiento de sus modelos aunque, afortunadamente, la creacion y disponibilidad de datos ha crecido exponencialmente gracias el enorme decrecimiento de coste e incremento de fiabilidad de la generacion de datos: fotos digitales, sensores mas baratos y precisos, etc. Ademas, las mejoras en el hardware de almacenamiento de los ultimos anos, asociado a los espectaculares avances en tecnica para su gestion con bases de datos NoSQL45, han permitido disponer de enormes conjuntos de datos para entrenar a los modelos de inteligencia artificial.
Mas alla de los aumentos en la disponibilidad de datos que ha propiciado internet y sus multiples aplicaciones, los recursos de datos especializados han catalizado el progreso del area. Muchas bases de datos abiertas han apoyado el rapido desarrollo de algoritmos de inteligencia artificial. Un ejemplo ImageNet46, la base de datos, de la que ya hemos hablado, disponible libremente con mas de 10 millones de imagenes etiquetadas a mano. Pero lo que hace ImageNet especial no es precisamente su tamano, sino la competicion que anualmente realiza, siendo una excelente manera de motivar a investigadores e ingenieros.
Mientras que en los primeros anos las propuestas se basaban en algoritmos de vision por computador tradicionales, en el 2012 Alex Krizhevsky uso una red neuronal Deep Learning, ahora conocida por AlexNet, que redujo el ratio de error a menos de la mitad de lo que se estaba consiguiendo por aquel entonces. Ya en el 2015, el algoritmo ganador rivalizo con las capacidades humanas, y a dia de hoy los algoritmos de Deep Learning superan con creces los ratios de error en esta competicion de los que tienen los humanos.
Pero ImageNet solo es una de las bases de datos disponibles que se han usado para entrenar redes Deep Learning durante estos ultimos anos; muchas otras han sido populares, como MNIST47, CIFAR48, SVHN 49, STL50 o IMDB51. Hablaremos de ellas mas adelante. Tambien es importante mencionar aqui Kaggle52, una plataforma que aloja competiciones de analisis de datos donde companias e investigadores aportan sus datos mientras ingenieros de datos de todo el mundo compiten por crear los mejores modelos de prediccion o clasificacion.
Democratizacion de la computacion
Ahora bien, que pasa si uno no dispone de esta capacidad de computacion en su empresa? La inteligencia artificial hasta ahora ha sido principalmente el juguete de las grandes companias de tecnologia como Amazon, Baidu, Google o Microsoft, asi como algunas nuevas empresas que disponian de estas capacidades. Para muchos otros negocios y partes de la economia, los sistemas de inteligencia artificial hasta ahora han sido demasiado costosos y demasiado dificiles de implementar por completo. Estamos hablando de Cloud Computing53.
Pero ahora estamos entrando en otra era de democratizacion de la computacion, y las empresas pueden disponer de acceso a grandes centros de procesado de datos de mas de 28?000 metros cuadrados (cuatro veces el campo del Bar‡a), con cientos de miles de servidores dentro.
Cloud Computing ha revolucionado la industria mediante la democratizacion de la computacion y ha cambiado completamente la manera de operar de los negocios. Y ahora es el turno de cambiar el escenario de la inteligencia artificial y Deep Learning, ofreciendo una gran oportunidad para las pequenas y medianas empresas que no pueden construir este tipo de infraestructuras, pero en cambio Cloud Computing si se lo puede ofrecer; de hecho, ofrece acceso a una capacidad de computacion que antes solo estaba disponible para grandes organizaciones o gobiernos.
Ademas, los proveedores de Cloud estan ahora ofreciendo lo que se conoce comoÿArtificial Intelligence algorithms as a Service (AI-as-a-Service), servicios de inteligencia artificial a traves de Cloud que pueden entrelazarse y trabajar conjuntamente con aplicaciones internas de las empresas a traves de simples API REST54.
Esto implica que esta al alcance de casi todos, ya que se trata de un servicio que solo se paga por el tiempo utilizado. Esto es disruptivo, porque ahora mismo permite a los desarrolladores de software usar y poner practicamente cualquier algoritmo de inteligencia artificial en produccion en un santiamen.
Amazon, Microsoft, Google e IBM estan liderando esta oleada de servicios AIaaS que permiten desde entrenamientos a puestas en produccion de manera rapida. En el momento de escribir este libro, Amazon AIaaS estaba disponible a dos niveles: analiticas predictivas con Amazon Machine Learning55 y la herramienta SageMaker56 para la construccion y despliegue rapido de modelos. Microsoft ofrece sus servicios a traves de su Azure Machine Learning que puede ser dividido en dos categorias principales tambien: Azure Machine Learning Studio57 y Azure Intelligence Gallery58. Google ofrece Prediction API59 y el Google ML Engine60. IBM ofrece servicios AIaaS a traves de su Watson Analytics61. Y no olvidemos soluciones que ya vienen de startups, como PredicSis62 and BigML63.
Sin duda, la inteligencia artificial liderara la proxima revolucion. Su exito dependera en gran medida de la creatividad de las empresas y no tanto de la tecnologia hardware en parte gracias a Cloud Computing.
Un mundo open-source para la comunidad Deep Learning
Hace algunos anos, Deep Learning requeria experiencia en lenguajes como C++ y CUDA; hoy en dia, con habilidades basicas de Python es suficiente. Esto ha sido posible gracias al gran numero de frameworks de software de codigo abierto que han ido apareciendo, como Keras, central en nuestro libro. Estos frameworks facilitan enormemente la creacion y entrenamiento de los modelos y permiten abstraer las peculiaridades del hardware al disenador del algoritmo para acelerar los procesos de entrenamiento.
Puestos a destacar algunos, les propongo que se queden con TensorFlow, Keras y PyTorch, pues son los mas dinamicos en estos momentos si nos basamos en los contributors y commits o starts de estos proyectos en GitHub64.
En concreto, recientemente ha tomado mucho impulso TensorFlow65 y sin duda es el dominante. Fue originalmente desarrollado por investigadores e ingenieros del grupo de Google Brain en Google. El sistema fue disenado para facilitar la investigacion en Machine Learning y hacer mas rapido la transicion de un prototipo de investigacion a un sistema de produccion. Si miramos en su pagina de Gihub66 veremos que tenemos, a fecha de escribir este libro, mas de 30?000 commits, mas de 1?400 contributors y casi 100?000 starts. Nada desdenable.
Le sigue Keras67 con una API de alto nivel para redes neuronales, que lo convierte en el entorno perfecto para iniciarse en el tema. El codigo se especifica en Python, y en estos momentos es capaz de ejecutarse encima de tres entornos destacados: TensorFlow, CNTK o Theano. En principio, el usuario puede cambiar el motor de ejecucion sin cambiar su codigo de Keras. Ahora mismo, Keras cuenta con mas de 4?500 commits, mas de 650 contributors y mas de 27?000 starts.
PyTorch y Torch68 son dos entornos de Machine Learning implementados en C, usando OpenMP69 y CUDAÿpara sacar provecho de infraestructuras altamente paralelas. PyTorch es la version mas focalizada para Deep Learning y basada en Python, desarrollado por Facebook. Es un entorno popular en mi campo de investigacion puesto que permite mucha flexibilidad en la construccion de las redes neuronales y tiene tensores dinamicos, entre otras cosas. En el momento de escribir este libro, Pytorch cuenta con mas de 10?500 commits, alrededor de 600 contributors y mas de 13?000 starts.
Finalmente, y aunque no es entorno exclusivo de Deep Learning, es importante mencionar Scikit-learn70 que se usa muy a menudo en la comunidad de Deep Learning para el preprocesado de los datos71. Scikit-learn cuenta con mas de 22?500 commits, mas de 1?000 contributors y mas de 27?000 starts.
Pero como ya he avanzado, hay muchisimos otros frameworks orientados a Deep Learning. Los que destacariamos son Theano72 (Montreal Institute of Learning Algortithms), Caffe73 (Universidad de Berkeley), Caffe274 (Facebook Research), CNTK75 (Microsoft), MXNET76 (soportado por Amazon entre otros), Deeplearning4j77, Chainer78 , DIGITS79 (Nvidia), Kaldi80, Lasagne81, Leaf82, MatConvNet83, OpenDeep84, Minerva85 y SoooA86 , entre muchos otros.
Una cultura de publicacion abierta
En estos ultimos anos, en esta area de investigacion, en contraste con otros campos cientificos, se ha generado una cultura de publicacion abierta, en la que muchos investigadores publican sus resultados inmediatamente(sin esperar la aprobacion de la revision por pares habitual en los congresos) en bases de datos como por ejemplo la arxiv.org de la Universidad de Cornell (arXiv)87. Esto conlleva que haya mucho software disponible en open source asociado a estos articulos que permiten que este campo de investigacion se mueva tremendamente rapido, puesto que cualquier nuevo hallazgo esta inmediatamente a disposicion para toda la comunidad para verlo y, si es el caso, construir encima.
Esto supone una gran oportunidad para los usuarios de estas tecnicas. Los motivos para publicar sus ultimos avances abiertamente por parte de los grupos de investigacion pueden ser diversos; por ejemplo Google, al publicar los resultados, consolida su reputacion como lider en el sector, atrayendo la siguiente ola de talento, que como comentaremos, es uno de los principales obstaculos para el avance del tema.
Mejoras en los algoritmos
Gracias a la mejora del hardware que ya hemos presentado y al disponer de mas capacidad de computacion por parte de los cientificos que investigaban en el area, se ha podido avanzar de manera espectacular en el diseno de nuevos algoritmos que han permitido superar importantes limitaciones detectadas en los mismos. Por ejemplo, hasta no hace muchos anos era muy dificil entrenar redes de muchas capas desde un punto de vista del algoritmo. Pero en este ultimo decenio ha habido impresionantes avances con mejoras en las funciones de activacion, uso de redes preentrenadas, mejoras en algoritmos de optimizacion del entrenamiento, etc. Hoy, algoritmicamente hablando, podemos entrenar modelos de centenares de capas sin ningun problema. Otra cosa es si tenemos los recursos de computacion para hacerlo realidad.
1.4 Preparar el entorno de trabajo
Antes de continuar, les recomiendo que tengan el entorno de desarrollo instalado en su ordenador para ir probando lo que se va explicando en cada capitulo, pues recuerden el enfoque del libro de learn by doing.
Jupyter notebook
Debido a que Keras es basicamente una libreria de Python, requerimos hacer un uso completo del interprete de Python. Nuestra propuesta es usar Jupyter88, puesto que es un entorno de desarrollo muy extendido que permite sacar partido a la interactividad de Python y, a la vez, proporciona una gran versatilidad para compartir parte de codigos con anotaciones a traves de la comodidad e independencia de plataforma que ofrece un navegador web.
Por este motivo, los notebook son usados a menudo para desarrollar redes neuronales en la comunidad de cientificos e ingenieros de datos. Un notebook es un fichero generado por Jupyter Notebook o Jupyter Lab que se puede editar desde un navegador web, permitiendo mezclar la ejecucion de codigo Python con anotaciones.
Si no tienen instalado Jupyter pueden seguir las indicaciones de su pagina oficial89. El codigo de este libro esta disponible en forma de notebooks en el GitHub90 del libro, aunque este se puede ejecutar como un programa normal en Python si asi lo desea el lector.
Keras
Para la instalacion de la libreria de Keras en un ordenador personal, el lector se puede dirigir a su pagina oficial, donde encontrara una version actualizada de los pasos a seguir para la instalacion de la ultima version de la libreria91. En esta pagina podemos ver la indicacion de tener previamente instalado uno de los backend que necesita, y nos recomienda usar TensorFlow (yo tambien se lo recomiendo). Para ello pueden visitar la pagina de instalacion de Tensorflow92 y seleccionar la version de acuerdo a su sistema operativo. A continuacion, para instalar Keras solo les queda seguir las instrucciones de su pagina de instalacion.
Una instalacion con solo una CPU nos sera suficiente para seguir el libro. Pero como veremos a la que nos adentramos en redes neuronales convolucionales, nos puede ser util tener potencia de calculo basada en general en GPU si no queremos que nuestras ejecuciones para entrenar redes tarden muchas horas. En este caso, si el lector dispone de este hardware, en la misma pagina de instalacion de Keras encontrara las instrucciones para la instalacion de la version de la libreria para GPU.
Docker
Una alternativa que les propongo es usar una imagen de docker que he preparado para una de mis asignaturas. Docker93 es un proyecto de codigo abierto que se ha hecho muy popular entre la comunidad de programadores ya que permite automatizar el despliegue de programas usando un contenedor software que permite aislar las aplicaciones entre si. De esta manera podemos preparar docker con todo el software que necesitamos para ejecutar el codigo que usamos en este libro y simplificar el proceso de instalacion. Si deciden ir por esta opcion, les indico los pasos a seguir para poder usar la imagen del docker.
Primero tenemos que instalar docker en nuestro ordenador. Para las plataformas Windows 10 Pro, Windows 10 Enterprise, MacOS o Linux podemos dirigirnos a Docker Store94. Para otras versiones de Windows, a Docker Toolbox95.
A continuacion debemos descargar y ejecutar la imagen de docker. Para ello abriremos un terminal (en Mac/Linux), cmd o powershell (en Windows 10 Pro) o Docker CLI (para otras versiones de Windows) y luego podemos ejecutar:
docker pull jorditorresbcn/dl
Los usuarios de MacOS y Windows tienen que tener el programa docker abierto para poder ejecutar el comando docker. Esta imagen esta basada en Ubuntu 16.04 con el siguiente software instalado: Python3.5, Keras, TensorFlow, nano, htop, iPython, Jupyter, matplotlib, NLTK y git.
Para ejecutar la imagen de docker por primera vez deben abrir un nuevo terminal y ejecutar:
docker run -it -p 8888:8888 jorditorresbcn/dl:latest
En el caso que queramos usar una imagen del docker anteriormente usada y la queremos reabrir podemos hacerlo de esta manera:
docker ps -a
docker ps -a docker start -i <ID de su contenedor docker>
Para clonar el repositorio en GitHub del libro dentro del contenedor podemos ejecutar el siguiente comando:
git clone https://github.com/jorditorresBCN/Deep-Learning-Introduccion- practica-con-Keras.git
Para lanzar el Jupyter Notebook dentro del contenedor podemos ejecutar el siguiente comando:
jupyter notebook --ip=0.0.0.0 --allow-root ?-no-brower
Ahora solo nos queda abrir en nuestro ordenador el navegador e ir a http://localhost:8888. El password es dl. En el caso de usuarios Windows que experimenten problemas de conectividad, pueden visitar este enlace96.
Para asegurar que todo funciona correctamente les propongo que creen un nuevo notebook y ejecuten un codigo como el siguiente, que muestra una grafica con 50 puntos aleatorios:
%matplotlib inline
from matplotlib import pyplot as plt
import numpy as np
N = 50
x = np.random.rand(N)
y = np.random.rand(N)
plt.scatter(x, y)
plt.show()
Cloud
Si queremos usar una GPU, y no disponemos de ello, podemos considerar usar los servicios que hay disponibles a traves de Cloud que ofrecen diferentes proveedores. Pero dada la diversidad de plataformas y el cambio constante en las API que proporcionan los proveedores de Cloud en relacion al acceso al hardware GPU (que van incorporando a sus servicios ultimamente), he considerado que era arriesgado aqui concretar mas las indicaciones de los pasos a seguir para ejecutar un Jupyter en Cloud sin el riesgo que las instrucciones indicadas queden obsoletas antes de incluso ver la luz el libro.
Por ello les propongo que en el momento de leer estas lineas vean las posibilidades del mercado. Como punto de partida por defecto les propongo que visiten la pagina Documentacion de las AMI de aprendizaje profundo de AWS 97 donde Amazon mantiene la ultima version de manual en PDF y HTML para ayudarnos a ejecutar un Jupyter Notebook en su Cloud usando una instancia p2.xlarge que permite acceso a GPU por un coste economico muy razonable, incluso hay un periodo gratuito suficiente para probar los notebooks de este libro.
Otra opcion es la que ofrece Google con Colaboratory98. Se trata de un proyecto de investigacion de Google creado para ayudar a diseminar la educacion e investigacion del Machine Learning. Es un entorno de notebook Jupyter que no requiere configuracion y se ejecuta completamente en Cloud permitiendo usar Keras, TensorFlow y PyTorch. Los notebooks se almacenan en Google Drive y se pueden compartir tal como lo haria con Google Docs. Este entorno es de uso gratuito que solo requiere tener una cuenta en Google. Ademas ente entorno permite el uso de una GPU K80 de NVIDIA gratuitamente.
Pero nuevamente, quiero recordar que si el lector no dispone de GPU ni de Cloud, porque simplemente se encuentra disfrutando de la lectura de este libro en medio de la montana sin acceso a internet, no hay problema. Adjunto al codigo del libro que se puede descargar de GitHub localmente a su portatil, y tambien podra descargarse los ficheros que contienen los pesos de las redes neuronales ya entrenadas para aquellas que requieren muchos recursos de computacion (en la segunda parte del libro).
Y ahora que tenemos el entorno listo, solo me queda decirles? enjoy!
2 Redes neuronales densamente conectadas
De la misma manera que cuando uno empieza a programar en un lenguaje nuevo existe la tradicion de hacerlo con un print Hello World, en Deep Learning se empieza por crear un modelo de reconocimiento de numeros escritos a mano. Mediante este ejemplo, en este capitulo se presentaran algunos conceptos basicos de las redes neuronales, reduciendo todo lo posible conceptos teoricos, con el objetivo de ofrecer al lector una vision global de un caso concreto para facilitar la lectura de los capitulos posteriores donde se entrara en mas detalle de diferentes temas del area. En este capitulo tambien se mostrara como se codifica este ejemplo con Keras para ofrecer al lector un primer contacto con esta libreria y entender la estructura que tiene la implementacion de este ejemplo con Keras.
2.1 Caso de estudio: reconocimiento de digitos
En este apartado presentamos los datos que usaremos para nuestro primer ejemplo de redes neuronales: el conjunto de datos MNIST, que contiene imagenes de digitos escritos a mano.
El conjunto de datos MNIST, que se pueden descargar de la pagina The MNIST database99, esta formado por imagenes de digitos hechos a mano. Este conjunto de datos contiene 60?000 elementos para entrenar el modelo y 10?000 adicionales para testearlo, y es ideal para adentrarse por primera vez en tecnicas de reconocimiento de patrones sin tener que dedicar mucho tiempo al preproceso y formateado de datos, ambos pasos muy importantes y costosos en el analisis de datos100 y de especial complejidad cuando se esta trabajando con imagenes; este conjunto de datos solo requieren pequenas transformaciones que comentaremos a continuacion.
Este conjunto de imagenes originales en blanco y negro han sido normalizadas a 20?20 pixeles conservando su relacion de aspecto. En este caso, es importante notar que las imagenes contienen niveles de grises como resultado de la tecnica de anti-aliasing101, usada en el algoritmo de normalizacion (reducir la resolucion de todas las imagenes a una de mas baja). Posteriormente, las imagenes se han centrado en una de 28?28 pixeles, calculando el centro de masa de estos y trasladando la imagen con el fin de posicionar este punto en el centro del campo de 28?28. Las imagenes son del siguiente estilo:
Ademas, el conjunto de datos dispone de una etiqueta (label) por cada una de las imagenes que indica que digito representa, tratandose pues de un aprendizaje supervisado el que trataremos en este capitulo.
Esta imagen de entrada se representa en una matriz con las intensidades de cada uno de los 28?28 pixeles con valores entre [0, 255]. Por ejemplo esta imagen (la octava del conjunto de entrenamiento):
Se representa con esta matriz de puntos (el lector puede comprobarlo en el notebook de este capitulo de 28?28):
[[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 5 63 197 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 20 254 230 24 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 20 254 254 48 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 20 254 255 48 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 20 254 254 57 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 20 254 254 108 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 16 239 254 143 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 178 254 143 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 178 254 143 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 178 254 162 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 178 254 240 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 113 254 240 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 83 254 245 31 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 79 254 246 38 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 214 254 150 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 144 241 8 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 144 240 2 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 144 254 82 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 230 247 40 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 168 209 31 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]]
Por otro lado, recordemos que tenemos las etiquetas, que en nuestro caso son numeros entre 0 y 9 que indican que digito representa la imagen, es decir, a que clase se asocia. En este ejemplo, vamos a representar esta etiqueta con un vector de 10 posiciones, donde la posicion correspondiente al digito que representa la imagen contiene un 1 y el resto son 0. Este proceso de transformar las etiquetas en un vector de tantos ceros como el numero de etiquetas distintas, y poner un 1 en el indice que le corresponde la etiqueta, se conoce como one-hot encoding, y lo presentaremos mas adelante en la segunda parte del libro.
2.2 Perceptron
Antes de avanzar, una breve explicacion intuitiva de como funciona una sola neurona para cumplir con su cometido de aprender del conjunto de datos de entrenamiento puede ser de ayuda para el lector. Veamos un ejemplo muy simple para ilustrar como puede aprender una neurona artificial.
Algoritmos de regresion
Recordando lo que se ha explicado en el capitulo anterior, dejennos hacer un breve recordatorio sobre algoritmos de regresion y clasificacion de Machine Learning clasico, ya que son el punto de partida de nuestras explicaciones de Deep Learning.
Podriamos decir que los algoritmos de regresion modelan la relacion entre distintas variables de entrada (features) utilizando una medida de error, la loss, que se intentara minimizar en un proceso iterativo para poder realizar predicciones ?lo mas acertadas posibles?. Hablaremos de dos tipos: regresion logistica y regresion lineal.
La diferencia principal entre regresion logistica y lineal es en el tipo de salida de los modelos; cuando nuestra salida sea discreta, hablamos de regresion logistica, y cuando la salida sea continua hablamos de regresion lineal.
Siguiendo las definiciones del primer capitulo, la regresion logistica es un algoritmo con aprendizaje supervisado y se utiliza para clasificar. El ejemplo que usaremos a continuacion, que consiste en identificar a que clase pertenece cada ejemplo de entrada asignandole un valor discreto de tipo 0 o 1, se trata de una clasificacion binaria.
Una neurona artificial simple
Para mostrar como es una neuronal basica, supongamos un ejemplo simple, donde tenemos un conjunto de puntos en un plano de dos dimensiones, y cada punto ya se encuentra etiquetado como ?cuadrado? o ?redonda?:
Dado un nuevo punto ?X?, queremos saber que etiqueta le corresponde:
Una aproximacion habitual es dibujar una lineaÿque separe los dos grupos y usarla como clasificador:
En este caso, los datos de entrada seran representados por vectores de la forma (x1, x2) que indican sus coordenadas en este espacio de dos dimensiones, y nuestra funcion retornara ?0? o ?1? (encima o debajo de la linea) para saber si se debe clasificar como ?cuadrado? o ?circulo?. Como hemos visto, se trata de un caso de regresion lineal, donde ?la linea? (el clasificador) puede ser definida por la recta:
y= w1x1+ w2x2+b
Siguiendo la notacion presentada en el capitulo 1. De manera mas generalizada, podemos expresar la recta como:
y = W * X + b
Para clasificar elementos de entrada X, en nuestro caso de dos dimensiones, debemos aprender un vector de peso W de la misma dimension que los vectores de entrada, es decir, el vector (w1, w2) y un sesgo b.
Con estos valores calculados, ahora ya podemos construir una neurona artificial para clasificar un nuevo elemento X. Basicamente la neurona aplica este vector W de pesos calculado, de manera ponderada sobre los valores en cada dimension del elemento X de entrada, le sumara el sesgo b, y el resultado lo pasara a traves de una funcion de ?activacion? no lineal para producir un resultado de ?0? o ?1?. La funcion de esta neurona artificial que acabamos de definir puede expresarse de una manera mas formal, como:
Una vez especificada la funcion que ejecuta la neurona artificial, pasemos a ocuparnos de ayudar al lector a intuir como esta neurona puede aprender los parametros W y b a partir de los datos de que ya disponemos etiquetados como ?cuadrados? o ?circulos?, y por otro lado ver que funcion nos permite convertir en ?0? o ?1? el resultado almacenado en z.
En lo que respecta a aprender los parametros W y b a partir de los datos de que ya disponemos etiquetados como ?cuadrados? o ?circulos?, en el siguiente capitulo presentaremos como se realiza este proceso de manera mas formal. Por el momento, empezamos a verlo mas intuitivamente; se trata de un proceso iterativo para todos los ejemplos etiquetados conocidos, comparando el valor de su label obtenida a traves del modelo, con el valor esperado de la label de cada elemento. Despues de cada iteracion, se ajustan los pesos de los parametros W y b de tal manera que se minimice la funcion de loss definida anteriormente.
Una vez tenemos los parametros W y b podemos calcular el valor de z. Entonces, necesitaremos una funcion que aplique una transformacion a esta variable para que se convierta en ?0? o ?1?. Aunque hay varias funciones (que llamaremos ?funciones de activacion? como veremos en el siguiente capitulo), para este ejemplo usaremos una conocida como funcion sigmoid102 que retorna un valor real de salida entre 0 y 1 para cualquier valor de entrada:
Si se piensa un poco en la formula, veremos que tiende siempre a dar valores proximos al 0 o al 1. Si la entrada z es razonablemente grande y positiva, "e" a la menos z es cero y, por tanto, la y toma el valor de 1. Si z tiene un valor grande y negativo, resulta que para ?e? elevado a un numero positivo grande, el denominador resultara ser un numero grande y por lo tanto el valor de y sera proximo a 0. Graficamente, la funcion sigmoid presenta esta forma:
Hasta aqui hemos presentado como se puede definir una neurona artificial, la arquitectura mas simple que puede tener una red neuronal. En concreto esta arquitectura es referenciada en la literatura del tema y se conoce como Perceptron103 (llamado tambien linear threshold unit (LTU)), inventada en 1957 por Frank Rosenblatt, y que visualmente se resume de manera general con el siguiente esquema:
El Perceptron es la version mas simple de red neuronal porque consta de una sola capa que contiene una sola neurona. Pero como veremos a lo largo del libro, lo normal hoy en dia es que nos encontremos con redes neuronales compuestas de numerosas capas y que cada una de ellas contenga muchas neuronas que se comunican con las de la capa anterior para recibir informacion, y estas a su vez comunican su informacion a las neuronas de la capa siguiente.
Como veremos en el siguiente capitulo, hay varias funciones de activacion ademas de la sigmoid, cada una con propiedades diferentes. Pero para el proposito de clasificar numeros escritos a mano, en este capitulo tambien les avanzare otra funcion de activacion llamada softmax104, que nos sera util para presentar un ejemplo de red neuronal minima para clasificar en mas de dos clases. Por el momento podemos considerar a la funcion softmax como una generalizacion de la funcion sigmoid que permite clasificar mas de dos clases.
Multi-Layer Perceptron
Pero antes de avanzar con el ejemplo, introduciremos brevemente la forma que toman habitualmente las redes neuronales construidas a partir de perceptrones como el que acabamos de presentar.
En la literatura del area nos referimos a un Multi-Layer Perceptron (MLP) cuando nos encontramos con redes neuronales que tienen una capa de entrada (input layer), una o mas capas compuestas por perceptrones, llamadas capas ocultas (hidden layers) y una capa final con varios perceptrones llamada la capa de salida (output layer). En general nos referimos a Deep Learning cuando el modelo basado en redes neuronales esta compuesto por multiples capas ocultas. Visualmente se puede presentar con el siguiente esquema:
Los MLP son a menudo usados para clasificacion, y en concreto cuando las clases son exclusivas, como es el caso de la clasificacion de imagenes de digitos que nos ocupa (en clases de 0 hasta 9), la capa de salida es una funcion softmax en la que la salida de cada neurona corresponde a la probabilidad estimada de la clase correspondiente. Visualmente lo podriamos representar de la siguiente forma:
2.3 Funcion de activacion softmax
Vamos a resolver el problema de manera que, dada una imagen de entrada, obtendremos las probabilidades de que sea cada uno de los 10 posibles digitos. De esta manera tendremos un modelo que, por ejemplo, podria predecir en una imagen un nueve, pero solo estar seguro en un 80% de que sea un nueve, ya que debido al dudoso bucle inferior piensa que podria llegar a ser un ocho en un 5% de posibilidades e incluso podria dar una cierta probabilidad a cualquier otro numero. Aunque en este caso concreto consideraremos que la prediccion de nuestro modelo es un 9, pues es el que tiene mayor probabilidad, esta aproximacion de usar una distribucion de probabilidades nos puede dar una mejor idea de cuan confiados estamos de nuestra prediccion. Esto es bueno en este caso, donde los numeros son hechos a mano, y seguramente en muchos otros no podemos reconocer los digitos con un 100% de seguridad.
Por tanto, para este ejemplo de clasificacion de MNIST, para cada ejemplo de entrada obtendremos como vector de salida de la red neuronal una distribucion de probabilidad sobre un conjunto deÿetiquetas mutuamente excluyentes, es decir, un vector de 10 probabilidades cada una correspondiente a un digito y que todas estas 10 probabilidades sumen 1 (las probabilidades se expresaran entre 0 y 1).
Como ya hemos avanzado, esto se logra mediante el uso de una capa de salida en nuestra red neuronal con la funcion de activacion softmax, en la que cada neurona en esta capa softmax depende de las salidas de todas las otras neuronas de la capa, puesto que la suma de la salida de todas ellas debe ser 1.
Pero como funciona la funcion de activacion softmax? La funcion softmax se basa en calcular ?las evidencias? de que una determinada imagen pertenece a una clase en particular y luego se convierten estas evidencias en probabilidades de que pertenezca a cada una de las posibles clases.
Para medir la evidencia de que una determinada imagen pertenece a una clase en particular, una aproximacion consiste en realizar una suma ponderada de la evidencia de pertenencia de cada uno de sus pixeles a esa clase. Para explicar la idea usare un ejemplo visual.
Supongamos que disponemos ya del modelo aprendido para el numero cero (mas adelante ya veremos como se aprenden estos modelos). Por el momento, podemos considerar un modelo como ?algo? que contiene informacion para saber si un numero es de una determinada clase. En este caso, para el numero cero, supongamos que tenemos un modelo como el que presentamos a continuacion:
Con una matriz de 28?28 pixeles, donde los pixeles en rojo (en la edicion en blanco/negro del libro es el gris mas claro) representa pesos negativos (es decir, reducir la evidencia de que pertenece), mientras que los pixeles en azul (en la edicion en blanco/negro del libro es el gris mas oscuro) representan pesos positivos (aumenta la evidencia de que pertenece). El color negro representa el valor neutro.
Imaginemos una hoja en blanco encima sobre la que trazamos un cero. En general, el trazo de nuestro cero caeria sobre la zona azul (recordemos que estamos hablando de imagenes que han sido normalizadas a 20?20 pixeles y posteriormente centradas a una imagen de 28?28). Resulta bastante evidente que si nuestro trazo pasa por encima de la zona roja lo mas probable es que no estemos escribiendo un cero; por tanto, usar una metrica basada en sumar si pasamos por zona azul y restar si pasamos por zona roja, parece razonable.
Para confirmar que es una buena metrica imaginemos ahora que trazamos un tres; esta claro que la zona roja del centro del anterior modelo que usabamos para el cero va a penalizar la metrica antes mencionada puesto que como podemos ver en la parte izquierda de esta figura al escribir un tres pasamos por encima:
Pero en cambio, si el modelo de referencia es el correspondiente al 3 como el mostrado en la parte derecha de la anterior figura, podemos observar que, en general, los diferentes posibles trazos que representan un tres se mantienen mayormente en la zona azul.
Espero que el lector, viendo este ejemplo visual, ya intuya como la aproximacion de los pesos indicados anteriormente nos permite hacer una estimacion de que numero se trata.
En la anterior figura se muestra los pesos de un ejemplo concreto de modelo aprendido para cada una de estas diez clases del MNIST (figura obtenida del ejemplo del tutorial de Tensorflow105). Recordemos que hemos escogido el rojo (gris mas claro en edicion de libro blanco y negro) en esta representacion visual para los pesos negativos, mientras que usaremos el azul (gris mas oscuro en edicion de libro en blanco y negro) para representar los positivos106.
Una vez se ha calculado la evidencia de pertenencia a cada una de las 10 clases, estas se deben convertir en probabilidades cuya suma de todos sus componentes sume 1. Para ello softmax usa el valor exponencial de las evidencias calculadas y luego las normaliza de modo que sumen uno, formando una distribucion de probabilidad. La probabilidad de pertenencia a la clase i es:
Intuitivamente, el efecto que se consigue con el uso de exponenciales es que una unidad mas de evidencia tiene un efecto multiplicador y una unidad menos tiene el efecto inverso. Lo interesante de esta funcion es que una buena prediccion tendra una sola entrada en el vector con valor cercano a 1, mientras que las entradas restantes estaran cerca de 0. En una prediccion debil tendran varias etiquetas posibles, que tendran mas o menos la misma probabilidad.
2.4 Datos para alimentar una red neuronal
A continuacion pasemos a un nivel mas practico en el ejemplo de reconocimiento de digitos MNIST, pero antes aprovechemos para explicar algunos detalles interesantes sobre los datos disponibles.
Conjunto de datos para entrenamiento, validacion y prueba
Antes de presentar la implementacion en Keras del ejemplo anterior, recordemos como debemos repartir los datos disponibles para poder configurar y evaluar el modelo correctamente.
Para la configuracion y evaluacion de un modelo en Machine Learning, y por ende Deep Learning, habitualmente se dividen los datos disponibles en tres conjuntos: datos de entrenamiento (training), datos de validacion (validation) y datos de prueba (test). Los datos de entrenamiento son los que se usan para que el algoritmo de aprendizaje obtenga los parametros del modelo. Si el modelo no acaba de adaptarse a los datos de entrada (por ejemplo, si presentara overfitting), en este caso modificariamos el valor de ciertos hiperparametros y despues de entrenarlo nuevamente con los datos de entrenamiento volveriamos a evaluarlo con los de validacion. Podemos ir haciendo estos ajustes de los hiperparametros guiados por los datos de validacion hasta que obtenemos unos resultados de validacion que consideremos correctos (en la segunda parte del libro entraremos en detalle en este tema de validacion). Si hemos seguido este procedimiento, debemos ser conscientes de que, en realidad, los datos de validacion han influido en el modelo para que se ajustara tambien a los datos de validacion. Por este motivo reservamos siempre un conjunto de datos de prueba para evaluacion final del modelo que solo se usaran al final de todo el proceso, cuando consideremos que el modelo esta acabado de afinar y ya no modificaremos mas ninguno de sus hiperparametros. Veremos en mas detalle este funcionamiento en futuros ejemplos de la segunda parte del libro.
Precarga de los datos en Keras
En Keras el conjunto de datos MNIST se encuentra precargado en forma de cuatro arrays Numpy y se pueden obtener con el siguiente codigo:
import keras
from keras.datasets import mnist
(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train y y_train conforman el conjunto de entrenamiento, mientras que x_test y y_test contienen los datos para el test. Las imagenes se encuentran codificadas como arrays Numpy y sus correspondientes etiquetas (labels) que van desde 0 hasta 9. Siguiendo la estrategia dellibro de ir introduciendo gradualmente los conceptos del tema, dejamos para mas adelante como separar una parte de los datos de entrenamiento para guardarlos como los datos validacion, y de momento solo tendremos en cuenta los datos de entrenamiento y de prueba.
Si queremos comprobar que valores hemos cargado, podemos elegir cualquiera de las imagenes del conjunto MNIST, por ejemplo la imagen 8, y usando el siguiente codigo Python:
import matplotlib.pyplot as plt
plt.imshow(x_train[8], cmap=plt.cm.binary)
Obtenemos la siguiente imagen:
Y si queremos ver su correspondiente etiqueta (label) podemos hacerlo mediante:
print(y_train[8])
1
Que como vemos nos devuelve el valor de ?1?, como era de esperar.
Representacion de los datos en Keras
Keras, que como hemos visto usa un array multidimensional de Numpy como estructura basica de datos, le llama a esta estructura de datos tensor. De manera resumida podriamos decir que un tensor tiene tres atributos principales:
* Numero de ejes (Rank o ndim): un tensor que contiene un solo numero lo llamaremos scalar (o un tensor 0-dimensional, o tensor 0D). Un array de numeros lo llamamos vector, o tensor 1D. Un array de vectores sera una matriz (matrix), o tensor 2D. Si empaquetamos esta matriz en un nuevo array, obtenemos un tensor 3D, que podemos interpretarlo visualmente como un cubo de numeros. Empaquetando un tensor 3D en un array, podemos crear un tensor 4D, y asi sucesivamente. En la libreria Numpy de Python esto se llama ndim del tensor.
* Forma (shape): se trata de una tupla de enteros que describen cuantas dimensiones tiene el tensor en cada eje. Un vector tiene un shape con un unico elemento, por ejemplo ?(5,)?, mientras que un escalar tiene un shape vacio ?( )?. En la libreria Numpy este atributo se llama shape.
* Tipo de datos (data type): este atributo indica el tipo de datos que contiene el tensor, que pueden ser por ejemplo uint8, float32, float64, etc. En raras ocasiones tenemos, en nuestro contexto, tensores de tipo char (nunca string). En la libreria Numpy este atributo se llama dtype.
Les propongo que obtengamos el numero de ejes y dimensiones del tensor train_images de nuestro ejemplo anterior:
print(x_train.ndim)
3
print(x_train.shape)
(60000, 28, 28)
Y si queremos saber que tipo de datos contiene:
print(x_train.dtype)
uint8
Normalizacion de los datos de entrada
Estas imagenes de MNIST de 28?28 pixeles se representan como una matriz de numeros cuyos valores van entre [0, 255] de tipo uint8. Perocomo veremos en posteriores capitulos, es habitual escalar los valores de entrada de las redes neuronales a unos rangos determinados. En el ejemplo de este capitulo los valores de entrada conviene escalarlos a valores de tipo float32 dentro del intervalo [0, 1]:
x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
x_train /= 255
x_test /= 255
Por otro lado, para facilitar la entrada de datos a nuestra red neuronal (veremos que en convolucionales no hace falta) debemos hacer una transformacion del tensor (imagen) de 2 dimensiones (2D) a un vector de una dimension (1D). Es decir, la matriz de 28?28 numeros se puede representar con un vector (array) de 784 numeros (concatenando fila a fila), que es el formato que acepta como entrada una red neuronal densamente conectada como la que veremos en este capitulo.
En Python, convertir cada imagen del conjunto de datos MNIST a un vector con 784 componentes se puede hacer de la siguiente manera:
x_train = x_train.reshape(60000, 784)
x_test = x_test.reshape(10000, 784)
Despues de ejecutar estas instrucciones Python, podemos comprobar que x_train.shape toma la forma de (60000, 784) y x_test.shape toma la forma de (10000, 784), donde la primera dimension indexa la imagen y la segunda indexa el pixel en cada imagen (ahora la intensidad del pixel es un valor entre 0 y 1):
print(x_train.shape)
print(x_test.shape)
(60000, 784)
(10000, 784)
Ademas tenemos las etiquetas (labels) para cada dato de entrada, (recordemos que en nuestro caso son numeros entre 0 y 9 que indican que digito representa la imagen, es decir, a que clase se asocia). En este ejemplo, y como ya hemos avanzado, vamos a representar esta etiqueta con un vector de 10 posiciones, donde la posicion correspondiente al digito que representa la imagen contiene un 1 y el resto de posiciones del vector contienen el valor 0.
En este ejemplo usaremos lo que se conoce como one-hot encoding, que ya hemos indicado que explicaremos mas adelante en la segunda parte del libro: en resumen, consiste en transformar las etiquetas en un vector de tantos ceros como el numero de etiquetas distinta, y que contiene el valor de 1 en el indice que le corresponde al valor de la etiqueta. Keras ofrece muchas funciones de soporte, y entre ellas to_categorical para realizar esta transformacion, que la podemos importar de keras.utils:
from keras.utils import to_categorical
Para ver el efecto de la transformacion podemos ver los valores antes y despues de aplicar to_categorical :
print(y_test[0])
7
print(y_train[0])
5
print(y_train.shape)
(60000,)
print(x_test.shape)
(10000, 784)
y_train = to_categorical(y_train, num_classes=10)
y_test = to_categorical(y_test, num_classes=10)
print(y_test[0])
[0. 0. 0. 0. 0. 0. 0. 1. 0. 0.]
print(y_train[0])
[0. 0. 0. 0. 0. 1. 0. 0. 0. 0.]
print(y_train.shape)
(60000, 10)
print(y_test.shape)
(10000, 10)
Ahora ya tenemos los datos preparados para ser usados en nuestro ejemplo de modelo simple que vamos a programar en Keras en la proxima seccion.
2.5 Redes densamente conectadas en Keras
En este apartado vamos a presentar como se especifica en Keras el modelo que hemos definido en los apartados anteriores.
Clase Sequential en Keras
La estructura de datos principal en Keras es la clase Sequential, que permite la creacion de una red neuronal basica. Keras ofrece tambien una API107 que permite implementar modelos mas complejos en forma de grafo que pueden tener multiples entradas, multiples salidas, con conexiones arbitrarias en medio, pero no lo presentaremos hasta el capitulo octavo del libro.
La claseÿSequential108 de la libreria de Keras es una envoltura para el modelo de red neuronal secuencial que ofrece Keras y se puede crear de la siguiente manera:
from keras.models import Sequential
model = Sequential()
En este caso, el modelo en Keras se considera como una secuencia de capas que cada una de ellas va ?destilando? gradualmente los datos de entrada para obtener la salida deseada. En Keras podemos encontrar todos los tipos de capas requeridas y se pueden agregar facilmente al modelo mediante el metodo add( ).
Definicion del modelo
La construccion en Keras de nuestro modelo para reconocer las imagenes de digitos podria ser el siguiente:
from keras.models import Sequential
from keras.layers.core import Dense, Activation
model = Sequential()
model.add(Dense(10, activation='sigmoid', input_shape=(784,)))
model.add(Dense(10, activation='softmax'))
Aqui, la red neuronal se ha definido como una secuencia de dos capas que estan densamente conectadas, es decir, que todas las neuronas de cada capa estan conectadas con todas las neuronas de la capa siguiente. Visualmente podriamos representarlo de la siguiente manera:
En este codigo expresamos explicitamente en el argumento input_shape de la primera capa como son los datos de entrada: un tensor que indica que tenemos 784 features del modelo (en realidad el tensor que se esta definiendo es de (None, 784,) como veremos mas adelante).
Una caracteristica muy interesante de la libreria de Keras es que esta deducira automaticamente la forma de los tensores entre capas despues de la primera. Esto significa que el programador solo tiene que establecer esta informacion para la primera de ellas. Ademas, para cada capa indicamos el numero de nodos que tiene y la funcion de activacion que aplicaremos en ella (en este caso, sigmoid).
La segunda capa es una capa softmax de 10 neuronas, lo que significa que devolvera una matriz de 10 valores de probabilidad que representan a los 10 digitos posibles (en general, la capa de salida de una red de clasificacion tendra tantas neuronas como clases, menos en una clasificacion binaria, en donde solo necesita una neurona). Cada valor sera la probabilidad de que la imagen del digito actual pertenezca a cada una de ellas.
Un metodo muy util que proporciona Keras para comprobar la arquitectura de nuestra modelo es summary():
model.summary()
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
dense_1 (Dense) (None, 10) 7850
_________________________________________________________________
dense_2 (Dense) (None, 10) 110
=================================================================
Total params: 7,960
Trainable params: 7,960
Non-trainable params: 0
Mas adelante entraremos en mas detalle con la informacion que nos retorna el metodo summary(), pues resulta muy valioso este calculo de parametros y tamanos de los datos que tiene la red neuronal cuando empezamos a construir modelos de redes muy grandes. Para nuestro ejemplo simple, vemos que indica que se requieren 7?960 parametros (columna Param #), que corresponden a los 7?850 parametros para la primera capa y 110 para la segunda.
En la primera capa por cada neurona i (entre 0 y 9) requerimos 784 parametros para los pesos wij y por tanto 10 x 784 parametros para almacenar los pesos de las 10 neuronas. Ademas de los 10 parametros adicionales para los 10 sesgos bj correspondientes a cada una de ellas. En la segunda capa, al ser una funcion softmax, se requiere conectar todos sus 10 nodos con los 10 nodos de la capa anterior, y por tanto se requieren 10x10 parametros wi ademas de los correspondientes 10 sesgos bj correspondientes a cada nodo.
En el manual de Keras se puede encontrar los detalles de los argumentos que podemos indicar para la capa Dense109. En nuestro ejemplo aparecen los mas relevantes, donde el primer argumento indica el numero de neuronas de la capa; el siguiente es la funcion de activacion que usaremos en ella. En el siguiente capitulo hablaremos en mas detalle de otras posibles funciones de activacion mas alla de las dos presentadas aqui: sigmoid y softmax.
Tambien a menudo se indica la inicializacion de los pesos como argumento de las capas Dense. Los valores iniciales deben ser adecuados para que el problema de optimizacion converja tan rapido como sea posible. En el manual de Keras se puede encontrar las diversas opciones de inicializacion110.
2.6 Pasos para implementar una red neuronal en Keras
A continuacion vamos a presentar una breve descripcion de los pasos que debemos realizar para implementar una red neuronal basica, y en los siguientes capitulos iremos introduciendo gradualmente mas detalles de cada uno de estos pasos.
Configuracion del proceso de aprendizaje
A partir del modelo Sequential, podemos definir las capas de manera sencilla con el metodo add(), tal como hemos avanzado en el apartado anterior. Una vez que tengamos nuestro modelo definido, podemos configurar como sera su proceso de aprendizaje con el metodo compile( ), con el que podemos especificar algunas propiedades a traves de argumentos del metodo.
El primero de estos argumentos es la funcion de loss que usaremos para evaluar el grado de error entre salidas calculadas y las salidas deseadas de los datos de entrenamiento. Por otro lado, se especifica un optimizador que, como veremos, es la manera que tenemos de especificar el algoritmo de optimitzaacion que permite a la red neuronal calcular los pesos de los parametros a partir de los datos de entrada y de la funcion de loss definida. Mas detalle del proposito exacto de la funcion deÿloss y el optimizador se presentaran en el siguiente capitulo.
Y finalmente debemos indicar la metrica que usaremos para monitorizar el proceso de aprendizaje (y prueba) de nuestra red neuronal. En este primer ejemplo solo tendremos en cuenta la accuracy (fraccion de imagenes que son correctamente clasificadas). Por ejemplo, en nuestro caso podemos especificar los siguientes argumentos en metodo compile( ) para probarlo en nuestro ordenador:
model.compile(loss="categorical_crossentropy",
optimizer="sgd",
metrics = ['accuracy'])
Donde especificamos que la funcion de loss es categorical_crossentropy, el optimizador usado es el stocastic gradient descent (sgd) y la metrica es accuracy, con la que evaluaremos el porcentaje de aciertos averiguando donde el modelo predice la etiqueta correcta.
Entrenamiento del modelo
Una vez definido nuestro modelo y configurado su metodo de aprendizaje, este ya esta listo para ser entrenado. Para ello podemos entrenar o ?ajustar? el modelo a los datos de entrenamiento de que disponemos invocando al metodo fit( ) del modelo:
model.fit(x_train, y_train, batch_size=100, epochs=5)
Donde en los dos primeros argumentos hemos indicado los datos con los que entrenaremos el modelo en forma de arrays Numpy. Con el argumento batch_size se indica el numero de datos que usaremos para cada actualizacion de los parametros del modelo y con epochs estamos indicando el numero de veces que usaremos todos los datos en el proceso de aprendizaje. Estos dos ultimos argumentos se explicaran con mucho mas detalle en el proximo capitulo.
Este metodo encuentra el valor de los parametros de la red mediante el algoritmo iterativo de entrenamiento que presentaremos con un poco mas de detalle en el siguiente capitulo. A grandes rasgos, en cada iteracion de este algoritmo, este coge datos de entrenamiento de x_train, los pasa a traves de la red neuronal (con los valores que en aquel momento tengan sus parametros), compara el resultado obtenido con el esperado (indicado en y_train) y calcula la loss para guiar el proceso de ajuste de los parametros del modelo, que intuitivamente consiste en aplicar el optimizador especificado anteriormente en el metodo compile() para calcular un nuevo valor de cada uno de los parametros (pesos y sesgos) del modelo en cada iteracion de tal forma de que se reduzca el de la loss.
Este es el metodo que, como veremos, puede llegar a tardar mas tiempo y Keras nos permite ver su avance usando el argumento verbose (por defecto, igual a 1), ademas de indicar una estimacion de cuanto tarda cada epoch:
Epoch 1/5
60000/60000 [==================] - 1s 15us/step - loss: 2.1822 - acc: 0.2916
Epoch 2/5
60000/60000 [==================] - 1s 12us/step - loss: 1.9180 - acc: 0.5283
Epoch 3/5
60000/60000 [==================] - 1s 13us/step - loss: 1.6978 - acc: 0.5937
Epoch 4/5
60000/60000 [==================] - 1s 14us/step - loss: 1.5102 - acc: 0.6537
Epoch 5/5
60000/60000 [==================] - 1s 13us/step - loss: 1.3526 - acc: 0.7034
10000/10000 [==================] - 0s 22us/step
Este es un ejemplo simple para que el lector al acabar el capitulo haya podido programar ya su primera red neuronal, pero como veremos el metodo fit( ) permite muchos mas argumentos que tienen un impacto muy importante en el resultado del aprendizaje. Ademas, este metodo retorna un objeto History que hemos omitido en este ejemplo. Su atributo History.history es el registro de los valores de loss para los datos de entrenamiento y resto de metricas en sucesivas epochs, asi como otras metricas para los datos de validacion si se han especificado. Mas adelante, en el capitulo 5 de la segunda parte del libro, veremos lo valioso de esta informacion para evitar por ejemplo el sobreajuste del modelo.
Evaluacion del modelo
En este punto ya se ha entrenado la red neuronal y ahora se puede evaluar como se comporta con datos nuevos de prueba (test) con el metodo evaluate(). Este devuelve dos valores:
test_loss, test_acc = model.evaluate(x_test, y_test)
Que indican como de bien o mal se comporta nuestro modelo con datos nuevos que nunca ha visto (que hemos almacenado en x_test y y_test cuando hemos realizado el mnist.load_data( ). De momento fijemonos solo en uno de ellos, la accuracy:
print('Test accuracy:', test_acc)
Test accuracy: 0.9018
Que nos esta indicando que el modelo que hemos creado en este capitulo aplicado sobre datos que nunca ha visto anteriormente, clasifica el 90% de ellos correctamente.
Debe el lector fijarse que, en este ejemplo, para evaluar este modelo solo nos hemos centrado en su accuracy, es decir la proporcion entre las predicciones correctas que ha hecho el modelo y el total de predicciones. Sin embargo, aunque en ocasiones resulta suficiente, otras veces es necesario profundizar un poco mas y tener en cuenta los tipos de predicciones correctas e incorrectas que realiza el modelo en cada una de sus categorias.
En el mundo de Machine Learning una herramienta para evaluar modelos es la matriz de confusion (confusion matrix), una tabla con filas y columnas que contabilizan las predicciones en comparacion con los valores reales. Usamos esta tabla para entender mejor como de bien el modelo se comporta y es muy util para mostrar de forma explicita cuando una clase es confundida con otra. Una matriz de confusion para un clasificador binario como el explicado al principio del capitulo tiene esta estructura:
En la que:
* VP es la cantidad de positivos que fueron clasificados correctamente como positivos por el modelo.
* VN es la cantidad de negativos que fueron clasificados correctamente como negativos por el modelo.
* FN es la cantidad de positivos que fueron clasificados incorrectamente como negativos.
* FP es la cantidad de negativos que fueron clasificados incorrectamente como positivos.
Con esta matriz de confusion, la accuracy se puede calcular sumando los valores de la diagonal y divido por el total:
Accuracy = (VP + VN) / (VP + FP + VN + TN)
Ahora bien, la accuracy puede ser enganosa en la calidad del modelo porque al medirla para el modelo concreto no distinguimos entre los errores de tipo falso positivo y falso negativo, como si ambos tuvieran la misma importancia. Por ejemplo, piensen en un modelo que predice si una seta es venenosa. En este caso, el coste de un falso negativo, es decir, una seta venenosa dada por comestible podria ser dramatico. En cambio al reves, un falso positivo, tiene un coste muy diferente.
Por ello tenemos otra metrica llamada Sensitivity (o recall) que nos indica como de bien el modelo evita los falsos negativos:
Sensitivity = VP / P = VP / (VP + FN)
Es decir, del total de observaciones positivas (setas venenosas), cuantas detecta el modelo.
A partir de la matriz de confusion se pueden obtener diversas metricas para focalizar otros casos como se muestra en este enlace111, pero queda fuera del alcance de este libro entrar mas detalladamente en este tema. La conveniencia de usar una metrica u otra dependera de cada caso en particular y, en concreto, del ?coste? asociado a cada error de clasificacion del modelo.
Pero el lector se preguntara como es esta matriz de confusion en nuestro clasificador, donde tenemos 10 posibles valores. En este caso les propongo usar el paquete Scikit-learn112 (que ya hemos mencionado anteriormente) para evaluar la calidad del modelo calculando la matriz de confusion113, presentada de la figura siguiente:
En este caso los elementos de la diagonal representan el numero de puntos en que la etiqueta que predice el modelo coincide con el valor real de la etiqueta, mientras que los otros valores nos indican los casos en que el modelo ha clasificado incorrectamente. Por tanto, cuanto mas altos son los valores de la diagonal mejor sera la prediccion. En este ejemplo, si el lector calcula la suma de los valores de la diagonal dividido por el total de valores de la matriz, observara que coincide con la accuracy que nos ha retornado el metodo evaluate().
En el GitHub del libro pueden encontrar el codigo usado para calcular esta matriz de confusion.
Generacion de predicciones
Finalmente, nos queda el paso de usar el modelo creado en los anteriores apartados para realizar predicciones sobre que digito representan nuevas images. Para ello Keras ofrece el metodo predict() de un modelo que ya ha sido previamente entrenado.
Para probar este metodo podemos elegir un elemento cualquiera, por ejemplo uno del conjunto de datos de test x_test. Por ejemplo elijamos el elemento 11 de este conjunto de datos x_test y veamos a que clase corresponde segun el modelo entrenado de que disponemos.
Antes vamos a ver la imagen para poder comprobar nosotros mismos si el modelo esta haciendo una prediccion correcta (antes de hacer el reshape anterior):
plt.imshow(x_test[11], cmap=plt.cm.binary)
Creo que el lector estara de acuerdo que en este caso se trata del numero 6.
Ahora comprobemos que el metodo predict() del modelo, ejecutando el siguiente codigo, nos lo predice correctamente el valor que acabamos de estimar nosotros que deberia predecir.
Para ello ejecutamos la siguiente linea de codigo:
predictions = model.predict(x_test)
Una vez calculado el vector resultado de la prediccion para este conjunto de datos podemos saber a que clase le da mas probabilidad de pertenencia mediante la funcion argmax de Numpy, que retorna el indice de la posicion que contiene el valor mas alto de la funcion. En concreto, para el elemento 11:
np.argmax(predictions[11])
6
Podemos comprobar imprimiendo el array:
print(predictions[11])
[0.06 0.01 0.17 0.01 0.05 0.04 0.54 0. 0.11 0.02]
Vemos que nos ha devuelto el indice 6, correspondiente a la clase ?6?, la que habiamos estimado nosotros.
Tambien podemos comprobar que el resultado de la prediccion es un vector cuya suma de todos sus componentes es igual a 1, como era de esperar. Para ello podemos usar:
np.sum(predictions[11])
1.0
Hasta aqui el lector ha podido crear su primer modelo en Keras que clasifica correctamente los digitos MNIST el 90% de las veces. En el siguiente capitulo vamos a presentar como funciona el proceso de aprendizaje y varios de los hiperparametros que podemos usar en una red neuronal para mejorar estos resultados. En el capitulo 4 veremos como podemos mejorar estos resultados de clasificacion usando redes neuronales convolucionales para el mismo ejemplo.
3 Como se entrena una red neuronal
En este capitulo vamos a presentar una vision intuitiva de los componentes principales del proceso de aprendizaje de una red neuronal. Ademas veremos algunos de los parametros e hiperparametros mas relevantes en Deep Learning. En la segunda parte del capitulo proponemos poner a prueba lo aprendido con una herramienta interactiva, y ver el comportamiento de una red neuronal cuando se le cambian los valores de los parametros e hiperparametros.
3.1 Proceso de aprendizaje de una red neuronal
Recordemos del capitulo anterior que una red neuronal esta formada de neuronas conectadas entre ellas; a su vez, cada conexion de nuestra red neuronal esta asociada a un peso que dictamina la importancia que tendra esa relacion en la neurona al multiplicarse por el valor de entrada.
Cada neurona tiene una funcion de activacion que define la salida de la neurona (recordemos la funcion sigmoid del capitulo anterior). La funcion de activacion se usa para introducir la no linealidad en las capacidades de modelado de la red (disponemos de varias opciones de funciones de activacion que presentaremos en la siguiente seccion).
Entrenar nuestra red neuronal, es decir, aprender los valores de nuestros parametros (pesos wij y sesgos bj) es la parte mas genuina de Deep Learning y podemos ver este proceso de aprendizaje en una red neuronal como un proceso iterativo de ?ir y venir? por las capas de neuronas. El ?ir? propagando hacia delante lo llamaremos forwardpropagation y el ?venir? retropropagando informacion en la red lo llamamos backpropagation.
La primera fase forwardpropagation se da cuando se expone la red a los datos de entrenamiento y estos cruzan toda la red neuronal para ser calculadas sus predicciones (labels). Es decir, pasar los datos de entrada a traves de la red de tal manera que todas las neuronas apliquen su transformacion a la informacion que reciben de las neuronas de la capa anterior y la envien a las neuronas de la capa siguiente. Cuando los datos hayan cruzado todas las capas, y todas sus neuronas han realizado sus calculos, se llegara a la capa final con un resultado de prediccion de la label para aquellos ejemplos de entrada.
A continuacion usaremos una funcion de loss para estimar la loss (o error) y para comparar y medir cuan bueno/malo fue nuestro resultado de la prediccion en relacion con el resultado correcto (recordemos que estamos en un entorno de aprendizaje supervisado y disponemos de la etiqueta que nos indica el valor esperado). Idealmente, queremos que nuestro coste sea cero, es decir, sin divergencia entre valor estimado y el esperado. Por eso a medida que se entrena el modelo se iran ajustando los pesos de las interconexiones de las neuronas de manera automatica hasta obtener buenas predicciones.
Una se tiene calculado la loss, se propaga hacia atras esta informacion. De ahi su nombre, retropropagacion, en ingles backpropagation. Partiendo de la capa de salida, esa informacion de loss se propaga hacia todas las neuronas de la capa oculta que contribuyen directamente a la salida. Sin embargo las neuronas de la capa oculta solo reciben una fraccion de la senal total de la loss, basandose aproximadamente en la contribucion relativa que haya aportado cada neurona a la salida original. Este proceso se repite, capa por capa, hasta que todas las neuronas de la red hayan recibido una senal de loss que describa su contribucion relativa a la loss total.
Visualmente, podemos resumir lo que hemos contado con este esquema visual de las etapas:
Ahora que ya hemos propagado hacia atras esta informacion, podemos ajustar los pesos de las conexiones entre neuronas. Lo que estamos haciendo es que la loss se aproxime lo mas posible a cero la proxima vez que volvamos usar la red para una prediccion. Para ello usaremos una tecnica llamada gradient descent. Esta tecnica va cambiando los pesos en pequenos incrementos con la ayuda del calculo de la derivada (o gradiente) de la funcion de loss, cosa que nos permite ver en que direccion ?descender? hacia el minimo global; esto lo va haciendo en general en lotes de datos (batches) en las sucesivas iteraciones (epochs) del conjunto de todos los datos que le pasamos a la red en cada iteracion.
Recapitulando, el algoritmo de aprendizaje consiste en:
* Empezar con unos valores (a menudo aleatorios ?random en ingles?) para los parametros de la red (pesos wij y sesgos bj)
* Coger un conjunto de ejemplos de datos de entrada y pasarlos por la red para obtener su prediccion.
* Comparar estas predicciones obtenidas con los valores de etiquetas esperadas y con ellas calcular la loss.
* Realizar el backpropagation para propagar esta loss a todos y cada uno de los parametros que conforman el modelo de la red neuronal.
* Usar esta informacion propagada para actualizar con el gradient descent los parametros de la red neuronal de manera que reduzca la loss total y obtener un mejor modelo.
* Continuar iterando en los anteriores pasos hasta que consideremos que tenemos un buen modelo (mas adelante veremos cuando debemos parar).
A continuacion presentamos en mas detalle de cada uno de los elementos que hemos destacado en esta seccion.
3.2 Funciones de activacion
Recordemos que usamos las funciones de activacion para propagar hacia adelante la salida de una neurona. Esta salida la reciben las neuronas de la siguiente capa a las que esta conectada esta neurona (hasta la capa de salida incluida). Como hemos comentado, la funcion de activacion sirve para introducir la no linealidad en las capacidades de modelado de la red. A continuacion vamos a enumerar las mas usadas en la actualidad; todas ellas pueden usarse en una capa de Keras (podemos encontrar mas informacion en su pagina web114).
Linear
La funcion de activacion linear es basicamente la funcion identidad en la que, en terminos practicos, significa que la senal no cambia.
Sigmoid
La funcion sigmoid fue introducida en el capitulo anterior y permite reducir valores extremos o atipicos en datos validos sin eliminarlos. Una funcion sigmoidea convierte variables independientes de rango casi infinito en probabilidades simples entre 0 y 1. La mayor parte de su salida estara muy cerca de los extremos de 0 o 1 (resulta importante que los valores esten en este rango en algunos tipos de redes neuronales).
Tanh
Del mismo modo que la tangente representa una relacion entre el lado opuesto y el adyacente de un triangulo rectangulo, tanh representa la relacion entre el seno hiperbolico y el coseno hiperbolico: tanh(x) = sinh(x)/cosh(x). A diferencia de la funcion sigmoid, el rango normalizado de tanh esta entre -1 y 1, que es la entrada que le va bien a algunas redes neuronales. La ventaja de tanh es que puede tratar mas facilmente con numeros negativos.
Softmax
La funcion de activacion softmax fue presentada en el capitulo anterior para generalizar la regresion logistica, en la medida de que en lugar de clasificar en binario puede contener multiples limites de decision. Como ya hemos visto, la funcion de activacion de softmax devuelve la distribucion de probabilidad sobre clases de salida mutuamente excluyentes. Softmax se encontrara a menudo en la capa de salida de un clasificador, tal como ocurre en el primero que el lector ha visto en el capitulo anterior.
ReLU
La funcion de activacion rectified linear unit (ReLU) es una transformacion muy interesante que activa un solo nodo si la entrada esta por encima de cierto umbral. El comportamiento por defecto y mas habitual es que mientras la entrada tenga un valor por debajo de cero, la salida sera cero, pero cuando la entrada se eleva por encima, la salida es una relacion lineal con la variable de entrada de la forma f (x) = x. La funcion de activacion ReLU ha demostrado funcionar en muchas situaciones diferentes, y actualmente es muy usada.
3.3 Elementos del backpropagation
En resumen, podemos ver el backpropagation como un metodo para alterar los parametros (pesos y sesgos) de la red neuronal en la direccion correcta. Empieza primero por calcular el termino de loss, y luego los parametros de la red neuronal son ajustados en orden reverso con un algoritmo de optimizacion teniendo en cuenta esta loss calculada.
Recordemos que en Keras se dispone del metodo compile() para definir como queremos que sean los componentes que intervienen en el proceso de aprendizaje:
model.compile(loss='categorical_crossentropy',
optimizer='sgd',
metrics=['accuracy'])
En concreto, en este ejemplo se le pasan tres argumentos: un optimizador, una funcion de loss y una lista de metricas. En los problemas de clasificacion como nuestro ejemplo se usa la accuracy como metrica. Entremos un poco mas en detalle de estos argumentos.
Funcion de loss
Una funcion de loss es uno de los parametros requeridos para cuantificar lo cercano que esta una determinada red neuronal de su ideal mientras esta en el proceso de entrenamiento.
En la pagina del manual de Keras115 podemos encontrar todos los tipos de funciones de loss disponibles en ella. Algunos tienen sus hiperparametros concretos que deben ser indicados; en el ejemplo del capitulo anterior, cuando usamos categorical_crossentropy como funcion de loss, nuestra salida debe ser en formato categorico, es decir que la variable de salida debe tomar un valor entre los 10 posibles. La eleccion de la mejor funcion de loss reside en entender que tipo de error es o no es aceptable para el problema en concreto.
Optimizadores
El optimizador es otro de los argumentos que se requieren en el metodo de compile(). Keras dispone en estos momentos de diferentes optimizadores que pueden usarse: SGD, RMSprop, Adagrad, Adadelta, Adam, Adamax, Nadam. Se puede encontrar mas detalle de cada uno de ellos en la documentacion de Keras116.
De forma general, podemos ver el proceso de aprendizaje como un problema de optimizacion global donde los parametros (los pesos y los sesgos) se deben ajustar de tal manera que la funcion de loss presentada anteriormente se minimice. En la mayoria de los casos, estos parametros no se pueden resolver analiticamente, pero en general se pueden aproximar bien con algoritmos de optimizacion iterativos u optimizadores, como los mencionados anteriormente.
Gradient descent
Vamos aqui a explicar uno de los optimizadores para que veamos su funcionamiento en general. Concretamente el gradient descent, la base de muchos y uno de los algoritmos de optimizacion mas comunes en Machine Learning y Deep Learning.
Gradient descent usa la primera derivada (gradiente) de la funcion de loss cuando realiza la actualizacion en los parametros. Recordemos que el gradiente nos da la pendiente de una funcion en ese punto. Sin poder entrar en detalle, el proceso consiste en encadenar las derivadas de la loss de cada capa oculta a partir de las derivadas de la loss de su capa superior, incorporando su funcion de activacion en el calculo (por eso las funciones de activacion deben ser derivables). En cada iteracion, una vez todas las neuronas disponen del valor del gradiente de la funcion loss que les corresponde, se actualizan los valores de los parametros en el sentido contrario a la que indica el gradiente. El gradiente, en realidad, siempre apunta en el sentido en la que se incrementa el valor de la funcion de loss. Por tanto, si se usa el negativo del gradiente podemos conseguir el sentido en que tendemos a reducir la funcion de loss.
Veamos el proceso de manera visual asumiendo solo una feature: supongamos que esta linea representa los valores que toma la funcion de loss para cada posible parametro y en el punto inicial indicado el negativo del gradiente se indica por la flecha:
Para determinar el siguiente valor para el parametro (para simplificar la explicacion, consideremos solo el peso/weight), el algoritmo de gradient descent modifica el valor del peso inicial para ir en sentido contrario al del gradiente (ya que este apunta en el sentido en que crece la loss y queremos reducirla), anadiendo una cantidad proporcional a este. La magnitud de este cambio esta determinado por el valor del gradiente y por un hiperparametro learning rate (que presentaremos en breve) que podemos especificar. Por lo tanto, conceptualmente es como si siguieramos la direccion de la pendiente cuesta abajo hasta que alcanzamos un minimo local:
El algoritmo gradient descent repite este proceso acercandose cada vez mas al minimo hasta que el valor del parametro llega a un punto mas alla del cual no puede disminuir la funcion de loss:
Mas adelante presentaremos maneras de parar este proceso iterativo.
Stochastic Gradient Descent (SGD)
De momento no hemos hablado sobre con que frecuencia se ajustan los valores de los parametros:
* Despues de cada ejemplo de entrada?
* Despues de cada recorrido sobre todo el conjunto de ejemplos de entrenamiento (epoch)?
* Despues de una muestra de ejemplos del conjunto de entrenamiento?
En el primer caso hablamos de online learning,cuando se estima el gradiente a partir de la loss observada para cada ejemplo del entrenamiento; tambien es cuando originalmente hablabamos de Stochastic Gradient Descent (SGD). Mientras que el segundo se conoce por batch learning y se llama Batch Gradient Descent. La literatura indica que se suele obtener mejores resultados con el online learning, pero existen motivos que justifican el batch learning porque muchas tecnicas de optimizacion solo funcionan con el.
Pero si los datos estan bien distribuidos, un pequeno subconjunto de ellos nos deberia dar una idea bastante buena del gradiente. Quizas no se obtenga su mejor estimacion, pero es mas rapido, y debido a que estamos iterando, esta aproximacion nos sirve; por esto se usa a menudo la tercera opcion antes mencionada conocida como mini-batch. Esta opcion suele ser mejor que la online y se requieren menos calculos para actualizar los parametros de la red neuronal. Ademas, el calculo simultaneo del gradiente para muchos ejemplos de entrada puede realizarse utilizando operaciones con matrices que se implementan de forma muy eficiente con GPU, como hemos visto en el capitulo 1.
Por eso, en realidad muchas aplicaciones usan el stochastic gradient descent (SGD) con un mini-bach de varios ejemplos. Para usar todos los datos lo que se hace es particionar los datos en varios lotes (que llamaremos batches). Entonces cogemos el primer batch, se pasa por la red, se calcula el gradiente de su loss y se actualizan los parametros de la red neuronal; esto seguiria sucesivamente hasta el ultimo batch. Ahora, en una sola pasada por todos los datos de entrada, se han realizado solo un numero de pasos igual que el numero de batches.
SGD es muy facil de implementar en Keras. En el metodo compile() se indica que el optimizador es SGD (valor sgd en el argumento), y entonces todo lo que se debe hacer es especificar el tamano de batch en el proceso de entrenamiento con el metodo fit() de la siguiente manera:
model.fit(X_train, y_train, epochs=5, batch_size=100)
Aqui, estamos dividiendo nuestros datos en batches de 100 con el argumento de batch_size. Con el numero de epochs estamos indicando cuantas veces realizamos este proceso sobre todos los datos. Mas adelante en este capitulo, cuando ya hayamos presentado los parametros habituales de los optimizadores, volveremos a hablar de estos dos argumentos.
3.4 Parametrizacion de los modelos
Si el lector al acabar el anterior capitulo ha creado un modelo con los hiperparametros que alli usamos, supongo que la accuracy del modelo (es decir, el numero de veces que acertamos respecto el total) le habra salido sobre el 90%. Son buenos estos resultados? Yo creo que son fantasticos, porque significa que el lector ya ha programado y ejecutado suÿprimera red neuronal con Keras. Congratulations!
Otra cosa es que haya modelos que permiten mejorar la accuracy. Y esto depende de tener mucho conocimiento y practica para manejarse bien con los muchos hiperparametros que podemos cambiar: por ejemplo, con un simple cambio de la funcion de activacion de la primera capa, pasando de una sigmoid a una relu:
model.add(Dense(10, activation='relu', input_shape=(784,)))
Podemos obtener un 2% mas de accuracy con un tiempo de calculo aproximadamente el mismo.
Tambien es posible aumentar el numero de epochs, agregar mas neuronas en una capa o agregar mas capas. Sin embargo, en estos casos las ganancias en accuracy tienen el efecto lateral de que aumenta el tiempo de ejecucion del proceso de aprendizaje. Por ejemplo, si a la capa intermedia en vez de 10 nodos le ponemos 512 nodos:
model.add(Dense(512, activation='relu', input_shape=(784,)))
Podemos comprobar con el metodo summary() que aumenta el numero de parametros (recordemos que es una fully connected) y el tiempo de ejecucion es notablemente superior, incluso reduciendo el numero de epochs. Con este modelo la accuracy, llega a 94%. Y si aumentamos a 20 epochs ya se consigue una accuracy de 96%.
En definitiva, todo un mundo de posibilidades que veremos con mas detalle en los siguientes capitulos, pero que el lector ya puede irse dando cuenta de que encontrar la mejor arquitectura con los mejores parametros e hiperparametros de las funciones de activacion requiere cierta pericia y experiencia dadas las multiples posibilidades que veremos que tenemos.
Parametros e hiperparametros
Hasta ahora, por simplicidad, no hemos puesto atencion explicita a diferenciar entre parametros e hiperparametros, pero creo que ha llegado el momento. En general, consideramos un parametro del modelo como una variable de configuracion que es interna al modelo y cuyo valor puede ser estimado a partir de los datos. En cambio, por hiperparametro nos referimos a variables de configuracion que son externas al modelo en si mismo y cuyo valor en general no puede ser estimado a partir de los datos, y son especificados por el programador para ajustar los algoritmos de aprendizaje.
Cuando digo que Deep Learning es mas un arte que una ciencia me refiero a que se requiere mucha experiencia e intuicion para encontrar los valores optimos de estos hiperparametros, que se deben especificar antes de iniciar el proceso de entrenamiento para que los modelos entrenen mejor y mas rapidamente.
Dado el caracter introductorio del libro no entraremos en detalle sobre todos ellos, pero tenemos hiperparametros que vale la pena comentar brevemente, tanto a nivel de estructura y topologia de la red neuronal (numero de capas, numero de neuronas, sus funciones de activacion, etc) como hiperparametros a nivel de algoritmo de aprendizaje (learning rate, momentum, epochs, batch size, etc).
A continuacion, vamos a introducir alguno de ellos y el resto iran apareciendo en los siguientes capitulos a medida que vayamos entrando en redes neuronales convolucionales y redes neuronales recurrentes.
Numero de epochs
Como ya hemos avanzado, epochs nos indica el numero de veces en las que todos los datos de entrenamiento han pasado por la red neuronal en el proceso de entrenamiento. Como presentaremos mas adelante, una buena pista es incrementar el numero de epochs hasta que la metrica accuracy con los datos de validacion empieza a decrecer, incluso cuando la accuracy de los datos de entrenamiento continua incrementandose (es cuando detectamos un potencial sobreajuste u overfitting).
Batch size
Tal como hemos comentado antes, podemos particionar los datos de entrenamiento en mini lotes para pasarlos por la red. En Keras, como hemos visto, el batch_size es el argumento que indica el tamano que se usara de estos lotes en el metodo fit() en una iteracion del entrenamiento para actualizar el gradiente. El tamano optimo dependera de muchos factores, entre ellos de la capacidad de memoria del computador que usemos para hacer los calculos.
Learning rate
El vector de gradiente tiene una direccion y una magnitud. Los algoritmos de gradient descent multiplican la magnitud del gradiente por un escalar conocido como learning rate (tambien denominado a veces step size) para determinar el siguiente punto; por ejemplo, si la magnitud del gradiente es 1,5 y el learning rate es 0,01, entonces el algoritmo de gradient descent seleccionara el siguiente punto a 0,015 del punto anterior.
El valor adecuado de este hiperparametro es muy dependiente del problema en cuestion, pero en general, si este es demasiado grande, se esta dando pasos enormes que podria ser bueno para ir rapido en el proceso de aprendizaje, pero es posible que se salte el minimo y dificultar asi que el proceso de aprendizaje se detenga porque al buscar el siguiente punto perpetuamente rebota al azar en el fondo del ?pozo?. Visualmente se aprecia en esta figura el efecto que puede producirse, en que nunca se llega al valor minimo (indicado con una pequena flecha en el dibujo):
Contrariamente, si el learning rate es pequeno, se haran avances constantes y pequenos, teniendose una mejor oportunidad de llegar a un minimo local, pero esto puede provocar que el proceso de aprendizaje sea muy lento. En general, una buena regla es si nuestro modelo de aprendizaje no funciona, disminuir la learning rate. Si sabemos que el gradiente de la funcion de loss es pequeno, entonces es seguro probar con learning rate que compensen el gradiente.
Learning rate decay
Ahora bien, el mejor learning rate en general es aquel que disminuye a medida que el modelo se acerca a una solucion. Para conseguir este efecto, disponemos de otro hipermarametro, el learning rate decay, que se usa para disminuir el learning rate a medida que van pasando epochs para permitir que el aprendizaje avance mas rapido al principio con learning rates mas grandes. A medida que se avanza, se van haciendo ajustes cada vez mas pequenos para facilitar que converja el proceso de entrenamiento al minimo de la funcion loss.
Momentum
En el ejemplo visual con el que hemos explicado el algoritmo de gradient descent, para minimizar la funcion de loss se tiene la garantia de encontrar el minimo global porque no hay un minimo local en el que su optimizacion se pueda atascar. Sin embargo, en realidad, los casos reales son mas complejos y visualmente es como si nos pudieramos encontrar con varios minimos locales y la funcion loss tuviera una forma como la de la siguiente figura:
En este caso, el optimizador puede quedarse atascado facilmente en un minimo local y el algoritmo puede pensar que se ha alcanzado el minimo global, lo que lleva a resultados suboptimos. El motivo es que en el momento en que nos atascamos, el gradiente es cero, y ya no podemos salir del minimo local siguiendo estrictamente lo que hemos contado de guiarnos por el gradiente.
Una manera de solventar esta situacion podria ser reiniciar el proceso desde diferentes posiciones aleatorias y, de esta manera, incrementar la probabilidad de llegar al minimo global.
Para evitar esta situacion, otra solucion que generalmente se utiliza involucra el hiperparametro momentum. De manera intuitiva, podemos verlo como si un avance tomara el promedio ponderado de los pasos anteriores para obtener asi un poco de impetu y superar los ?baches? como una forma de no atascarse en los minimos locales. Si consideramos que el promedio de los anteriores eran mejores, quizas nos permita hacer el salto.
Pero usar la media ha demostrado ser una solucion muy drastica, porque quizas en gradientes anteriores es mucho menos relevante que justo en el gradiente anterior. Por eso se ha optado por ponderar los anteriores gradientes, y el momentum es una constante entre 0 y 1 que se usa para esta ponderacion. Se ha demostrado que los algoritmos que usan momentum funcionan mejor en la practica.
Una variante es el Nesterov momentum, que es una version ligeramente diferente de la actualizacion del momentum que muy recientemente ha ganado popularidad y que basicamente ralentiza el gradiente cuando esta ya cerca de la solucion.
Pero dado el caracter introductorio del libro, descarto entrar entrar en mas detalle en explicar este hiperparametro.
Inicializacion de los pesos de los parametros
La inicializacion del peso de los parametros no es exactamente un hiperparametro, pero es tan importante como cualquiera de ellos y por eso hacemos un breve inciso en esta seccion. Es recomendable inicializar los pesos con unos valores aleatorios y pequenos para romper la simetria entre diferentes neuronas, puesto que si dos neuronas tienen exactamente los mismos pesos siempre tendran el mismo gradiente; eso supone que ambas tengan los mismos valores en las subsecuentes iteraciones, por lo que no seran capaces de aprender caracteristicas diferentes.
El inicializar los parametros de forma aleatoria siguiendo una distribucion normal estandar es correcto, pero nos puede provocar posibles problemas de vanishing gradients o exploding gradients, que trataremos en el capitulo 7. En general se pueden usar heuristicas teniendo en cuenta el tipo de funciones de activacion que tiene nuestra red. Queda fuera del nivel introductorio de este libro entrar en estos detalles, pero si el lector quiere profundizar un poco mas le propongo que visite la pagina web del curso CS231n117 de Andrej Karpathy en Stanford, donde encontrara conocimientos muy valiosos en esta area expuestos de manera muy didactica (en ingles).
Hiperparametros y optimizadores en Keras
Como podemos especificar estos hiperparametros? Recordemos que el optimizador es uno de los argumentos que se requieren en el metodo compile() del modelo; hasta ahora los hemos llamado por su nombre (con un simple strings que los identifica). Pero Keras permite tambien pasar como argumento una instancia de la clase optimizer con la especificacion de alguno hiperparametros.
Por ejemplo el optimizador stochastic gradient descent permite usar los hiperparametros momentum, learning rate decay y Nesterov momentum. En concreto:
keras.optimizers.SGD(lr=0.01, momentum=0.0, decay=0.0, nesterov=False)
Los valores indicados en los argumentos del anterior metodo son los que toma por defecto y cuyo rango pueden ser:
* lr: float >= 0. (learning rate)
* momentum: float >= 0
* decay: float >= 0 (learning rate decay).
* nesterov: boolean (que indica si usar o no Nesterov momentum).
Como hemos dicho, hay varios optimizadores en Keras que el lector puede explorar en su pagina de documentacion118.
3.5 Practicando con una clasificacion binaria
Dado el caracter introductorio de este libro, una herramienta muy interesante que puede ser de ayuda al lector para ver como se comporta una red neuronal y poner en practica alguno de los conceptos aqui presentados sin tener que entrar en las matematicas que hay detras es TensorFlow Playground119.