时间序列预测15:Multi-input / Multi-head CNN 实现用电量/发电量预测


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


接上文,本文介绍如何为多变量数据开发多输入通道多步时间序列预测的CNN模型和多子模型异构多步时间序列预测的CNN模型。


文章目录

  • 2. 多输入通道 CNN 模型
    • 2.1 建模
    • 2.2 完整代码
  • 3. 多头(子模型异构)CNN 模型
    • 3.1 建模
    • 3.2 完整代码
  • 总结


2. 多输入通道 CNN 模型

顾名思义,多通道就是有多个时间序列,即多个特征。本部分使用数据集中的八个时间序列变量(八个特征,数据集信息如下图所示)来分别预测下一个标准周的每日总有功功率。可以将每个变量时间序列作为单独的输入通道提供给模型来实现多通道输入。然后,CNN将使用一个单独的内核,并将每个输入序列读取到一组单独的过滤器映射图上,实质上是从每个输入时间序列变量中学习特征。注意,以上过程都是在同一个CNN模型中实现的,不同于下文提到的多头(子模型异构)CNN模型,为每个输入序列都定义一个CNN模型。

使用多输入通道的CNN模型,对于输出序列是预测多个不同特征(不局限于所预测的某个特征)的任务来说很有帮助。目前尚不清楚在电力消耗问题上是否如此,但我们可以对此进行探讨。接下来需要重新划分训练样本和测试样本,使得样本中包含全部八个特征,而不仅仅是日总有有功率这一个特征。先看一下本文使用的数据集信息:
在这里插入图片描述

2.1 建模

由上图可知,本文使用的数据集shape为(1442,8),采样点为1442个,特征数(features)为8个(8列)。通过滑动窗口和切片相结合的方式来将以上采样数据划分成样本(samples),其中滑动窗口的宽度和 滑动步长(sw_width) 可以设置为超参数,方便后期调参的时候,找到适合自己业务需求的窗口宽度和滑动步长。代码实现:

def sliding_window(train, sw_width=7, n_out=7, in_start=0):'''该函数实现窗口宽度为7、滑动步长为1的滑动窗口截取序列数据截取所有特征'''data = train.reshape((train.shape[0] * train.shape[1], train.shape[2])) # 将以周为单位的样本展平为以天为单位的序列X, y = [], []for _ in range(len(data)):in_end = in_start + sw_widthout_end = in_end + n_out# 保证截取样本完整,最大元素索引不超过原序列索引,则截取数据;否则丢弃该样本if out_end < len(data):# 因为是for循环,所以滑动窗口的滑动步长为1;想调整滑动步长可以通过yield实现,后边的文章会讲;X.append(data[in_start:in_end, :]) # 截取窗口宽度数量的采样点的全部8个特征y.append(data[in_end:out_end, 0]) # 截取样本之后7个时间步长的总有功功耗(截取一个单列片段,有7个元素)in_start += 1return np.array(X), np.array(y)

如果没有看过之前的文章,代码中第一条语句可能有疑问,这里说明一下:

data = train.reshape((train.shape[0] * train.shape[1], train.shape[2])) # 将以周为单位的样本展平为以天为单位的序列

其实在这个自定义函数之前,还有一个将数据集划分为训练集和测试集的自定义函数 split_dataset(),这个函数通过切片的方式截取,将前三年每天的采样数据作为训练集(共159周,1113天),最后一年的采样数据作为测试集(共46周,322天),本文使用的数据的shape为(1442,8),经过以上划分一共使用了1113+322=1435个采样点数据,第一天和最后六天无法组成完整的标准周(周天开始周六结束),因此丢弃不用。

然后通过 numpy 的 split 函数将单日数据重采样成以周为单位的训练样本,因此,训练数据的shape变为(159, 7, 8),测试数据的shape变为(46, 7, 8) 。三维数组怎么理解,这里解释一下,第一个维度“159”表示159周,每周的数据作为一个样本;第二个维度“7”表示一个样本有七个采样点的值,即包含7个时间步长的数据;第三个维度“8”表示有八个特征(也可理解为八个变量,八列可用数据)。训练集的shape同理。讲到这里,应该可以明白上边拿出来的语句的功能了,即将三维数组重塑成二维数组,这样就还原回以每日为单位的采样序列,便于做滑动窗口。当然也可以不用这么麻烦,直接重写划分训练集和测试集的函数即可。

