Caso práctico de TensorFlow: Uso de LSTM para la predicción de potencia (con el conjunto de datos y el código completo de Python)


Hola a todos, hoy compartiré con ustedes cómo usar LSTM para completar la predicción de series temporales, este artículo es para la predicción de una sola característica y la posterior predicción de múltiples características. Si te ha gustado este artículo, recuerda darle me gusta y suscribirte. Consulte el final del artículo para obtener la versión completa del código y los datos.

1. Importar el kit de herramientas

Aquí, la computación acelerada por GPU se usa para acelerar el entrenamiento de la red.

import tensorflow as tf
from tensorflow import keras
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import warnings
warnings.filterwarnings('ignore')
# 调用GPU加速
gpus = tf.config.experimental.list_physical_devices(device_type='GPU')
for gpu in gpus:
    tf.config.experimental.set_memory_growth(gpu, True)

2. Obtenga el conjunto de datos

**El conjunto de datos necesita recuperación automática: **https://pan.baidu.com/s/1uWW7w1Ci04U3d8YFYPf3Cw Código de extracción : 00qw

Lea datos de series temporales de batería con la ayuda de la biblioteca pandas, dos columnas de datos de funciones, tiempo y batería

#(1)获取数据,按时间间隔1h记录的电力数据
filepath = 'energy.csv'
data = pd.read_csv(filepath)
print(data.head())

3. Preprocesamiento de datos

Dado que la predicción se basa en series de tiempo, el índice de los datos se cambia a tiempo y la columna de función de potencia AFP se toma como la función de entrenamiento .

Debido a la gran diferencia entre el valor máximo y el valor mínimo de los datos originales, para evitar que los datos afecten la estabilidad del entrenamiento de la red, se estandarizan los datos característicos para el entrenamiento.

#(3)选择特征
temp = data['AEP_MW'] # 获取电力数据
temp.index = data['Datetime'] # 将索引改为时间序列
temp.plot()  # 绘图展示

#(4)对训练集预处理
temp_mean = temp[:train_num].mean()  # 均值
temp_std = temp[:train_num].std()  # 标准差
# 标准化
inputs_feature = (temp - temp_mean) / temp_std

Trazar la distribución de datos original

4. Divide el conjunto de datos

En primer lugar, es necesario seleccionar los valores de las características y sus correspondientes valores de etiqueta a través de una ventana deslizante de series temporales . Por ejemplo, para la predicción en un momento determinado, se estipula que cada 20 autovalores se pronostiquen para obtener un valor de etiqueta. Dado que solo hay una columna de datos de características, es equivalente a predecir los datos 21 con los primeros 20 datos . De manera similar, para una predicción de un segmento de tiempo determinado, use los datos del 1 al 20 para predecir las potencias del 21 al 30.

#(2)构建时间序列采样函数
'''
dataset为输入的特征数据,选取用哪些特征
start_index 这么多数据选择从哪个开始,一般从0开始取序列
history_size表示时间窗口大小;若为20,代表从起始索引开始找20个样本当作x,下一个索引当作y
target_size表示需要预测的结果时窗口后的第几个时间点;0表示下一时间点的预测结果,取其当作标签;若为一个序列,预测一个序列的指标
indices=range(i, i+history_size) 代表窗口序列的索引,i表示每个窗口的起始位置,窗口中所有数据的索引
'''
def database(dataset, start_index, end_index, history_size, target_size):
    data = []  # 存放特征值
    labels = []  # 存放目标值
    
    # 初始的取值片段[0:history_size]
    start_index = start_index + history_size

    # 如果不指定特征值终止索引,就取到最后一个分区前
    if end_index is None:
        end_index = len(dataset) - target_size
    
    # 遍历整个电力数据,取出特征及其对应的预测目标
    for i in range(start_index, end_index):
        indices = range(i - history_size, i) # 窗口内的所有元素的索引
        # 保存特征值和标签值
        data.append(np.reshape(dataset[indices], (history_size, 1)))
        labels.append(dataset[i+target_size]) # 预测未来几个片段的天气数据
    # 返回数据集
    return np.array(data), np.array(labels)

A continuación, puede dividir el conjunto de entrenamiento, el conjunto de validación y el conjunto de prueba en el conjunto de datos original , representando 90:9.8:0.2 respectivamente.

# 取前90%个数据作为训练集
train_num = int(len(data) * 0.90)
# 90%-99.8%用于验证
val_num = int(len(data) * 0.998)
# 最后1%用于测试

#(5)划分训练集和验证集
# 窗口为20条数据,预测下一时刻气温
history_size = 20
target_size=0

# 训练集
x_train, y_train = database(inputs_feature.values, 0, train_num, 
                            history_size, target_size)

# 验证集
x_val, y_val = database(inputs_feature.values, train_num, val_num,
                          history_size, target_size)

# 测试集
x_test, y_test = database(inputs_feature.values, val_num, None,
                          history_size, target_size)

# 查看数据信息
print('x_train.shape:', x_train.shape)  # x_train.shape: (109125, 20, 1)

5. Construya el conjunto de datos

