Notice: Function _load_textdomain_just_in_time was called incorrectly. Translation loading for the wp-plugin-bluehost domain was triggered too early. This is usually an indicator for some code in the plugin or theme running too early. Translations should be loaded at the init action or later. Please see Debugging in WordPress for more information. (This message was added in version 6.7.0.) in /home1/spotsail/public_html/martra/wp-includes/functions.php on line 6114

Warning: Cannot modify header information - headers already sent by (output started at /home1/spotsail/public_html/martra/wp-includes/functions.php:6114) in /home1/spotsail/public_html/martra/wp-includes/rest-api/class-wp-rest-server.php on line 1893

Warning: Cannot modify header information - headers already sent by (output started at /home1/spotsail/public_html/martra/wp-includes/functions.php:6114) in /home1/spotsail/public_html/martra/wp-includes/rest-api/class-wp-rest-server.php on line 1893

Warning: Cannot modify header information - headers already sent by (output started at /home1/spotsail/public_html/martra/wp-includes/functions.php:6114) in /home1/spotsail/public_html/martra/wp-includes/rest-api/class-wp-rest-server.php on line 1893

Warning: Cannot modify header information - headers already sent by (output started at /home1/spotsail/public_html/martra/wp-includes/functions.php:6114) in /home1/spotsail/public_html/martra/wp-includes/rest-api/class-wp-rest-server.php on line 1893

Warning: Cannot modify header information - headers already sent by (output started at /home1/spotsail/public_html/martra/wp-includes/functions.php:6114) in /home1/spotsail/public_html/martra/wp-includes/rest-api/class-wp-rest-server.php on line 1893

Warning: Cannot modify header information - headers already sent by (output started at /home1/spotsail/public_html/martra/wp-includes/functions.php:6114) in /home1/spotsail/public_html/martra/wp-includes/rest-api/class-wp-rest-server.php on line 1893

Warning: Cannot modify header information - headers already sent by (output started at /home1/spotsail/public_html/martra/wp-includes/functions.php:6114) in /home1/spotsail/public_html/martra/wp-includes/rest-api/class-wp-rest-server.php on line 1893