可能会问为什么要按照每周来划分,其实这是针对本系列文章所提出的问题的;原问题是用历史数据预测下一周该家庭的总有功功率的情况,因此处理成按周划分的数据,方便演示和说明问题。当然可以使用更大的窗口宽度,比如用两个星期的数据预测下一个星期的数据,其实这些都是超参数,后期需要针对不同的业务场景进行调整和超参数搜索,来找到最佳的先验时间步长。之后的文章再介绍如何调参。

还有几点需要注意,这里三维数组的各个维度所代表的含义,只是针对本系列文章中提出的问题;在使用的过程中,根据自己的需求修改就可以了。主要是弄明白滑动窗口、滑动窗口的宽度、滑动步长、样本、特征这些概念和实现方法,这样在处理自己遇到的问题的时候就能随机应变,得心应手了。


上一篇文章中提到的预测函数也需要进一步修改。完整代码如下:

def forecast(model, pred_seq, sw_width):'''该函数实现对输入数据的预测多个特征'''data = np.array(pred_seq)data = data.reshape((data.shape[0]*data.shape[1], data.shape[2]))input_x = data[-sw_width:, :] # 获取输入数据的最后一周的数据input_x = input_x.reshape((1, input_x.shape[0], input_x.shape[1])) # 重塑形状为[1, sw_width, n]yhat = model.predict(input_x, verbose=0) # 预测下周数据yhat = yhat[0] # 获取预测向量return yhat

此处使用一个稍复杂的模型,包含三层卷积,两层池化,一个flatten层和两个全连接层。使用均方误差损失函数mse,使用随机梯度下降adam进行优化。

2.2 完整代码

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt# 设置中文显示
plt.rcParams['font.sans-serif'] = ['Microsoft JhengHei']
plt.rcParams['axes.unicode_minus'] = Falseimport math
import sklearn.metrics as skm
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Flatten
from tensorflow.keras.layers import Conv1D,MaxPooling1Ddef 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 sliding_window(train, sw_width=7, n_out=7, in_start=0):'''该函数实现窗口宽度为7、滑动步长为1的滑动窗口截取序列数据截取所有特征'''data = train.reshape((train.shape[0] * train.shape[1], train.shape[2])) # 将以周为单位的样本展平为以天为单位的序列X, y = [], []for _ in range(len(data)):in_end = in_start + sw_widthout_end = in_end + n_out# 保证截取样本完整,最大元素索引不超过原序列索引,则截取数据;否则丢弃该样本if out_end < len(data):# 因为是for循环,所以滑动窗口的滑动步长为1;想调整滑动步长可以通过yield实现,后边的文章会讲;X.append(data[in_start:in_end, :]) # 截取窗口宽度数量的采样点的全部8个特征y.append(data[in_end:out_end, 0]) # 截取样本之后7个时间步长的总有功功耗(截取一个单列片段,有7个元素)in_start += 1return np.array(X), np.array(y)def multi_input_cnn_model(train, sw_width, in_start=0, verbose=0, epochs=20, batch_size=16):'''该函数定义 多输入序列 CNN 模型'''train_x, train_y = sliding_window(train, sw_width, in_start=0)n_timesteps, n_features, n_outputs = train_x.shape[1], train_x.shape[2], train_y.shape[1]model = Sequential()model.add(Conv1D(filters=32, kernel_size=3, activation='relu', input_shape=(n_timesteps, n_features)))model.add(Conv1D(filters=32, kernel_size=3, activation='relu'))model.add(MaxPooling1D(pool_size=2))model.add(Conv1D(filters=16, kernel_size=3, activation='relu'))model.add(MaxPooling1D(pool_size=2))model.add(Flatten())model.add(Dense(100, activation='relu'))model.add(Dense(units=n_outputs))model.compile(loss='mse', optimizer='adam', metrics=['accuracy'])print(model.summary())model.fit(train_x, train_y,epochs=epochs, batch_size=batch_size, verbose=verbose)return modeldef forecast(model, pred_seq, sw_width):'''该函数实现对输入数据的预测多个特征'''data = np.array(pred_seq)data = data.reshape((data.shape[0]*data.shape[1], data.shape[2]))input_x = data[-sw_width:, :] # 获取输入数据的最后一周的数据input_x = input_x.reshape((1, input_x.shape[0], input_x.shape[1])) # 重塑形状为[1, sw_width, n]yhat = model.predict(input_x, verbose=0) # 预测下周数据yhat = yhat[0] # 获取预测向量return yhatdef evaluate_model(model, train, test, sd_width):'''该函数实现模型评估'''history_fore = [x for x in train]predictions = list() # 用于保存每周的前向验证结果;for i in range(len(test)):yhat_sequence = forecast(model, history_fore, sd_width) # 预测下周的数据predictions.append(yhat_sequence) # 保存预测结果history_fore.append(test[i, :]) # 得到真实的观察结果并添加到历史中以预测下周predictions = np.array(predictions) # 评估一周中每天的预测结果score, scores = evaluate_forecasts(test[:, :, 0], predictions)return score, scoresdef model_plot(score, scores, days, name):'''该函数实现绘制RMSE曲线图'''plt.figure(figsize=(8,6), dpi=150)plt.plot(days, scores, marker='o', label=name)plt.grid(linestyle='--', alpha=0.5)plt.ylabel(r'$RMSE$', size=15)plt.title('多输入序列 CNN 模型预测结果',  size=18)plt.legend()plt.show()def main_run(dataset, sw_width, days, name, in_start, verbose, epochs, batch_size):'''主函数:数据处理、模型训练流程'''# 划分训练集和测试集train, test = split_dataset(dataset.values)# 训练模型model = multi_input_cnn_model(train, sw_width, in_start, verbose, epochs, batch_size)# 计算RMSEscore, scores = evaluate_model(model, train, test, sw_width)# 打印分数summarize_scores(name, score, scores)# 绘图model_plot(score, scores, days, name)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']name = 'cnn'sliding_window_width=14input_sequence_start=0epochs_num=80batch_size_set=16verbose_set=0main_run(dataset, sliding_window_width, days, name, input_sequence_start,verbose_set, epochs_num, batch_size_set)

