24

我已经实现了一个简单的神经网络框架,它只支持多层感知器和简单的反向传播。它适用于线性分类和通常的 XOR 问题,但对于正弦函数逼近,结果并不令人满意。

我基本上试图用一个由 6-10 个神经元组成的隐藏层来近似正弦函数的一个周期。该网络使用双曲正切作为隐藏层的激活函数和输出的线性函数。结果仍然是对正弦波的一个相当粗略的估计,并且需要很长时间来计算。

我查看了encog以供参考,但即使如此,我也无法通过简单的反向传播使其工作(通过切换到弹性传播,它开始变得更好,但仍然比这个类似问题中提供的超级光滑的 R 脚本差得多)。那么我真的在尝试做一些不可能的事情吗?用简单的反向传播(没有动量,没有动态学习率)不可能近似正弦吗?R中神经网络库使用的实际方法是什么?

编辑:我知道即使使用简单的反向传播(如果您对初始权重非常幸运) ,也绝对有可能找到足够好的近似值,但实际上我更想知道这是否是一种可行的方法。与我的实现甚至 encog 的弹性传播相比,我链接到的 R 脚本似乎收敛得非常快和健壮(在 40 个 epoch 中只有很少的学习样本)。我只是想知道是否可以做一些事情来改进我的反向传播算法以获得相同的性能,或者我是否必须研究一些更高级的学习方法?

4

3 回答 3

10

使用 TensorFlow 等神经网络的现代框架可以很容易地实现这一点。

例如,在我的计算机上,每层使用 100 个神经元的两层神经网络可以在几秒钟内进行训练,并给出了一个很好的近似值:

在此处输入图像描述

代码也很简单:

import tensorflow as tf
import numpy as np

with tf.name_scope('placeholders'):
    x = tf.placeholder('float', [None, 1])
    y = tf.placeholder('float', [None, 1])

with tf.name_scope('neural_network'):
    x1 = tf.contrib.layers.fully_connected(x, 100)
    x2 = tf.contrib.layers.fully_connected(x1, 100)
    result = tf.contrib.layers.fully_connected(x2, 1,
                                               activation_fn=None)

    loss = tf.nn.l2_loss(result - y)

with tf.name_scope('optimizer'):
    train_op = tf.train.AdamOptimizer().minimize(loss)

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())

    # Train the network
    for i in range(10000):
        xpts = np.random.rand(100) * 10
        ypts = np.sin(xpts)

        _, loss_result = sess.run([train_op, loss],
                                  feed_dict={x: xpts[:, None],
                                             y: ypts[:, None]})

        print('iteration {}, loss={}'.format(i, loss_result))
于 2017-07-19T17:16:14.177 回答
3

你绝对不是在尝试不可能的事情。神经网络是通用逼近器——这意味着对于任何函数 F 和误差 E,都存在一些神经网络(只需要一个隐藏层)可以以小于 E 的误差逼近 F。

当然,找到那个(那些)网络是完全不同的事情。我能告诉你的最好的方法是反复试验......这是基本程序:

  1. 将数据分成两部分:训练集(~2/3)和测试集(~1/3)。
  2. 在训练集中的所有项目上训练您的网络。
  3. 在测试集中的所有项目上测试(但不训练)您的网络并记录平均错误。
  4. 重复第 2 步和第 3 步,直到您达到最小测试错误(当您的网络开始在训练数据上变得超级好而损害其他一切时,会发生“过度拟合”)或直到您的整体错误不再显着减少(暗示网络将达到最佳状态)。
  5. 如果此时的错误是可以接受的低,你就完成了。如果不是,您的网络还不够复杂,无法处理您正在为其训练的功能;添加更多隐藏的神经元并回到开始......

有时改变你的激活函数也会产生影响(只是不要使用线性,因为它会抵消添加更多层的力量)。但同样,要知道什么是最好的,这将是反复试验。

希望对您有所帮助(抱歉,我不能更有用)!

PS: 我也知道这是可能的,因为我见过有人用网络近似正弦。我想说她没有使用 sigmoid 激活函数,但我不能保证我的记忆力……

于 2012-12-16T12:28:42.613 回答
0

sklearn.neural_network 的类似实现:

from sklearn.neural_network import MLPRegressor
import numpy as np

f = lambda x: [[x_] for x_ in x]
noise_level = 0.1
X_train_ = np.arange(0, 10, 0.2)
real_sin = np.sin(X_train_)
y_train = real_sin+np.random.normal(0,noise_level,len(X_train_))    
N = 100
regr = MLPRegressor(hidden_layer_sizes= tuple([N]*5)).fit(f(X_train_), y_train)
predicted_sin = regr.predict(f(X_train_))

结果如下所示: 用NN预测罪

于 2021-05-04T13:51:03.790 回答