如何使用神经网络实现最简单的序列预测?

一、内容摘要

神经网络在序列预测任务中具有广泛的应用,它们能够对各种类型的序列数据进行建模和预测,例如时间序列、趋势分析、自然语言和DNA序列等。

在这篇博客中,我们将介绍如何使用神经网络进行简单的序列预测任务,包括数据准备、模型构建、训练和预测等方面。

 说明:本文涉及方法均为说明性demo,实际数据应用请使用符合数据特性的模型和方法。

二、版本及环境

Anaconda做环境控制(与项目本身关系不大)

Python

Pytorch

三、结构及方法

1.样例数据准备

样例数据使用了一种非常简单的构造方法,即叠加两种不同频率的波形构成目标数据(参考傅里叶变换),因此得到的数据其实是一种较为理想纯净的、具有明显频率特征的数据,代码如下:

def seq2sets(seq, ws):
    out = []
    L = len(seq)
    for i in range(L - ws):
        window = seq[i:i + ws]
        label = seq[i + ws:i + ws + 1]
        out.append((window, label))
    return out

# Sequence and Datasets
t = np.arange(0, 1, 0.001)  # 时刻序列
train_seq = torch.FloatTensor(np.sin(2 * np.pi * 1 * t) + np.sin(2 * np.pi * 300 * t))
train_data = seq2sets(train_seq, WINDOW_SIZE)
plt.plot(train_seq)
plt.show()

 该数据序列绘图如下,可以看出由高频和低频两部分组成:

数据集裁剪方式为根据设定的窗口大小进行切片,长序列裁剪成许多短序列(参考代码中的seq2sets函数)。代码仅供说明用途,非最佳处理方式。

序列预测的目标:预测1000~1200位置上的数据。

  • 模型输入:一个WINDOW_SIZE大小的输入
  • 模型输出:一个单点输出

多步预测可以采用将预测值继续丢进网络进行下一步预测的方法实现。

2.BP神经网络

可以认为是最基本的神经网络结构,能学习和存贮大量的输入-输出模式映射关系,而无需事前揭示描述这种映射关系的数学方程。

BP网络通过反向传播来不断调整网络的权值和阈值,使网络的误差最小。

class BP(nn.Module):
    def __init__(self, input_dim):
        super().__init__()
        self.Linear1 = nn.Linear(input_dim, 50)
        self.Linear2 = nn.Linear(50, 1)
        self.relu = nn.ReLU()

    def forward(self, x):
        x = self.Linear1(x)
        x = self.relu(x)
        x = self.Linear2(x)
        return x

3.CNN(卷积神经网络)

图像识别中经典的网络结构,以局部视野和全局共享为最大特性。