输出:

Model: "sequential_4"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv1d_4 (Conv1D)            (None, 12, 32)            800       
_________________________________________________________________
conv1d_5 (Conv1D)            (None, 10, 32)            3104      
_________________________________________________________________
max_pooling1d_4 (MaxPooling1 (None, 5, 32)             0         
_________________________________________________________________
conv1d_6 (Conv1D)            (None, 3, 16)             1552      
_________________________________________________________________
max_pooling1d_5 (MaxPooling1 (None, 1, 16)             0         
_________________________________________________________________
flatten_4 (Flatten)          (None, 16)                0         
_________________________________________________________________
dense_8 (Dense)              (None, 100)               1700      
_________________________________________________________________
dense_9 (Dense)              (None, 7)                 707       
=================================================================
Total params: 7,863
Trainable params: 7,863
Non-trainable params: 0
_________________________________________________________________
None
actual.shape[0]:46, actual.shape[1]:7
cnn: [399.443] 407.8, 388.4, 396.2, 388.1, 370.9, 321.5, 501.1

与上一节中的单变量CNN相比,有些更好,有些更差。最后一天,星期六,仍然是充满挑战的一天,而星期五则是容易预测的一天。设计模型以专注于减少较难预测的日期的误差可能会有帮助。使用调整后的模型或多个不同模型的组合是否可以进一步降低每日得分之间的差异是值得探索的。输出的RMSE如图所示:
在这里插入图片描述


3. 多头(子模型异构)CNN 模型

进一步扩展CNN模型,使每个输入变量具有一个单独的子CNN模型,可以将其称为多头CNN模型。这需要重新划分训练集和测试集数据。从建模开始,需要为八个输入变量分别定义一个单独的CNN模型。模型的配置(包括层数及其超参数)也进行了修改,以更好地适应新方法。模型配置通过多次试验验证获得,可能并非最佳配置。

3.1 建模

我们可以循环遍历每个变量,创建一个子模型,该子模型接受一个14天的一维数据序列,并输出一个包含序列学习特征信息的平面向量。这些向量中的每一个都可以通过级联合并成一个非常长的向量,然后在进行预测之前通过全连接层进行解释。这样就可以在模型的定义中指定输入,并在合并层中使用平坦层组成的列表。

训练模型时,将需要八个数组分别输入八个子模型。可以通过创建3D数组列表来实现,其中每个3D数组的shape都为:[samples,timesteps,1]

对测试数据集进行预测时,必须将 [1,14,8] 的输入数组转换为八个3D数组的列表,每个数组的shape都为 [1,14,1]


3.2 完整代码

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt# 设置中文显示
plt.rcParams['font.sans-serif'] = ['Microsoft JhengHei']
plt.rcParams['axes.unicode_minus'] = Falseimport math
import sklearn.metrics as skm
from tensorflow.keras.models import Model
from tensorflow.keras.layers import Dense, Flatten, Input
from tensorflow.keras.layers import Conv1D, MaxPooling1D
from tensorflow.keras.layers import concatenate
from tensorflow.keras.utils import plot_modeldef 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))print('train.shape:{}, test.shape:{}\n'.format(train.shape, test.shape))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 sliding_window(train, sw_width=7, n_out=7, in_start=0):'''该函数实现窗口宽度为7、滑动步长为1的滑动窗口截取序列数据截取所有特征'''data = train.reshape((train.shape[0] * train.shape[1], train.shape[2])) # 将以周为单位的样本展平为以天为单位的序列X, y = [], []for _ in range(len(data)):in_end = in_start + sw_widthout_end = in_end + n_out# 保证截取样本完整,最大元素索引不超过原序列索引,则截取数据;否则丢弃该样本if out_end <= len(data):# 因为是for循环,所以滑动窗口的滑动步长为1;想调整滑动步长可以通过yield实现,后边的文章会讲;X.append(data[in_start:in_end, :]) # 截取窗口宽度数量的采样点的全部8个特征y.append(data[in_end:out_end, 0]) # 截取样本之后7个时间步长的总有功功耗(截取一个单列片段,有7个元素)in_start += 1 # 实现简单的滑动窗口,滑动步长为1return np.array(X), np.array(y)def multi_head_cnn_model(train, sw_width, in_start=0, verbose=0, epochs=20, batch_size=16):'''该函数定义 Multi-head CNN 模型'''train_x, train_y = sliding_window(train, sw_width)n_timesteps, n_features, n_outputs = train_x.shape[1], train_x.shape[2], train_y.shape[1]in_layers, out_layers = [], [] # 用于存放每个特征序列的CNN子模型for i in range(n_features):inputs = Input(shape=(n_timesteps, 1))conv1 = Conv1D(filters=32, kernel_size=3, activation='relu')(inputs)conv2 = Conv1D(filters=32, kernel_size=3, activation='relu')(conv1)pool1 = MaxPooling1D(pool_size=2)(conv2)flat = Flatten()(pool1)in_layers.append(inputs)out_layers.append(flat)merged = concatenate(out_layers) # 合并八个CNN子模型dense1 = Dense(200, activation='relu')(merged) # 全连接层对上一层输出特征进行解释dense2 = Dense(100, activation='relu')(dense1)outputs = Dense(n_outputs)(dense2)model = Model(inputs=in_layers, outputs=outputs)model.compile(loss='mse', optimizer='adam', metrics=['accuracy'])print(model.summary())plot_model(model, to_file='multi-head-cnn-energy-usage-prediction.png', show_shapes=True, show_layer_names=True, dpi=300)input_data = [train_x[:,:,i].reshape((train_x.shape[0], n_timesteps, 1)) for i in range(n_features)]# 这里只是为了方便演示和输出loss曲线,不建议这么做,这样其实是训练了2倍的epoch;# 可以保存模型,再加载预测;或者直接将预测函数定影在这里,省去调用步骤。model.fit(input_data, train_y, epochs=epochs, batch_size=batch_size, verbose=verbose)history = model.fit(input_data, train_y, epochs=epochs, batch_size=batch_size, verbose=verbose)return model, history def forecast(model, pred_seq, sw_width):'''该函数实现对输入数据的预测多个特征'''data = np.array(pred_seq)data = data.reshape((data.shape[0]*data.shape[1], data.shape[2]))input_x = data[-sw_width:, :] # 获取输入数据的最后一周的数据input_x = [input_x[:,i].reshape((1,input_x.shape[0],1)) for i in range(input_x.shape[1])]# 8个形状为[1, sw_width, 1]的列表yhat = model.predict(input_x, verbose=0) # 预测下周数据yhat = yhat[0] # 获取预测向量return yhatdef evaluate_model(model, train, test, sd_width):'''该函数实现模型评估'''history_fore = [x for x in train]predictions = list() # 用于保存每周的前向验证结果;for i in range(len(test)):yhat_sequence = forecast(model, history_fore, sd_width) # 预测下周的数据predictions.append(yhat_sequence) # 保存预测结果history_fore.append(test[i, :]) # 得到真实的观察结果并添加到历史中以预测下周predictions = np.array(predictions) # 评估一周中每天的预测结果score, scores = evaluate_forecasts(test[:, :, 0], predictions)return score, scoresdef model_plot(score, scores, days, name, history):'''该函数实现绘制RMSE曲线图和训练损失图'''plt.figure(figsize=(8,6), dpi=150)plt.subplot(2,1,1)plt.plot(days, scores, marker='o', label=name)plt.grid(linestyle='--', alpha=0.5)plt.xlabel(r'$weekday$', size=15)plt.ylabel(r'$RMSE$', size=15)plt.title('Multi-head CNN 模型预测结果',  size=18)plt.subplot(2,1,2)plt.plot(history.history['loss'], label='train')plt.title('loss', y=0, loc='center')plt.xlabel('$epochs$', size=10)plt.ylabel('$loss$', size=10)plt.legend()plt.grid(linestyle='--', alpha=0.5)plt.tight_layout()plt.show()def main_run(dataset, sw_width, days, name, in_start, verbose, epochs, batch_size):'''主函数:数据处理、模型训练流程'''# 划分训练集和测试集train, test = split_dataset(dataset.values)# 训练模型 model, history = multi_head_cnn_model(train, sw_width, in_start, verbose, epochs, batch_size)# 计算RMSEscore, scores = evaluate_model(model, train, test, sw_width)# 打印分数summarize_scores(name, score, scores)# 绘制RMSE图和训练损失图model_plot(score, scores, days, name, history)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']name = 'cnn'sliding_window_width=14input_sequence_start=0epochs_num=80 #25batch_size_set=16verbose_set=0main_run(dataset, sliding_window_width, days, name, input_sequence_start,verbose_set, epochs_num, batch_size_set)

