TCN时间序列卷积神经网络

技术

时间序列卷积神经网络(TCN)是一种用于处理时间序列数据的深度学习模型

1. TCN优点

相较于传统的循环神经网络(RNN)和长短期记忆网络(LSTM),TCN 具有以下优点:

  • 长期依赖性建模能力: TCN 使用了带有不同扩张率(dilation rate)的卷积层,使得网络可以捕捉到序列中不同尺度的模式和长期依赖性,从而能够更好地建模长期的时间相关性
  • 参数效率: 相对于循环神经网络(RNN)和长短期记忆网络(LSTM)等传统的递归结构,TCN 中的卷积操作可以高效地并行计算,减少了参数数量和计算复杂度,从而加速了训练和推理过程
  • 平移不变性: TCN 使用的卷积操作是平移不变的,即不论输入序列的时间位置如何改变,模型学习到的特征仍然有效,这使得模型更加稳健,能够更好地适应序列数据中的时间偏移和变化
  • 易于并行化: TCN 中的卷积操作可以非常有效地并行计算,因此在现代硬件(如 GPU)上能够充分发挥并行计算的优势,加速训练过程
  • 可扩展性: TCN 模型结构相对灵活,可以根据任务的需求进行简单的修改和扩展。例如,通过调整网络的深度、宽度、卷积核大小和扩张率等超参数,可以适应不同的时间序列数据和任务
  • 不需要状态存储: 与传统的 RNN 和 LSTM 不同,TCN 不需要显式地存储和更新隐藏状态,这减少了内存占用并简化了模型的实现和调试过程

2. TCN Github网址


        
            

          https://github.com/philipperemy/keras-tcn
        
      

3 . 代码实现

3.1 数据展示


          
import pandas as pd
          
import numpy as np
          
df = pd.read_excel('数据.xlsx',index_col=0, parse_dates=['数据时间'])
          
import matplotlib.pyplot as plt
          
plt.rcParams['font.sans-serif'] = 'SimHei' # 设置中文显示
          
plt.rcParams['axes.unicode_minus'] = False
          
plt.figure(figsize=(15, 5))
          
plt.plot(df['总有功功率(kw)'], label='原始数据', color='g',  alpha=0.3)
          
plt.title('时序图')
          
plt.grid(True)
          
plt.legend()
          
plt.show()
      

picture.image

3.2 数据形状处理


          
# 0-1标准化
          
df_max = np.max(df['总有功功率(kw)'])
          
df_min = np.min(df['总有功功率(kw)'])
          
df_bz = (df['总有功功率(kw)']-df_min)/(df_max-df_min)
          

          
def prepare_data(data, win_size):
          
    X = []  # 用于存储输入特征的列表
          
    y = []  # 用于存储目标值的列表
          

          
    # 遍历数据,形成样本窗口
          
    for i in range(len(data) - win_size):
          
        temp_x = data[i:i + win_size]  # 提取窗口大小范围内的输入特征
          
        temp_y = data[i + win_size]    # 提取对应的目标值
          
        X.append(temp_x)
          
        y.append(temp_y)
          

          
    # 转换列表为 NumPy 数组
          
    X = np.asarray(X)
          
    y = np.asarray(y)
          

          
    # 将数据维度调整为适用于TCN模型的形式
          
    X = np.expand_dims(X, axis=-1)
          

          
    return X, y
          

          
win_size = 12
          
X, y = prepare_data(df_bz.values, win_size)
          

          
# 假设X和y是已经准备好的适用于TCN模型的输入特征和目标值矩阵
          
train_size = int(len(X) * 0.7)  # 训练集占总样本数的70%
          

          
X_train, X_test = X[:train_size], X[train_size:]
          
y_train, y_test = y[:train_size], y[train_size:]
          

          
# 打印训练集和测试集的形状
          
print("训练集形状:", X_train.shape, y_train.shape)
          
print("测试集形状:", X_test.shape, y_test.shape)
      

picture.image

