用pybrain预测正弦函数

时间:2016-09-30 10:15:25

标签: python neural-network time-series prediction pybrain

为了理解神经网络和pybrain,我试图仅使用时间索引作为输入来预测噪声中的正弦函数。因此,前提是简单的NN结构可以模仿 y(t)= sin(t)

设计是:1个输入层(线性),1个隐藏层(tanh)和1个输出层(线性)。节点数为:每个相应层1,10,1。

缩放输入(时间变量 t ),使其范围为 [0; 1] 。目标的缩放范围为 [0; 1] [ - 1; 1] ,结果不同(如下所示)。

这是我的Python 2.7代码:

#!/usr/bin/python
from __future__ import division
import numpy as np
import pylab as pl

from pybrain.structure import TanhLayer, LinearLayer #SoftmaxLayer, SigmoidLayer
from pybrain.datasets import SupervisedDataSet 
from pybrain.supervised.trainers import BackpropTrainer 
from pybrain.structure import FeedForwardNetwork
from pybrain.structure import FullConnection 

np.random.seed(0)
pl.close('all')

#create NN structure:
net = FeedForwardNetwork()
inLayer = LinearLayer(1)
hiddenLayer = TanhLayer(10)
outLayer = LinearLayer(1)

#add classes of layers to network, specify IO:
net.addInputModule(inLayer)
net.addModule(hiddenLayer)
net.addOutputModule(outLayer)

#specify how neurons are to be connected:
in_to_hidden = FullConnection(inLayer, hiddenLayer)
hidden_to_out = FullConnection(hiddenLayer, outLayer)

#add connections to network:
net.addConnection(in_to_hidden)
net.addConnection(hidden_to_out)

#perform internal initialisation:
net.sortModules()

#construct target signal:
T = 1
Ts = T/10
f = 1/T
fs = 1/Ts

#NN input signal:
t0 = np.arange(0,10*T,Ts)
L = len(t0)

#NN target signal:
x0 = 10*np.cos(2*np.pi*f*t0) + 10 + np.random.randn(L)

#normalise input signal:
t = t0/np.max(t0)

#normalise target signal to fit in range [0,1] (min) or [-1,1] (mean):
dcx = np.min(x0) #np.min(x0) #np.mean(x0) 
x = x0-dcx
sclf = np.max(np.abs(x))
x /= sclf

#add samples and train NN:
ds = SupervisedDataSet(1, 1)
for c in range(L):
 ds.addSample(t[c], x[c])

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

for c in range(20):
 e1 = trainer.train()
 print 'Epoch %d Error: %f'%(c,e1)

y=np.zeros(L)
for c in range(L):
 #y[c] = net.activate([x[c]])
 y[c] = net.activate([t[c]])

yout = y*sclf  
yout = yout + dcx

fig1 = pl.figure(1)
pl.ion()

fsize=8
pl.subplot(211)
pl.plot(t0,x0,'r.-',label='input')
pl.plot(t0,yout,'bx-',label='predicted')
pl.xlabel('Time',fontsize=fsize)
pl.ylabel('Amplitude',fontsize=fsize)
pl.grid()
pl.legend(loc='lower right',ncol=2,fontsize=fsize)
pl.title('Target range = [0,1]',fontsize=fsize)

fig1name = './sin_min.png'
print 'Saving Fig. 1 to:', fig1name
fig1.savefig(fig1name, bbox_inches='tight')

输出数据如下。

Output when target is scaled to fit range *[0;1]*

Output when target is scaled to fit range *[-1;1]*

虽然第一个数字显示更好的结果,但两个输出都不令人满意。我错过了一些基本的神经网络原理还是我的代码有缺陷?我知道在这种情况下估计目标信号有更简单的统计方法,但目的是在这里使用简单的NN结构。

2 个答案:

答案 0 :(得分:0)

问题是输入和输出值的范围。通过standardizing这些信号,问题得以解决。

NN input and output signal

这可以通过考虑下面显示的 sigmoid tanh 激活函数来解释。 sigmoid and tanh activation functions

结果取决于具体应用。此外,更改激活功能(请参阅this answer)可能也会影响输入和输出信号的最佳缩放值。

答案 1 :(得分:-1)

通过一点点调整(更多的学习步骤),可以用神经网络准确地预测窦功能。为了确定神经网络的极限,预测"反向运动学"会更有用。在该示例中,大多数神经网络将失败,因为求解器产生高CPU需求而没有任何结果。测试神经网络极限的另一个例子是来自游戏的强化学习问题。

神经网络的令人失望的方面是,他们可以预测简单的数学函数,但在复杂的领域失败。作为" easy"定义了求解器(Backproptrainer)需要低CPU功率才能达到给定精度的每个问题。