神经网络的强大在于其能在有限区间内近似任意函数,更精确的说是MLP(多层感知机)是万能的函数近似机,证明由Cybenko给出。注意是在有限区间内,论文中也是在单位超立方体(the unit hypercube)内讨论。如果不是有限区间,可能得靠RNN,比如某些具有周期性质的函数,就能使用RNN近似。
MLP近似爱心函数
看到微博上推的使用MLP来近似函数的博文,我觉得少点东西,做点补充。第一步就挑一个有趣点的函数吧,随便挑个心形函数。然后用keras很快就能搭个MLP,具体见github。
1 2 3 4 5 | model = Sequential() model.add(Dense(output_dim=64, input_dim=2)) model.add(Activation("tanh")) model.add(Dense(output_dim=1)) model.compile(loss='mean_squared_error', optimizer=Adam()) |
训练之后就能得到对这个函数的近似,画成图如下:

还有个哥们居然搞了个penis的函数,无法直视,有兴趣的可以尝试。
RNN近似周期函数
超出训练的范围,MLP的近似就无效了,想想也知道,泛化能力不可能那么强。而RNN在一定程度上可以弥补一下,最好是有点周期性的函数。为了简单起见,就先用测试好了。同样用keras快速搭个RNN,具体见github。
1 2 3 4 5 6 7 8 9 | feature_length = 32 seq_length = 80 interval = 0.1 # RNN model using LSTM model = Sequential() model.add(LSTM(256, return_sequences=True, input_dim=feature_length)) model.add(TimeDistributed(Dense(feature_length))) #model.add(Activation('tanh')) model.compile(loss='mean_squared_error', optimizer=Adam()) |
关键是训练数据如何构造,也就是输入输出是怎样的。跟MLP不同,这里用函数值预测函数值,而不是输入。因为在如时间序列预测的情况下,输入
是未知的,只能使用之前已知的函数值。我用相邻
feature_length个点组成一步的输入,总共
seq_length 步,其中每个点间隔
interval 。那预测就是后面的点,也可以只预测一个,我测试是预测
feature_length个,其中一半重合。比如0到32个点预测16到48个点(这样的做法似乎也能使用在MLP预测时间序列中,Quantitative Finance和论文)。说不清楚看下图或者看代码。

之后就是训练了,可以说是完美近似,后面因为累积误差导致不能近似的很好也是正常的。我又测试了
,有一个递增项,效果就没有
好了,但短期内效果还是好的。注意我画得图的区间不在测试区间内,也就是网络没看到过的数据,正因为RNN具有一定泛化能力才能有如此表现。


累积误差比较蛋疼,如下的情况,就算是测试数据的范围内也会有问题。可以用beamsearch,或者其他目标函数做,比如Q-learning。比较复杂,这里只讨论最简单的情况。

总结
MLP还是很厉害的,只要参数足够多,就能在一定区间内近似任意函数。而RNN相当于图灵机,之前也写过使用RNN做时间序列预测的博文,由于数据不能放出,所以也没有把代码放出。这次的代码与上次是类似的,改改也能试试做时间序列预测,就我的经验来看,没有传统方法好。
One thought to “神经网络近似函数”