输出:

train.shape:(159, 7, 8), test.shape:(46, 7, 8)Model: "model"
__________________________________________________________________________________________________
Layer (type)                    Output Shape         Param #     Connected to                     
==================================================================================================
input_1 (InputLayer)            [(None, 14, 1)]      0                                            
__________________________________________________________________________________________________
input_2 (InputLayer)            [(None, 14, 1)]      0                                            
__________________________________________________________________________________________________
input_3 (InputLayer)            [(None, 14, 1)]      0                                            
__________________________________________________________________________________________________
input_4 (InputLayer)            [(None, 14, 1)]      0                                            
__________________________________________________________________________________________________
input_5 (InputLayer)            [(None, 14, 1)]      0                                            
__________________________________________________________________________________________________
input_6 (InputLayer)            [(None, 14, 1)]      0                                            
__________________________________________________________________________________________________
input_7 (InputLayer)            [(None, 14, 1)]      0                                            
__________________________________________________________________________________________________
input_8 (InputLayer)            [(None, 14, 1)]      0                                            
__________________________________________________________________________________________________
conv1d_7 (Conv1D)               (None, 12, 32)       128         input_1[0][0]                    
__________________________________________________________________________________________________
conv1d_9 (Conv1D)               (None, 12, 32)       128         input_2[0][0]                    
__________________________________________________________________________________________________
conv1d_11 (Conv1D)              (None, 12, 32)       128         input_3[0][0]                    
__________________________________________________________________________________________________
conv1d_13 (Conv1D)              (None, 12, 32)       128         input_4[0][0]                    
__________________________________________________________________________________________________
conv1d_15 (Conv1D)              (None, 12, 32)       128         input_5[0][0]                    
__________________________________________________________________________________________________
conv1d_17 (Conv1D)              (None, 12, 32)       128         input_6[0][0]                    
__________________________________________________________________________________________________
conv1d_19 (Conv1D)              (None, 12, 32)       128         input_7[0][0]                    
__________________________________________________________________________________________________
conv1d_21 (Conv1D)              (None, 12, 32)       128         input_8[0][0]                    
__________________________________________________________________________________________________
conv1d_8 (Conv1D)               (None, 10, 32)       3104        conv1d_7[0][0]                   
__________________________________________________________________________________________________
conv1d_10 (Conv1D)              (None, 10, 32)       3104        conv1d_9[0][0]                   
__________________________________________________________________________________________________
conv1d_12 (Conv1D)              (None, 10, 32)       3104        conv1d_11[0][0]                  
__________________________________________________________________________________________________
conv1d_14 (Conv1D)              (None, 10, 32)       3104        conv1d_13[0][0]                  
__________________________________________________________________________________________________
conv1d_16 (Conv1D)              (None, 10, 32)       3104        conv1d_15[0][0]                  
__________________________________________________________________________________________________
conv1d_18 (Conv1D)              (None, 10, 32)       3104        conv1d_17[0][0]                  
__________________________________________________________________________________________________
conv1d_20 (Conv1D)              (None, 10, 32)       3104        conv1d_19[0][0]                  
__________________________________________________________________________________________________
conv1d_22 (Conv1D)              (None, 10, 32)       3104        conv1d_21[0][0]                  
__________________________________________________________________________________________________
max_pooling1d_6 (MaxPooling1D)  (None, 5, 32)        0           conv1d_8[0][0]                   
__________________________________________________________________________________________________
max_pooling1d_7 (MaxPooling1D)  (None, 5, 32)        0           conv1d_10[0][0]                  
__________________________________________________________________________________________________
max_pooling1d_8 (MaxPooling1D)  (None, 5, 32)        0           conv1d_12[0][0]                  
__________________________________________________________________________________________________
max_pooling1d_9 (MaxPooling1D)  (None, 5, 32)        0           conv1d_14[0][0]                  
__________________________________________________________________________________________________
max_pooling1d_10 (MaxPooling1D) (None, 5, 32)        0           conv1d_16[0][0]                  
__________________________________________________________________________________________________
max_pooling1d_11 (MaxPooling1D) (None, 5, 32)        0           conv1d_18[0][0]                  
__________________________________________________________________________________________________
max_pooling1d_12 (MaxPooling1D) (None, 5, 32)        0           conv1d_20[0][0]                  
__________________________________________________________________________________________________
max_pooling1d_13 (MaxPooling1D) (None, 5, 32)        0           conv1d_22[0][0]                  
__________________________________________________________________________________________________
flatten_5 (Flatten)             (None, 160)          0           max_pooling1d_6[0][0]            
__________________________________________________________________________________________________
flatten_6 (Flatten)             (None, 160)          0           max_pooling1d_7[0][0]            
__________________________________________________________________________________________________
flatten_7 (Flatten)             (None, 160)          0           max_pooling1d_8[0][0]            
__________________________________________________________________________________________________
flatten_8 (Flatten)             (None, 160)          0           max_pooling1d_9[0][0]            
__________________________________________________________________________________________________
flatten_9 (Flatten)             (None, 160)          0           max_pooling1d_10[0][0]           
__________________________________________________________________________________________________
flatten_10 (Flatten)            (None, 160)          0           max_pooling1d_11[0][0]           
__________________________________________________________________________________________________
flatten_11 (Flatten)            (None, 160)          0           max_pooling1d_12[0][0]           
__________________________________________________________________________________________________
flatten_12 (Flatten)            (None, 160)          0           max_pooling1d_13[0][0]           
__________________________________________________________________________________________________
concatenate (Concatenate)       (None, 1280)         0           flatten_5[0][0]                  flatten_6[0][0]                  flatten_7[0][0]                  flatten_8[0][0]                  flatten_9[0][0]                  flatten_10[0][0]                 flatten_11[0][0]                 flatten_12[0][0]                 
__________________________________________________________________________________________________
dense_10 (Dense)                (None, 200)          256200      concatenate[0][0]                
__________________________________________________________________________________________________
dense_11 (Dense)                (None, 100)          20100       dense_10[0][0]                   
__________________________________________________________________________________________________
dense_12 (Dense)                (None, 7)            707         dense_11[0][0]                   
==================================================================================================
Total params: 302,863
Trainable params: 302,863
Non-trainable params: 0
__________________________________________________________________________________________________
None
actual.shape[0]:46, actual.shape[1]:7
cnn: [492.451] 575.9, 437.3, 498.6, 473.7, 511.1, 417.1, 516.2