代码对时间序列数据进行0-1标准化处理,并将其转换为适用于TCN模型的训练数据格式,并最终划分为训练集和测试集,在这里数据集为单序列数据,时间窗口为12

3.3 LSTM模型建立

lstm模型代码参考往期文章 基于VMD分解的VMD-LSTM时间序列预测模型实现,大力提升预测精度! 其中存在对于该数据的lstm模型建立代码

3.4 简单卷积神经网络模型建立


          
import tensorflow.compat.v1 as tf
          
from tensorflow.keras.layers import Conv1D, MaxPooling1D, Flatten, Dense
          
from tensorflow.keras.models import Sequential
          

          
# 构建卷积神经网络
          
model = Sequential()
          
model.add(Conv1D(filters=64, kernel_size=3, activation='relu', input_shape=(win_size, 1)))
          
model.add(MaxPooling1D(pool_size=2))
          
model.add(Conv1D(filters=128, kernel_size=3, activation='relu'))
          
model.add(MaxPooling1D(pool_size=2))
          
model.add(Flatten())
          
model.add(Dense(10, activation='relu'))
          
model.add(Dense(1, activation='sigmoid'))
          

          
# 编译和训练模型
          
model.compile(optimizer='adam', loss='mse')
          
history = model.fit(X_train, y_train, epochs=100, batch_size=32, validation_data=(X_test, y_test))
          

          
# 可视化训练集和测试集的损失
          
import matplotlib.pyplot as plt
          
plt.plot(history.history['loss'], label='Training Loss')
          
plt.plot(history.history['val_loss'], label='Validation Loss')
          
plt.xlabel('Epoch')
          
plt.ylabel('Loss')
          
plt.legend()
          
plt.show()
      

picture.image


          
from sklearn import metrics
          
y_pred = model.predict(X_test)
          
# 计算均方误差(MSE)
          
mse = metrics.mean_squared_error(y_test, np.array([i for arr in y_pred for i in arr]))
          
# 计算均方根误差(RMSE)
          
rmse = np.sqrt(mse)
          
# 计算平均绝对误差(MAE)
          
mae = metrics.mean_absolute_error(y_test, np.array([i for arr in y_pred for i in arr]))
          
from sklearn.metrics import r2_score # 拟合优度
          
r2 = r2_score(y_test, np.array([i for arr in y_pred for i in arr]))
          
print("均方误差 (MSE):", mse)
          
print("均方根误差 (RMSE):", rmse)
          
print("平均绝对误差 (MAE):", mae)
          
print("拟合优度:", r2)
      

picture.image

模型评价指标,模型指标解读参考往期文章 回归任务常见评价指标解读以及Python实现


          
def predict_future_values(model, sequence, future_steps):
          
    prediction_results = []
          
    for _ in range(future_steps):
          
        # 检查序列的维度并调整形状
          
        if len(sequence.shape) == 1:
          
            sequence = sequence.reshape(1, sequence.shape[0], 1)
          
        elif len(sequence.shape) == 2:
          
            sequence = sequence.reshape(1, sequence.shape[0], sequence.shape[1])
          
        # 对当前序列进行预测
          
        next_day_prediction = model.predict(sequence)
          
        # 将预测结果加入到结果列表中
          
        prediction_results.append(next_day_prediction[0, 0])
          
        # 更新序列,舍弃第一个时间步,将预测结果加入序列末尾
          
        sequence = np.append(sequence[:, 1:, :], next_day_prediction.reshape(1, 1, 1), axis=1)
          

          
    return prediction_results
          

          
sequence = X_test[-1]
          
future_predictions = predict_future_values(model, sequence, 10)
          

          
series = np.array(future_predictions)*(df_max-df_min)+df_min
          
plt.figure(figsize=(15,4), dpi =300)
          
plt.plot(y_test*(df_max-df_min)+df_min, color = 'c', label = '每日实际功率波动曲线')
          
plt.plot(y_pred*(df_max-df_min)+df_min, color = 'r', label = '预测每日功率波动曲线')
          
plt.plot(range(len(y_pred), len(y_pred)+len(series)), series, color = 'b', label = '向后预测30天')
          
