用千层面近似一个简单的sin()函数



我正在尝试用千层面和nolearn NeuralNet函数来近似一个简单的sin函数。毕竟,神经网络被证明是通用逼近器,所以我想在一个简单的非线性函数上尝试千层面,以实验方式证明这一事实。这是代码:

import lasagne
import numpy as np
from lasagne import layers
from lasagne.updates import nesterov_momentum
from nolearn.lasagne import NeuralNet
import matplotlib.pylab as pylab
x=np.linspace(0,1,1000)
y=np.sin(8*x)
# Fit the dimensions and scale
x=x.reshape(1000,1).astype(np.float32)
y=y.astype(np.float32)
y=(y-np.min(y))/np.max(y)

得到以下函数:

pylab.plot(x,y)
pylab.show()

缩放后的sin函数

现在我们创建一个包含100个隐藏单元的简单神经网络来近似函数:

net= NeuralNet(
layers=[
    ('input', layers.InputLayer),
    ('hidden', layers.DenseLayer),
    ('output', layers.DenseLayer),
],
input_shape=(None,1),
hidden_num_units=100,
hidden_nonlinearity=lasagne.nonlinearities.rectify,
hidden_W=lasagne.init.GlorotUniform(),
output_num_units=1,
output_nonlinearity=None,
output_W=lasagne.init.GlorotUniform(),
update=nesterov_momentum,
update_learning_rate=0.001,
update_momentum=0.9,
regression=True,
max_epochs=500,
verbose=0,
)
net=net.fit(x,y)

现在我们用训练网络预测x值,看看我们得到什么:

yp=net.predict(x)
pylab.plot(x,yp,hold=1)
pylab.plot(x,y)
pylab.show()

这就是我们得到的!近似函数。这简直是可笑!如果我们增加隐藏神经元的数量或者增加训练的次数,什么都不会改变。其他类型的非线性只会让情况变得更糟。从理论上讲,这应该更好,我错过了什么?

我终于知道是怎么回事了。我把我的猜想贴出来,以防有人遇到同样的问题。

众所周知,来自nollearn环境的NeuralNet使用批处理训练。我不太清楚它是如何选择批次的,但在我看来,它是按顺序选择的。然后,如果数据不是随机的,那么一批数据在统计上就不能代表整体(数据不是平稳的)。在我的例子中,我制作了x=np.linspace(0,1,1000),因此每批的统计属性将是不同的,因为有一个自然的顺序。

如果您随机创建数据,即x=np.random.uniform(size=[1000,1]),则每批数据都具有统计代表性,而与数据的来源无关。一旦你这样做了,你可以增加训练的时间,并提高收敛到真正的最优。我不知道我的猜测是否正确,但至少它对我有用。尽管如此,我还是会深入研究的。

最新更新