输出RMSE曲线和训练损失曲线:
在这里插入图片描述
保存的模型结构图:
在这里插入图片描述


总结

在这两篇关于CNN做时间序列预测任务的文章中,主要介绍了如下内容:

  • 如何为单变量数据开发多步时间序列预测的CNN模型;
  • 如何为多变量数据开发多通道多步时间序列预测的CNN模型;
  • 如何为多变量数据开发多头多步时间序列预测的CNN模型。

下一篇文章开始介绍LSTM实现时间序列预测任务。


在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/24224.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

人工智能迅猛发展,如何应对避免失业?

“人工智能从感知智能向认知智能演进”&#xff0c;人工智能的发展带给我们哪些思考&#xff1f;它究竟会给我们的工作生活带来哪些变化?我们要如何去应对&#xff1f; 阿里达摩院票选出2020年十大科技趋势&#xff1a; 量子计算进入攻坚期工业互联网的超融合保护数据隐私的A…

【杂谈】人脸图像书看完了感觉不过瘾?这些拓展人脸资料值得你关注一下

相信许多朋友都看过我这本人脸图像处理的书籍了&#xff0c;内容涵盖了人脸检测&#xff0c;人脸关键点检测&#xff0c;人脸识别&#xff0c;人脸属性分析&#xff0c;人脸美颜&#xff0c;人脸编辑与风格化&#xff0c;三维人脸重建内容&#xff0c;基本上包括了人脸的所有领…

