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":2516,"date":"2022-10-06T15:41:43","date_gmt":"2022-10-06T15:41:43","guid":{"rendered":"https:\/\/martra.uadla.com\/?p=2516"},"modified":"2022-10-22T21:02:55","modified_gmt":"2022-10-22T21:02:55","slug":"crear-un-modelo-multiple-outputs-con-el-api-funcional-de-keras","status":"publish","type":"post","link":"https:\/\/martra.uadla.com\/crear-un-modelo-multiple-outputs-con-el-api-funcional-de-keras\/","title":{"rendered":"Crear un modelo ‘Multiple Outputs’ con el API funcional de Keras."},"content":{"rendered":"\n

Lo m\u00e1s normal es que cuando empezamos a trabajar con Tensorflow utilicemos el formato secuencial para crear Modelos usando la librer\u00eda Keras. Con los modelos secuenciales podemos solucionar multitud de problemas en todos los campos del deep Learning, tanto sean de reconocimiento o clasificaci\u00f3n de im\u00e1genes, Natural Language Processing, Forecasting de series…. son unos modelos lo suficientemente potentes como para ser usados en la mayor\u00eda de los problemas. <\/p>\n\n\n\n

Pero hay veces que necesitamos ir un poco mas lejos en el uso de Keras con TensorFlow y podemos usar el API para la creaci\u00f3n de modelos, que nos abre un mundo muy amplio, con muchas m\u00e1s posibilidades, que no ten\u00edamos al usar modelos secuenciales. <\/p>\n\n\n\n

En este art\u00edculo vamos a ver la creaci\u00f3n de un Modelo capaz de predecir dos variables diferentes usando los mismos datos, y el mismo proceso de aprendizaje, compartiendo gran parte de las capas del modelo. <\/p>\n\n\n\n

Es decir, vamos a crear un modelo Multi Salida con dos ramas de capas. Tal como podemos ver en la imagen: <\/p>\n\n\n\n

\"Modelo
Modelo API Keras<\/figcaption><\/figure>\n\n\n\n

El modelo est\u00e1 formado por una capa de entrada, seguida por dos capas densas que son compartidas. Estas tres capas son la parte com\u00fan del modelo. A partir de aqu\u00ed, el modelo, se divide en dos ramas diferentes. En una de las ramas encontramos la capa de salida de la variable de clasificaci\u00f3n. La otra rama est\u00e1 compuesta por una capa Densa y la capa de salida que predice la variable re regresi\u00f3n. <\/p>\n\n\n\n

El c\u00f3digo completo se puede encontrar en Kaggle: https:\/\/www.kaggle.com\/code\/peremartramanonellas\/guide-multiple-outputs-with-keras-functional-api<\/a>. En un Notebook qu\u00e9 se puede ejecutar y que utiliza un Dataset para predecir el tipo de vino como variable de clasificaci\u00f3n y la calidad del vino como variable de regresi\u00f3n. <\/p>\n\n\n\n

En este art\u00edculo vamos a ver tan solo como generar y ejecutar el modelo. El tratamiento de datos y la posterior evaluaci\u00f3n del modelo, as\u00ed como ideas de c\u00f3mo mejorarlo, se pueden encontrar en el notebook de Kaggle<\/a>. <\/p>\n\n\n\n

El problema a solucionar. <\/h3>\n\n\n\n

He usado un Dataset de Kaggle que contiene informaci\u00f3n sobre vinos. Son datos en formato tabular, con 11 columnas que se pueden considerar features y dos que ser\u00e1n nuestras labels. <\/p>\n\n\n\n

Como primer label he seleccionado la calidad del vino (quality)<\/em><\/strong>, que va de 0 a 9 y he decidido tratarla como si fuera una variable de regresi\u00f3n y no una de clasificaci\u00f3n, ya que es una variable en la que el incremento es importante y significa que el vino es mejor. <\/p>\n\n\n\n

