Caso práctico de TensorFlow: predicción de datos de temperatura LSTM basada en entrada de funciones múltiples (con código completo de Python y conjunto de datos)

Hola a todos, en la sección anterior introduje la predicción de una característica única de LSTM, si te interesa puedes echar un vistazo a: Caso práctico de TensorFlow: Uso de LSTM para predicción de potencia

Hoy compartiré con ustedes cómo usar la red neuronal recurrente LSTM para completar la predicción de temperatura con múltiples funciones. La versión completa del código y los datos se pueden obtener al final del artículo.

1. Importar el kit de herramientas

Uso GPU para acelerar la computación, los amigos sin GPU pueden eliminar el segmento de código que llama GPU.

import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# 调用GPU加速
gpus = tf.config.experimental.list_physical_devices(device_type='GPU')
for gpu in gpus:
    tf.config.experimental.set_memory_growth(gpu, True)

2. Leer el conjunto de datos

El conjunto de datos se registra cada 10 minutos, con filas de datos de 42w y columnas de características de 14. Las primeras columnas de características de 10, excepto la columna de tiempo, se seleccionan para este modelo. Use el método de trazado de pandas para trazar características en función del tiempo.

#(1)读取数据集
filepath = 'D:/deeplearning/test/神经网络/循环神经网络/climate.csv'
data = pd.read_csv(filepath)
print(data.head())  # 数据是10min记录一次的

#(2)特征选择
# 选择从第1列开始往后的所有行的数据
feat = data.iloc[:, 1:11]  # 最后4个特征列不要
date = data.iloc[:, 0]   # 获取时间信息

#(3)利用pandas绘图展示每个特征点分布情况
feat.plot(subplots=True, figsize=(80,10),  # 为每一列单独开辟子图,设置画板大小
          layout=(5,2), title='climate features')  # 14张图的排序方式,设置标题

La información del conjunto de datos es la siguiente

Trazar los datos característicos de las últimas 10 columnas, excepto la columna DateTime característica de tiempo como una función de tiempo

3. Preprocesamiento de datos

Debido a la gran cantidad de datos, todos ellos utilizados para el entrenamiento pueden causar un error de uso de memoria insuficiente.Aquí, los primeros 2w de datos se toman para el entrenamiento. Encuentre la media y la desviación estándar de cada columna de características en el conjunto de entrenamiento y use la media y la desviación estándar del conjunto de entrenamiento para el preprocesamiento de estandarización para todo el conjunto de datos . Utilice los datos de temperatura del aire normalizados como etiqueta .

#(4)特征数据预处理
train_num = 20000  # 取前2w组数据用于训练
val_num = 23000  # 取2w-2.3w的数据用于验证
# 2.3w-2.5w的数据用于验证用于测试

# 求训练集的每个特征列的均值和标准差
feat_mean = feat[:train_num].mean(axis=0)
feat_std = feat[:train_num].std(axis=0)

# 对整个数据集计算标准差
feat = (feat - feat_mean) / feat_std

# 保存所有的气温数据,即标签数据
targets = feat.iloc[:,1]   # 取标准化之后的气温数据作为标签值

4. Funciones de series de tiempo para extraer características y etiquetas

Muévase sobre el conjunto de datos a través de una ventana deslizante, por ejemplo, prediga la temperatura en un punto/segmento en el futuro usando 20 filas de 10 características actuales. La tarea requiere el uso de 5 días consecutivos de datos para predecir el valor de la temperatura en el siguiente momento, y los datos se registran una vez cada 10 minutos.

Predicción para un punto de tiempo determinado: Hay 5*24*6=720 datos en cinco días, la ventana se desliza un paso a la vez, el primer rango de ventana deslizante es el rango (0, 720, 1) y la temperatura 720 es predicho. El segundo rango de la ventana deslizante es el rango (1,721,1) y se predice la temperatura 721. range() toma el valor independientemente de la cabeza y la cola