Warning: Cannot modify header information - headers already sent by (output started at /home1/spotsail/public_html/martra/wp-includes/functions.php:6114) in /home1/spotsail/public_html/martra/wp-includes/rest-api/class-wp-rest-server.php on line 1893
{"id":2439,"date":"2022-07-25T10:06:20","date_gmt":"2022-07-25T10:06:20","guid":{"rendered":"https:\/\/martra.uadla.com\/?p=2439"},"modified":"2022-07-25T10:33:37","modified_gmt":"2022-07-25T10:33:37","slug":"preparando-la-certificacion-tensorflow-developer-by-google-2-transfer-learning-image-classification","status":"publish","type":"post","link":"https:\/\/martra.uadla.com\/preparando-la-certificacion-tensorflow-developer-by-google-2-transfer-learning-image-classification\/","title":{"rendered":"Preparando la certificaci\u00f3n Tensorflow Developer by Google. 2-Transfer learning & image classification."},"content":{"rendered":"\n

En el primer post de preparar la certificaci\u00f3n de TensorFlow Developer<\/a>, vimos el notebook preparado para solucionar un problema de clasificaci\u00f3n de im\u00e1genes multiples usando el dataset Fashion MNIST que viene con Tensorflow. <\/p>\n\n\n\n

En el notebook actual voy a usar un Dataset muy conocido, el de gatos y perros de Microsoft, opara solucionar un problema de clasificaci\u00f3n binaria. El Dataset muy diferente al usado en el notebook anterior. No tan solo por el tama\u00f1o de las im\u00e1genes. Este debe descargarse un fichero .zip, descomprirlo en el disco y cargar las imagines usando un ImageDataGenerator. Una t\u00e9cnica que no se vio en el ejemplo anterior. <\/p>\n\n\n\n

Puntos cubiertos del examen TensorFlow Developer en el notebook. <\/h3>\n\n\n\n

(2) Building and training neural network models using TensorFlow 2.x<\/strong>
\u274f Build, compile and train machine learning (ML) models using TensorFlow.
\u274f Preprocess data to get it ready for use in a model.<\/mark>
\u274f Use models to predict results.
\u274f Build sequential models with multiple layers.<\/mark>
\u274f Build and train models for binary classification.<\/mark>
\u274f Build and train models for multi-class categorization.
\u274f Plot loss and accuracy of a trained model.<\/mark>
\u274f Identify strategies to prevent overfitting, including augmentation and dropout.
\u274f Use pretrained models (transfer learning).<\/mark>
\u274f Extract features from pre-trained models.
\u274f Ensure that inputs to a model are in the correct shape.
\u274f Ensure that you can match test data to the input shape of a neural network.
\u274f Ensure you can match output data of a neural network to specified input shape for test data.
\u274f Understand batch loading of data.<\/mark>
\u274f Use callbacks to trigger the end of training cycles.
\u274f Use datasets from different sources.
\u274f Use datasets in different formats, including json and csv.
\u274f Use datasets from tf.data.datasets.<\/p>\n\n\n\n

(3) Image classification
<\/strong>\u274f Define Convolutional neural networks with Conv2D and pooling layers.
\u274f Build and train models to process real-world image datasets.
\u274f Understand how to use convolutions to improve your neural network.
\u274f Use real-world images in different shapes and sizes..
\u274f Use image augmentation to prevent overfitting.
\u274f Use ImageDataGenerator.
\u274f Understand how ImageDataGenerator labels images based on the directory structure.<\/mark><\/p>\n\n\n\n

He intentado cubrir todas las marcadas en amarillo en el Notebook IMAGERecog.ipynb<\/a> disponible en el repositorio de GitHub<\/a> donde est\u00e1n todos los notebooks preparados para el examen de TensorFlow Developer. <\/p>\n\n\n\n

Contenido y estructura del notebook. <\/h3>\n\n\n\n

El notebook esta dividido en diferentes secciones. Primero se cargan las librer\u00edas necesarias y los datos. Se crea la estructura. Despu\u00e9s se definen funciones gen\u00e9ricas, los modelos. A partir de aqu\u00ed se hace el aprendizaje de los diferentes modelos, con y sin data augmentation. En el ultimo apartado se usan dos procesos diferentes de Transfer Learning, usando los modelos prentrenados InceptionV3 y VGG16. <\/p>\n\n\n\n

Importar librer\u00edas y datos. <\/h4>\n\n\n\n
#First steep is import the libraries. \nimport tensorflow as tf\ntf.random.set_seed(42)\n#Numpy is a lybrary that allow us to work with arrays. \nimport numpy as np\n#keras is an open source neural networks lybrary writted in python that run's in varios frameworks, TensorFlow included. \nfrom tensorflow import keras\nimport matplotlib.pyplot as plt\nimport matplotlib.image as mpimg\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\n\nfrom tensorflow.keras.optimizers import RMSprop\nfrom tensorflow.keras.optimizers import Adam\n\nprint (tf.__version__)\n          \ngEpochs=30  <\/pre>\n\n\n\n

Se importan las t\u00edpicas librer\u00edas, se define una semilla para que los datos se repartan siempre igual en todas las ejecuciones. Importo dos optimizadores, por que he realizado pruebas con ambos, aunque me gusta m\u00e1s c\u00f3mo funciona Adam. <\/p>\n\n\n\n

Se importa ImageDataGenerator que se utiliza para trabajar con el Dataset. <\/p>\n\n\n\n

#obtain the data from microsoft.com\n#the same dataset is available in kaggle but with a different organization\n#https:\/\/www.kaggle.com\/competitions\/dogs-vs-cats\/data\n\n#If it dosn't run be sure to have wget installed in your local machine. It works fine in Colab. \n\n!wget --no-check-certificate \\\nhttps:\/\/download.microsoft.com\/download\/3\/E\/1\/3E1C3F21-ECDB-4869-8368-6DEBA77B919F\/kagglecatsanddogs_5340.zip \\-O \/tmp\/catsvsdogs.zip<\/pre>\n\n\n\n

Obtenemos el fichero .zip. Hay que recalcar que el c\u00f3digo funciona tanto en Google Colab como en un notebook Jupyter en el disco local. Nos deja el fichero .zip en el directorio \/tmp\/<\/p>\n\n\n\n

#unzip the data\nimport zipfile\ncvr_zip_file = '\/tmp\/catsvsdogs.zip'\nzipmem = zipfile.ZipFile(cvr_zip_file)\nzipmem.extractall('\/tmp\/catsvsdogs')\nzipmem.close()<\/pre>\n\n\n\n

Para descomprimirlo importamos zipfile, y no hay ning\u00fan secreto. el zip viene con las imagenes en dos directorios: <\/p>\n\n\n\n

dira=<\/strong>\"\/tmp\/catsvsdogs\/PetImages\/Cat\/\" \ndirb=<\/strong>\"\/tmp\/catsvsdogs\/PetImages\/Dog\/\" <\/pre>\n\n\n\n

Tendremos que pasarlo de estos dos directorios a otros para tener datos de entreno y datos de validaci\u00f3n. <\/p>\n\n\n\n

destDirTraina=<\/strong>'\/tmp\/datacvd\/train\/cats\/' \ndestDirTrainb=<\/strong>'\/tmp\/datacvd\/train\/dogs\/'\ndestDirVala=<\/strong>'\/tmp\/datacvd\/validation\/cats\/' \ndestDirValb=<\/strong>'\/tmp\/datacvd\/validation\/dogs\/'\ndirTrain=<\/strong>'\/tmp\/datacvd\/train\/'\ndirVal=<\/strong>'\/tmp\/datacvd\/validation\/'<\/pre>\n\n\n\n

La estructura de directorios se debe crear en el disco, ya sea en el que nos monta de forma temporal Colab, como en el nuestro. <\/p>\n\n\n\n

#create the directory structure\nimport os\n\n#we need a try block, because it fails when the directories already exist. \ntry:\n  os.mkdir('\/tmp\/datacvd')\n  os.mkdir('\/tmp\/datacvd\/train')\n  os.mkdir('\/tmp\/datacvd\/validation')\n  os.mkdir('\/tmp\/datacvd\/train\/cats')\n  os.mkdir('\/tmp\/datacvd\/train\/dogs')\n  os.mkdir('\/tmp\/datacvd\/validation\/cats')\n  os.mkdir('\/tmp\/datacvd\/validation\/dogs')\nexcept:\n  pass<\/pre>\n\n\n\n

La funci\u00f3n mkdir devuelve una excepci\u00f3n en caso de que el directorio ya est\u00e9 creado, por eso lo he puesto dentro de un bloque try y he ignorado la excepci\u00f3n. <\/p>\n\n\n\n

Con los directorios ya creados podemos copiar las im\u00e1genes, para ello tengo una funci\u00f3n que recibe los directorios origen, los destino y el n\u00famero de im\u00e1genes que quiero usar como validadoras. <\/p>\n\n\n\n

#we need 4 datasets, two for training the model and two for validate or test the model. \n#to classify the images in this dataset we can move it from their original directories to \n#a new ones with the correct structure. \n\ndef getimagesfromdir(dira=\"\", dirb=\"\", destDirTraina=\"\", destDirTrainb=\"\", destDirVala=\"\", destDirValb=\"\", NumVal=100):\n    from shutil import copyfile\n\n    #this array contents all the images to move\/copy\n    imagesA=[]\n    imagesB=[]\n\n    for imagename in os.listdir(dira):\n      imageCat = dira + imagename\n      if (os.path.getsize(imageCat)) > 0:\n        imagesA.append(imagename)\n\n    for imagename in os.listdir(dirb):\n      imageDog = dirb + imagename\n      if (os.path.getsize(imageDog)) > 0:\n        imagesB.append(imagename)\n\n\n    counterImage = 0\n    for imagename in imagesA:\n      if  counterImage < 2000:\n        copyfile(dira + imagename, destDirVala+imagename)\n      else:\n        copyfile(dira + imagename, destDirTraina+imagename)\n      counterImage +=1\n\n    counterImage = 0\n    for imagename in imagesB:\n      if  counterImage < 2000:\n        copyfile(dirb + imagename, destDirValb+imagename)\n      else:\n        copyfile(dirb + imagename, destDirTrainb+imagename)\n      counterImage +=1\n\n    print(len(os.listdir(destDirValb)))\n    print(len(os.listdir(destDirTrainb)))\n    print(len(os.listdir(destDirVala)))\n    print(len(os.listdir(destDirTraina)))\n    return imagesA, imagesB<\/pre>\n\n\n\n

La llamada a la funci\u00f3n es muy sencilla: <\/p>\n\n\n\n

imagesCats, imagesDogs = getimagesfromdir(dira=dira, \n                                          dirb=dirb, \n                                         destDirTraina=destDirTraina, \n                                         destDirTrainb=destDirTrainb,\n                                         destDirVala=destDirVala, \n                                         destDirValb=destDirValb,\n                                         NumVal=2000)<\/pre>\n\n\n\n

La llamada a la funci\u00f3n nos devuelve los datos divididos en dos arrays, uno para cada categor\u00eda, pero no es lo importante. Lo que realmente ha hecho es dividir las im\u00e1genes en los cuatro directorios para poder crear datos de entreno y datos de validaci\u00f3n partiendo del directorio en el que se han situado. <\/p>\n\n\n\n

Funciones del Notebook. <\/h4>\n\n\n\n

Son las funciones gen\u00e9ricas, usadas para imprimir gr\u00e1ficos, o tratar los datos. Muchas de ellas compartidas entre diferentes notebooks. <\/p>\n\n\n\n

def SimpleDataGenerator():\n    #TRAIN Dataset\n    #Normalize the images\n    train_idg = ImageDataGenerator(rescale=1\/255)\n    train_data = train_idg.flow_from_directory(\n        '\/tmp\/datacvd\/train', \n        target_size = (150, 150), \n        batch_size = 105, \n        class_mode='binary'\n    )\n    #VALIDATION Dataset\n    val_idg = ImageDataGenerator(rescale=1\/255)\n    val_data = val_idg.flow_from_directory(\n        '\/tmp\/datacvd\/validation', \n        target_size = (150, 150), \n        batch_size = 100, \n        class_mode='binary'\n    )\n    return train_data, val_data<\/pre>\n\n\n\n

Aqu\u00ed se preparan los juegos de datos, el de training y el de validation. Usando ImageDataGenerator<\/em><\/strong> se normalizan las im\u00e1genes. Acto seguido con flow_from_directory<\/em><\/strong> se cargan las im\u00e1genes. Le podemos indicar el target size, pera que todas tengan el mismo, debe coincidir con el shape de entrada de nuestro modelo. <\/p>\n\n\n\n

La funci\u00f3n devuelvo los dos juegos de datos. <\/p>\n\n\n\n

#Print accuracy & val_accura vs loss & val_loss \n\ndef plot_loss_acc(history):\n  '''Plots the training and validation loss and accuracy from a history object'''\n  acc = history.history['accuracy']\n  val_acc = history.history['val_accuracy']\n  loss = history.history['loss']\n  val_loss = history.history['val_loss']\n\n  epochs = range(len(acc))\n\n  plt.plot(epochs, acc, 'bo-', label='Training accuracy')\n  plt.plot(epochs, val_acc, 'go-', label='Validation accuracy')\n  plt.title('Training and validation accuracy')\n  plt.legend()\n\n  plt.figure()\n\n  plt.plot(epochs, loss, 'bo-', label='Training Loss')\n  plt.plot(epochs, val_loss, 'go-', label='Validation Loss')\n  plt.title('Training and validation loss')\n  plt.legend()\n\n  plt.show()<\/pre>\n\n\n\n

Esta funci\u00f3n nos crea un gr\u00e1fico comparando el loss y el accuracy del history de la ejecuci\u00f3n del modelo que le pasemos. <\/p>\n\n\n\n

Modelos. <\/h4>\n\n\n\n
def get_model(kindmodel):\n    switcher = {\n\n        #it's a minimal model for images, with just an Convolutionatl layer and a MaxPooling layer\n        0: tf.keras.models.Sequential([\n            tf.keras.layers.Conv2D(16, (4,4), activation=\"relu\", input_shape=(150, 150, 3)),\n            tf.keras.layers.MaxPooling2D(2,2),  \n            tf.keras.layers.Flatten(), \n            tf.keras.layers.Dense(128, activation=\"relu\"), \n            tf.keras.layers.Dense(1, activation=\"sigmoid\")]),\n        #keeping it simple just add more convolutional anv maxpooling layers\n        #es incluso menos pesado que el anterior, gracias a las capas de maxpooling\n        1: tf.keras.models.Sequential([\n            tf.keras.layers.Conv2D(16, (4,4), activation=\"relu\", input_shape=(150, 150, 3)),\n            tf.keras.layers.MaxPooling2D(2,2),  \n            tf.keras.layers.Conv2D(32, (4,4), activation=\"relu\"),\n            tf.keras.layers.MaxPooling2D(2,2),  \n            tf.keras.layers.Conv2D(64, (4,4), activation=\"relu\"),\n            tf.keras.layers.MaxPooling2D(2,2),  \n            tf.keras.layers.Flatten(), \n            tf.keras.layers.Dense(512, activation=\"relu\"), \n            tf.keras.layers.Dense(1, activation=\"sigmoid\")]),\n        3: tf.keras.models.Sequential([\n            tf.keras.layers.Conv2D(16, (4,4), activation=\"relu\", input_shape=(150, 150, 3)),\n            tf.keras.layers.MaxPooling2D(2,2),  \n            tf.keras.layers.Dropout(0.5), \n            tf.keras.layers.Flatten(), \n            tf.keras.layers.Dense(128, activation=\"relu\"), \n            tf.keras.layers.Dense(1, activation=\"sigmoid\")]),\n        4: tf.keras.models.Sequential([\n            tf.keras.layers.Conv2D(16, (4,4), activation=\"relu\", input_shape=(150, 150, 3)),\n            tf.keras.layers.MaxPooling2D(2,2),\n            tf.keras.layers.Dropout(0.2),   \n            tf.keras.layers.Conv2D(32, (4,4), activation=\"relu\"),\n            tf.keras.layers.MaxPooling2D(2,2),  \n            tf.keras.layers.Dropout(0.2),  \n            tf.keras.layers.Conv2D(64, (4,4), activation=\"relu\"),\n            tf.keras.layers.MaxPooling2D(2,2),  \n            tf.keras.layers.Dropout(0.5), \n            tf.keras.layers.Flatten(), \n            tf.keras.layers.Dense(512, activation=\"relu\"), \n            tf.keras.layers.Dense(1, activation=\"sigmoid\")]),\n    }\n    return switcher.get(kindmodel, None)<\/pre>\n\n\n\n

Los modelos los he puesto todos dentro de una funci\u00f3n en lugar de irlos creando por el notebook. Me facilita la vida para compararlos, buscarlos o editarlos. como pode\u00eds ver hay dos modelos y son todos muy sencillos. <\/p>\n\n\n\n

Tenemos un modelo con una sola capa convolucional y despu\u00e9s otro con tres capas convolucionales. Cada capa convolutional se acompa\u00f1a de una capa MaxPooling2D. <\/p>\n\n\n\n

Los dos siguientes modelos son exactamente los mismos pero incorporando capas de Dropout detr\u00e1s de la capa MaxPooling2D. <\/p>\n\n\n\n

Modelo con una sola capa convolucional. <\/h4>\n\n\n\n
tf.keras.models.Sequential([\n            tf.keras.layers.Conv2D(16, (4,4), activation=\"relu\", input_shape=(150, 150, 3)),\n            tf.keras.layers.MaxPooling2D(2,2),  \n            tf.keras.layers.Flatten(), \n            tf.keras.layers.Dense(128, activation=\"relu\"), \n            tf.keras.layers.Dense(1, activation=\"sigmoid\")])<\/pre>\n\n\n\n

Es un modelo muy simple, tan solo una capa convolucional, una de MaxPooling2D y la capa densa con 128 neurones. <\/p>\n\n\n\n

Resultados: <\/p>\n\n\n\n

6s 180ms\/step – loss: 0.1124 – accuracy: 0.9857 – val_loss: 1.4532 – val_accuracy: 0.8167<\/p>\n\n\n\n

84s 418ms\/step – loss: 0.3824 – accuracy: 0.8318 – val_loss: 0.3082 – val_accuracy: 0.8762Con Data Augmentation<\/sup><\/p>\n\n\n\n

Como es normal, el modelo tiene un gran problema de overfitting, que se ve solucionado parcialmente al usar Image Augmentation. <\/p>\n\n\n\n

\n
\n
\"\"<\/figure>\n<\/div>\n\n\n\n
\n
\"\"<\/figure>\n<\/div>\n<\/div>\n\n\n\n

Con Image Augmentation: <\/p>\n\n\n\n

\n
\n
\"\"
Con Image Augmentation<\/figcaption><\/figure>\n<\/div>\n\n\n\n
\n
\"\"
Con Image Augmentation<\/figcaption><\/figure>\n<\/div>\n<\/div>\n\n\n\n

Modelo con tres capas convolucionales. <\/h4>\n\n\n\n
tf.keras.models.Sequential([\n            tf.keras.layers.Conv2D(16, (4,4), activation=\"relu\", input_shape=(150, 150, 3)),\n            tf.keras.layers.MaxPooling2D(2,2),  \n            tf.keras.layers.Conv2D(32, (4,4), activation=\"relu\"),\n            tf.keras.layers.MaxPooling2D(2,2),  \n            tf.keras.layers.Conv2D(64, (4,4), activation=\"relu\"),\n            tf.keras.layers.MaxPooling2D(2,2),  \n            tf.keras.layers.Flatten(), \n            tf.keras.layers.Dense(512, activation=\"relu\"), \n            tf.keras.layers.Dense(1, activation=\"sigmoid\")])<\/pre>\n\n\n\n

Este modelo es el t\u00edpico en el que a cada convolucional le sigue una de MaxPooling2D, y se aumentan los filtros aplicados en cada capa convolucional a\u00f1adida. Se aumentan tambi\u00e9n el n\u00famero de neurones de la capa Densa. <\/p>\n\n\n\n

Resultados: <\/p>\n\n\n\n

36s 180ms\/step – loss: 0.1124 – accuracy: 0.9857 – val_loss: 1.4532 – val_accuracy: 0.8167<\/p>\n\n\n\n

84s 418ms\/step – loss: 0.3824 – accuracy: 0.8318 – val_loss: 0.3082 – val_accuracy: 0.8762Con Data augmentation<\/sup><\/p>\n\n\n\n

\n
\n
\"\"<\/figure>\n<\/div>\n\n\n\n
\n
\"\"<\/figure>\n<\/div>\n<\/div>\n\n\n\n

Con Image Augmentation: <\/p>\n\n\n\n

\n
\n
\"\"
Image Augmentation<\/figcaption><\/figure>\n<\/div>\n\n\n\n
\n
\"\"
Image Augmentation<\/figcaption><\/figure>\n<\/div>\n<\/div>\n\n\n\n

Mejora los n\u00fameros del modelo simple, pero mantiene exactamente el mismo problema de Overfitting y reacciona igual a la soluci\u00f3n de usar Data Augmentation. <\/p>\n\n\n\n

En los dos modelos se aprecia una irregularidad en la curva de Loss. Una posible causa es el Learning Rate usado para el optimizador RMSprop que se ha usado. Se podr\u00eda crear una funci\u00f3n para identificar que learning rate puede ser mejor y usar el optimizador Adam para ver si se consigue una curva con menos estridencias. <\/p>\n\n\n\n

Con tres capas convolucionales y Dropout. <\/h4>\n\n\n\n
tf.keras.models.Sequential([\n            tf.keras.layers.Conv2D(16, (4,4), activation=\"relu\", input_shape=(150, 150, 3)),\n            tf.keras.layers.MaxPooling2D(2,2),\n            tf.keras.layers.Dropout(0.2),   \n            tf.keras.layers.Conv2D(32, (4,4), activation=\"relu\"),\n            tf.keras.layers.MaxPooling2D(2,2),  \n            tf.keras.layers.Dropout(0.2),  \n            tf.keras.layers.Conv2D(64, (4,4), activation=\"relu\"),\n            tf.keras.layers.MaxPooling2D(2,2),  \n            tf.keras.layers.Dropout(0.5), \n            tf.keras.layers.Flatten(), \n            tf.keras.layers.Dense(512, activation=\"relu\"), \n            tf.keras.layers.Dense(1, activation=\"sigmoid\")])<\/pre>\n\n\n\n

Se incorpora una capa de Dropout d\u00e9spues de cada capa de MaxPooling2D. <\/p>\n\n\n\n

Resultados: <\/p>\n\n\n\n

85s 423ms\/step – loss: 0.3076 – accuracy: 0.8639 – val_loss: 0.3255 – val_accuracy: 0.8672Con Image Augmentation<\/sup>. <\/p>\n\n\n\n

\n
\n
\"\"
Image Augmentation<\/figcaption><\/figure>\n<\/div>\n\n\n\n
\n
\"\"
Image augmentation<\/figcaption><\/figure>\n<\/div>\n<\/div>\n\n\n\n

Solo he realizado entrenos con Data Augmentation. No se aprecia overfitting, pero la curva continua teniendo unos picos que tendr\u00edan que eliminarse, o reducirse. <\/p>\n\n\n\n

Transfer Learning. <\/h3>\n\n\n\n

He usado dos modelos preentrenados diferentes InceptionV3 y VGG16. He usado dos t\u00e9cnicas diferentes para bajarme los pesos y crear el modelo. <\/p>\n\n\n\n

Con Transfer Learning lo que se hace es aprovechar modelos existentes que ya est\u00e1n entrenados. Se puede seleccionar el modelo completo, o tan solo las capas que queramos del modelo. Despu\u00e9s se complementa con nuestras capas finales, y entrenamos tan solo las capas que hemos incorporado. Con esto no se aprovecha tan solo la forma del modelo, que ya es mucho, sino que tambi\u00e9n aprovechamos el esfuerzo de entreno, tanto en horas como en datos que se ha realizado con el modelo pre entrenado. <\/p>\n\n\n\n

Transfer Learning con InceptionV3<\/h4>\n\n\n\n
from tensorflow.keras import Model\n\n# Download the pre-trained weights. No top means it excludes the fully connected layer it uses for classification.\n!wget --no-check-certificate \\\n    https:\/\/storage.googleapis.com\/mledu-datasets\/inception_v3_weights_tf_dim_ordering_tf_kernels_notop.h5 \\\n    -O \/tmp\/inception_v3_weights_tf_dim_ordering_tf_kernels_notop.h5<\/pre>\n\n\n\n

Importamos Model de Keras, para crear el modelo. Nos bajamos los pesos del modelo, parta cargarlos al crear el modelo.<\/p>\n\n\n\n

#conver layers in non trainable. \ndef notrainlayers(model):\n    for layer in model.layers:\n        layer.trainable=False\n    return model  <\/pre>\n\n\n\n

Esta funci\u00f3n nos permite marcar c\u00f3mo no entrenables las capas del modelo que reciba. Al bajarnos un modelo pre entrenado, con sus pesos correspondientes no queremos volver a entrenar el modelo. Para ello marcamos las capas como entrenables. <\/p>\n\n\n\n

#import Inceptionv3. \nfrom tensorflow.keras.applications.inception_v3 import InceptionV3\n\n#create the model. \ninception_pre_trained=InceptionV3(input_shape=(150, 150, 3), \n                                 include_top=False, \n                                 weights=None)\n\n#store name of the file in a variable. \nlocal_weigth_file = '\/tmp\/inception_v3_weights_tf_dim_ordering_tf_kernels_notop.h5'\n#load the weights, obtained downloading \ninception_pre_trained.load_weights(local_weigth_file)<\/pre>\n\n\n\n

El modelo InceptionV3 esta precargado en la libreria keras, por lo que lo importamos directamente. <\/p>\n\n\n\n

Al crear el modelo con InceptionV3 le pasamos tres parametros: <\/p>\n\n\n\n