class CNN(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1d = nn.Conv1d(1, 64, kernel_size=5, stride=3)
        self.relu = nn.ReLU(inplace=True)
        self.Linear1 = nn.Linear(64 * 66, 50)
        self.Linear2 = nn.Linear(50, 1)

    def forward(self, x):
        x = self.conv1d(x)
        x = self.relu(x)
        x = x.view(-1)
        x = self.Linear1(x)
        x = self.relu(x)
        x = self.Linear2(x)
        return x

4.LSTM(长短期记忆网络)

LSTM是一种特殊的递归神经网络 。被设计用于解决一般递归神经网络中普遍存在的长期依赖问题,使用LSTM可以有效的传递和表达长时间序列中的信息并且不会导致长时间前的有用信息被忽略(遗忘)。

class LSTM(nn.Module):
    def __init__(self, inp_dim, out_dim, mid_dim, mid_layers):
        super(LSTM, self).__init__()

        self.rnn = nn.LSTM(inp_dim, mid_dim, mid_layers)  # rnn
        self.reg = nn.Sequential(
            nn.Linear(mid_dim, mid_dim),
            nn.ReLU(),
            nn.Linear(mid_dim, out_dim),
        )  # regression

    def forward(self, x):
        y = self.rnn(x)[0]  # y, (h, c) = self.rnn(x)
        seq_len, batch_size, hid_dim = y.shape
        y = y.view(-1, hid_dim)
        y = self.reg(y)
        y = y.view(seq_len, batch_size, -1)
        return y

    def output_y_hc(self, x, hc):
        y, hc = self.rnn(x, hc)  # y, (h, c) = self.rnn(x)

        seq_len, batch_size, hid_dim = y.size()
        y = y.view(-1, hid_dim)
        y = self.reg(y)
        y = y.view(seq_len, batch_size, -1)
        return y, hc

四、完整代码

import numpy as np
import matplotlib.pyplot as plt
import torch
import torch.nn as nn
import time


class BP(nn.Module):
    def __init__(self, input_dim):
        super().__init__()
        self.Linear1 = nn.Linear(input_dim, 50)
        self.Linear2 = nn.Linear(50, 1)
        self.relu = nn.ReLU()

    def forward(self, x):
        x = self.Linear1(x)
        x = self.relu(x)
        x = self.Linear2(x)
        return x


class CNN(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1d = nn.Conv1d(1, 64, kernel_size=5, stride=3)
        self.relu = nn.ReLU(inplace=True)
        self.Linear1 = nn.Linear(64 * 66, 50)
        self.Linear2 = nn.Linear(50, 1)

    def forward(self, x):
        x = self.conv1d(x)
        x = self.relu(x)
        x = x.view(-1)
        x = self.Linear1(x)
        x = self.relu(x)
        x = self.Linear2(x)
        return x


class LSTM(nn.Module):
    def __init__(self, inp_dim, out_dim, mid_dim, mid_layers):
        super(LSTM, self).__init__()

        self.rnn = nn.LSTM(inp_dim, mid_dim, mid_layers)  # rnn
        self.reg = nn.Sequential(
            nn.Linear(mid_dim, mid_dim),
            nn.ReLU(),
            nn.Linear(mid_dim, out_dim),
        )  # regression

    def forward(self, x):
        y = self.rnn(x)[0]  # y, (h, c) = self.rnn(x)
        seq_len, batch_size, hid_dim = y.shape
        y = y.view(-1, hid_dim)
        y = self.reg(y)
        y = y.view(seq_len, batch_size, -1)
        return y

    def output_y_hc(self, x, hc):
        y, hc = self.rnn(x, hc)  # y, (h, c) = self.rnn(x)

        seq_len, batch_size, hid_dim = y.size()
        y = y.view(-1, hid_dim)
        y = self.reg(y)
        y = y.view(seq_len, batch_size, -1)
        return y, hc


def seq2sets(seq, ws):
    out = []
    L = len(seq)
    for i in range(L - ws):
        window = seq[i:i + ws]
        label = seq[i + ws:i + ws + 1]
        out.append((window, label))
    return out


def train(model, optimizer, criterion, epoch):
    model.train()
    for seq_i, y_train in train_data:
        optimizer.zero_grad()
        y_pred = model(seq_i.reshape(1, 1, -1))
        loss = criterion(y_pred, y_train)
        loss.backward()
        optimizer.step()
    print(f'Epoch: {epoch:2} Loss: {loss.item():10.8f}')


def predict(model, future_step):
    model.eval()
    # 选取序列最后WINDOW_SIZE个值开始预测
    preds = train_seq[-WINDOW_SIZE:].tolist()
    # 循环的每一步表示向时间序列向后滑动一格
    for i in range(future_step):
        seq_i = torch.FloatTensor(preds[-WINDOW_SIZE:])
        with torch.no_grad():
            preds.append(model(seq_i.reshape(1, 1, -1)).item())
    return preds[-future_step:]


if __name__ == '__main__':

    # Configurations
    WINDOW_SIZE = 200
    FUTURE_STEP = 200
    EPOCH_MAX = 20
    LEARNING_RATE = 0.0001
    MODEL_DICT = {'method_index': [0, 1, 2, 3],
                  'method_name': ['BP', 'CNN', 'LSTM'],
                  'model': [BP(input_dim=WINDOW_SIZE),
                            CNN(),
                            LSTM(inp_dim=WINDOW_SIZE, out_dim=1, mid_dim=20, mid_layers=3)],
                  }

    # Sequence and Datasets
    t = np.arange(0, 1, 0.001)  # 时刻序列
    train_seq = torch.FloatTensor(np.sin(2 * np.pi * 1 * t) + np.sin(2 * np.pi * 300 * t))
    # train_seq = torch.FloatTensor(np.load('frequence.npz')['arr_0'])
    train_data = seq2sets(train_seq, WINDOW_SIZE)
    plt.plot(train_seq)
    plt.show()

    # Model setting
    for model_index, model in enumerate(MODEL_DICT['method_name']):
        model = MODEL_DICT['model'][model_index]
        criterion = nn.MSELoss()  # loss function: mse
        optimizer = torch.optim.Adam(model.parameters(), lr=LEARNING_RATE)  # optimizer and lr
        start_time = time.time()
        for epoch in range(EPOCH_MAX):
            train(model, optimizer, criterion, epoch)
        print(f'\nDuration: {time.time() - start_time:.0f} seconds')
        preds = predict(model, future_step=WINDOW_SIZE)

        # 对比真实值和预测值
        plt.grid()
        plt.plot(train_seq)
        plt.plot(np.arange(len(train_seq), len(train_seq) + FUTURE_STEP, 1), preds)
        # x = np.arange('2018-02-01', '2019-02-01', dtype='datetime64[M]').astype('datetime64[D]')
        plt.show()

五、部分运行结果

三种方法的结果展示:

说明:该结果仅基于极短时间的训练。并且由于数据非常简单,因此BP体现出较好的效果。

但本结果并不能表明三种模型在实际应用中的性能,一般来说,LSTM和Transformer类型的网络能对序列数据处理更好。

 

 

 

可能的额外工作

1.数据加噪/去噪

2.结合数据特性进行频域分析

3.选择适当的窗口大小和步长

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个使用MATLAB实现TCN时间卷积神经网络的时间序列预测简单示例: ```matlab % 准备数据 data = csvread('data.csv'); % 加载数据 sequenceLength = 64; % 时间序列长度 numFeatures = size(data, 2); % 特征数量 numObservations = size(data, 1) - sequenceLength; % 样本数量 X = zeros(sequenceLength, numFeatures, numObservations); % 输入数据 Y = zeros(1, numObservations); % 输出数据 for i = 1:numObservations X(:,:,i) = data(i:i+sequenceLength-1,:); Y(i) = data(i+sequenceLength,1); end % 构建TCN模型 numFilters = 64; filterSize = 3; layers = [ ... sequenceInputLayer(numFeatures, 'Name', 'input') tcnLayer(numFilters, filterSize, 'Name', 'tcn') reluLayer('Name', 'relu') fullyConnectedLayer(1, 'Name', 'fc') regressionLayer('Name', 'output') ]; lgraph = layerGraph(layers); % 训练模型 options = trainingOptions('adam', ... 'MaxEpochs', 100, ... 'MiniBatchSize', 32, ... 'ValidationData', validation_ds, ... 'ValidationFrequency', 10, ... 'Verbose', true); net = trainNetwork(X, Y, lgraph, options); % 测试模型 XTest = data(end-sequenceLength+1:end,:); YPred = predict(net, XTest); ``` 在这个示例中,我们加载了一个时间序列数据文件,并将其划分为多个输入序列和一个输出序列。我们使用tcnLayer函数构建了一个TCN模型,其中包括一个tcn层、一个relu层、一个fullyConnected层和一个regression层。我们使用trainingOptions函数指定了训练选项,并使用trainNetwork函数训练模型。在测试模型时,我们使用最后一组时间序列作为输入,并使用predict函数进行预测。 这只是一个简单的示例,实际的实现可能需要更多的调整和优化,例如使用多个tcn层来增加模型深度,使用交叉验证来评估模型性能等。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值