Predicción para un cierto período de tiempo: dado que el conjunto de datos se registra una vez cada 10 minutos, la diferencia entre las dos líneas de datos es muy pequeña. Puede establecer un tamaño de paso para tomar los datos de características cada 60 minutos, y el primer rango de ventana deslizante range(0 , 720, 6) , prediga los datos de temperatura por hora para el próximo día completo , es decir, range(720, 720+24*6, 6) . El segundo rango de ventana deslizante es el rango (1,721,6), y el rango de temperatura por hora (721, 721 + 24 * 6, 6) se pronostica para el día siguiente

Aquí está la predicción de los datos en un momento determinado. Los parámetros son los siguientes, que puede modificar usted mismo.

'''
dataset 代表特征数据
start_index 代表从数据的第几个索引值开始取
history_size 滑动窗口大小
end_index 代表数据取到哪个索引就结束
target_size 代表预测未来某一时间点还是时间段的气温。例如target_size=0代表用前20个特征预测第21个的气温
step 代表在滑动窗口中每隔多少步取一组特征
point_time 布尔类型,用来表示预测未来某一时间点的气温,还是时间段的气温
true 原始气温数据的所有标签值
'''

def TimeSeries(dataset, start_index, history_size, end_index, step,
               target_size, point_time, true):
    
    data = []  # 保存特征数据
    labels = []  # 保存特征数据对应的标签值
    
    start_index = start_index + history_size  # 第一次的取值范围[0:start_index]
    
    # 如果没有指定滑动窗口取到哪个结束,那就取到最后
    if end_index is None:
        # 数据集最后一块是用来作为标签值的,特征不能取到底
        end_index = len(dataset) - target_size
        
    # 滑动窗口的起始位置到终止位置每次移动一步
    for i in range(start_index, end_index):
        
        # 滑窗中的值不全部取出来用,每隔60min取一次
        index = range(i-history_size, i, step)  # 第一次相当于range(0, start_index, 6)
        
        # 根据索引取出所有的特征数据的指定行
        data.append(dataset.iloc[index])
        
        # 用这些特征来预测某一个时间点的值还是未来某一时间段的值
        if point_time is True:  # 预测某一个时间点
            # 预测未来哪个时间点的数据,例如[0:20]的特征数据(20取不到),来预测第20个的标签值
            labels.append(true[i+target_size])
        
        else:  # 预测未来某一时间区间
            # 例如[0:20]的特征数据(20取不到),来预测[20,20+target_size]数据区间的标签值
            labels.append(true[i:i+target_size])
    
    # 返回划分好了的时间序列特征及其对应的标签值
    return np.array(data), np.array(labels)

5. Divide el conjunto de datos

Utilice la función de serie temporal anterior para obtener los valores de características y etiquetas necesarios para el entrenamiento. Este es un ejemplo de predicción del valor de temperatura en el siguiente punto de tiempo. history_size especifica el tamaño de la ventana de la serie de tiempo , es decir, cuántas filas de datos se utilizan para predecir el valor de temperatura en un punto de tiempo; target_size representa el valor en qué punto de tiempo en el futuro , que es 0, como rango La función de (0, 720, 1) se usa para predecir el valor de temperatura en el punto de tiempo 720+0. Cuando point_time=False, significa predecir un período de tiempo determinado .

#(6)划分数据集
history_size = 5*24*6  # 每个滑窗取5天的数据量=720
target_size =  0  # 预测未来下一个时间点的气温值
step = 1  # 步长为1取所有的行

# 构造训练集
x_train, y_train = TimeSeries(dataset=feat, start_index=0, history_size=history_size, end_index=train_num,
                              step=step, target_size=target_size, point_time=True, true=targets)

# 构造验证集
x_val, y_val = TimeSeries(dataset=feat, start_index=train_num, history_size=history_size, end_index=val_num,
                          step=step, target_size=target_size, point_time=True, true=targets)

