[人工智能学习日志]深度学习-电力消耗预测案例


来自 LSTM电力消耗案例bilibili课程,属于单变量预测案例

1、加载数据集、预处理

- 引入包
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

from sklearn.preprocessing import MinMaxScaler
from sklearn.metrics import r2_score

import tensorflow as tf
from tensorflow.keras import Sequential, layers, utils #新版使用.keras一定要用tensorflow.keras

import warnings
warnings.filterwarnings('ignore')
- 读取数据集
dataset = pd.read_csv('DOM_hourly.csv')
- 数据处理-设置索引
# 将字段Datetime数据类型转换为日期类型
dataset['Datetime'] = pd.to_datetime(dataset['Datetime'], format="%Y-%m-%d %H:%M:%S")

# 将字段Datetime设置为索引列
# 目的:后续基于索引来进行数据集的切分
dataset.index = dataset.Datetime #会产生一列新的索引列
dataset.drop(columns=['Datetime'], axis=1, inplace=True) #把原来的日期列删去(使用'drop'),inplace=True保存新的dataset

# 可视化显示DOM_MW的数据分布情况-作出曲线图
dataset['DOM_MW'].plot(figsize=(16,8)) #把'DOM_MW'列做曲线图,figsize是尺寸
plt.show()
- 数据处理-数据归一化处理
# 数据进行归一化
scaler = MinMaxScaler() #均值为0标准差为1的归一化
dataset['DOM_MW'] = scaler.fit_transform(dataset['DOM_MW'].values.reshape(-1, 1)) 
#注意:一定要定位到.values获取列的值。reshape(-1,1)中'-1'表示行,不知道行数,电脑自行计算,'1'表示1列

2、特征工程

- 构造特征数据集和标签集
# 功能函数:构造特征数据集和标签集
def create_new_dataset(dataset, seq_len = 12):
    '''基于原始数据集构造新的序列特征数据集
    Params:
        dataset : 原始数据集
        seq_len : 序列长度(时间跨度)
    
    Returns:
        X, y
    '''
    X = [] # 初始特征数据集为空列表
    y = [] # 初始标签数据集为空列表
    
    start = 0 # 初始位置
    end = dataset.shape[0] - seq_len # 截止位置
    
    for i in range(start, end): # for循环构造特征数据集
        sample = dataset[i : i+seq_len] # 基于时间跨度seq_len创建样本
        label = dataset[i+seq_len] # 创建sample对应的标签
        X.append(sample) # 保存sample
        y.append(label) # 保存label
    
    # 返回特征数据集和标签集
    return np.array(X), np.array(y)
- 切分训练集train和测试集test
# 功能函数:基于新的特征的数据集和标签集,切分:X_train, X_test
def split_dataset(X, y, train_ratio=0.8):
    '''基于X和y,切分为train和test
    Params:
        X : 特征数据集
        y : 标签数据集
        train_ratio : 训练集占X的比例
    
    Returns:
        X_train, X_test, y_train, y_test
    '''
    X_len = len(X) # 特征数据集X的样本数量
    train_data_len = int(X_len * train_ratio) # 训练集的样本数量,用'int'做了数据类型转换
    
    X_train = X[:train_data_len] # 训练集,取0到train_data_len
    y_train = y[:train_data_len] # 训练标签集
    
    X_test = X[train_data_len:] # 测试集,取train_data_len到结尾
    y_test = y[train_data_len:] # 测试集标签集
    
    # 返回值
    return X_train, X_test, y_train, y_test
- 构造批数据
# 功能函数:基于新的X_train, X_test, y_train, y_test创建批数据(batch dataset)
def create_batch_data(X, y, batch_size=32, data_type=1):
    '''基于训练集和测试集,创建批数据
    Params:
        X : 特征数据集
        y : 标签数据集
        batch_size : batch的大小,即一个数据块里面有几个样本
        data_type : 数据集类型(测试集表示1,训练集表示2)
   
    Returns:
        train_batch_data 或 test_batch_data
    '''
    if data_type == 1: # 测试集
        dataset = tf.data.Dataset.from_tensor_slices((tf.constant(X), tf.constant(y))) # 封装X和y,成为tensor类型
        test_batch_data = dataset.batch(batch_size) # 构造批数据;'batch'是进行数据的封装
        # 返回
        return test_batch_data
    else: # 训练集
        dataset = tf.data.Dataset.from_tensor_slices((tf.constant(X), tf.constant(y))) # 封装X和y,成为tensor类型;这里用了tf.constant进行转换为不能改变的常数(不转换也可以)
        train_batch_data = dataset.cache().shuffle(1000).batch(batch_size) # 构造批数据;'cache'将数据加载到内存中去,调用时不用通过本地调用,速度更快;'shuffle'在训练集中随机选择1000个然后打乱
        # 返回
        return train_batch_data