El segundo label es el tipo de vino (type)<\/em><\/strong>, que indica si el vino es blanco o negro. Esta es claramente una variable de clasificaci\u00f3n. As\u00ed que tenemos dos variables de diferente tipo a predecir en un solo modelo. <\/p>\n\n\n\n


type<\/th>
fixed acidity<\/th>volatile acidity<\/th>citric acid<\/th>residual sugar<\/th>chlorides<\/th>free sulfur dioxide<\/th>total sulfur dioxide<\/th>density<\/th>pH<\/th>sulphates<\/th>alcohol<\/th>quality<\/th><\/tr><\/thead>
0<\/th>0<\/td>7.0<\/td>0.270<\/td>0.36<\/td>20.7<\/td>0.045<\/td>45.0<\/td>170.0<\/td>1.00100<\/td>3.00<\/td>0.45<\/td>8.8<\/td>6<\/td><\/tr>
1<\/th>0<\/td>6.3<\/td>0.300<\/td>0.34<\/td>1.6<\/td>0.049<\/td>14.0<\/td>132.0<\/td>0.99400<\/td>3.30<\/td>0.49<\/td>9.5<\/td>6<\/td><\/tr>
2<\/th>0<\/td>8.1<\/td>0.280<\/td>0.40<\/td>6.9<\/td>0.050<\/td>30.0<\/td>97.0<\/td>0.99510<\/td>3.26<\/td>0.44<\/td>10.1<\/td>6<\/td><\/tr>
3<\/th>0<\/td>7.2<\/td>0.230<\/td>0.32<\/td>8.5<\/td>0.058<\/td>47.0<\/td>186.0<\/td>0.99560<\/td>3.19<\/td>0.40<\/td>9.9<\/td>6<\/td><\/tr>
4<\/th>0<\/td>7.2<\/td>0.230<\/td>0.32<\/td>8.5<\/td>0.058<\/td>47.0<\/td>186.0<\/td>0.99560<\/td>3.19<\/td>0.40<\/td>9.9<\/td>6<\/td><\/tr>
…<\/th>…<\/td>…<\/td>…<\/td>…<\/td>…<\/td>…<\/td>…<\/td>…<\/td>…<\/td>…<\/td>…<\/td>…<\/td>…<\/td><\/tr>
6492<\/th>1<\/td>6.2<\/td>0.600<\/td>0.08<\/td>2.0<\/td>0.090<\/td>32.0<\/td>44.0<\/td>0.99490<\/td>3.45<\/td>0.58<\/td>10.5<\/td>5<\/td><\/tr>
6493<\/th>1<\/td>5.9<\/td>0.550<\/td>0.10<\/td>2.2<\/td>0.062<\/td>39.0<\/td>51.0<\/td>0.99512<\/td>3.52<\/td>NaN<\/td>11.2<\/td>6<\/td><\/tr>
6494<\/th>1<\/td>6.3<\/td>0.510<\/td>0.13<\/td>2.3<\/td>0.076<\/td>29.0<\/td>40.0<\/td>0.99574<\/td>3.42<\/td>0.75<\/td>11.0<\/td>6<\/td><\/tr>
6495<\/th>1<\/td>5.9<\/td>0.645<\/td>0.12<\/td>2.0<\/td>0.075<\/td>32.0<\/td>44.0<\/td>0.99547<\/td>3.57<\/td>0.71<\/td>10.2<\/td>5<\/td><\/tr>
6496<\/th>1<\/td>6.0<\/td>0.310<\/td>0.47<\/td>3.6<\/td>0.067<\/td>18.0<\/td>42.0<\/td>0.99549<\/td>3.39<\/td>0.66<\/td>11.0<\/td>6<\/td><\/tr><\/tbody><\/table>
Dataset, despu\u00e9s de ser tratado. <\/figcaption><\/figure>\n\n\n\n

Visto el Dataset pasamos a la construcci\u00f3n del modelo. <\/p>\n\n\n\n

