Saltar al contenido principal

Modelo con mutiples salidas

· 4 min de lectura
Darvin Cotrina

Modelo con mutiples salidas

En este notebook, crearemos un modelo con multiples salidas usando el API funcional de keras.

Para el modelo usaremos lo datos de Energy efficiency

Importar modulos

::: {.cell _cell_guid=‘bc1c482a-3443-4deb-bfbe-35775986216c’ _uuid=‘3869d47c-4312-4dae-8587-4c76fe28cb21’ execution=‘{“iopub.execute_input”:“2023-08-11T20:34:57.287840Z”,“iopub.status.busy”:“2023-08-11T20:34:57.286929Z”,“iopub.status.idle”:“2023-08-11T20:34:57.295622Z”,“shell.execute_reply”:“2023-08-11T20:34:57.293802Z”,“shell.execute_reply.started”:“2023-08-11T20:34:57.287795Z”}’ jupyter=‘{“outputs_hidden”:false}’ trusted=‘true’ execution_count=1}

import tensorflow as tf
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn import preprocessing
import requests
from io import BytesIO
import zipfile

:::

Preparar los datos

Descargamos el dataset y preparamos nuestros datos de entrenamiento y pruebas

# download file
url = 'https://archive.ics.uci.edu/static/public/242/energy+efficiency.zip'
r = requests.get(url)
zip_data = BytesIO(r.content)

# unzip
with zipfile.ZipFile(zip_data, 'r') as zip_file:
with zip_file.open('ENB2012_data.xlsx') as excel_file:
df = pd.read_excel(excel_file)

# random sort
df = df.sample(frac=1)

df.head()
X1X2X3X4X5X6X7X8Y1Y2
4700.66759.5318.5220.53.540.25412.8616.17
3790.64784.0343.0220.53.550.25217.1120.43
310.71710.5269.5220.53.550.0006.4011.67
7470.74686.0245.0220.53.550.40514.3916.70
7370.79637.0343.0147.07.030.40541.9637.70

::: {.cell _cell_guid=‘966384d2-52f6-43fe-a9a7-30a34005525c’ _uuid=‘246e7b03-c479-425e-b12e-0d31b6caa74c’ execution=‘{“iopub.execute_input”:“2023-08-11T20:35:01.995196Z”,“iopub.status.busy”:“2023-08-11T20:35:01.994656Z”,“iopub.status.idle”:“2023-08-11T20:35:02.010268Z”,“shell.execute_reply”:“2023-08-11T20:35:02.008886Z”,“shell.execute_reply.started”:“2023-08-11T20:35:01.995155Z”}’ jupyter=‘{“outputs_hidden”:false}’ trusted=‘true’ execution_count=3}

# split data
train, test = train_test_split(df, test_size=0.2)

def format_data(df: pd.DataFrame):
y1 = df['Y1'].values
y2 = df['Y2'].values
X = df.drop(['Y1', 'Y2'], axis=1)
return X, (y1, y2)

X_train, Y_train = format_data(train)
X_test, Y_test = format_data(test)

:::

::: {.cell _cell_guid=‘f867a2c3-849d-476b-8068-deea62ff3ea8’ _uuid=‘3717aebb-1951-47bc-aeb9-ef1ee7af3ced’ execution=‘{“iopub.execute_input”:“2023-08-11T20:35:06.917556Z”,“iopub.status.busy”:“2023-08-11T20:35:06.917099Z”,“iopub.status.idle”:“2023-08-11T20:35:06.925773Z”,“shell.execute_reply”:“2023-08-11T20:35:06.924386Z”,“shell.execute_reply.started”:“2023-08-11T20:35:06.917524Z”}’ jupyter=‘{“outputs_hidden”:false}’ trusted=‘true’ execution_count=4}

# normalize data
scaler = preprocessing.StandardScaler()
X_train_norm = scaler.fit_transform(X_train)
X_test_norm = scaler.transform(X_test)

