RNN无法学习积分函数

时间:2017-11-08 09:04:05

标签: time-series lstm integral pytorch rnn

为了研究深度学习,RNN,LSTM等我试图使RNN适合整合功能。我把0到1的随机信号作为RNN的输入,并通过-0.5输入信号偏置成为积分,使0:1之间的积分限制并作为RNN目标学习。 Blue - random input, orange - integrated input

所以我的时间序列只有一个输入(随机)和一个输出(输入的有限积分),我希望RNN通过输入预测输出。 我使用了Pytorch并试图使用香草RNN,GRU单元,不同大小的隐藏层,堆叠几个RNN,将密集连接层放入RNN输出,不同时间深度反向传播(从2到50梯度回滚)。我根本无法取得好成绩!它以某种方式工作,但我找不到一种精确拟合积分函数的方法。这是我最好的结果: green - RNN output绿线(模型输出)在许多情况下不适合橙线 - 这就是问题所在。

Here is my source code in jupyter。 我的问题:是否有可能 - 通过RNN学习饱和积分函数?我的问题在哪里?我可以做些什么来获得更好的质量? 理想情况下,我希望RNN输出在所有时间序列中都是相等的所需输出(积分函数)。

PS: 我原始格式的代码:

import numpy as np
from scipy.stats import truncnorm
import random
import math
import copy
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
import matplotlib.cm as cm

def generate_data(num_of_data):
    input_data=[]
    output_data=[]
    current_input_value=0
    current_output_value=0
    for i in range(num_of_data):
        if (random.random()<0.1):
            current_input_value=random.random()
#            current_output_value=0
        current_input_value=current_input_value+(random.random()-0.5)*0
        current_output_value=current_output_value+0.0*(current_input_value-current_output_value)+(current_input_value-0.5)*0.1
        if (current_output_value<0):
            current_output_value=0
        if (current_output_value>1):
            current_output_value=1

        input_data.append(current_input_value)
        output_data.append(current_output_value)
    return input_data,output_data

%matplotlib inline
matplotlib.rcParams['figure.figsize'] = (20, 6)

input_data,output_data=generate_data(500)
plt.plot(input_data)
plt.plot(output_data)
plt.show()


import torch
import torch.nn as nn
from torch.autograd import Variable
from torch import optim


class RNN(nn.Module):
    def __init__(self, input_size, hidden_size, output_size):
        super(RNN, self).__init__()
        self.number_of_layers=1
        self.hidden_size = hidden_size
        self.gru = nn.GRU(input_size, hidden_size,self.number_of_layers)
        self.Dense1 = nn.Linear(hidden_size, hidden_size)
        self.Dense1A = nn.ReLU()
        self.Dense2 = nn.Linear(hidden_size, output_size)


    def forward(self, input, hidden):
        gru_output, hidden = self.gru(input, hidden)
        Dense1Out=self.Dense1(gru_output)
        Dense1OutAct=self.Dense1A(Dense1Out)
        output=self.Dense2(Dense1OutAct)
        return output, hidden

    def initHidden(self):
        return Variable(torch.zeros(self.number_of_layers,1,self.hidden_size))



import time
import math
import operator

def timeSince(since):
    now = time.time()
    s = now - since
    m = math.floor(s / 60)
    s -= m * 60
    return '%dm %ds' % (m, s)
rnn = RNN(1, 50, 1)

n_iters = 250000
print_every = 2000
plot_every = 2000
all_losses = []
total_loss_print = 0
total_loss_plot = 0

criterion=nn.L1Loss()

print("training...\n")

start = time.time()
optimizer = optim.Adam(rnn.parameters(), lr=0.0002)
rnn_hidden = rnn.initHidden()
rnn.zero_grad()
loss = 0
#for gata_q in range(int(n_iters/500)):
#    rnn_hidden = rnn.initHidden()

input_data,output_data=generate_data(n_iters)
for data_index in range(len(input_data)):
    input_tensor=torch.zeros(1, 1, 1)
    input_tensor[0][0][0]=input_data[data_index]

    output_tensor=torch.zeros(1, 1, 1)
    output_tensor[0][0][0]=output_data[data_index]

    rnn_output, rnn_hidden = rnn(Variable(input_tensor), rnn_hidden)
    loss += criterion(rnn_output, Variable(output_tensor))


    if data_index%2==0:
        loss.backward()

        total_loss_print += loss.data[0]
        total_loss_plot += loss.data[0]
        optimizer.step()
        rnn_hidden=Variable(rnn_hidden.data)
        rnn.zero_grad()
        loss = 0

    if data_index % print_every == 0:
        print('%s (%d %d%%) tl=%.4f' % (timeSince(start), data_index, data_index / n_iters * 100,total_loss_print/print_every))
        total_loss_print = 0

    if data_index % plot_every == 0:
        all_losses.append(total_loss_plot / plot_every)
        total_loss_plot = 0



import matplotlib.pyplot as plt
import matplotlib.ticker as ticker

plt.figure()
plt.plot(all_losses)
plt.show()

rnn_hidden = rnn.initHidden()

rnn.zero_grad()
loss = 0

rnn_output_data=[]
input_data,output_data=generate_data(1500)
for data_index in range(len(input_data)):
    input_tensor=torch.zeros(1, 1, 1)
    input_tensor[0][0][0]=input_data[data_index]
    rnn_output, rnn_hidden = rnn(Variable(input_tensor), rnn_hidden)
    rnn_output_data.append(rnn_output.data.numpy()[0][0][0])

plt.plot(input_data)#blue
plt.plot(output_data)#ogange
plt.plot(rnn_output_data)#green
plt.show()

1 个答案:

答案 0 :(得分:0)

我自己发现了这个问题。在某些情况下,问题是对最新数据的过度拟合,因为在强化学习案例中,过度拟合可能会在利用最新策略时发生。因为我没有使用任何迷你批次并且在新数据点之后直接应用优化器,并且由于数据点类似于20-50个样本,优化器只是简单地将网络安装到忘记先前拟合的最新点。我通过时间收集50个点的梯度数据来解决它,并且只有在我应用了一步优化器之后才解决它。网络现在可以学得更好,但仍然不完美。

以下是修改代码以使其工作:

rnn_output, rnn_hidden = rnn(Variable(input_tensor), rnn_hidden)

loss += criterion(rnn_output, Variable(output_tensor))

if data_index % 2==0:
    loss.backward()
    total_loss_print += loss.data[0]
    rnn_hidden=Variable(rnn_hidden.data)
    loss = 0
   # torch.nn.utils.clip_grad_norm(rnn.parameters(), 0.01)
if data_index % 50==0:
    optimizer.step()
    rnn.zero_grad()

积分学习的新成果: pic