Convierta el conjunto de entrenamiento de tipo numpy dividido y el conjunto de validación al tipo de tensor para entrenamiento de red. Use la función shuffle() para mezclar los datos del conjunto de entrenamiento y la función batch() para especificar cuántos conjuntos de datos entrenar en cada paso. Con la ayuda del iterador iter(), use la función next() para obtener un lote de datos del conjunto de datos para su verificación.

#(6)构造tf数据集
# 训练集
train_ds = tf.data.Dataset.from_tensor_slices((x_train, y_train))
train_ds = train_ds.shuffle(10000).batch(128)
# 验证集
val_ds = tf.data.Dataset.from_tensor_slices((x_val, y_val))
val_ds = val_ds.batch(128) 

# 查看数据信息
sample = next(iter(train_ds))
print('x_batch.shape:', sample[0].shape, 'y_batch.shape:', sample[1].shape)
print('input_shape:', sample[0].shape[-2:])
# x_batch.shape: (128, 20, 1) y_batch.shape: (128,)
# input_shape: (20, 1)

6. Construcción de modelos

Dado que la cantidad de datos en este caso es relativamente pequeña y solo hay una característica, no es necesario utilizar una red compleja. Se utiliza una capa LSTM para extraer características y una capa totalmente conectada para generar resultados de predicción.

# 构造输入层
inputs = keras.Input(shape=sample[0].shape[-2:])
# 搭建网络各层
x = keras.layers.LSTM(8)(inputs)
x = keras.layers.Activation('relu')(x)
outputs = keras.layers.Dense(1)(x)  # 输出结果是1个
# 构造模型
model = keras.Model(inputs, outputs)
# 查看模型结构
model.summary()

La arquitectura de la red es la siguiente:

Layer (type)                 Output Shape              Param #   
=================================================================
input_1 (InputLayer)         [(None, 20, 1)]           0         
_________________________________________________________________
lstm_1 (LSTM)                (None, 8)                 320       
_________________________________________________________________
activation_1 (Activation)    (None, 8)                 0         
_________________________________________________________________
dense_1 (Dense)              (None, 1)                 9         
=================================================================
Total params: 329
Trainable params: 329
Non-trainable params: 0

7. Capacitación en red

Primero, compile el modelo, use el optimizador de adam para establecer la tasa de aprendizaje en 0.01, use el error absoluto medio como la función de pérdida durante el entrenamiento de la red, y la red itera 20 veces. El problema de regresión no puede establecer el indicador de monitoreo de métricas como la tasa de precisión, que generalmente se usa para problemas de clasificación.

#(8)模型编译
opt = keras.optimizers.Adam(learning_rate=0.001)  # 优化器

model.compile(optimizer=opt, loss='mae')  # 平均误差损失

#(9)模型训练
epochs=20
history = model.fit(train_ds, epochs=epochs, validation_data=val_ds)

El proceso de formación es el siguiente:

Epoch 1/20
853/853 [==============================] - 5s 5ms/step - loss: 0.4137 - val_loss: 0.0878
Epoch 2/20
853/853 [==============================] - 4s 5ms/step - loss: 0.0987 - val_loss: 0.0754
---------------------------------------------------
---------------------------------------------------
Epoch 19/20
853/853 [==============================] - 4s 5ms/step - loss: 0.0740 - val_loss: 0.0607
Epoch 20/20
853/853 [==============================] - 4s 4ms/step - loss: 0.0736 - val_loss: 0.0628

8. Ver información de entrenamiento

La variable de historial contiene toda la información sobre el proceso de entrenamiento y trazamos las curvas de pérdida del conjunto de entrenamiento y pérdida del conjunto de validació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()

![](https://img-blog.csdnimg.cn/c51b00e987954b21aa0cc6b9f91b2591.png

9. Etapa de predicción

Prediga el conjunto de prueba previamente dividido , guarde los pesos de la red entrenada en el modelo , use la función predict() para predecir la potencia y_predict correspondiente a la característica x_test , el valor real y_test, y el gráfico muestra el grado de desviación entre el valor predicho y el valor real. También se pueden calcular indicadores como la varianza o la desviación estándar entre el valor predicho y el valor real para indicar la precisión de la predicción.

#(12)预测
y_predict = model.predict(x_test)  # 对测试集的特征值进行预测

# x_test 等同于经过预处理后的 temp[val_num:-20].values
dates = temp[val_num:-20].index  # 获取时间索引

#(13)绘制预测结果和真实值对比图
fig = plt.figure(figsize=(10,5))
# 真实值
axes = fig.add_subplot(111)
axes.plot(dates, y_test, 'bo', label='actual')
# 预测值,红色散点
axes.plot(dates, y_predict, 'ro', label='predict')
# 设置横坐标刻度
axes.set_xticks(dates[::30])
axes.set_xticklabels(dates[::30],rotation=45)

plt.legend()  # 注释
plt.grid()  # 网格
plt.show()

Dado que x_test corresponde a la información de características indexada después de val_num en los datos originales , encuentre las fechas de tiempo correspondientes a cada elemento en x_test como la escala del eje x

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 ①, Agregar ID de WeChat: dkl88191, Observaciones: de CSDN + Método de energía eléctrica
②, Número público de búsqueda de WeChat: aprendizaje de Python y extracción de datos, respuesta en segundo plano: Energía eléctrica

Supongo que te gusta

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