负荷预测是一个长久的研究课题

本文提供一个负荷预测的代码仅供参考

导入包

import datetime
from darts import TimeSeries
from darts.datasets import AirPassengersDataset
from darts.models import NBEATSModel
from darts.dataprocessing.transformers import Scaler
# 解决中文显示问题
import matplotlib.pyplot as plt
# todo:每天将新数据再次用于训练后,并预测
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# path_url = '你的文件路径'

N_list = [5]  # 使用前N天的数据作为输入,预测第8天数据
Train_Month = 2  # 使用前Train_Month个月的数据作为训练集

读取数据

def read_data(path_url):
    df_15min = pd.read_csv(path_url)
    res1 = pd.to_datetime(df_15min['stat_time'])
    df_15min_after = df_15min.set_index(res1)
    mp_7932_series1 = df_15min_after['mp_7932']
    conv_h_d = df_15min_after[['h_d', 'd_w']]

    return mp_7932_series1, conv_h_d

划分验证与测试集合

def split_train_test(mp_7932_series1, conv_h_d, N,i):
    train_length = int((Train_Month * 30+20+i) * 96)  # 前8个月的数据点数

    labels = mp_7932_series1.index[train_length:]
    val_data = mp_7932_series1[train_length - N * 96:]

    sales_ts = TimeSeries.from_series(mp_7932_series1)
    conv_ts = TimeSeries.from_series(conv_h_d)

    # 划分训练集和验证集,这里假设前8个月的数据用于训练,其余用于预测
    train_series = sales_ts[:train_length]
    val_series = sales_ts[train_length:]

    conv_h_d_train = conv_ts[:train_length]  # 用于训练的conv
    conv_h_d_val = conv_ts[train_length - N * 96:]  # 用于验证的conv
    val_ts = sales_ts[train_length - N * 96:]  # 验证集

    scaler_train = Scaler()
    scaler_val = Scaler()
    val_ts_sca = Scaler()
    train_scaled = scaler_train.fit_transform(train_series)  # 归一化数据
    val_scaled = scaler_val.fit_transform(val_series)
    val_ts_scaled = val_ts_sca.fit_transform(val_ts)

    return train_scaled, val_ts, val_ts_scaled, val_ts_sca, conv_h_d_train, conv_h_d_val, val_series

写评价指标代码

def get_MAPE(real_data, predict_data):
    new_real = []
    new_pred = []
    for i in range(len(real_data)):
        if real_data[i] != 0:
            new_real.append(real_data[i])
            new_pred.append(predict_data[i])
    new_real, new_pred = np.array(new_real), np.array(new_pred)
    # MAPE1 = np.mean(np.abs(real_data - predict_data) / np.mean(real_data))
    MAPE = np.mean(np.abs(new_real - new_pred) / np.abs(new_real))
    return 1 - abs(MAPE)

加载模型

def load_model(N, train_flag, num_blocks, num_layers, layers_widths,model_url):
    if train_flag:
        nbeats_model = NBEATSModel(input_chunk_length=96 * N, output_chunk_length=96, n_epochs=1, num_blocks=num_blocks,
                                   num_layers=num_layers, layer_widths=layers_widths)
    else:
        nbeats_model = NBEATSModel.load(model_url)
    return nbeats_model

计算误差

def caculatemape(model, val_ts_scaled, val_series, conv_h_d_val, val_ts_sca, N, num_blocks, num_layers, layers_widths):
    res_mape = []
    for n in range(1):
        index_7days = val_ts_scaled[n * 96:96 * (n + N)]
        past_conv = conv_h_d_val[n * 96:96 * (n + N)]

        pred1 = model.predict(series=index_7days, n=96, past_covariates=past_conv)

        pred1 = val_ts_sca.inverse_transform(pred1)
        real_data = val_series[96 * (n):96 * (n + 1)]
        pred1.plot(label='pred')
        real_data.plot(label='true')

        real_data = real_data.values()
        pred1_re_scaled = pred1.values()
        mape = get_MAPE(real_data, pred1_re_scaled)
        day = datetime.datetime.now().strftime('%y-%m-%d')
        fig_floder = ('./T_test_Nbeats' + day + 'N_' + str(N)
                      + 'num_blocks_' + str(num_blocks)
                      + 'num_layers_' + str(num_layers)
                      + 'layers_widths_' + str(layers_widths)
                      + 'result_fig')
        fig_save = fig_floder + '/mape_' + str(mape) + '.jpg'
        if not os.path.exists(fig_floder):
            os.mkdir(fig_floder)
        plt.savefig(fig_save)
        plt.close()
        res_mape.append(mape)
    return res_mape

模型训练代码


def train_model(model, train_scaled, conv_h_d_train,
                val_ts_scaled, val_series, conv_h_d_val, val_ts_sca, N, num_blocks, num_layers, layers_widths):
    '''

    :param model: 模型
    :param train_scaled:归一化后的训练数据
    :param conv_h_d_train: 训练相关的conv
    :param val_ts_scaled: 验证集的
    :param val_series:
    :param conv_h_d_val:
    :param val_ts_sca:
    :return:
    '''
    epoch = 1
    # epoch = 1
    best_mape = 0.0
    count = 0
    for i in range(epoch):
        model.fit(train_scaled, past_covariates=conv_h_d_train)
        res_mape = caculatemape(model, val_ts_scaled, val_series, conv_h_d_val, val_ts_sca, N, num_blocks, num_layers,
                                layers_widths)
        print(res_mape)
        now_mean_mape = np.mean(res_mape)
        if now_mean_mape > best_mape:
            print("有更加优秀的结果,mape为:\t", now_mean_mape)
            best_mape = now_mean_mape

            day = datetime.datetime.now().strftime('%y-%m-%d')
            foldername = ('./T_test_NBeats' + day + 'N_' + str(N) + 'num_blocks_' +
                          str(num_blocks) + 'num_layers_' +
                          str(num_layers) + 'layers_widths_' +
                          str(layers_widths) + 'Nbeats_Model/')
            if not os.path.exists(foldername):
                os.mkdir(foldername)

            save_url = foldername + '/NBeats_mape_' + str(round(best_mape, 4)) + '.pth'
            best_url = foldername + '/NBeats_best.pth'
            model.save(save_url)
            model.save(best_url)
            count = 0
        else:
            count += 1
        if count > 10:
            print("超过10次未更加优化")
            break

至于调用部分,你就自己写吧,臭宝