%pip install numpy==1.19.5
%pip install tensorflow==2.1
%matplotlib inline
# Importamos TensorFlow y Keras
import tensorflow as tf
import tensorflow.keras as keras
# Importamos el modelo Sequential
from tensorflow.keras.models import Sequential
# Importamos las capas que utilizaremos
from tensorflow.keras.layers import Dense, Dropout, Flatten, Conv1D, MaxPool1D, LSTM, GRU
# Importamos el normalizador de los datos
from sklearn.preprocessing import MinMaxScaler, StandardScaler
#importamos los optimizadores
from tensorflow.keras.optimizers import RMSprop, Adam
# Importamos el evaluador de la predicción
from sklearn.metrics import mean_absolute_error, mean_squared_error
# Importamos las librerias de análisis de datos
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
import datetime, random, math
# Dependencia necesaria para descomponer las graficas y corroborar su estacionalidad.
from statsmodels.tsa.seasonal import seasonal_decompose
# Controlamos la aleatoriedad con una semilla
np.random.seed(42)
tf.random.set_seed(42)
# Controlamos los warning
import warnings
warnings.filterwarnings('ignore')
/usr/local/lib/python3.7/dist-packages/statsmodels/tools/_testing.py:19: FutureWarning: pandas.util.testing is deprecated. Use the functions in the public API at pandas.testing instead.
import pandas.util.testing as tm
from google.colab import drive
drive.mount('/content/drive/')
Drive already mounted at /content/drive/; to attempt to forcibly remount, call drive.mount("/content/drive/", force_remount=True).
%cd 'drive/MyDrive/data'
/content/drive/MyDrive/data
df = pd.read_csv('demanda_electrica_diaria.csv')
data_electrica = df[['fecha','sistema','dmin','dmax']]
data_electrica
data_electrica.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 10099 entries, 0 to 10098
Data columns (total 4 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 fecha 10099 non-null object
1 sistema 10099 non-null object
2 dmin 10099 non-null float64
3 dmax 10099 non-null float64
dtypes: float64(2), object(2)
memory usage: 315.7+ KB
# Transformaremos la columna fecha que se encuentra en formato "string" (object) a formato "fecha" (datetime)
data_electrica['fecha'] = pd.to_datetime(data_electrica['fecha'], format='%d/%m/%Y')
# Luego dejaremos nuestra columna fecha como indice del DataFrame
data_electrica = data_electrica.set_index('fecha')
# Transformaremos la columna sistema que se encuentra en formato "string" (object) a formato "categorico" (category)
data_electrica['sistema'] = data_electrica['sistema'].astype('category')
# Luego tenemos los formatos que queremos.
data_electrica.info()
<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 10099 entries, 2006-01-01 to 2021-09-30
Data columns (total 3 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 sistema 10099 non-null category
1 dmin 10099 non-null float64
2 dmax 10099 non-null float64
dtypes: category(1), float64(2)
memory usage: 246.7 KB
# Veremos que tenemos 3 categorias en la columna sistema
data_electrica['sistema'].unique()
sns.boxplot(data = df, x = 'sistema', y='dmin')
plt.show()
sns.boxplot(data = df, x = 'sistema', y='dmax')
plt.show()
# Dividimos la data según los sitemas
data_sic = data_electrica[data_electrica['sistema'] == 'SIC']
data_sing = data_electrica[data_electrica['sistema'] == 'SING']
data_sen = data_electrica[data_electrica['sistema'] == 'SEN']
print(f'Tenemos un total de {data_sic.shape[0]} datos en el sistema SIC')
print(f'Tenemos un total de {data_sing.shape[0]} datos en el sistema SING')
print(f'Tenemos un total de {data_sen.shape[0]} datos en el sistema SEN')
Tenemos un total de 4347 datos en el sistema SIC
Tenemos un total de 4383 datos en el sistema SING
Tenemos un total de 1369 datos en el sistema SEN
print(f'El sistema SIC dispone de {data_sic.index.min()} hasta {data_sic.index.max()}')
print(f'El sistema SING dispone de {data_sing.index.min()} hasta {data_sing.index.max()}')
print(f'El sistema SEN dispone de {data_sen.index.min()} hasta {data_sen.index.max()}')
El sistema SIC dispone de 2006-01-01 00:00:00 hasta 2017-12-31 00:00:00
El sistema SING dispone de 2006-01-01 00:00:00 hasta 2017-12-31 00:00:00
El sistema SEN dispone de 2018-01-01 00:00:00 hasta 2021-09-30 00:00:00
data_sic
# Comenzamos por ver la demanda mínima del SIC
plt.figure(figsize=(10,5))
plt.plot(data_sic['dmin'], c='b', label = 'SIC')
plt.title('Demanda mínima diaria SIC', fontsize = 20)
plt.xlabel('años', fontsize = 18)
plt.ylabel('MW', fontsize = 18)
plt.legend(loc = 'lower right', fontsize = 14)
plt.show()
data_sic_mes = data_sic.resample('M').sum()
data_sic_mes
plt.figure(figsize=(10,5))
plt.plot(data_sic_mes['dmin'], c='r', label = 'dmin')
#plt.plot(data_sic_mes['dmean'], c='b', label = 'dmean')
plt.plot(data_sic_mes['dmax'], c = 'g', label = 'dmax')
plt.title('Demanda mensual SIC', fontsize = 20)
plt.xlabel('años', fontsize = 18)
plt.ylabel('MW', fontsize = 18)
plt.legend(loc = 'lower right', fontsize = 11)
plt.show()
fig = plt.figure(figsize=(10,10))
ax = plt.subplot(2,1,1)
ax.plot(data_sic_mes['dmin'].loc['2015'].values, label = 'dmin 2015')
ax.plot(data_sic_mes['dmin'].loc['2016'].values, label = 'dmin 2016')
ax.plot(data_sic_mes['dmin'].loc['2017'].values, label = 'dmin 2017')
plt.title('Últimos 3 años demanda mínima SIC', fontsize = 18)
plt.ylabel('MW', fontsize = 16)
plt.legend(loc = 'lower right', fontsize = 11)
ax = plt.subplot(2,1,2)
ax.plot(data_sic_mes['dmax'].loc['2015'].values, label = 'dmax 2015')
ax.plot(data_sic_mes['dmax'].loc['2016'].values, label = 'dmax 2016')
ax.plot(data_sic_mes['dmax'].loc['2017'].values, label = 'dmax 2017')
plt.title('Últimos 3 años demanda máxima SIC', fontsize = 16)
plt.xlabel('Mes', fontsize = 16)
plt.ylabel('MW', fontsize = 16)
plt.legend(loc = 'lower right', fontsize = 11)
plt.show()
print(seasonal_decompose(data_sic_mes['dmin']).plot())
Figure(432x288)
print(seasonal_decompose(data_sic_mes['dmax']).plot())
Figure(432x288)
data_sing
# Comenzamos por ver la demanda mínima del SING
plt.figure(figsize=(10,5))
plt.plot(data_sing['dmin'], c='b', label = 'SING')
plt.title('Demanda mínima diaria SING', fontsize = 20)
plt.xlabel('años', fontsize = 18)
plt.ylabel('MW', fontsize = 18)
plt.legend(loc = 'lower right', fontsize = 14)
plt.show()
data_sing_mes = data_sing.resample('M').sum()
data_sing_mes
plt.figure(figsize=(10,5))
plt.plot(data_sing_mes['dmin'], c='r', label = 'dmin')
plt.plot(data_sing_mes['dmax'], c = 'g', label = 'dmax')
plt.title('Demanda mensual SING', fontsize = 20)
plt.xlabel('años', fontsize = 18)
plt.ylabel('MW', fontsize = 18)
plt.legend(loc = 'lower right', fontsize = 11)
plt.show()
fig = plt.figure(figsize=(10,10))
ax = plt.subplot(2,1,1)
ax.plot(data_sing_mes['dmin'].loc['2015'].values, label = 'dmin 2015')
ax.plot(data_sing_mes['dmin'].loc['2016'].values, label = 'dmin 2016')
ax.plot(data_sing_mes['dmin'].loc['2017'].values, label = 'dmin 2017')
plt.title('Últimos 3 años demanda mínima SING', fontsize = 18)
plt.ylabel('MW', fontsize = 16)
plt.legend(loc = 'lower right', fontsize = 11)
ax = plt.subplot(2,1,2)
ax.plot(data_sing_mes['dmax'].loc['2015'].values, label = 'dmax 2015')
ax.plot(data_sing_mes['dmax'].loc['2016'].values, label = 'dmax 2016')
ax.plot(data_sing_mes['dmax'].loc['2017'].values, label = 'dmax 2017')
plt.title('Últimos 3 años demanda máxima SING', fontsize = 16)
plt.xlabel('Mes', fontsize = 16)
plt.ylabel('MW', fontsize = 16)
plt.legend(loc = 'lower right', fontsize = 11)
plt.show()
print(seasonal_decompose(data_sing_mes['dmin']).plot())
Figure(432x288)
print(seasonal_decompose(data_sing_mes['dmax']).plot())
Figure(432x288)
data_sen
# Graficaremos la data para poder visualizar su comportamiento (dmin)
plt.figure(figsize=(10,5))
plt.plot(data_sen['dmin'], c='b', label = 'SEN')
plt.title('Demanda mínima diaria SEN', fontsize = 20)
plt.xlabel('años', fontsize = 18)
plt.ylabel('MW', fontsize = 18)
plt.legend(loc = 'lower right', fontsize = 14)
plt.show()
data_sen_mes = data_sen.resample('M').sum()
data_sen_mes.head() # Mostramos los primeros 5 meses de SEN
plt.figure(figsize=(10,5))
plt.plot(data_sen_mes['dmin'], c='r', label = 'dmin')
plt.plot(data_sen_mes['dmax'], c = 'g', label = 'dmax')
plt.title('Demanda mínima mensual SEN', fontsize = 20)
plt.xlabel('años', fontsize = 18)
plt.ylabel('MW', fontsize = 18)
plt.legend(loc = 'lower right', fontsize = 11)
plt.show()
fig = plt.figure(figsize=(10,10))
ax = plt.subplot(2,1,1)
ax.plot(data_sen_mes['dmin'].loc['2018'].values, label = 'dmin 2018')
ax.plot(data_sen_mes['dmin'].loc['2019'].values, label = 'dmin 2019')
ax.plot(data_sen_mes['dmin'].loc['2020'].values, label = 'dmin 2020')
plt.title('Últimos 3 años demanda mínima SEN', fontsize = 18)
plt.ylabel('MW', fontsize = 16)
plt.legend(loc = 'lower right', fontsize = 9)
ax = plt.subplot(2,1,2)
ax.plot(data_sen_mes['dmax'].loc['2018'].values, label = 'dmax 2018')
ax.plot(data_sen_mes['dmax'].loc['2019'].values, label = 'dmax 2019')
ax.plot(data_sen_mes['dmax'].loc['2020'].values, label = 'dmax 2020')
plt.title('Últimos 3 años demanda máxima SEN', fontsize = 16)
plt.xlabel('Mes', fontsize = 16)
plt.ylabel('MW', fontsize = 16)
plt.legend(loc = 'lower right', fontsize = 9)
plt.show()
print(seasonal_decompose(data_sen_mes['dmin']).plot())
Figure(432x288)
print(seasonal_decompose(data_sen_mes['dmax']).plot())
Figure(432x288)
## FUNCIONES PARA EL AJUSTE
# Con esta función obtendremos información numérica del dataset
def info_data(data, dmand:str):
rango = round((data[dmand].max() - data[dmand].min()),2)
min = data[dmand].min()
Q1 = data[dmand].quantile(q=0.25)
Q2 = data[dmand].quantile(q=0.50)
Q3 = data[dmand].quantile(q=0.75)
max = data[dmand].max()
iqr = round((Q3 - Q1),2)
count = data[dmand].count()
mean = round(data[dmand].mean(),2)
std = round(data[dmand].std(),2)
print(f'Count: {count}\nMinimo: {min}\nMaximo: {max}\nRango: {rango}')
print(f'Q1: {Q1}\nQ2: {Q2}\nQ3: {Q3}\nIQR: {iqr}\nMean: {mean}\nStd: {std}')
# En esta función ajustamos la data dado el rango intercuartil de esta, presentando además una tabla de los
# datos outliers que fueron reemplazados por una media movil de 3 periodos anteriores.
def ajust_media_movil(data, dmand:str):
Q1 = data[dmand].quantile(q=0.25)
Q3 = data[dmand].quantile(q=0.75)
iqr = Q3 - Q1 # Rango intercuartil (IQR)
new_min = round(Q1 - 1.5*iqr,2) # limite inferir -> Q1 - 1.5IQR
new_max = round(Q3 + 1.5*iqr,2) # limite superior -> Q3 + 1.5IQR
# Aquí quitamos la fecha de indice y la pasamos a columna, reseteando el indice a numeros.
data_ajust = data[[dmand]].rename_axis('fecha').reset_index()
lista = []
for index, valor in enumerate(data_ajust[dmand]):
if (valor < new_min) or (valor > new_max):
new_valor = round((data_ajust[[dmand]].loc[index-1][0]+data_ajust[[dmand]].loc[index-2][0]+data_ajust[[dmand]].loc[index-3][0])/3,2)
lista.append([data_ajust['fecha'].loc[index], valor, new_valor])
data_ajust[dmand][index] = new_valor
changes = pd.DataFrame(lista, columns=['fecha','outlier','new_valor'])
data_ajust = data_ajust.set_index('fecha')
return data_ajust, changes
def graph_new_distribution(data_ajust, data, dmand:str):
limit = (0,6000)
if dmand == 'dmin':
limit = (0,9000)
else:
limit = (6000,11500)
figura = plt.figure(figsize=(20,10))
ax = plt.subplot(1,2,1)
ax.plot(data[[dmand]])
plt.xlabel('Fecha', fontsize = 15)
plt.ylabel('Distribución Original', fontsize =15)
plt.ylim(limit)
ax = plt.subplot(1,2,2)
plt.xlabel('Fecha', fontsize = 15)
plt.ylabel('Distribución Ajustada', fontsize = 15)
ax.plot(data_ajust)
plt.ylim(limit)
plt.show()
## FUNCIONES PARA PODER APLICAR LOS MODELOS
# La función encargada de transformar nuestra Serie Temporal en un problema de tipo supervisado.
def series_to_supervised(data, n_in=1, n_out=1, dropnan=True):
n_vars = 1 if type(data) is list else data.shape[1]
df = pd.DataFrame(data)
cols, names = list(), list()
# input sequence (t-n, ... t-1)
for i in range(n_in, 0, -1):
cols.append(df.shift(i))
names += [('var%d(t-%d)' % (j+1, i)) for j in range(n_vars)]
# forecast sequence (t, t+1, ... t+n)
for i in range(0, n_out):
cols.append(df.shift(-i))
if i == 0:
names += [('var%d(t)' % (j+1)) for j in range(n_vars)]
else:
names += [('var%d(t+%d)' % (j+1, i)) for j in range(n_vars)]
# put it all together
agg = pd.concat(cols, axis=1)
agg.columns = names
# drop rows with NaN values
if dropnan:
agg.dropna(inplace=True)
return agg
# Función encargada de normalizar y transformar los datos a aprendizaje supervisado
def normalize_and_supervised(pronostic_mes):
values = pronostic_mes.values
values = values.astype('float32')
# normalize features
values=values.reshape(-1, 1) # esto lo hacemos porque tenemos 1 sola dimension
scaled = SCALER.fit_transform(values)
transform_data = series_to_supervised(scaled, PAST_HISTORY,PREDICTION)
return transform_data
# Función encargada de gráficar el proceso de entrenamiento del modelo
def plot_history(history):
hist = pd.DataFrame(history.history)
hist['epoch'] = history.epoch
fig = plt.figure(figsize=(20,5))
ax = plt.subplot(1,2,1)
plt.ylabel('Loss - Mean Squared Error')
ax.plot(hist['epoch'], hist['loss'], label= 'Train loss')
ax.plot(hist['epoch'], hist['val_loss'], label='Validation loss')
#plt.ylim(0.03,0.08)
plt.legend()
ax = plt.subplot(1,2,2)
plt.ylabel('Mean Absolute Error')
ax.plot(hist['epoch'], hist['mae'], label= 'Train Error')
ax.plot(hist['epoch'], hist['val_mae'], label='Validation Error')
#plt.ylim(0.0,0.025)
plt.legend()
plt.show()
# Función encargada de gráficar las predicciónes del modelo
def graph_prediction(index, test, predict):
fig = plt.figure(figsize=(15,10))
ax = plt.subplot(1,1,1)
ax.plot(index ,test, c='b', label='Datos_test')
ax.plot(index ,predict, '.-r', label='Predicción')
plt.ylabel('MW', fontsize = 16)
plt.xlabel('Fecha', fontsize = 16)
plt.xticks(rotation=35, fontsize=14)
plt.yticks(fontsize=14)
ax.legend()
plt.show()
############## CONFIGURACIÓN GENERAL DE LOS MODELOS ########################################################
# Seleccionamos el rango para el aprendizaje supervisado ( t-n, t-(n-1), ... , t-2, t-1, t)
PAST_HISTORY = 30
PREDICTION = 1
# Generando el escalador de los datos.
SCALER = MinMaxScaler(feature_range=(0,1))
# Como se entrenara el modelo
LOSS ='mean_squared_error'
OPTIMIZER_1 = Adam(learning_rate=0.0003)
OPTIMIZER_2 = RMSprop(learning_rate=0.0003) # un segundo optimizador para hacer pruebas
METRICS = ["mae"]
############# CONFIGURACIÓN MODELO ################################################################
# Función de activación
ACTIVATION = 'relu'
# Seleccionamos la cantidad de repeticiones que se entrenará (cantidad de EPOCH)
EPOCHS_1 = 40
EPOCHS_2 = 10
BATCH_SIZE = 32
plt.figure(figsize=(10,5))
plt.plot(data_sen[['dmin']])
plt.title('Demanda mínima diaria SEN', fontsize=14)
plt.ylabel('MW', fontsize = 14)
plt.xlabel('Fecha', fontsize= 14)
plt.show()
# Vemos la distrubución de la demanda minima de SEN con un histograma
sns.histplot(data_sen['dmin'])
plt.show()
# Veremos un diagrama de caja para ver la mediana, los quartiles y datos outliers de SEN dmin
sns.boxplot(data_sen['dmin'])
plt.show()
# Veremos un poco de información de los datos (todos los valores estan en MW, menos Count)
info_data(data_sen, 'dmin')
Count: 1369
Minimo: 1.88
Maximo: 8726.74
Rango: 8724.86
Q1: 7462.11
Q2: 7711.29
Q3: 7956.83
IQR: 494.72
Mean: 7686.08
Std: 450.02
tratamiento_sen_dmin = ajust_media_movil(data_sen, 'dmin')
sen_dmin_ajust = tratamiento_sen_dmin[0]
changes_sen_dmin = tratamiento_sen_dmin[1]
# Veremos los datos outliers con su correspondiente fecha y el valor por el que fueron reemplazados
changes_sen_dmin
# Vemos la distribución de los datos de SEN dmin ajustados
sns.histplot(sen_dmin_ajust['dmin'])
plt.show()
# Podemos ver el gráfico de caja sin datos outliers.
sns.boxplot(sen_dmin_ajust['dmin'])
plt.show()
# Vemos un cambio en la información con los datos ajustados.
info_data(sen_dmin_ajust,'dmin')
Count: 1369
Minimo: 6734.31
Maximo: 8669.49
Rango: 1935.18
Q1: 7464.02
Q2: 7711.42
Q3: 7956.83
IQR: 492.81
Mean: 7702.56
Std: 360.29
# Hacemos una comparación de los datos antes (izquierda) y despues del ajuste intercuartil (derecha)
graph_new_distribution(sen_dmin_ajust, data_sen,'dmin')
plt.figure(figsize=(10,5))
plt.plot(data_sen[['dmax']])
plt.title('Demanda máxima diaria SEN', fontsize=14)
plt.ylabel('MW', fontsize = 14)
plt.xlabel('Fecha', fontsize= 14)
plt.show()
# Vemos la distribución de los datos de SEN dmax con un histograma
sns.histplot(data_sen['dmax'])
plt.show()
# Veremos un diagrama de caja para ver la mediana, los cuartiles y datos outliers de SEN dmax
sns.boxplot(data_sen['dmax'])
plt.show()
# Veremos un poco de información de los datos (todos los valores estan en MW, menos Count)
info_data(data_sen, 'dmax')
Count: 1369
Minimo: 8234.84
Maximo: 11235.16
Rango: 3000.32
Q1: 9459.19
Q2: 9789.38
Q3: 10152.75
IQR: 693.56
Mean: 9801.45
Std: 520.97
# Se realiza el ajuste de los datos y se rescata el df con los datos outliers y sus nuevos valores.
tratamiento_sen_dmax = ajust_media_movil(data_sen, 'dmax')
sen_dmax_ajust = tratamiento_sen_dmax[0]
changes_sen_dmax = tratamiento_sen_dmax[1]
# Veremos los datos outliers con su correspondiente fecha y el valor por el que fueron reemplazados
changes_sen_dmax
# Vemos la distribución de los datos ajustados
sns.histplot(sen_dmax_ajust['dmax'])
plt.show()
# Vemos el gráfico de caja sin datos outliers.
sns.boxplot(sen_dmax_ajust['dmax'])
plt.show()
# Vemos un cambio en la información con los datos ajustados.
info_data(sen_dmax_ajust,'dmax')
Count: 1369
Minimo: 8434.51
Maximo: 11128.55
Rango: 2694.04
Q1: 9459.59
Q2: 9789.38
Q3: 10152.75
IQR: 693.16
Mean: 9804.08
Std: 510.84
# Hacemos una comparación de los datos antes (izquierda) y despues del ajuste intercuartil (derecha)
graph_new_distribution(sen_dmax_ajust, data_sen,'dmax')
# Seleccionamos el rango de fecha en el que miraremos hacia atras para predecir
end_train_sen = '2021-07'
start_test_sen = '2021-08'
# Separando los datos de SIC
sen_train_dmin, sen_test_dmin = sen_dmin_ajust.loc[:end_train_sen], sen_dmin_ajust.loc[start_test_sen:]
sen_train_dmax, sen_test_dmax = sen_dmax_ajust.loc[:end_train_sen], sen_dmax_ajust.loc[start_test_sen:]
#################### OBTENIENDO MÁS INTERVALOS DE PRUEBA #####################################################
# PARA SEN DMIN
sen_test_dmin_aug = sen_dmin_ajust.loc['2021-07':'2021-08'] # Agosto
sen_test_dmin_as = sen_dmin_ajust.loc['2021-07':] # Agosto y septiembre
# PARA SEN DMAX
sen_test_dmax_aug = sen_dmax_ajust.loc['2021-07':'2021-08']
sen_test_dmax_as = sen_dmax_ajust.loc['2021-07':]
##############################################################################################################
print(f'SEN\nDatos Train: {sen_train_dmin.shape}\nDatos Test: {sen_test_dmin.shape}')
SEN
Datos Train: (1308, 1)
Datos Test: (61, 1)
transform_sen_train_dmax = normalize_and_supervised(sen_train_dmax)
transform_sen_train_dmax.shape
# x_train e y_train de sen dmax
x_train_sen_dmax = transform_sen_train_dmax.iloc[:,:-1]
y_train_sen_dmax = transform_sen_train_dmax.iloc[:,-1]
# Vemos las dimensiones de los datos de entrenamiento
x_train_sen_dmax.shape, y_train_sen_dmax.shape
def model_MLP_sen():
model = Sequential()
model.add(Dense(64, input_dim = x_train_sen_dmax.shape[1], activation = ACTIVATION))
model.add(Dense(128, activation=ACTIVATION))
model.add(Dense(PREDICTION, activation=ACTIVATION))
model.compile(loss= LOSS,
optimizer= OPTIMIZER_1,
metrics= METRICS)
return model
model_sen_dmax_mlp = model_MLP_sen()
# Mostramos la estructura del modelo para la dmax
model_sen_dmax_mlp.summary()
Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
dense (Dense) (None, 64) 1984
_________________________________________________________________
dense_1 (Dense) (None, 128) 8320
_________________________________________________________________
dense_2 (Dense) (None, 1) 129
=================================================================
Total params: 10,433
Trainable params: 10,433
Non-trainable params: 0
_________________________________________________________________
# Entrenamos el modelo de dmax
history_sen_dmax_mlp = model_sen_dmax_mlp.fit(x_train_sen_dmax, y_train_sen_dmax,
epochs=EPOCHS_1,
batch_size = BATCH_SIZE,
validation_split=0.1,
shuffle= False,
verbose = 0)
hist_sen_dmax_mlp = pd.DataFrame(history_sen_dmax_mlp.history)
hist_sen_dmax_mlp['epoch'] = history_sen_dmax_mlp.epoch
# Mostramos las últimas 5 filas del total de epoch de entrenamiento
hist_sen_dmax_mlp.tail()
# Redimensionando los datos de x_train para el modelo LSTM
x_train_sen_dmax = x_train_sen_dmax.values.reshape((x_train_sen_dmax.shape[0], x_train_sen_dmax.shape[1],1))
x_train_sen_dmax.shape
def model_LSTM_sen():
model = Sequential()
model.add(LSTM(60, input_shape = (x_train_sen_dmax.shape[1],x_train_sen_dmax.shape[2]), return_sequences=True))
model.add(LSTM(60, return_sequences=True))
model.add(Flatten())
model.add(Dense(PREDICTION))
model.compile(loss= LOSS,
optimizer= OPTIMIZER_1,
metrics= METRICS)
return model
model_sen_dmax_lstm = model_LSTM_sen()
# Mostramos la estructura del modelo para la dmax
model_sen_dmax_lstm.summary()
Model: "sequential_1"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
lstm (LSTM) (None, 30, 60) 14880
_________________________________________________________________
lstm_1 (LSTM) (None, 30, 60) 29040
_________________________________________________________________
flatten (Flatten) (None, 1800) 0
_________________________________________________________________
dense_3 (Dense) (None, 1) 1801
=================================================================
Total params: 45,721
Trainable params: 45,721
Non-trainable params: 0
_________________________________________________________________
# Entrenamos el modelo de dmax
history_sen_dmax_lstm = model_sen_dmax_lstm.fit(x_train_sen_dmax, y_train_sen_dmax,
epochs=70,
batch_size = BATCH_SIZE,
validation_split = 0.1,
shuffle= False,
verbose = 0)
hist_sen_dmax_lstm = pd.DataFrame(history_sen_dmax_lstm.history)
hist_sen_dmax_lstm['epoch'] = history_sen_dmax_lstm.epoch
# Mostramos las ultimas 5 filas del total de epoch de entrenamiento
hist_sen_dmax_lstm.tail()
x_train_sen_dmax.shape, y_train_sen_dmax.shape
def model_GRU():
model = Sequential()
model.add(GRU(64, input_shape = (x_train_sen_dmax.shape[1],x_train_sen_dmax.shape[2]), return_sequences=True))
model.add(GRU(64, return_sequences = True))
model.add(Flatten())
model.add(Dense(PREDICTION))
model.compile(loss= LOSS,
optimizer= OPTIMIZER_1,
metrics= METRICS)
return model
model_sen_dmax_gru = model_GRU()
# Mostramos la estructura del modelo para la dmax
model_sen_dmax_gru.summary()
Model: "sequential_2"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
gru (GRU) (None, 30, 64) 12864
_________________________________________________________________
gru_1 (GRU) (None, 30, 64) 24960
_________________________________________________________________
flatten_1 (Flatten) (None, 1920) 0
_________________________________________________________________
dense_4 (Dense) (None, 1) 1921
=================================================================
Total params: 39,745
Trainable params: 39,745
Non-trainable params: 0
_________________________________________________________________
# Entrenamos el modelo de dmax
history_sen_dmax_gru = model_sen_dmax_gru.fit(x_train_sen_dmax, y_train_sen_dmax,
epochs= 60,
batch_size = BATCH_SIZE,
validation_split = 0.1,
shuffle= False,
verbose = 0)
hist_sen_dmax_gru = pd.DataFrame(history_sen_dmax_gru.history)
hist_sen_dmax_gru['epoch'] = history_sen_dmax_gru.epoch
# Mostramos las ultimas 5 filas del total de epoch de entrenamiento
hist_sen_dmax_gru.tail()
x_train_sen_dmax.shape, y_train_sen_dmax.shape
def model_hibrido():
model = Sequential()
model.add(Conv1D(32,8, input_shape = (x_train_sen_dmax.shape[1],x_train_sen_dmax.shape[2]),activation='relu',padding='same'))
model.add(MaxPool1D())
model.add(Conv1D(32,8, activation=ACTIVATION, padding='same'))
model.add(MaxPool1D())
model.add(LSTM(32, return_sequences=True))
model.add(Flatten())
model.add(Dense(PREDICTION))
model.compile(loss= LOSS,
optimizer= OPTIMIZER_1,
metrics= METRICS)
return model
model_sen_dmax_hibrido = model_hibrido()
# Mostramos la estructura del modelo para la dmax
model_sen_dmax_hibrido.summary()
Model: "sequential_3"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv1d (Conv1D) (None, 30, 32) 288
_________________________________________________________________
max_pooling1d (MaxPooling1D) (None, 15, 32) 0
_________________________________________________________________
conv1d_1 (Conv1D) (None, 15, 32) 8224
_________________________________________________________________
max_pooling1d_1 (MaxPooling1 (None, 7, 32) 0
_________________________________________________________________
lstm_2 (LSTM) (None, 7, 32) 8320
_________________________________________________________________
flatten_2 (Flatten) (None, 224) 0
_________________________________________________________________
dense_5 (Dense) (None, 1) 225
=================================================================
Total params: 17,057
Trainable params: 17,057
Non-trainable params: 0
_________________________________________________________________
# Entrenamos el modelo de dmax
history_sen_dmax_hibrido = model_sen_dmax_hibrido.fit(x_train_sen_dmax, y_train_sen_dmax,
epochs= 40,
batch_size = BATCH_SIZE,
validation_split = 0.1,
shuffle= False,
verbose = 0)
hist_sen_dmax_hibrido = pd.DataFrame(history_sen_dmax_hibrido.history)
hist_sen_dmax_hibrido['epoch'] = history_sen_dmax_hibrido.epoch
# Mostramos las ultimas 5 filas del total de epoch de entrenamiento
hist_sen_dmax_hibrido.tail()
x_train_sen_dmax.shape, y_train_sen_dmax.shape
def model_hibrido2():
model = Sequential()
model.add(Conv1D(32,9, input_shape = (x_train_sen_dmax.shape[1],x_train_sen_dmax.shape[2]),activation='relu',padding='same'))
model.add(MaxPool1D())
model.add(Conv1D(32,9, activation=ACTIVATION, padding='same'))
model.add(MaxPool1D())
model.add(GRU(32, return_sequences=True))
model.add(Flatten())
model.add(Dense(PREDICTION))
model.compile(loss= LOSS,
optimizer= OPTIMIZER_1,
metrics= METRICS)
return model
model_sen_dmax_hibrido2 = model_hibrido2()
# Mostramos la estructura del modelo para la dmax
model_sen_dmax_hibrido2.summary()
Model: "sequential_4"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv1d_2 (Conv1D) (None, 30, 32) 320
_________________________________________________________________
max_pooling1d_2 (MaxPooling1 (None, 15, 32) 0
_________________________________________________________________
conv1d_3 (Conv1D) (None, 15, 32) 9248
_________________________________________________________________
max_pooling1d_3 (MaxPooling1 (None, 7, 32) 0
_________________________________________________________________
gru_2 (GRU) (None, 7, 32) 6336
_________________________________________________________________
flatten_3 (Flatten) (None, 224) 0
_________________________________________________________________
dense_6 (Dense) (None, 1) 225
=================================================================
Total params: 16,129
Trainable params: 16,129
Non-trainable params: 0
_________________________________________________________________
# Entrenamos el modelo de dmax
history_sen_dmax_hibrido2 = model_sen_dmax_hibrido2.fit(x_train_sen_dmax, y_train_sen_dmax,
epochs= 40,
batch_size = BATCH_SIZE,
validation_split = 0.1,
shuffle= False,
verbose = 0)
hist_sen_dmax_hibrido2 = pd.DataFrame(history_sen_dmax_hibrido2.history)
hist_sen_dmax_hibrido2['epoch'] = history_sen_dmax_hibrido2.epoch
# Mostramos las ultimas 5 filas del total de epoch de entrenamiento
hist_sen_dmax_hibrido2.tail()
# Transformando a aprendizaje supervisado y normalizando los datos de prueba (test) de SEN
transform_test_sen_dmax_as = normalize_and_supervised(sen_test_dmax_as) # Agosto y Septiembre
# Datos de x_test e y_test de SEN dmin
# Agosto y Septiembre
x_test_sen_dmax_as = transform_test_sen_dmax_as.iloc[:,:-1]
y_test_sen_dmax_as = transform_test_sen_dmax_as.iloc[:,-1]
# Evaluando el modelo con los datos de prueba
evaluate_model_sen_dmax_mlp_as = model_sen_dmax_mlp.evaluate(x_test_sen_dmax_as, y_test_sen_dmax_as)
62/62 [==============================] - 0s 948us/sample - loss: 0.0121 - mae: 0.0900
predict_model_sen_dmax_mlp_as = model_sen_dmax_mlp.predict(x_test_sen_dmax_as)
# Calculando el error de la predicción
results_predict_model_sen_dmax_mlp_as = [round(float(mean_squared_error(y_test_sen_dmax_as, predict_model_sen_dmax_mlp_as)),6),
round(float(mean_absolute_error(y_test_sen_dmax_as, predict_model_sen_dmax_mlp_as)),6),
round(float(math.sqrt(mean_squared_error(y_test_sen_dmax_as, predict_model_sen_dmax_mlp_as))),6),
round(float((mean_absolute_error(y_test_sen_dmax_as, predict_model_sen_dmax_mlp_as))*100),6)]
print(f'mse: {results_predict_model_sen_dmax_mlp_as[0]}\nmae: {results_predict_model_sen_dmax_mlp_as[1]}')
print(f'rmse: {results_predict_model_sen_dmax_mlp_as[2]}\nmape: {results_predict_model_sen_dmax_mlp_as[3]}')
mse: 0.01205
mae: 0.089975
rmse: 0.109774
mape: 8.997539
index_as = sen_test_dmax_as.iloc[30:].index
# Escalamos la predicción a su escala original
predict_model_sen_dmax_mlp_as = SCALER.inverse_transform(predict_model_sen_dmax_mlp_as)
# Redimensionando los datos de x_test de SEN dmin
x_test_sen_dmax_as = x_test_sen_dmax_as.values.reshape((x_test_sen_dmax_as.shape[0], x_test_sen_dmax_as.shape[1],1))
# Evaluando el modelo con los datos de prueba
evaluate_model_sen_dmax_lstm_as = model_sen_dmax_lstm.evaluate(x_test_sen_dmax_as, y_test_sen_dmax_as)
62/62 [==============================] - 0s 7ms/sample - loss: 0.0144 - mae: 0.0939
predict_model_sen_dmax_lstm_as = model_sen_dmax_lstm.predict(x_test_sen_dmax_as)
# Calculando el error de la predicción
results_predict_model_sen_dmax_lstm_as = [round(float(mean_squared_error(y_test_sen_dmax_as, predict_model_sen_dmax_lstm_as)),6),
round(float(mean_absolute_error(y_test_sen_dmax_as, predict_model_sen_dmax_lstm_as)),6),
round(float(math.sqrt(mean_squared_error(y_test_sen_dmax_as, predict_model_sen_dmax_lstm_as))),6),
round(float((mean_absolute_error(y_test_sen_dmax_as, predict_model_sen_dmax_lstm_as))*100),6)]
print(f'mse: {results_predict_model_sen_dmax_lstm_as[0]}\nmae: {results_predict_model_sen_dmax_lstm_as[1]}')
print(f'rmse: {results_predict_model_sen_dmax_lstm_as[2]}\nmape: {results_predict_model_sen_dmax_lstm_as[3]}')
mse: 0.014398
mae: 0.093879
rmse: 0.11999
mape: 9.387862
# Escalamos la predicción a su escala original
predict_model_sen_dmax_lstm_as = SCALER.inverse_transform(predict_model_sen_dmax_lstm_as)
# Evaluando el modelo con los datos de prueba
evaluate_model_sen_dmax_gru_as = model_sen_dmax_gru.evaluate(x_test_sen_dmax_as, y_test_sen_dmax_as)
62/62 [==============================] - 0s 6ms/sample - loss: 0.0125 - mae: 0.0933
predict_model_sen_dmax_gru_as = model_sen_dmax_gru.predict(x_test_sen_dmax_as)
# Calculando el error de la predicción
results_predict_model_sen_dmax_gru_as = [round(float(mean_squared_error(y_test_sen_dmax_as, predict_model_sen_dmax_gru_as)),6),
round(float(mean_absolute_error(y_test_sen_dmax_as, predict_model_sen_dmax_gru_as)),6),
round(float(math.sqrt(mean_squared_error(y_test_sen_dmax_as, predict_model_sen_dmax_gru_as))),6),
round(float((mean_absolute_error(y_test_sen_dmax_as, predict_model_sen_dmax_gru_as))*100),6)]
print(f'mse: {results_predict_model_sen_dmax_gru_as[0]}\nmae: {results_predict_model_sen_dmax_gru_as[1]}')
print(f'rmse: {results_predict_model_sen_dmax_gru_as[2]}\nmape: {results_predict_model_sen_dmax_gru_as[3]}')
mse: 0.012464
mae: 0.093338
rmse: 0.11164
mape: 9.33379
# Escalamos la predicción a su escala original
predict_model_sen_dmax_gru_as = SCALER.inverse_transform(predict_model_sen_dmax_gru_as)
# Evaluando el modelo con los datos de prueba
evaluate_model_sen_dmax_hibrido_as = model_sen_dmax_hibrido.evaluate(x_test_sen_dmax_as, y_test_sen_dmax_as)
62/62 [==============================] - 0s 4ms/sample - loss: 0.0136 - mae: 0.0926
predict_model_sen_dmax_hibrido_as = model_sen_dmax_hibrido.predict(x_test_sen_dmax_as)
# Calculando el error de la predicción
results_predict_model_sen_dmax_hibrido_as = [round(float(mean_squared_error(y_test_sen_dmax_as, predict_model_sen_dmax_hibrido_as)),6),
round(float(mean_absolute_error(y_test_sen_dmax_as, predict_model_sen_dmax_hibrido_as)),6),
round(float(math.sqrt(mean_squared_error(y_test_sen_dmax_as, predict_model_sen_dmax_hibrido_as))),6),
round(float((mean_absolute_error(y_test_sen_dmax_as, predict_model_sen_dmax_hibrido_as))*100),6)]
print(f'mse: {results_predict_model_sen_dmax_hibrido_as[0]}\nmae: {results_predict_model_sen_dmax_hibrido_as[1]}')
print(f'rmse: {results_predict_model_sen_dmax_hibrido_as[2]}\nmape: {results_predict_model_sen_dmax_hibrido_as[3]}')
mse: 0.013623
mae: 0.092645
rmse: 0.11672
mape: 9.264451
# Escalamos la predicción a su escala original
predict_model_sen_dmax_hibrido_as = SCALER.inverse_transform(predict_model_sen_dmax_hibrido_as)
# Evaluando el modelo con los datos de prueba
evaluate_model_sen_dmax_hibrido2_as = model_sen_dmax_hibrido2.evaluate(x_test_sen_dmax_as, y_test_sen_dmax_as)
62/62 [==============================] - 0s 4ms/sample - loss: 0.0120 - mae: 0.0881
predict_model_sen_dmax_hibrido2_as = model_sen_dmax_hibrido2.predict(x_test_sen_dmax_as)
# Calculando el error de la predicción
results_predict_model_sen_dmax_hibrido2_as = [round(float(mean_squared_error(y_test_sen_dmax_as, predict_model_sen_dmax_hibrido2_as)),6),
round(float(mean_absolute_error(y_test_sen_dmax_as, predict_model_sen_dmax_hibrido2_as)),6),
round(float(math.sqrt(mean_squared_error(y_test_sen_dmax_as, predict_model_sen_dmax_hibrido2_as))),6),
round(float((mean_absolute_error(y_test_sen_dmax_as, predict_model_sen_dmax_hibrido2_as))*100),6)]
print(f'mse: {results_predict_model_sen_dmax_hibrido2_as[0]}\nmae: {results_predict_model_sen_dmax_hibrido2_as[1]}')
print(f'rmse: {results_predict_model_sen_dmax_hibrido2_as[2]}\nmape: {results_predict_model_sen_dmax_hibrido2_as[3]}')
mse: 0.012032
mae: 0.088099
rmse: 0.10969
mape: 8.80991
# Escalamos la predicción a su escala original
predict_model_sen_dmax_hibrido2_as = SCALER.inverse_transform(predict_model_sen_dmax_hibrido2_as)
# Creamos un df con los resultados del entrenamiento de los modelos
results_train = pd.concat([hist_sen_dmax_mlp.tail(1).iloc[:,:-1],
hist_sen_dmax_lstm.tail(1).iloc[:,:-1],
hist_sen_dmax_gru.tail(1).iloc[:,:-1],
hist_sen_dmax_hibrido.tail(1).iloc[:,:-1],
hist_sen_dmax_hibrido2.tail(1).iloc[:,:-1]],ignore_index=True)
# Renombramos el nombre de los indices y columnas para una mejor comprensión
results_train.rename(index = {0:'MLP',
1:'LSTM',
2:'GRU',
3:'HYBRID_1',
4:'HYBRID_2'},
columns = {'loss':'MSE_TRAIN',
'mae':'MAE_TRAIN',
'val_loss':'MSE_VAL',
'val_mae':'MAE_VAL'},
inplace = True)
# Creamos un df con los resultados de las predicciones de los modelos
results_predicts = [results_predict_model_sen_dmax_mlp_as,
results_predict_model_sen_dmax_lstm_as,
results_predict_model_sen_dmax_gru_as,
results_predict_model_sen_dmax_hibrido_as,
results_predict_model_sen_dmax_hibrido2_as]
# Le asignamos indices y columnas
results_predicts = pd.DataFrame(results_predicts, index = ['MLP','LSTM','GRU','HYBRID_1','HYBRID_2'],
columns=['MSE_PREDICT','MAE_PREDICT','RMSE_PREDICT','MAPE_PREDICT'])
# Concatenaremos los df
df_results = pd.concat([results_train, results_predicts], axis = 1)
df_results
# Ordenando los resultados de menor a mayor por MSE_PREDICT
df_results.sort_values('MSE_PREDICT')
# Ordenando los resultados de menor a mayor por MAE_PREDICT
df_results.sort_values('MAE_PREDICT')