#Empezamos con una capa de entrada de tipo Input. \ninputs = tf.keras.layers.Input(shape=(11,))\n\n#A\u00f1adimos dos capas densas, que ser\u00e1n comunes para todo el modelo. \n#La primera capa a la derecha recibe la capa (inputs). Mientras que la segunda\n#recibe el conjunto de capas (x). \nx = Dense(units=32, activation='relu')(inputs)\nx = Dense(units=32, activation='relu')(x)\n\n#A\u00f1adimos la capa de salida para la variable de clasificaci\u00f3n. \n#Como pod\u00e9is ver recibe el conjunto de capas (x). Que contiene \n#la capa de entrada y las capas densas. \ny_t_layer = Dense(units = 1, activation='sigmoid', name='y_t_layer')(x)\n\n#Aqu\u00ed el modelo empieza la segunda rama. Con una capa densa que recibe el conjunto de capas (x)\n#Con esto ya tenemos que a partir de la \u00faltima capa que forma el conjunto de capas (x)\n#se ha a\u00f1adido una capa de salida y ahora esta capa densa. \nquality_layer=Dense(units=64, name='quality_layer', activation='relu')(x)\n\n#La capa de salida para la variable que predice la calidad del vino. Se a\u00f1ade d\u00e9spues del grupo \n#de capas(quality_layer) que contiene todas las capas de (x) mas la densa especifica de esta rama.  \ny_q_layer = Dense(units=1, name='y_q_layer')(quality_layer)\n\n#TPOara crear el modelo tenemos que indicar las entradas y salidas. \n#En este modelo tenemos tan solo una entrada, pero con el API podemos definir modelos multientrada. \n#El nombre de los outputs es el mismo que el de las variables y los nombres internos de las capas. \nmodel = Model(inputs=inputs, outputs=[y_q_layer, y_t_layer])\n\n#He probado con dos optimizadores. Sin jugar demasiado me ha funcionado mejor Adam. \noptimizer = tf.keras.optimizers.RMSprop(learning_rate=0.0001)\n#optimizer = tf.keras.optimizers.Adam()\n\n#Al compilar el modelo se le tiene que pasar dos diccionarios que contenga\n#las funciones de loss y m\u00e9tricas de las variables a predecir. El nombre \n# de las variables del diccionario debe coincidir con el nombre interno de las capas. \n#To compile the model we use two dictionaries, to indicate the loss functions and metrics \n#for each output layer. Note that the name of the layer must be the same than the \n#internal name of the layer. \nmodel.compile(optimizer=optimizer, \n              loss = {'y_t_layer' : 'binary_crossentropy', \n                      'y_q_layer' : 'mse'\n                     },\n              metrics = {'y_t_layer' : 'accuracy', \n                         'y_q_layer': tf.keras.metrics.RootMeanSquaredError()\n                       }\n             )<\/pre>\n\n\n\n

Como se puede ver, crear un modelo de este tipo no es nada complicado y nos abre un mundo de posibilidades nuevas si lo comparamos con los modelos secuenciales. <\/p>\n\n\n\n

Se pueden encontrar todas las explicaciones en los comentarios del c\u00f3digo. Pero me gustar\u00eda remarcar un par de cosas. <\/p>\n\n\n\n

Suelo emplear el mismo nombre para el nombre interno de las capas y las variables que lo contienen. No tan solo para que c\u00f3digo quede m\u00e1s claro. Cuando indicamos la funci\u00f3n de loss y las m\u00e9tricas debemos utilizar el nombre interno de la capa para relacionaros. Al indicar los outputs debemos indicar el nombre de las variables que contienen las capas. Prefiero tener siempre el mismo y me ahorro confusiones. <\/p>\n\n\n\n

Podemos usar diferentes funciones de perdida y m\u00e9tricas para cada una de los outputs del modelo. Se indican en dos listas, una para las funciones de perdida, y otra para las m\u00e9tricas, que se le pasan a la funci\u00f3n compile del modelo. <\/p>\n\n\n\n

model.compile(optimizer=optimizer, \n              loss = {'y_t_layer' : 'binary_crossentropy', \n                      'y_q_layer' : 'mse'\n                     },\n              metrics = {'y_t_layer' : 'accuracy', \n                         'y_q_layer': tf.keras.metrics.RootMeanSquaredError()\n                       }\n             )<\/code><\/pre>\n\n\n\n