plt.title('每日实际功率波动与预测每日功率波动比对图')
          
plt.grid(True)
          
plt.xlabel('时间')
          
plt.ylabel('总有功功率(kw)')
          
plt.legend()
          
plt.show()
      

picture.image

根据训练的模型和序列数据进行未来值的预测,最后将预测结果与实际值进行可视化对比

3.5 TCN模型建立


          
from tcn import TCN
          

          
model_tcn = Sequential()
          
model_tcn.add(TCN(nb_filters=64, kernel_size=6, activation='relu', input_shape=(win_size, 1), dilations=[1, 2, 4, 8, 16]))
          
model_tcn.add(Flatten())
          
model_tcn.add(Dense(32, activation='relu'))
          
model_tcn.add(Dense(10, activation='relu'))
          
model_tcn.add(Dense(1, activation='sigmoid'))
          

          
# 编译和训练模型
          
model_tcn.compile(optimizer='adam', loss='mse')
          
history = model_tcn.fit(X_train, y_train, epochs=100, batch_size=32, validation_data=(X_test, y_test))
          

          
# 可视化训练集和测试集的损失
          
import matplotlib.pyplot as plt
          
plt.plot(history.history['loss'], label='Training Loss')
          
plt.plot(history.history['val_loss'], label='Validation Loss')
          
plt.xlabel('Epoch')
          
plt.ylabel('Loss')
          
plt.legend()
          
plt.show()
      

picture.image


        
            

          model\_tcn.summary()
        
      

picture.image


          
from sklearn import metrics
          
y_pred = model_tcn.predict(X_test)
          
# 计算均方误差(MSE)
          
mse = metrics.mean_squared_error(y_test, np.array([i for arr in y_pred for i in arr]))
          
# 计算均方根误差(RMSE)
          
rmse = np.sqrt(mse)
          
# 计算平均绝对误差(MAE)
          
mae = metrics.mean_absolute_error(y_test, np.array([i for arr in y_pred for i in arr]))
          
from sklearn.metrics import r2_score # 拟合优度
          
r2 = r2_score(y_test, np.array([i for arr in y_pred for i in arr]))
          
print("均方误差 (MSE):", mse)
          
print("均方根误差 (RMSE):", rmse)
          
print("平均绝对误差 (MAE):", mae)
          
print("拟合优度:", r2)
      

picture.image


          
future_predictions = predict_future_values(model_tcn, sequence, 10)
          
series = np.array(future_predictions)*(df_max-df_min)+df_min
          
plt.figure(figsize=(15,4), dpi =300)
          
plt.plot(y_test*(df_max-df_min)+df_min, color = 'c', label = '每日实际功率波动曲线')
          
plt.plot(y_pred*(df_max-df_min)+df_min, color = 'r', label = '预测每日功率波动曲线')
          
plt.plot(range(len(y_pred), len(y_pred)+len(series)), series, color = 'b', label = '向后预测10天')
          
plt.title('每日实际功率波动与预测每日功率波动比对图')
          
plt.grid(True)
          
plt.xlabel('时间')
          
plt.ylabel('总有功功率(kw)')
          
plt.legend()
          
plt.show()
      

picture.image

3.6 模型对比

picture.image

TCN模型相较于CNN和LSTM模型在均方误差、均方根误差、平均绝对误差和拟合优度等评价指标上均表现更好

4 . 往期推荐

基于VMD分解的VMD-CNN-LSTM时间序列预测模型实现

基于VMD分解的VMD-LSTM时间序列预测模型实现,大力提升预测精度!

ARIMA模型进阶——具有季节性的SARIMAX模型实现

时间序列——移动平均(SMA、EMA、WMA)

时间序列——平稳性检验

时间序列——季节性检验

长短期记忆网络LSTM在时序数据预测演示

如果你对类似于这样的文章感兴趣。

欢迎关注、点赞、转发~

0
0
0
0
评论
未登录
看完啦,登录分享一下感受吧~
暂无评论