# 构造测试集
x_test, y_test =  TimeSeries(dataset=feat, start_index=val_num, history_size=history_size, end_index=25000,
                              step=step, target_size=target_size, point_time=True, true=targets)

# 查看数据集信息
print('x_train_shape:', x_train.shape)  # (19280, 720, 10)
print('y_train_shape:', y_train.shape)  # (19280,)

6. Construya el conjunto de datos

Convierta los valores de las características divididas y los valores de las etiquetas al tipo de tensor, baraje aleatoriamente () las filas de características del conjunto de entrenamiento y entrene el tamaño del lote = 128 conjuntos de datos por paso en cada iteración. Configure el iterador iter() , tome un lote de datos del conjunto de datos next() . El valor de etiqueta y_train representa un valor de temperatura de etiqueta por cada 720 filas de datos de características en la ventana deslizante .

#(7)构造数据集
train_ds = tf.data.Dataset.from_tensor_slices((x_train, y_train))  # 训练集
train_ds = train_ds.batch(128).shuffle(10000)  # 随机打乱、每个step处理128组数据

val_ds = tf.data.Dataset.from_tensor_slices((x_val, y_val))  # 验证集
val_ds = val_ds.batch(128)  

test_ds = tf.data.Dataset.from_tensor_slices((x_test, y_test))  # 测试集
test_ds = test_ds.batch(128)  

# 查看数据集信息
sample = next(iter(train_ds))  # 取出一个batch的数据
print('x_train.shape:', sample[0].shape)  # [128, 720, 10]
print('y_train.shape:', sample[1].shape)  # [128, ]

7. Construcción de modelos

El siguiente paso es personalizar la red LSTM. No importa cómo quieras construirla. Cabe señalar que hay un parámetro return_sequences en la capa layers.LSTM(), que representa el último valor en la salida devuelta. secuencia, o todos los valores . Predeterminado Falso . Generalmente, return_sequences=True se usa cuando se usa la siguiente capa o LSTM.

#(8)模型构建
inputs_shape = sample[0].shape[1:]  # [120,10]  不需要写batch的维度大小
inputs = keras.Input(shape=inputs_shape)  # 输入层

# LSTM层,设置l2正则化
x = layers.LSTM(units=8, dropout=0.5, return_sequences=True, kernel_regularizer=tf.keras.regularizers.l2(0.01))(inputs)
x = layers.LeakyReLU()(x)
x = layers.LSTM(units=16, dropout=0.5, return_sequences=True, kernel_regularizer=tf.keras.regularizers.l2(0.01))(inputs)
x = layers.LeakyReLU()(x)
x = layers.LSTM(units=32, dropout=0.5, kernel_regularizer=tf.keras.regularizers.l2(0.01))(x)
x = layers.LeakyReLU()(x)
# 全连接层,随即正态分布的权重初始化,l2正则化
x = layers.Dense(64,kernel_initializer='random_normal',kernel_regularizer=tf.keras.regularizers.l2(0.01))(x)
x = layers.Dropout(0.5)(x)
# 输出层返回回归计算后的未来某一时间点的气温值
outputs = layers.Dense(1)(x)  # 标签shape要和网络shape一样

# 构建模型
model = keras.Model(inputs, outputs)

# 查看网络结构
model.summary()

La estructura de la red es la siguiente

_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input_3 (InputLayer)         [(None, 720, 10)]         0         
_________________________________________________________________
lstm_7 (LSTM)                (None, 720, 16)           1728      
_________________________________________________________________
leaky_re_lu_7 (LeakyReLU)    (None, 720, 16)           0         
_________________________________________________________________
lstm_8 (LSTM)                (None, 32)                6272      
_________________________________________________________________
leaky_re_lu_8 (LeakyReLU)    (None, 32)                0         
_________________________________________________________________
dense_4 (Dense)              (None, 64)                2112      
_________________________________________________________________
dropout_2 (Dropout)          (None, 64)                0         
_________________________________________________________________
dense_5 (Dense)              (None, 1)                 65        
=================================================================
Total params: 10,177
Trainable params: 10,177
Non-trainable params: 0
_________________________________________________________________