Guava、Spring 如何抽象观察者模式?

什么是观察者模式 观察者模式 是一种行为设计模式&#xff0c;允许定义一种订阅通知机制&#xff0c;可以在对象&#xff08;被观察者&#xff09;事件发生时通知多个 “观察” 该对象的观察者对象&#xff0c;所以也被称为 发布订阅模式 其实我个人而言&#xff0c;不太喜欢使…

苹果「Find My iPhone」立功,帮警察追踪偷车嫌犯

By 超神经 内容提要&#xff1a;在澳大利亚墨尔本的一起入室盗窃案中&#xff0c;警方在 iPad 上「Find My」的协助下追踪到嫌犯位置&#xff0c;但追踪过程中嫌犯却因车祸丧生。 关键词&#xff1a;Find My 协警 盗窃 苹果的「Fing My」最近在一起入室抢劫案中立功了。 2 月 …

Hive 知识体系保姆级教程

Hive涉及的知识点如下图所示&#xff0c;本文将逐一讲解&#xff1a; 正文开始&#xff1a; 一. Hive概览 1.1 hive的简介 Hive是基于Hadoop的一个数据仓库工具&#xff0c;可以将结构化的数据文件映射为一张数据库表&#xff0c;并提供类SQL查询功能。 其本质是将SQL转换为Map…

