2000字范文,分享全网优秀范文,学习好帮手!
2000字范文 > 时间序列预测12:用电量预测 02 朴素模型多步预测建模

时间序列预测12:用电量预测 02 朴素模型多步预测建模

时间:2020-10-12 00:46:02

相关推荐

时间序列预测12:用电量预测 02 朴素模型多步预测建模

【时间序列预测/分类】 全系列60篇由浅入深的博文汇总:传送门

接上文,本文使用朴素模型来对家庭用电数据集进行单变量多步预测。主要内容如下:

如何为模型准备数据集;如何开发指标、划分数据集、评估预测模型;如何开发和评估和比较朴素模型的性能;

文章目录

如何开发用于多时间步家庭用电量预测的朴素模型1. 数据处理1.1 异常值处理1.2 缺失值处理 2. 模型评估2.1 问题建模2.2 评价指标2.3 训练集和测试集划分2.4 前向验证2.5 朴素预测模型(简单模型)2.5.1 每日持久性预测2.5.2 每周持久性预测2.5.3 一年前每周的持久性预测 3. 完整代码

如何开发用于多时间步家庭用电量预测的朴素模型

1. 数据处理

1.1 异常值处理

从上一篇文章中得知,数据集中有大量标记为的异常值,这就需要把这些异常值处理为np.nan的浮点类型,提高数据处理速度。代码如下:

import numpy as npimport pandas as pdimport matplotlib.pyplot as plt# 函数的参数在上篇文章中已经介绍,此处不再赘述。dataset = pd.read_csv('household_power_consumption.txt', sep=';', header=0, low_memory=False, infer_datetime_format=True, engine='c',parse_dates={'datetime':[0,1]}, index_col=['datetime'])dataset.replace('?', np.nan, inplace=True) # 替换异常值values = dataset.values.astype('float32') # 统一数据类型为float类型,提高精度和速度

1.2 缺失值处理

刚才我们把异常值替换成了缺失值(nan),这一步我们填充这些缺失的值。一个非常简单的方法是复制前一天同一时刻的采样值。使用自定义的fill_missing()函数来实现:

def fill_missing(values):'''该函数实现缺失值填充思路:将前一天同一时刻的采样值用来填充缺失值'''one_day = 60 * 24for row in range(values.shape[0]):# 行循环for col in range(values.shape[1]): # 列循环if np.isnan(values[row, col]):values[row, col] = values[row - one_day, col]fill_missing(dataset.values) # 填充缺失值

处理完成后,添加新列并将处理完成的数据保存,计算公式已经在前一篇文章中解释过,此处不赘述。代码如下:

# 添加剩余用电量的列values = dataset.valuesdataset['sub_metering_4'] = (values[:,0] * 1000 / 60) - (values[:,4] + values[:,5] + values[:,6])dataset.to_csv('household_power_consumption.csv')

至此,数据处理完成。

2. 模型评估

本节介绍如何开发和评估家庭用电量数据集的预测模型。本节主要包括以下四部分内容:

问题建模评价指标训练集测试集划分前向验证

2.1 问题建模

有许多方法探索家庭用电量数据集。本文使用这些数据来探索一个具体的问题:用最近一段时间的数据来预测未来一周的用电量是多少。这需要建立一个预测模型预测未来七天每天的总有功功率。这类问题被称为多步时间序列预测问题。利用多个输入变量的模型可称为多变量(特征)多步时间序列预测模型。

要达到这样的目的,为了便于处理,先把原数据每分钟的耗电量采样数据重新采样成每日总耗电量。这不是必需的,但是有意义,因为我们关心的是每天的总功率。可以使用 Pandas中的resample()函数实现,设置参数“D”调用此函数,以允许按日期-时间索引加载数据并按天将数据重新采样分组。然后,可以通过计算每天所有采样值的总和,为这8个变量(特征)创建新的日耗电量数据集。

查看重新采样的结果:

daily_groups = dataset.resample('D')daily_groups.sum()

新采样包含的原采样点个数统计:

daily_groups.count()

重采样:

daily_data = daily_groups.sum()

可以从以上输出信息得知重新采样之后,数据的shape为(1442, 8)

保存为新的csv文件:

