所以,我一直在学习神经网络,并尝试从头开始编写它们,并在某些情况下取得了成功。所以,我想到了将一个简单的单层神经网络拟合到正弦波。我知道我可以使用 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 作为激活函数。我没有尝试使用该激活。那是我应该尝试的吗?