RNN学习-序列模型预测实战

一、任务

  • 构建一个序列,1000个模拟sin的数据,加上normal噪声
  • 利用一个双线性层来训练
  • 得到的结果分别利用单步、自预测和多步预测对比

思路参考:李沐《动手学深度学习》
附加说明:由于是练习,所以内容实现全部用自己构建的函数实现,没用d2l

二、代码

import torch
import matplotlib.pyplot as plt
from torch.utils.data import DataLoader,TensorDataset
import torch.nn as nn

# 封装数据
def load_array(x,y,batchsize=16,is_train=True):
    data = TensorDataset(x,y)
    return DataLoader(data,batchsize,shuffle=is_train)

# 构建序列数据
def get_data(x,stride):
    features = torch.zeros((T-stride,stride))
    for i in range(stride):
        features[:,i] = x[i:i+T-stride]
    labels = x[stride:]
    return features,labels.reshape(-1,1)

# 初始化网络-xavier
def init_net(m):
    if type(m) == nn.Linear:
        nn.init.xavier_normal_(m.weight)

# 构建简单的双线性层网络
class net(nn.Module):
    def __init__(self):
        super(net, self).__init__()
        self.model = nn.Sequential(
            nn.Linear(4,10),
            nn.ReLU(),
            nn.Linear(10,1)
        )
    def forward(self,x):
        x = self.model(x)
        return x

# 训练函数
def train(data,net,loss,optim,epochs):
    for epoch in range(epochs):
        l_sum = 0
        for x,y in data:
            optim.zero_grad()
            pred = net(x)
            l = loss(pred,y)
            l.sum().backward()
            optim.step()
            l_sum += l.mean().detach().numpy()
        print(f"epoch:{epoch+1} loss:{l_sum}")

# 预测现有的数据,将训练集的全部数据作为预测
def predict_one_step(features,net):
    preds_out = net(features)
    plt.title('preds_for_one_step')
    plt.xlabel('time');plt.ylabel('y')
    plt.plot(time,x,'-m',label='initial')
    plt.plot(time[stride:],preds_out.detach().numpy(),'-b',label='1_step')
    plt.show()

# 将预测的数据作为输入再预测
def predict_after_preds(features,net,tao):
    preds_for_preds = torch.zeros((T))
    preds_for_preds[:train_num+tao] = features[:train_num+tao,0]
    for i in range(train_num+tao,T):
        preds_for_preds[i] = net(preds_for_preds[i-tao:i])
    plt.title('preds_for_preds')
    plt.xlabel('time');plt.ylabel('y')
    plt.plot(time, x, '-m', label='initial')
    plt.plot(time[train_num+tao:], preds_for_preds[train_num+tao:].detach().numpy(), '-g', label='preds_preds')
    plt.show()

# 多步预测
def preds_for_multi_step(features,net,tao):
    step = [1,4,16,64]
    color = ['y','m','r','b']
    max_step = 64
    preds_for_multi_s = torch.zeros((T - tao - max_step + 1,tao + max_step))
    preds_for_multi_s[:,:tao] = features[:T - tao - max_step+1,:]
    for i in range(tao,tao + max_step):
        preds_for_multi_s[:,i] = net(preds_for_multi_s[:,i-tao:i]).reshape(-1)
    plt.title('preds_for_multi')
    plt.xlabel('time');plt.ylabel('y')
    plt.plot(time, x, '-m', label='initial')
    for i in range(len(step)):
        plt.plot(time[tao+step[i]-1:T - max_step+step[i]], preds_for_multi_s[:,tao+step[i]-1].detach().numpy(), f'-{color[i]}', label=f'{step[i]}-steps')
    plt.show()


if __name__ == '__main__':
    T = 1000
    stride = 4
    time = torch.arange(1, T + 1, dtype=torch.float32)
    x = torch.sin(0.01 * time) + torch.normal(0,0.2,size=(T,))
    features, labels = get_data(x, stride)
    train_num = 600
    train_iter = load_array(features[:train_num], labels[:train_num], batchsize=16, is_train=True)
    net = net()
    net.apply(init_net)
    Criterion = nn.MSELoss(reduction='none')
    optim = torch.optim.SGD(net.parameters(),lr=0.01)
    epochs = 50
    train(train_iter,net,Criterion,optim,epochs)
    predict_one_step(features,net)
    predict_after_preds(features,net,stride)
    preds_for_multi_step(features,net,stride)

三、序列预测结果

3.1 单步预测

RNN学习-序列模型预测实战_第1张图片

3.2 自预测

RNN学习-序列模型预测实战_第2张图片

3.3 多步预测

RNN学习-序列模型预测实战_第3张图片

你可能感兴趣的:(深度学习集训,rnn,学习,深度学习)