用神经网络逼近正弦函数

Mut*_*ton 18 machine-learning neural-network

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

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

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

编辑:我知道即使使用简单的反向传播也很有可能找到一个足够好的近似值(如果你的初始权重非常幸运)但我实际上更感兴趣的是知道这是否是一种可行的方法.与我的实现或甚至阻塞的弹性传播相比,我链接到的R脚本似乎只是非常快速和强大地收敛(在40个时代,只有很少的学习样本).我只是想知道我是否可以做些什么来改进我的反向传播算法以获得相同的性能,或者我是否需要研究一些更高级的学习方法?

Jon*_*ler 7

使用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))
Run Code Online (Sandbox Code Playgroud)

  • 您的代码实际上实现了3层神经网络,而不是2层.命名方案包括隐藏层和输出层,因此您的三个层是`x1`,`x2`和`result`. (2认同)

Xav*_*olt 5

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

当然,找到(那些)网络是完全不同的事情。我能告诉你的最好的就是尝试和错误......这是基本程序:

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

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

希望有帮助(抱歉我不能更有用)!

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