首页 > 解决方案 > 用于拟合正弦波的神经网络

问题描述

所以,我一直在学习神经网络,并尝试从头开始编写它们,并在某些情况下取得了成功。所以,我想到了将一个简单的单层神经网络拟合到正弦波。我知道我可以使用 keras,但我想学习内部工作。我的输入 x 是使用 numpy 从 0 到 10 的值以 0.1 步和 y = sin(x) 生成的,我初始化了网络的权重和偏差,还对反向传播进行了编码。但是在我尝试预测时拟合数据后给了我一条直线。我将层的激活从 sigmoid 更改为 tanh 以及它们各自的梯度,但输出不能预测正弦波。翻遍论坛后,不断出现这种周期性函数,使用RNN。

import numpy as np
from matplotlib import pyplot as plt
from tqdm import tqdm


def init_weight_and_bias_NN(M1, M2):
    W = np.random.randn(M1, M2) / np.sqrt(M1 + M2)
    b = np.zeros(M2)
    return W.astype(np.float32), b.astype(np.float32)


def out(x, w, b):
    return np.add(np.dot(x, w), b)


def softmax(A):
    expA = np.exp(A)
    return expA / expA.sum(axis=1, keepdims=True)


def relu(x):
    return x * (x > 0)


def start(x, y):
    alpha = 0.01
    reg = 0.3
    epochs = 1
    hiddennodes = 3
    M, D = x.shape
    w1, b1 = init_weight_and_bias_NN(D, hiddennodes)
    w2, b2 = init_weight_and_bias_NN(hiddennodes, 1)
    with tqdm(total=epochs, desc="Training") as prog:
        for i in range(epochs):
            hidden = relu(out(x, w1, b1))
            output = softmax(out(hidden, w2, b2))
            w2 = np.subtract(w2, np.multiply(alpha, np.add(np.dot(hidden.T, np.subtract(output, y)), reg * w2)))
            b2 = np.subtract(b2, np.multiply(alpha, np.sum(np.subtract(output, y))))
            hiddenError = np.dot(np.subtract(output, y), w2.T)
            w1 = np.subtract(w1, np.multiply(alpha, np.add(np.dot(x.T, hiddenError), reg * w1)))
            b1 = np.subtract(b1, np.multiply(alpha, np.sum(hiddenError)))
            prog.update(1)
    return w1, b1, w2, b2


def predict(w1, b1, w2, b2, x):
    y = []
    for val in x:
        hidden = relu(out(val, w1, b1))
        y.append(softmax(out(hidden, w2, b2)).tolist().pop().pop())
    return np.array(y)


if __name__ == '__main__':
    x = np.arange(0, 10, 0.1)
    x1 = x.reshape((1, x.shape[0]))
    y = np.sin(x)
    w1, b1, w2, b2 = start(x1, y)
    x2 = np.arange(10, 20, 0.1)
    ynew = predict(w1, b1, w2, b2, x2)
    plt.plot(x, y, c='r')
    plt.plot(x, ynew, c='b')
    plt.title("Original vs machine produced")
    plt.legend(["Original", "Machine"])
    plt.show()

最终情节 这是我得到的结果。我知道我不应该在最后一层使用 softmax。但我已经尝试了一切,这是我最新的代码。同样对于不同的激活,我尝试了许多时期和许多隐藏节点,它们的 alpha(learningrate) 和 reg(lambda 正则化器) 值不同我做错了什么?我应该在这里尝试RNN吗?我在某处看到使用顺序模型使用了 keras,并且使用了泄漏的 relu 作为激活函数。我没有尝试使用该激活。那是我应该尝试的吗?

标签: pythonneural-networkactivationsigmoidrelu

解决方案


训练时,您显示的神经网络 x 值介于 0 和 10 之间。在预测期间,您使用的 x 值介于 10 和 20 之间。这些值比网络以前见过的值大,因此它无法为您提供漂亮的正弦波。

当值超出他们所看到的范围时,神经网络无法很好地推断。如果你想学习神经网络在 0 到 10 之间的正弦波是什么样子并预测它在训练期间没有看到的点,你可以取 1000 个 0 到 10 之间的随机点及其 sin(x) 值并使用 80%其中用于训练网络,20% 用于测试预测。我想你会得到很好的结果。

但是,当您想预测正弦波如何超过 10 时,您应该在元组上训练您的模型,例如 4 个点,第 5 个点作为标签。在预测时,您给出净 4 个连续的 y 值并让它预测第五个。对于下一个预测,您使用 3 个旧点加上之前的预测,然后再次预测下一个点。不要使用任何 x 值进行训练。

让我知道这是否不完全清楚。如果没有,我会画一个。


推荐阅读