- 数据实际处理
# ① 原始数据集
dataset_original = dataset
# ② 构造特征数据集和标签集,seq_len序列长度为12小时
SEQ_LEN = 20 # 序列长度
X, y = create_new_dataset(dataset_original.values, seq_len = SEQ_LEN)
# ③ 数据集切分
X_train, X_test, y_train, y_test = split_dataset(X, y, train_ratio=0.9)
# ④ 基于新的X_train, X_test, y_train, y_test创建批数据(batch dataset)
test_batch_dataset = create_batch_data(X_test, y_test, batch_size=256, data_type=1) # 测试批数据
train_batch_dataset = create_batch_data(X_train, y_train, batch_size=256, data_type=2) # 训练批数据

√ 批数据batch和epoch的关系:epoch是整体模型运行的遍数,若数据有1000条,batch为5,则一共会有200个batch,数据按‘批’训练,epoch=2时,则需要运行400个batch,一共epoch是将模型全运行一遍。
√ 构建特征数据集:(116169,1)=>(116169,20,1) 其中’20’代表序列长度,'1’代表只有一个特征
√ 数据集切分:(116169,20,1)=>(104552,20,1)和(11617,20,1)

3、构建模型

- 模型搭建
model = Sequential([
    layers.LSTM(8, input_shape=(SEQ_LEN, 1)), #一层LSTM,需要设定input_shape
    layers.Dense(1) #一层全连接层
])
- 设定权重文件保存

'checkpoint’属于回调函数,就是在训练过程中会保存最好的一组训练模型

# 定义 checkpoint,保存权重文件
file_path = "./checkpoint/best_checkpoint.h5" #保存文件名可以为.h或.ckpt;例子本身保存为.hdf5,暂时不知道为什么运行失败了
checkpoint_callback = tf.keras.callbacks.ModelCheckpoint(filepath=file_path, 
                                                         monitor='loss', 
                                                         mode='min',
                                                         save_best_only=True,
                                                         save_weights_only=True)
#检测‘loss’另最小,并且保存最好的weights

4、模型编译、训练、验证

- 模型编译使用compile
# 模型编译
model.compile(optimizer='adam', loss="mae") #loss:mae/mse
- 模型训练使用fit
# 模型训练
history = model.fit(train_batch_dataset,#训练数据
          epochs=10,#训练10轮
          validation_data=test_batch_dataset,#验证数据:测试集
          callbacks=[checkpoint_callback])#回调函数
# 显示 train loss 和 val loss
plt.figure(figsize=(16,8))
plt.plot(history.history['loss'], label='train loss') #训练loss
plt.plot(history.history['val_loss'], label='val loss') #验证loss
plt.title("LOSS")
plt.xlabel("Epochs")
plt.ylabel("Loss")
plt.legend(loc='best')
plt.show()
- 模型验证
# 模型验证
test_pred = model.predict(X_test, verbose=1) #做预测
score = r2_score(y_test, test_pred) #计算r2平方差
print("r^2 的值: ", score)
# 绘制模型验证结果,把预测值和实际值做曲线比较
plt.figure(figsize=(16,8))
plt.plot(y_test, label="True label")
plt.plot(test_pred, label="Pred label")
plt.title("True vs Pred")
plt.legend(loc='best')
plt.show()
# 绘制test中前100个点的真值与预测值
y_true = y_test[:100]
y_pred = test_pred[:100]
fig, axes = plt.subplots(2, 1, figsize=(16,8))
axes[0].plot(y_true, marker='o', color='red')
axes[1].plot(y_pred, marker='*', color='blue')
plt.show()

√ r^2值越靠近1,效果越好

5、模型测试

① 预测1个样本

# 选择test中的最后一个样本
sample = X_test[-1]
sample = sample.reshape(1, sample.shape[0], 1)
# 模型预测
sample_pred = model.predict(sample)

② 预测后续20个点的值

ture_data = X_test[-1] # 真实test的最后20个数据点
list(ture_data[:,0])

def predict_next(model, sample, epoch=20):
    temp1 = list(sample[:,0])
    for i in range(epoch):
        sample = sample.reshape(1, SEQ_LEN, 1)
        pred = model.predict(sample)
        value = pred.tolist()[0][0]
        temp1.append(value)
        sample = np.array(temp1[i+1 : i+SEQ_LEN+1])
    return temp1

preds = predict_next(model, ture_data, 20)
#绘图
plt.figure(figsize=(12,6))
plt.plot(preds, color='yellow', label='Prediction')
plt.plot(ture_data, color='blue', label='Truth')
plt.xlabel("Epochs")
plt.ylabel("Value")
plt.legend(loc='best')
plt.show()
  • 7
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值