daily_data.to_csv('household_power_consumption_days.csv'

2.2 评价指标

预测输出为七个值组成的向量,每个值代表预测的未来一周中每一天的耗电量。多步预测问题通常是对每一个预测时间步分别进行评价。有如下建议:

每隔一定周期(例如预测1天、预测3天的模型)对技能进行评价;根据预测日期长短的不同对比模型(例如,擅长预测1天的模型与擅长预测5天的模型);

总功率的单位是千瓦,应该使用具有统一单位的误差度量方法。**均方根误差(RMSE)绝对平均误差(MAE)**都符合这个单位统一的要求,本文采用更常用的 RMSE。与MAE不同,RMSE对预测错误的惩罚更大。此问题的性能指标是从第1天到第7天的每天的的RMSE。用分数来评估模型的表现以帮助模型的选择,是便捷有效的方法。一个可用的评估分数是所有单日的 RMSE。自定义的evaluate forecast()函数可以实现这个功能。

2.3 训练集和测试集划分

使用前三年的数据训练预测模型,最后一年的数据评估模型。将数据按照标准周(星期天开始到星期六结束)进行划分。这对模型的选定是一种有效的方法,可以预测未来一周的耗电量。也有助于建模,模型可用于预测特定的一天(如周三)或整个序列。

以周为单位对数据进行处理,先截取测试数据,剩下的为训练数据。数据的最后一年是,的第一个星期天是1月3日,数据在11月26日结束,最近的最后一个星期六是11月20日。一共46周的测试数据。下面提供测试数据集的第一行和最后一行每日数据以供确认。

由之前的统计可知(上文中的图),每日耗电量数据从12月16日开始。数据集中的第一个周日是12月17日,这是第二行数据。将数据组织成标准周,可提供159个完整的标准周用于训练预测模型。

自定义的split_dataset()函数将每天的数据分成训练集和测试集,并将它们组织成标准周。特定的行偏移量用于使用数据集的知识拆分数据。然后使用NumPy的split()函数将分割的数据集组织为每周数据。此处注意split()函数的功能是等间距划分,如果数据能整除会报错。

2.4 前向验证

模型使用前向验证进行评估。流程为:先提供给模型一周的数据,预测第二周;接着给第二周的实际数据,用前两周的数据,预测第三周;然后给第三周的实际数据,使用前三周的数据,预测第四周,以此类推…在下面用输入数据和输出/预测数据来演示:

Input, Predict[Week1] Week2[Week1 + Week2] Week3[Week1 + Week2 + Week3] Week4...

在此数据集上评估预测模型的前向验证方法通过自定义的evaluate_model()函数实现。model_func参数为函数名。提供的这个函数用来定义模型,拟合模型,并预测一周的用电量。然后,evaluate_model()函数根据测试数据集对模型所做的预测进行求值。

2.5 朴素预测模型(简单模型)

在任何新的预测问题上,测试朴素预测模型是很重要的。朴素模型的预测结果定量地显示了预测问题的难度,并提供了一个标准性能(baseline),通过它可以评估更复杂的预测方法。本节比较三种针对家庭功率预测问题的简单预测方法:

每日持久性预测;每周持久性预测;一年前每周的持久性预测;

2.5.1 每日持久性预测

该模型取预测期前最后一天(如周六)的有功功率,作为预测期内(周日至周六)每天的有功功率值。daily_persistence()函数实现了该策略。

2.5.2 每周持久性预测

该模型预测取前一周的整个时间作为下一周的预测。这是基于下周将与本周非常相似的想法。weekly_persistence()函数实现了该策略。

2.5.3 一年前每周的持久性预测

类似于利用上周预测下周的想法,即根据下周将与一年前的同一周相似的想法,使用52周前的观察周作为预测。year_persistence()函数实现了该策略。

3. 完整代码

import numpy as npimport pandas as pdimport matplotlib.pyplot as pltimport mathimport sklearn.metrics as skm# 设置中文显示plt.rcParams['font.sans-serif'] = ['Microsoft JhengHei']plt.rcParams['axes.unicode_minus'] = Falsedef split_dataset(data):'''该函数实现以周为单位切分训练数据和测试数据'''# data为按天的耗电量统计数据,shape为(1442, 8)# 测试集取最后一年的46周(322天)数据,剩下的159周(1113天)数据为训练集,以下的切片实现此功能。train, test = data[1:-328], data[-328:-6]train = np.array(np.split(train, len(train)/7)) # 将数据划分为按周为单位的数据test = np.array(np.split(test, len(test)/7))return train, testdef evaluate_forecasts(actual, predicted):'''该函数实现根据预期值评估一个或多个周预测损失思路:统计所有单日预测的 RMSE'''scores = list()for i in range(actual.shape[1]):mse = skm.mean_squared_error(actual[:, i], predicted[:, i])rmse = math.sqrt(mse)scores.append(rmse)s = 0 # 计算总的 RMSEfor row in range(actual.shape[0]):for col in range(actual.shape[1]):s += (actual[row, col] - predicted[row, col]) ** 2score = math.sqrt(s / (actual.shape[0] * actual.shape[1]))print('actual.shape[0]:{}, actual.shape[1]:{}'.format(actual.shape[0], actual.shape[1]))return score, scoresdef summarize_scores(name, score, scores):s_scores = ', '.join(['%.1f' % s for s in scores])print('%s: [%.3f] %s\n' % (name, score, s_scores))def evaluate_model(model_func, train, test):'''该函数实现评估单个模型'''history = [x for x in train] # # 以周为单位的数据列表predictions = [] # 每周的前项预测值for i in range(len(test)):yhat_sequence = model_func(history) # 预测每周的耗电量predictions.append(yhat_sequence)history.append(test[i, :]) # 将测试数据中的采样值添加到history列表,以便预测下周的用电量predictions = np.array(predictions)score, scores = evaluate_forecasts(test[:, :, 0], predictions) # 评估一周中每天的预测损失return score, scoresdef daily_persistence(history):last_week = history[-1] # 获取之前一周七天的总有功功率value = last_week[-1, 0] # 获取前一周最后一天的总有功功率forecast = [value for _ in range(7)] # 准备7天预测return forecastdef weekly_persistence(history):last_week = history[-1] # 将之前一周的数据作为预测数据return last_week[:, 0]def week_one_year_ago_persistence(history):last_week = history[-52] # 将去年同一周的数据预测数据return last_week[:, 0]def model_predict_plot(dataset, days):train, test = split_dataset(dataset.values)#定义要评估的模型的名称和函数models = dict()models['daily'] = daily_persistencemodels['weekly'] = weekly_persistencemodels['week-oya'] = week_one_year_ago_persistenceplt.figure(figsize=(8,6), dpi=150)for name, func in models.items():score, scores = evaluate_model(func, train, test)summarize_scores(name, score, scores)plt.plot(days, scores, marker='o', label=name)plt.grid(linestyle='--', alpha=0.5)plt.ylabel(r'$RMSE$', size=15)plt.title('三种模型预测结果比较', color='blue', size=20)plt.legend()plt.show()if __name__ == '__main__':dataset = pd.read_csv('household_power_consumption_days.csv', header=0, infer_datetime_format=True, engine='c',parse_dates=['datetime'], index_col=['datetime'])days = ['sun', 'mon', 'tue', 'wed', 'thr', 'fri', 'sat']model_predict_plot(dataset, days)

运行该示例首先打印每个模型的总分数和每日分数。我们可以看到,周策略的表现优于日策略,一年前的一周数据预测当前周的策略表现最好。我们可以在每个模型的总体RMSE得分和每个预测日的得分中看到这一点。一个例外是第一天(星期天)的预测错误,在这一天,每日持久性模型的性能似乎优于两周策略。我们可以使用一年前的一周数据预测当前周的策略,以465.294千瓦的总RMSE作为性能基线,来评估其它复杂模型在该数据集上的表现。

actual.shape[0]:46, actual.shape[1]:7daily: [511.886] 452.9, 596.4, 532.1, 490.5, 534.3, 481.5, 482.0actual.shape[0]:46, actual.shape[1]:7weekly: [469.389] 567.6, 500.3, 411.2, 466.1, 471.9, 358.3, 482.0actual.shape[0]:46, actual.shape[1]:7week-oya: [465.294] 550.0, 446.7, 398.6, 487.0, 459.3, 313.5, 555.1

下一篇文章介绍ARIMA模型实现用电量多步预测。

参考:

/naive-methods-for-forecasting-household-electricity-consumption/

/pandas-docs/stable/reference/api/pandas.DataFrame.resample.html?highlight=resample#pandas.DataFrame.resample

/stable/generated/statsmodels.graphics.tsaplots.plot_acf.html?highlight=plot_acf

/index.html

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。