TensorFlow 实战案例:利用 LSTM 进行电量预测(附 Python 完整代码和数据集)


大家好,今天和各位分享一下如何使用 LSTM 完成时间序列预测,本文是针对单个特征的预测,后续对多个特征的预测。 喜欢本文记得点赞、收藏。完整版代码和数据见文末

1、导入工具包

这里使用GPU加速计算,加快网络的训练速度。

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、获取数据集

**数据集有需要的自取:**https://pan.baidu.com/s/1uWW7w1Ci04U3d8YFYPf3Cw 提取码:00qw

借助pandas库读取电量时间序列数据,两列特征数据,时间和电量

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

3、数据预处理

由于是基于时间序列的预测,将数据中的索引变成时间,取AFP电量特征列作为训练的特征

由于原始数据最大值和最小值之间相差较大,为了避免数据影响网络训练的稳定性,对训练用的特征数据进行标准化处理。

#(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

绘制原始数据分布图

4、划分数据集

首先,需要通过时间序列滑动窗口选择特征值及其对应的标签值。比如对某一时间点预测,规定每20个特征值,预测得到一个标签值。由于只有一列特征数据,相当于,用前20个数据预测第21个数据。同理对某一时间片段预测,用第1到20个数据预测第21到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)

接下来就可以在原始数据集中划分训练集、验证集、测试集分别占比 90:9.8:0.2

# 取前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、构造数据集

将划分好的numpy类型的训练集和验证集转换为tensor类型,用于网络训练。使用**shuffle()**函数打乱训练集数据,batch()函数指定每个step训练多少组数据。借助迭代器iter()使用next()函数从数据集中取出一个batch的数据用于验证。

#(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、模型构建

由于本案例数据量比较少,特征也只有一个,因此不需要使用复杂网络,使用一个LSTM层用于提取特征,一个全连接层用于输出预测结果。

# 构造输入层
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()

网络架构如下:

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、网络训练

首先进行模型编译,使用adam优化器设置学习率0.01,使用平均绝对误差作为网络训练时的损失函数,网络迭代20次。回归问题不能设置metrics监控指标为准确率,这一般用于分类问题。

#(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)

训练过程如下:

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、查看训练信息

history变量中保存了训练过程的所有信息,我们绘制训练集损失和验证集损失曲线。

#(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、预测阶段

对先前划分好的测试集进行预测,model中保存了网络训练好了的权重,使用 predict() 函数预测特征 x_test 分别对应的电量 y_predict,真实值 y_test,绘图展示预测值和真实值的偏离程度。也可以计算预测值和真实值之间的方差或标准差等指标来表明预测的准确性。

#(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()

由于 x_test 对应原始数据中索引在 val_num 之后的特征信息,找到 x_test 中每个元素对应的时间 dates,作为x轴刻度

完整代码及数据

完整代码及数据已放置后台,按关键字回复即可

想加入技术交流,添加时最好的备注方式为:来源+兴趣方向,方便找到志同道合的朋友

方式①、添加微信号:dkl88191,备注:来自CSDN+ 电力
方式②、微信搜索公众号:Python学习与数据挖掘,后台回复:电力

  • 10
    点赞
  • 86
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
TensorFlow是一个开源的深度学习框架,拥有丰富的API和工具,可以用于各种应用场景,包括股票数据预测。在这个案例中,我们将使用LSTM(长短期记忆)和GRU(门控循环单元)这两种常用的循环神经网络模型,对股票数据进行预测。以下是Python完整代码示例: ```python import tensorflow as tf import pandas as pd import numpy as np from sklearn.preprocessing import MinMaxScaler # 读取数据 data = pd.read_csv('stock_data.csv') close_prices = data['close'].values.reshape(-1, 1) # 数据预处理 scaler = MinMaxScaler() scaled_close_prices = scaler.fit_transform(close_prices) # 划分训练集和测试集 train_size = int(len(scaled_close_prices) * 0.8) train_data = scaled_close_prices[:train_size] test_data = scaled_close_prices[train_size:] # 构建训练集和测试集 def create_dataset(data): X, y = [], [] for i in range(len(data) - 60): X.append(data[i:i+60]) y.append(data[i+60]) return np.array(X), np.array(y) X_train, y_train = create_dataset(train_data) X_test, y_test = create_dataset(test_data) # 构建LSTM模型 model_lstm = tf.keras.Sequential([ tf.keras.layers.LSTM(50, return_sequences=True, input_shape=(60, 1)), tf.keras.layers.LSTM(50), tf.keras.layers.Dense(1) ]) model_lstm.compile(optimizer='adam', loss='mean_squared_error') model_lstm.fit(X_train, y_train, epochs=10, batch_size=32) # 构建GRU模型 model_gru = tf.keras.Sequential([ tf.keras.layers.GRU(50, return_sequences=True, input_shape=(60, 1)), tf.keras.layers.GRU(50), tf.keras.layers.Dense(1) ]) model_gru.compile(optimizer='adam', loss='mean_squared_error') model_gru.fit(X_train, y_train, epochs=10, batch_size=32) # 模型预测 predictions_lstm = model_lstm.predict(X_test) predictions_gru = model_gru.predict(X_test) # 反归一化 scaled_predictions_lstm = scaler.inverse_transform(predictions_lstm) scaled_predictions_gru = scaler.inverse_transform(predictions_gru) scaled_y_test = scaler.inverse_transform(y_test) # 评估模型 def evaluate_model(predictions, y): rmse = np.sqrt(np.mean((predictions - y) ** 2)) return rmse rmse_lstm = evaluate_model(scaled_predictions_lstm, scaled_y_test) rmse_gru = evaluate_model(scaled_predictions_gru, scaled_y_test) print('LSTM模型的RMSE:', rmse_lstm) print('GRU模型的RMSE:', rmse_gru) ``` 在这个案例中,我们首先读取了股票数据,并进行了数据预处理,包括数据归一化和训练集和测试集的划分。然后,我们使用LSTM和GRU分别构建了模型,并训练了模型。接下来,我们使用模型对测试集进行预测,并对预测结果进行反归一化。最后,我们评估了模型的性能,使用均方根误差(RMSE)作为评估指标。输出结果中,LSTM模型的RMSE和GRU模型的RMSE可以帮助我们了解模型预测的准确性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值