使用PyBrain神经网络预测时间序列数据

8

问题

我正在尝试使用连续的历史数据(5年)来预测下一年的值。

数据结构

我的输入数据input_04_08长这样,其中第一列是一年中的天数(1到365),第二列是记录的输入值。

1,2
2,2
3,0
4,0
5,0

我的输出数据output_04_08看起来像这样,是一列数据,记录了该年的那一天的输出。
27.6
28.9
0
0
0

我会将值归一化到0到1之间,这样传递给网络的第一个样本看起来就像

Number of training patterns:  1825
Input and output dimensions:  2 1
First sample (input, target):
[ 0.00273973  0.04      ] [ 0.02185273]

方法

前馈神经网络

我已在PyBrain中实现了以下代码。

input_04_08 = numpy.loadtxt('./data/input_04_08.csv', delimiter=',')
input_09 = numpy.loadtxt('./data/input_09.csv', delimiter=',')
output_04_08 = numpy.loadtxt('./data/output_04_08.csv', delimiter=',')
output_09 = numpy.loadtxt('./data/output_09.csv', delimiter=',')

input_04_08 = input_04_08 / input_04_08.max(axis=0)
input_09 = input_09 / input_09.max(axis=0)
output_04_08 = output_04_08 / output_04_08.max(axis=0)
output_09 = output_09 / output_09.max(axis=0)
ds = SupervisedDataSet(2, 1)

for x in range(0, 1825):
    ds.addSample(input_04_08[x], output_04_08[x])

n = FeedForwardNetwork()
inLayer = LinearLayer(2)
hiddenLayer = TanhLayer(25)
outLayer = LinearLayer(1)
n.addInputModule(inLayer)
n.addModule(hiddenLayer)
n.addOutputModule(outLayer)
in_to_hidden = FullConnection(inLayer, hiddenLayer)
hidden_to_out = FullConnection(hiddenLayer, outLayer)
n.addConnection(in_to_hidden)
n.addConnection(hidden_to_out)
n.sortModules()

trainer = BackpropTrainer(n, ds, learningrate=0.01, momentum=0.1)

for epoch in range(0, 100000000): 
    if epoch % 10000000 == 0:
        error = trainer.train()  
        print 'Epoch: ', epoch
        print 'Error: ', error


result = numpy.array([n.activate(x) for x in input_09])

这给了我以下结果,最终误差为0.00153840123381

enter image description here

毫无疑问,这看起来很不错。然而,阅读更多有关LSTM(长短时记忆)神经网络及其在时间序列数据中的适用性方面的内容后,我正在尝试构建一个。

LSTM网络

以下是我的代码

input_04_08 = numpy.loadtxt('./data/input_04_08.csv', delimiter=',')
input_09 = numpy.loadtxt('./data/input_09.csv', delimiter=',')
output_04_08 = numpy.loadtxt('./data/output_04_08.csv', delimiter=',')
output_09 = numpy.loadtxt('./data/output_09.csv', delimiter=',')

input_04_08 = input_04_08 / input_04_08.max(axis=0)
input_09 = input_09 / input_09.max(axis=0)
output_04_08 = output_04_08 / output_04_08.max(axis=0)
output_09 = output_09 / output_09.max(axis=0)
ds = SequentialDataSet(2, 1)

for x in range(0, 1825):
    ds.newSequence()
    ds.appendLinked(input_04_08[x], output_04_08[x])


fnn = buildNetwork( ds.indim, 25, ds.outdim, hiddenclass=LSTMLayer, bias=True, recurrent=True)
trainer = BackpropTrainer(fnn, ds, learningrate=0.01, momentum=0.1)

for epoch in range(0, 10000000): 
    if epoch % 100000 == 0:
        error = trainer.train()  
        print 'Epoch: ', epoch
        print 'Error: ', error

result = numpy.array([fnn.activate(x) for x in input_09])

这导致最终误差为0.000939719502501,但是这次当我输入测试数据时,输出图表看起来很糟糕。

enter image description here

可能出现的问题

我在这里查看了几乎所有与PyBrain相关的问题,但是以下问题并没有帮助我解决问题:

我阅读了一些博客文章,这些文章对我的理解有所帮助,但显然还不够

自然地,我也阅读了PyBrain文档,但在这里顺序数据集方面找不到太多帮助。欢迎任何想法/技巧/方向。
1个回答

7
我认为这里发生的事情是,您尝试根据某些经验法则分配超参数值,这对第一个案例有效,但对第二个案例无效。
1)您正在查看的误差估计是训练集的乐观预测误差估计。实际预测误差很高,但由于您没有在未见过的数据上测试模型,因此无法知道它。统计学习要素对这种现象进行了很好的描述。我强烈推荐这本书。您可以在网上免费获取它。

2) 要获得具有低预测误差的估计器,您需要执行超参数调整。例如,应该变化并在未见数据上进行测试的隐藏节点数、学习率和动量,以知道哪种组合导致最低的预测误差。scikit-learnGridSearchCVRandomizedSearchCV 来做到这一点,但它们只适用于 sklearn 的估计器。不过,您可以自己编写估计器,这在 文档 中有描述。个人认为,模型选择和模型评估是两个不同的任务。对于第一个任务,您只需运行单个 GridSearchCV 或 RandomizedSearchCV,并获取任务的最佳超参数集。对于模型评估,您需要运行更复杂的分析,例如嵌套交叉验证,甚至是重复的嵌套交叉验证,如果您想要更准确的估计。

3)我对LSTM网络不是很了解,但我看到在第一个例子中您分配了25个隐藏节点,但对于LSTM,您只提供了5个。也许这不足以学习模式。您还可以像示例中那样删除输出偏差。

P.S. 我认为这个问题实际上属于http://stats.stackexchange.com,在那里您可能会得到更详细的答案来解决您的问题。

编辑:我刚注意到您正在进行1000万次的模型训练!我认为这太多了,可能是过度拟合的问题之一。我认为实现早停是一个好主意,即如果达到某个预定义的错误,则停止训练。


好的,谢谢。我需要考虑一下。我最好开始阅读了。我重新运行了带有25个隐藏节点的LSTM,并相应地更新了问题,以便能够更好地与前馈网络进行比较。 - Philip O'Brien

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接