Sequential Model

Concept and Principle

序列模型是考虑时间信息的模型

  • 序列数据

    • 数据带有时序结构,如电影的评价随时间变化
      • 电影拿奖后评分上升
      • 导演、演员负面报道后评分下降
  • 统计工具

    • 将序列中每个元素看作随机变量,显然他们不是独立的
    • 在实际操作中,时序序列一般只能正向建模去预测
    • 要使用序列模型预测T时刻x的概率,核心是求T时刻的条件概率(似然),这里的f可看作神经网络,神经网络将训练集建模。自回归指的是用数据对见过的数据建模(因为最后预测也是在预测相同的数据),与非序列模型用数据对独立于数据的标签建模不同。
    • 具体如何建模?
      • 马尔科夫假设
        当前预测的数据只跟过去的tau个数据相关,tau是一个固定常数。假设x是标量数据,此时只需要将其看作回归问题,使用MLP把tau个x当作特征训练得到t时刻标量x。MLP进行梯度优化的过程便是最大化似然概率的过程
      • 潜变量模型
        引入一个可不断更新的潜变量用于概括历史信息,使得建模更加简单(RNN)

Implementation

  • 马尔可夫假设+MLP
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    import torch
    from torch import nn
    from torch.utils.data import TensorDataset
    from torch.utils.data.dataloader import DataLoader
    from torch import optim
    import math

    # 使用正弦函数加上噪声生成序列数据
    T=1000

    time=torch.arange(1,T+1,dtype=torch.float32)
    data=torch.sin(0.01*time)+torch.normal(0,0.1,time.shape)

    # 将数据映射为数据对
    tau=4
    labels=data[tau:].view(-1,1)
    features=torch.zeros(T-tau,tau)
    for i in range(tau):
    features[:,i]=data[i:T-tau+i]

    train_dataset=TensorDataset(features[:600],labels[:600])
    test_dataset=TensorDataset(features[600:],labels[600:])

    train_iter=DataLoader(train_dataset,batch_size=16)
    test_iter=DataLoader(test_dataset,batch_size=16)

    net=nn.Sequential(
    nn.Linear(4,32),
    nn.Dropout(0.1),
    nn.ReLU(),
    nn.Linear(32,16),
    nn.ReLU(),
    nn.Linear(16,1)
    )
    loss_f=nn.MSELoss()
    opt=optim.Adam(net.parameters())

    try:
    net.load_state_dict(torch.load("9.params"))

    except:
    for epoch in range(100):
    train_loss=[]
    test_loss=[]
    for X,y in train_iter:
    out=net(X)
    l=loss_f(out,y)

    l.backward()
    train_loss.append(l.item())
    opt.step()
    opt.zero_grad()

    with torch.no_grad():
    for X,y in test_iter:
    out=net(X)
    l=loss_f(out,y)
    test_loss.append(l.item())

    print(f"{epoch+1},{sum(train_loss)} {sum(test_loss)}")
    torch.save(net.state_dict(),"9.params")

    # 使用测试集预测
    from matplotlib import pyplot as plt
    t=600
    steps=396

    plt.plot([i for i in range(t,t+steps)],net(features[600:]).view(-1).detach().numpy())

    # 使用预测值进行多步预测

    win=[math.sin(i*0.01) for i in range(t-4,t)]
    true=[]
    pred=[]
    for i in range(steps):
    X=torch.tensor(win,dtype=torch.float32)
    out=net(X)
    truth=math.sin((t+i)*0.01)
    true.append(truth);pred.append(out.item())
    # print(out.item(),t)
    win.pop(0)
    win.append(out)


    plt.plot([i for i in range(t,t+steps)],pred)
    plt.plot([i for i in range(t,t+steps)],true)
    plt.show()