:::

El modelo

Ahora construiremos nuestro modelo teniendo en cuenta que va a tener dos salidas

def build_model():
input_layer = tf.keras.layers.Input(shape=(8,))
hidden_layer = tf.keras.layers.Dense(128, activation='relu')(input_layer)
hidden_layer = tf.keras.layers.Dense(128, activation='relu')(hidden_layer)

# ouput 1
y1 = tf.keras.layers.Dense(1, name='y1')(hidden_layer)

# output 2
hidden_layer = tf.keras.layers.Dense(64, activation='relu')(hidden_layer)

y2 = tf.keras.layers.Dense(1, name='y2')(hidden_layer)

return tf.keras.models.Model(inputs=input_layer, outputs=[y1, y2])

Graficar nuestro modelo

Vamos a graficar nuestro modelo donde podemos observar de forma mas simple nuestras dos salidas y1 y y2, tambien podemos ver que y2 tiene una capa extra, esta es la de tf.keras.layers.Dense(units=1, name='y2', activation='linear')(X)

model = build_model()
model.summary()
Model: "model"
__________________________________________________________________________________________________
Layer (type) Output Shape Param # Connected to
==================================================================================================
input_1 (InputLayer) [(None, 8)] 0 []

dense (Dense) (None, 128) 1152 ['input_1[0][0]']

dense_1 (Dense) (None, 128) 16512 ['dense[0][0]']

dense_2 (Dense) (None, 64) 8256 ['dense_1[0][0]']

y1 (Dense) (None, 1) 129 ['dense_1[0][0]']

y2 (Dense) (None, 1) 65 ['dense_2[0][0]']

==================================================================================================
Total params: 26,114
Trainable params: 26,114
Non-trainable params: 0
__________________________________________________________________________________________________

Configurar parametros

model.compile(
optimizer=tf.optimizers.SGD(learning_rate=0.001),
loss={
'y1': tf.keras.losses.MeanSquaredError(),
'y2': tf.keras.losses.MeanSquaredError(),
},
metrics={
'y1': tf.keras.metrics.RootMeanSquaredError(),
'y2': tf.keras.metrics.RootMeanSquaredError(),
}
)

Entrenar el modelo

model.fit(
X_train_norm, Y_train,
epochs=500, batch_size=10,
validation_data=(X_test_norm, Y_test),
verbose=0
)
<keras.callbacks.History at 0x1e161d1ed10>

Evaluar el modelo

Ahora vamos a evaluar el modelo y graficar los datos para tener una mejor idea de lo que esta pasando

model.evaluate(X_test_norm, Y_test)
5/5 [==============================] - 0s 2ms/step - loss: 0.9150 - y1_loss: 0.2067 - y2_loss: 0.7082 - y1_root_mean_squared_error: 0.4547 - y2_root_mean_squared_error: 0.8416
[0.9149883389472961,
0.2067471146583557,
0.7082412838935852,
0.454694539308548,
0.8415707349777222]

Comparar datos reales y predichos

pred = model.predict(X_test_norm)
print(pred[0][:5])
Y_test[0][:5]
5/5 [==============================] - 0s 1ms/step
[[33.359097]
[37.002422]
[23.915794]
[35.689697]
[24.020735]]
array([33.16, 37.26, 24.03, 35.94, 24.24])
def plot_values(ax, y_true, y_pred, title):
ax.scatter(y_true, y_pred, alpha=0.5)
ax.plot([y_true.min(), y_true.max()], [y_true.min(), y_true.max()], '--')
ax.set_xlabel('True value')
ax.set_ylabel('Predicted value')
ax.set_title(title)

# Y1 vs pred
fig, ax = plt.subplots(1, 2, figsize=(15, 5))
plot_values(ax[0], Y_test[0], pred[0], 'Y1')
plot_values(ax[1], Y_test[1], pred[1], 'Y2')