\u00bfPara qu\u00e9 podemos usar los modelos Multi Output? <\/h3>\n\n\n\n

No pretendo dar una respuesta completa, ya que se trata tan solo de mi visi\u00f3n, y Data Scientists con m\u00e1s experiencia pueden encontrarles m\u00e1s utilidades. <\/p>\n\n\n\n

Este tipo de modelo es muy \u00fatil en entornos donde se deba realizar entrenos peri\u00f3dicos con gran volumen de datos para predecir m\u00e1s de una variable. El tiempo ahorrado si lo comparamos con entrenar dos o tres modelos diferentes puede ser muy significativo, no tan solo en tiempo, sino en coste. <\/p>\n\n\n\n

Tambi\u00e9n pueden ahorrar mucho tiempo y proceso en entornos donde se deban ejecutar una gran cantidad de predicciones de forma repetitiva y el resultado de estas sea de m\u00e1s de una variable. <\/p>\n\n\n\n

Como contrapartida cuestan m\u00e1s de tunear, ya que por ejemplo es m\u00e1s complicado dar con un learning rate que pueda ser \u00f3ptimo para todas las variables. <\/p>\n\n\n\n

Conclusi\u00f3n. <\/h3>\n\n\n\n

Un tipo de modelo que es sencillo de crear y puede ahorrar mucho tiempo de proceso. <\/p>\n\n\n\n

Espero ir publicando, a partir de ahora, muchas m\u00e1s t\u00e9cnicas un poco m\u00e1s avanzadas de Tensorflow, as\u00ed que si os interesa el tema pod\u00e9is suscribiros al blog, o seguirme en mi perfil de Kaggle<\/a>. <\/p>\n\n\n\n

\"\"<\/a>
Pere Martra | Tensorflow Certified Developer<\/figcaption><\/figure>\n\n\n\n

<\/p>\n

\r\n
\r\n\r\n
\r\n \r\n \r\n Como crear un Chatbot con GPT 3.5, OpenAI y Panel. <\/a>\r\n\r\n
\r\n \r\n\r\n \"Developer\r\n\r\n <\/a>\r\n <\/div>\r\n

\r\n En este art\u00edculo veremos una breve introducci\u00f3n al funcionamiento del API de OpenAI, usaremos uno de sus famosos modelos, en Read more<\/a> <\/p>\r\n <\/div>\r\n

\r\n \r\n \r\n Curso practico de IA sin Prerrequisitos. <\/a>\r\n\r\n
\r\n \r\n\r\n \"Curso <\/picture>\r\n\r\n <\/a>\r\n <\/div>\r\n

\r\n Introducci\u00f3n al apasionante mundo de la I.A. mediante Machine Learning, sin necesidad de tener conocimientos previos de Python o Algrebra. Read more<\/a> <\/p>\r\n <\/div>\r\n

\r\n \r\n \r\n Solucionamos un problema de regresi\u00f3n con Supervised Learning y Scikit-Learn. <\/a>\r\n\r\n
\r\n \r\n\r\n \"Machine <\/picture>\r\n\r\n <\/a>\r\n <\/div>\r\n

\r\n Pues ya est\u00e1 aqu\u00ed la segunda entrega de esta serie de Machine Learning, que forma parte del \"curso\" pr\u00e1ctico de Read more<\/a> <\/p>\r\n <\/div>\r\n

\r\n \r\n \r\n Tutorial GAN-3. C\u00f3mo utilizar TPUs de Google para entrenar GANs en un abrir y cerrar de ojos. <\/a>\r\n\r\n
\r\n \r\n\r\n \"\"\r\n\r\n <\/a>\r\n <\/div>\r\n

\r\n Aprende a usar las TPU de Google Colab para acelerar el proceso de entreno de tus Notebooks. <\/p>\r\n <\/div>\r\n \r\n <\/div>\r\n\r\n