跟着 Guava、Spring 学习如何设计观察者模式

文章首发在公众号&#xff08;龙台的技术笔记&#xff09;&#xff0c;之后同步到掘金和个人网站&#xff1a;xiaomage.info 今天讲解一篇行为型设计模式&#xff0c;什么是行为型&#xff1f;行为型主要负责设计 类或对象之间的交互。工作中常用的观察者模式就是一种行为型设…

【总结】有三AI重要原创人脸相关的技术文章汇总(2022年8月)

人脸图像的应用领域想必所有做视觉算法的都不会陌生&#xff0c;所有的安防监控、几乎现在所有的在线身份认证、支付、考勤都需要用到人脸检测与人脸识别&#xff0c;人脸识别甚至被用于追逃疑犯&#xff0c;找寻失踪人口。 所有的在线直播平台&#xff0c;手机拍照软件&#x…

【总结】有三AI所有原创人脸相关的学习资料汇总(2022年12月)

人脸图像的应用领域想必所有做视觉算法的都不会陌生&#xff0c;所有的安防监控、几乎现在所有的在线身份认证、支付、考勤都需要用到人脸检测与人脸识别&#xff0c;人脸识别甚至被用于追逃疑犯&#xff0c;找寻失踪人口。 所有的在线直播平台&#xff0c;手机拍照软件&#x…

CV:计算机视觉技最强学习路线之CV简介(传统视觉技术/相关概念)、早期/中期/近期应用领域(偏具体应用)、经典CNN架构(偏具体算法)概述、常用工具/库/框架/产品、环境安装、常用数据集、编程技巧

CV&#xff1a;计算机视觉技最强学习路线之CV简介(传统视觉技术/相关概念)、早期/中期/近期应用领域(偏具体应用)、经典CNN架构(偏具体算法)概述、常用工具/库/框架/产品、环境安装、常用数据集、编程技巧 导读&#xff1a;计算机视觉技最强学习路线&#xff0c;2022年10月18日…