8. Capacitación en red

Utilice el error absoluto medio como función de pérdida de regresión, evalúe **.evaluate()** en todo el conjunto de prueba después del entrenamiento y calcule la pérdida de todo el conjunto de prueba.

# 网络编译
model.compile(optimizer = keras.optimizers.Adam(0.001),  # adam优化器学习率0.001
              loss = tf.keras.losses.MeanAbsoluteError())  # 计算标签和预测之间绝对差异的平均值
                          
epochs = 15  # 网络迭代次数

# 网络训练
history = model.fit(train_ds, epochs=epochs, validation_data=val_ds)

# 测试集评价
model.evaluate(test_ds)  # loss: 0.1212

El proceso de formación es el siguiente:

Epoch 1/15
151/151 [==============================] - 11s 60ms/step - loss: 0.8529 - val_loss: 0.4423
Epoch 2/15
151/151 [==============================] - 9s 56ms/step - loss: 0.3999 - val_loss: 0.2660
------------------------------------------
------------------------------------------
Epoch 14/15
151/151 [==============================] - 9s 56ms/step - loss: 0.1879 - val_loss: 0.1442
Epoch 15/15
151/151 [==============================] - 9s 56ms/step - loss: 0.1831 - val_loss: 0.1254

9. Visualización del proceso de entrenamiento

Todos los indicadores del proceso de entrenamiento de la red se guardan en el historial. Aquí solo se usa la pérdida de error absoluta media y se dibuja la curva de cambio del indicador de pérdida con cada iteración.

#(10)查看训练信息
history_dict = history.history  # 获取训练的数据字典
train_loss = history_dict['loss']  # 训练集损失
val_loss = history_dict['val_loss']  # 验证集损失

#(11)绘制训练损失和验证损失
plt.figure()
plt.plot(range(epochs), train_loss, label='train_loss')  # 训练集损失
plt.plot(range(epochs), val_loss, label='val_loss')  # 验证集损失
plt.legend()  # 显示标签
plt.xlabel('epochs')
plt.ylabel('loss')
plt.show()

10. Etapa de predicción

Para aclarar el dibujo, solo se predicen los primeros 200 grupos de características en el conjunto de prueba** (cada grupo tiene 720 filas y 10 columnas, 720 representa el tamaño de una ventana deslizante, 10 representa el número de columnas de características) se predicen, usando la función .predict()** Obtiene el valor de temperatura pronosticado de cada grupo correspondiente al siguiente momento.

#(12)预测阶段
# x_test[0].shape = (720,10)
x_predict = x_test[:200]  # 用测试集的前200组特征数据来预测 
y_true = y_test[:200]  # 每组特征对应的标签值

y_predict = model.predict(x_predict)  # 对测试集的特征预测

# 绘制标准化后的气温曲线图
fig = plt.figure(figsize=(10,5))  # 画板大小
axes = fig.add_subplot(111)  # 画板上添加一张图
# 真实值, date_test是对应的时间
axes.plot(y_true, 'bo', label='actual')
# 预测值,红色散点
axes.plot(y_predict, 'ro', label='predict')
 
plt.legend()  # 注释
plt.grid()  # 网格
plt.show()

La comparación entre el valor predicho y el valor real es la siguiente

Código completo y datos

El código completo y los datos se han colocado en segundo plano, solo responda con una palabra clave

Si desea unirse al intercambio técnico, la mejor manera de comentar al agregar es: fuente + dirección de interés, que es conveniente para encontrar amigos de ideas afines

Método ①, Añadir ID de WeChat: dkl88191, Observaciones: de CSDN+
Método de temperatura ②, Número público de búsqueda de WeChat: aprendizaje de Python y extracción de datos, respuesta en segundo plano: temperatura

Supongo que te gusta

Origin blog.csdn.net/m0_59596937/article/details/127193545
Recomendado
Clasificación