{"cells":[{"metadata":{"_uuid":"acec03a5349f652365134989c150cbdf28ba2076","trusted":true},"cell_type":"code","source":"%reload_ext autoreload\n%autoreload 2\n%matplotlib inline","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"5d52707f344f0dcfe5baa73532d64fc3456e06c6"},"cell_type":"markdown","source":"# HispanIA DL: 1 (fastai v3)"},{"metadata":{"_uuid":"fe57324f4745fb9d4383198da02a202031625fbb"},"cell_type":"markdown","source":"## Competición: 'Dogs vs Cats'"},{"metadata":{"_uuid":"dbac44c46ab037faf84621b6c1a8d582b7ef31a4"},"cell_type":"markdown","source":"Vamos a crear una solución para la competicion \"Dogs vs Cats\" de Kaggle. Hay 25000 imágenes de perros y gatos, de las cuales 12500 son para el validation set. \n\nEn el momento en que la competición fue lanzada (2013), el estado del arte estaba en el 80% de precisión. Por lo que si batimos esta marca, estaríamos construyendo un modelo top del año 2013.\n"},{"metadata":{"_uuid":"23458afac17c6c5ab691b5bad3e1292082539bfc","trusted":true},"cell_type":"code","source":"from fastai.vision import *\nfrom fastai.datasets import *\nfrom fastai.metrics import *\n\nimport numpy as np\nimport pandas as pd\nimport os\nimport re\n\nimport matplotlib.pyplot as plt","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"276daac1c68af55ffc03e89d20c853bdf23e8522","trusted":true},"cell_type":"code","source":"PATH = \"../input/\"\npath_img = f'{PATH}train/'","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"df06b77a10811933d38e3fdcf019937b73f2dc5b"},"cell_type":"code","source":"os.listdir(PATH)","execution_count":null,"outputs":[]},{"metadata":{"heading_collapsed":true,"_uuid":"e7371d1918f4903352b82bb8f4b2ca55fa4386ca"},"cell_type":"markdown","source":"## Echamos un vistazo a las imagenes"},{"metadata":{"hidden":true,"scrolled":false,"_uuid":"ee3a6d31ba52de6d1f294998d48b56073ee31604","trusted":true},"cell_type":"code","source":"# os.listdir(path_img)","execution_count":null,"outputs":[]},{"metadata":{"hidden":true,"_uuid":"a9fb6a8048fa18c65800b1865876bf8cccfa0e86","trusted":true},"cell_type":"code","source":"fnames = get_image_files(path_img)\nfnames[:5]","execution_count":null,"outputs":[]},{"metadata":{"hidden":true,"_uuid":"09f87570c2cd82eb3eed603565240021a5a888fe","trusted":true},"cell_type":"code","source":"img = plt.imread(f'{fnames[-1]}')\nplt.imshow(img);","execution_count":null,"outputs":[]},{"metadata":{"hidden":true,"_uuid":"1d87111c18c0cb0b3326f8e5ff61e18651c13b40"},"cell_type":"markdown","source":"Las imagenes tienen esta pinta:"},{"metadata":{"hidden":true,"_uuid":"5ba79cbbb1fbab9dbcbc35834f62a8b024942d2e","trusted":true},"cell_type":"code","source":"img.shape","execution_count":null,"outputs":[]},{"metadata":{"hidden":true,"_uuid":"cfef74b040d59c22cb769c6cdfa5cb9cf40066cf","trusted":true},"cell_type":"code","source":"img[:4,:4]","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"b65b1afd1a6218affcfd38b0c254454d0ac20d54"},"cell_type":"markdown","source":"## Organizando nuestros datos (imagenes y labels) mediante ImageDataBunch"},{"metadata":{"trusted":true,"_uuid":"7d1f3402674112a9a362f7ed73611cb9428f8ce1"},"cell_type":"code","source":"np.random.seed(33)\npattern = re.compile(r'/([^/]+)\\.\\d+.jpg$')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"783d1a0c5c036dab4b9f2a613d28064d4481f537"},"cell_type":"code","source":"data = ImageDataBunch.from_name_re(\n    path_img, fnames, pattern, ds_tfms=get_transforms(), size=150, bs=32\n                                  ).normalize(imagenet_stats)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"42624c2d7f4549128cdc03d4f55fc2eafa92c95b"},"cell_type":"code","source":"data.show_batch(rows=3, figsize=(7,6))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"866e505f9db858ac034df6f7c2296b354d68a9c9"},"cell_type":"code","source":"print(data.classes)\nlen(data.classes),data.c","execution_count":null,"outputs":[]},{"metadata":{"heading_collapsed":true,"_uuid":"500f86792c2bd9c9373d883eb301b74219a9b2a7"},"cell_type":"markdown","source":"## El modelo: ResNet-34 pre-entrenado"},{"metadata":{"_uuid":"d5b84f890ea5f0b217578256ed6e3bc1b4741b9e"},"cell_type":"markdown","source":"Utilizaremos una CNN (convolutional neural network) pre-entrenada, una red neuronal **creada** y **entrenada** por otra persona que resolvía un problema de una naturaleza parecida. \n\nResNet esta basado en [las capas residuales](https://github.com/KaimingHe/deep-residual-networks). Estas capas residuales son como las capas convecionales pero con la peculiaridad de que el input en crudo pasa a ser parte del output."},{"metadata":{"_uuid":"e57ebf25753d62ef39575283dbf9922c1c76f589"},"cell_type":"markdown","source":"### Arquitectura de la ResNet-34 ### \n[Visualizacion del modelo](http://ethereon.github.io/netscope/#/gist/db945b393d40bfa26006)\n![](https://cdn-images-1.medium.com/max/800/1*4tlPOipWjcwIoNUlQ6IWFQ.png)"},{"metadata":{"_uuid":"17781389ec65ca7afc3e3a737f136790fd6e49dd"},"cell_type":"markdown","source":"Con tan solo **1 linea** tenemos nuestro modelo pre-entrenado:\n\nNota: La siguiente línea descarga de internet el modelo ResNet-34 (arquitectura y pesos) y los guarda en la variables 'learn'. Necesitamos el parámetro *path* para indicarle en qué carpeta guardar dicho modelo. "},{"metadata":{"hidden":true,"scrolled":false,"_uuid":"34c2f123f94ac01f68f8ab36a2943486fbe35ab5","trusted":true},"cell_type":"code","source":"learn = create_cnn(data, models.resnet34, metrics=accuracy, path='./')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"c037b1d68febc042578adf68c9fa8a88779db1db"},"cell_type":"code","source":"learn.fit_one_cycle(1) # Aqui falta LR","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"cecf47a1c3046bf3f9084f0cc21405923b255138"},"cell_type":"code","source":"learn.save('stage-1')","execution_count":null,"outputs":[]},{"metadata":{"hidden":true,"_uuid":"3fd2cdb6e89c1163a19008ce233445b192db8d9a"},"cell_type":"markdown","source":"## **98% de precisión** con unas pocas lineas, increible ##\n\n**Con este resultado, habríamos ganado la competición de Kaggle del 2013** con unos pocos segundos y 3 líneas de código:\n\n![](https://i.gyazo.com/b3cc85c6f5cfcd2c096fa884e6ba60ab.png)\n\nEl estado del arte previo a esta competición estaba en una precisión  del 80%. Gracias a esta competición el SOTA dió un gran salto al 98.9% de precisión. Ahora, 4 años más tarde y gracias a fastai, podemos acercarnos muchísimo e incluso batir dicho resultado en apenas unos minutos y con muy pocas lineas de código.\n"},{"metadata":{"_uuid":"2d48d56c7ecf690e49da4705967193f39e68956d"},"cell_type":"markdown","source":"## Ejemplos de clasificadores de imagenes ##\n\n* AlphaGo.\n\n* Splunk.com: detectando transacciones fraudulentas a partir del movimiento del ratón\n\n* Google deepmind redució  en un 40% la factura de la luz de los centros de datos de Google. [Enlace](https://deepmind.com/blog/deepmind-ai-reduces-google-data-centre-cooling-bill-40/)\n\n* Diagnosticando cancer de pulmón\n![](https://cdn-images-1.medium.com/max/800/1*_E0tiKelpZ3_7u0rOo6T5A.png)\n\n* Otro ejemplo:\n\n![](https://cdn-images-1.medium.com/max/800/1*BFG_B7UpS3AvJxE6lH0lug.gif)"},{"metadata":{"_uuid":"0ff7696ba224ae48f93b61a1e5acba8a5bb1416f"},"cell_type":"markdown","source":"## Deep learning: la solución 'definitiva' ##\n\n**Una combinación de capa lineal seguida de una función no lineal a nivel de elementos nos permite crear formas arbitrariamente complejas; esta es la esencia del teorema de aproximación universal.**\n\n![](https://cdn-images-1.medium.com/max/800/1*R4qix1l4TjKOrLkrA4t6EA.png)"},{"metadata":{"_uuid":"ead45a2036e6b55799041e41a210bf8a06f72a05"},"cell_type":"markdown","source":"## La librería fast.ai ##\n\nJeremy ha construido una librería potentísima en la que, con tan solo 3 líneas de código, podemos construir un clasificador de imágenes de calidad *world-class*, consiguiendo resultados top con muy pocas líneas de código.\n\nLa librería fast.ai auna todas las mejores prácticas de deep learning que van saliendo a la luz. Cada vez que sale algún nuevo paper con alguna técnica prometedora, Jeremy lo implementa y lo prueba. Si ve que funciona correctamente, lo adapta ala librería para que la podamos usar de manera super sencilla, automatizando la mayoría de cosas y encargándose de toda la parte engorrosa del deep learning.\n\nFast.ai está escrita sobre la librería PyTorch. La mayoría de gente la única librería que conoce es TensorFlow. Pero Jeremy dice que, hoy en día, la mayoría de investigadores que él conoce utilizan PyTorch.\n\nFast.ai junta todas las mejores prácticas del deep learning y las pone a disposición de todo el mundo de manera gratuita.\n\n"},{"metadata":{"_uuid":"e7e545849f872efb01089c80a8188dec0d0f6f96"},"cell_type":"markdown","source":"# Analizando e intepretando los resultados. *ClassificationInterpretation*"},{"metadata":{"trusted":true,"_uuid":"b8431af8e254c4e7c690aea286e19a626b30ce61"},"cell_type":"code","source":"interp = ClassificationInterpretation.from_learner(learn)\n\nlosses,idxs = interp.top_losses()\n\nlen(data.valid_ds)==len(losses)==len(idxs)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"d6b2ff221a8a3071bbd1016a4a848d04db086d19"},"cell_type":"code","source":"interp.plot_top_losses(9, figsize=(15,11))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"8bd6be963b94750b6ac9d17ffebb2e3edca742f4"},"cell_type":"code","source":"interp.plot_confusion_matrix(figsize=(6,6), dpi=80)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"345f66038ad8f6faf4d238264ddb509521799947"},"cell_type":"code","source":"interp.most_confused(min_val=2)","execution_count":null,"outputs":[]},{"metadata":{"heading_collapsed":true,"_uuid":"9881009afc9dae99a579b5d7409dbc662a61b638"},"cell_type":"markdown","source":"## Unfreezing, fine-tuning y learning-rates"},{"metadata":{"_uuid":"809801a1825ae9f4e2142558256a338b88e56872"},"cell_type":"markdown","source":"### Learning rate ## \nJeremy ha implementado una técnica para encontrar el learning rate más adecuado para cada problema. Es de un paper que encontró, que no mucha gente conoce y que es muy util a la hora de afinar al máximo nuestro modelo.l"},{"metadata":{"trusted":true,"_uuid":"b602dd8c812513d8270afe4cf296fb694a1ca6ab"},"cell_type":"code","source":"learn.lr_find()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"f1603923188c0708a8d5bd3dbcead32ea339b190"},"cell_type":"code","source":"learn.recorder.plot()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"e824110b17ebc73ced152b5e4f1db9c8cf203db9"},"cell_type":"markdown","source":"### Unfreeze y fine-tuning ###"},{"metadata":{"hidden":true,"_uuid":"14336cf080fda4f6c9ef0f6b1d59367353e3129d"},"cell_type":"markdown","source":"Cuando hemos cargado el modelo **resnet-34** implicitamente fastai ha *congelado*  todos los layers de la red neuronal **excepto la última**. Es decir, fastai no permite que los pesos de las capas congeladas se reajusten y sólo ha dejado que se entrene la última capa del modelo.\n\nEs improbable que las primeras capas de la ResNet-34  necesiten ser reentrenadas, ya que estas capas detectan las formas más básicas de una imagen:\n* La primera capa detecta bordes\n* La segunda capa reconoce curvas y esquinas.\n\nPor lo tanto, no necesitan ser modificadas.\n\n<img src=\"https://image.slidesharecdn.com/practicaldeeplearning-160329181459/95/practical-deep-learning-16-638.jpg\" width=\"500\">\n\nSin embargo, no ocurre lo mismo con las últimas capas, las cuales es más probable que necesiten reentrenarse\n\n**Unfreezing**: cuando descongelamos todas las capas"},{"metadata":{"hidden":true,"_uuid":"5564b4234690421173ae39c0838d84ad119b0d16","trusted":true},"cell_type":"code","source":"learn.unfreeze()","execution_count":null,"outputs":[]},{"metadata":{"hidden":true,"scrolled":true,"_uuid":"9c6b0f525504ab510c3b7eb93f86abf57c85780c","trusted":true},"cell_type":"code","source":"learn.fit_one_cycle(2, max_lr=slice(1e-5,1e-3))","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"3fe987419c743a3c9e697b19c38e9fb23af371ee"},"cell_type":"markdown","source":"¡Ha mejorado bastante!"},{"metadata":{"_uuid":"024b2e25cde14909fc692f8580ebf1efe654c895"},"cell_type":"markdown","source":"## Visualizando una CNN ##"},{"metadata":{"_uuid":"44f8673f06038b8417eeae7601e3efb339cd81c9"},"cell_type":"markdown","source":"![](https://cdn-images-1.medium.com/max/800/1*RPakI9UqMTYmGIm4ELhh6w.png)"},{"metadata":{"_uuid":"aa8efdb05fb90019eeb1ae6f3550692809830729"},"cell_type":"markdown","source":"[¿Cómo funciona una CNN? KERNELS](http://setosa.io/ev/image-kernels/)"},{"metadata":{"trusted":true,"_uuid":"6bc6788367c987f6a14356b142dd783267291e82"},"cell_type":"markdown","source":"## Probemos con ResNet-50"},{"metadata":{"trusted":true,"_uuid":"77d1f68bfc6a30fb4805a59e193f8c956a2ac994"},"cell_type":"code","source":"data = ImageDataBunch.from_name_re(path_img, fnames, pattern, ds_tfms=get_transforms(),\n                                   size=150, bs=16).normalize(imagenet_stats)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"a6042626bba4b8a008a61f5c65e41102462416c1"},"cell_type":"code","source":"learn = create_cnn(data, models.resnet50, metrics=accuracy, path='./')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"276559642fc03ec86d6092e7683c95a0448d1834"},"cell_type":"code","source":"learn.lr_find()\nlearn.recorder.plot()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"3a04857143d87e3c78821f74bda446c0a6a3be17"},"cell_type":"code","source":"learn.fit_one_cycle(4)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"05fd0da93ff1519550ca4931bfe9142b6c2f56cb"},"cell_type":"code","source":"learn.save('stage-1-50')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"581cca7d3a886664300c08bac92ec2d832d7b615"},"cell_type":"code","source":"learn.unfreeze()\nlearn.fit_one_cycle(3, max_lr=slice(1e-5,1e-2))","execution_count":null,"outputs":[]},{"metadata":{"heading_collapsed":true,"_uuid":"3e3db3bd9fe817641063ff0e37bfb4bcf6b33967"},"cell_type":"markdown","source":"## Resumen: los pasos para construir un clasificador top mundial"},{"metadata":{"hidden":true,"_uuid":"54eef5b76bc4e37be5aee47b7eab68fe04bea567"},"cell_type":"markdown","source":"1. Usamos `lr_find()` para encontrar el learning rate más alto en el que el modelo está claramente mejorando.\n1. Entrenar la última capa 1 o 2 epochs.\n1. Learner.Unfreeze\n1. Entrenar toda la red neuronal con cycle_mult=2 hasta que tengamos over-fitting"},{"metadata":{"heading_collapsed":true,"_uuid":"1c8befa45315236b9d6dd4a914dc0f92e796539e"},"cell_type":"markdown","source":"## ¿Qué es una red neuronal? ##"},{"metadata":{"_uuid":"6a5d2d90e6c23aab3a9c08b965498cb5367dd03d"},"cell_type":"markdown","source":"Lo único que tenemos que saber por ahora es que una red neuronal es una función que puede resolver cualquier problema con una precisión proporcional al número de parámetros que tenga dicha red (Teorema de Aproximación Universal)\n\nUna red neuronal consiste en una cantidad determinada de capas de funciones lineales simples entremezcladas por otras capas de funciones no-lineales simples.\n\n![](https://cdn-images-1.medium.com/max/800/1*0YOpyzGWkrS4VW3ntJRQ5Q.png)"},{"metadata":{"collapsed":true,"hidden":true,"_uuid":"288b455ed693196360ce02d77bcf321cc0d76ede","trusted":false},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.6.6","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"toc":{"colors":{"hover_highlight":"#DAA520","navigate_num":"#000000","navigate_text":"#333333","running_highlight":"#FF0000","selected_highlight":"#FFD700","sidebar_border":"#EEEEEE","wrapper_background":"#FFFFFF"},"moveMenuLeft":true,"nav_menu":{"height":"266px","width":"252px"},"navigate_menu":true,"number_sections":true,"sideBar":true,"threshold":4,"toc_cell":false,"toc_section_display":"block","toc_window_display":false,"widenNotebook":false}},"nbformat":4,"nbformat_minor":1}