python - 用于拟合正弦波的神经网络
问题描述
所以,我一直在学习神经网络,并尝试从头开始编写它们,并在某些情况下取得了成功。所以,我想到了将一个简单的单层神经网络拟合到正弦波。我知道我可以使用 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 作为激活函数。我没有尝试使用该激活。那是我应该尝试的吗?
解决方案
训练时,您显示的神经网络 x 值介于 0 和 10 之间。在预测期间,您使用的 x 值介于 10 和 20 之间。这些值比网络以前见过的值大,因此它无法为您提供漂亮的正弦波。
当值超出他们所看到的范围时,神经网络无法很好地推断。如果你想学习神经网络在 0 到 10 之间的正弦波是什么样子并预测它在训练期间没有看到的点,你可以取 1000 个 0 到 10 之间的随机点及其 sin(x) 值并使用 80%其中用于训练网络,20% 用于测试预测。我想你会得到很好的结果。
但是,当您想预测正弦波如何超过 10 时,您应该在元组上训练您的模型,例如 4 个点,第 5 个点作为标签。在预测时,您给出净 4 个连续的 y 值并让它预测第五个。对于下一个预测,您使用 3 个旧点加上之前的预测,然后再次预测下一个点。不要使用任何 x 值进行训练。
让我知道这是否不完全清楚。如果没有,我会画一个。
推荐阅读
- c# - Why Unity Transform only allows to put up to 4 decimals?
- python - 如何更改张量定义而不在图中分配新名称
- swiftui - SwiftUI - 从锚定到按钮框架的按钮点击动画到屏幕上
- python - 比较 2 个 numpy 数组时比较索引号并返回元素结果
- ios - AVRoutePickerView 不接受 overrideOutputAudioPort(.speaker) 对路由所做的更改
- c++ - 调用 Qt 的 setui 方法后是否应该检查空指针?
- flutter - 子小部件中的 setState()
- javascript - 在 Eclipse 中将 jquery 添加到我的“动态 Web 项目”中
- itext - Itext 7 - 梳状字段 - 填写表格
- javascript - 为什么组件内部的函数在 componentDidMount 之前执行?