Hive——函数-Explode(含案例演示建议收藏)

创建文件 vim movie.txt数据准备&#xff1a; 《疑犯追踪》 悬疑,动作,科幻,剧情 《Lie to me》 悬疑,警匪,动作,心理,剧情 《战狼 2》 战争,动作,灾难创建新表&#xff1a; create table movie_info(movie string,category string) row format delimited fields …

看美剧《疑犯追踪》,学地道美语 Learn idiomatic American English by watching Tv series Person of Interest

看美剧《疑犯追踪》&#xff0c;学地道美语 Learn idiomatic American English by watching Tv series Person of Interest cemike126.com 题记&#xff1a;暑期看了美剧《疑犯追踪》&#xff08;Person of Interest&#xff09;。开始只是记下第一级中一些引发我思考的片段台词…

疑犯追踪第五季/全集Person of Interest迅雷下载

英文全名Person of Interest&#xff0c;第5季(2015)CBS. 本季看点&#xff1a;《疑犯追踪》本季剧组暗示Finch可能重建机器&#xff0c;这次他会给机器更多自由&#xff08;如Root一直要求的那样&#xff09;。或许新机器更像个战士&#xff0c;比旧机器更强大。目前&#xff…

现实版的“疑犯追踪”是如何开展的?

为什么80%的码农都做不了架构师&#xff1f;>>> 童鞋们&#xff0c; 还记得在美剧《疑犯追踪》中&#xff0c; Finch发明的人工智能“The Machine”吗&#xff1f; 它通过获得和关联大量数据&#xff0c; 可分析出即将发生的犯罪事件并发出预警。 可以说是灰常滴了…

南澳行

上周随部门到南澳&#xff0c;其实这是我第二次去南澳了&#xff0c;不过上次去了大鹏古城&#xff0c;这次主要是在海边玩沙滩足球&#xff0c;好过隐呀&#xff01; 以前觉得南澳不错&#xff0c;因为可以在海边玩耍&#xff0c;至少比红树林感觉要好吧。但去年去了海南之后&…

大三期末网页设计作业 以旅游景点风景主题介绍网站设计与实现 (广东名胜古迹)

&#x1f329;️ 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f482; 作者主页: 【进入主页—&#x1f680;获取更多源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;HTML5网页期末作业 (1000套…

JS根据城市名称获取所在省份

微信小程序开发交流qq群 173683895 承接微信小程序开发。扫码加微信。 实现代码&#xff1a; var provinces require(../../../utils/provinces);var city 昆明市;provinces.forEach((item,index) > {item.city.forEach((itt, idx) > {if (itt.name city) {console.…

JS搜索省份匹配出省份的所有城市

微信小程序开发交流qq群 173683895 承接微信小程序开发。扫码加微信。 效果图&#xff1a; 模糊搜索和精确搜索省份的所有城市名称&#xff0c; 模糊搜索和精确搜索城市名称&#xff0c; js // pages/test/test.js var val; var provinces require(../../utils/provinces…

微信小程序选择市,区县

微信小程序开发交流qq群 173683895 承接微信小程序开发。扫码加微信。 微信小程序选择市&#xff0c;区县的实现 demo的需求是 做一个两列选择器&#xff0c;选择江西省范围内的所有市以及区县&#xff0c;滑动到每个城市 自动匹配出它的区县并赋值到第二列&#xff0c;用户…

python实现【国家统计局】三级区划代码和城乡划分代码爬取

今天找了点时间做了一个小爬虫&#xff0c;主要目标网站就是国家统计局&#xff0c;里面有历年来的区划代码和城乡划分代码数据&#xff0c;这在一些项目中都是会使用到的&#xff0c;爬虫本身的实现没有太复杂的内容&#xff0c;我们今天采集的是最新的也就是2018年的三级划分…

穿越南澳桔钓沙海岸线看海景

穿越南澳桔钓沙海岸线看海景 <?xml:namespace prefix o ns "urn:schemas-microsoft-com:office:office" /> Dec 31.2011 今天是12月份的最后一天&#xff0c;也是2011年的最后一天…… 这个12月份&#xff0c;注定是精彩的&#xff01;暖暖的冬日里&#xf…