【问题标题】:Loss function increasing instead of decreasing损失函数增加而不是减少
【发布时间】:2020-06-17 11:28:31
【问题描述】:

我一直在尝试从头开始制作自己的神经网络。一段时间后,我做到了,但遇到了一个我无法解决的问题。我一直在关注tutorial,它展示了如何做到这一点。我遇到的问题是我的网络如何更新权重和偏差。好吧,我知道梯度下降不会总是减少损失,并且在几个时期它甚至可能会增加一点,它仍然应该减少并且比我的工作得更好。有时整个过程卡在损失 9 和 13 上,无法摆脱。我检查了许多教程、视频和网站,但我在我的代码中找不到任何错误。 self.activateself.dactivateself.lossself.dloss

# sigmoid
self.activate = lambda x: np.divide(1, 1 + np.exp(-x))
self.dactivate = lambda x: np.multiply(self.activate(x), (1 - self.activate(x)))

# relu
self.activate = lambda x: np.where(x > 0, x, 0)
self.dactivate = lambda x: np.where(x > 0, 1, 0)

# loss I use (cross-entropy)
clip = lambda x: np.clip(x, 1e-10, 1 - 1e-10) # it's used to squeeze x into a probability between 0 and 1 (which I think is required)
self.loss = lambda x, y: -(np.sum(np.multiply(y, np.log(clip(x))) + np.multiply(1 - y, np.log(1 - clip(x))))/y.shape[0])
self.dloss = lambda x, y: -(np.divide(y, clip(x)) - np.divide(1 - y, 1 - clip(x)))

我用于前向传播的代码:

self.activate(np.dot(X, self.weights) + self.biases) # it's an example for first hidden layer

这就是反向传播的代码:

第一部分,DenseNeuralNetwork 类:

last_derivative = self.dloss(output, y)

for layer in reversed(self.layers):
    last_derivative = layer.backward(last_derivative, self.lr)

第二部分,Dense 类:

def backward(self, last_derivative, lr):
    w = self.weights

    dfunction = self.dactivate(last_derivative)
    d_w = np.dot(self.layer_input.T, dfunction) * (1./self.layer_input.shape[1])
    d_b = (1./self.layer_input.shape[1]) * np.dot(np.ones((self.biases.shape[0], last_derivative.shape[0])), last_derivative)

    self.weights -= np.multiply(lr, d_w)
    self.biases -= np.multiply(lr, d_b)

    return np.dot(dfunction, w.T)

我还做了一个repl,这样你就可以检查整个代码并毫无问题地运行它。

【问题讨论】:

    标签: python numpy machine-learning deep-learning neural-network


    【解决方案1】:

    1.

    第 12 行

    self.dloss = lambda x, y: -(np.divide(y, clip(x)) - np.divide(1 - y, 1 - clip(x)))
    

    如果你要剪辑 x,你也应该剪辑 y。
    我的意思是有一些方法可以实现这一点,但如果你打算使用这种方式。
    改为

    self.dloss = lambda x, y: -(np.divide(clip(y), clip(x)) - np.divide(1 - clip(y), 1 - clip(x)))
    

    2.

    第 75 行

    dfunction = self.dactivate(last_derivative)
    

    这个反向传播部分是错误的。
    改为

    dfunction = last_derivative*self.dactivate(np.dot(self.layer_input, self.weights) + self.biases)
    

    3.

    第 77 行

    d_b = (1./self.layer_input.shape[1]) * np.dot(np.ones((self.biases.shape[0], last_derivative.shape[0])), last_derivative)
    

    last_derivative 应该是 dfunction。我认为这只是一个错误。
    改为

    d_b = (1./self.layer_input.shape[1]) * np.dot(np.ones((self.biases.shape[0], last_derivative.shape[0])), dfunction)
    

    4.

    第 85 行

    self.weights = np.random.randn(neurons, self.neurons) * np.divide(6, np.sqrt(self.neurons * neurons))
    self.biases = np.random.randn(1, self.neurons) * np.divide(6, np.sqrt(self.neurons * neurons))
    

    不知道你要去哪里,但我认为初始化的值太大了。我们没有进行精确的超调,所以我只是把它变小了。

    self.weights = np.random.randn(neurons, self.neurons) * np.divide(6, np.sqrt(self.neurons * neurons)) / 100
    self.biases = np.random.randn(1, self.neurons) * np.divide(6, np.sqrt(self.neurons * neurons)) / 100
    

    现在一切都好

    在此之后,我将学习率更改为 0.01,因为它很慢,而且效果很好。
    我认为您误解了反向传播。您可能应该仔细检查它是如何工作的。其他部分我觉得还可以。

    【讨论】:

    • 谢谢!我喜欢你!我试图解决这个问题几个星期,但我无法得到任何接近答案。
    【解决方案2】:

    这可能是由您的训练数据引起的。它要么太小,要么太多不同的标签(我从您共享的链接中的代码中得到什么)。

    我多次重新运行您的代码,它产生了不同的训练性能。有时损失会一直减少到最后一个时期,有时它会不断增加,有一次它会减少到某个点并且它会增加。 (最小损失达到 0.5)

    我认为这次重要的是您的训练数据。不过学习率已经足够好了(假设您正确计算了线性组合、反向传播等)。

    【讨论】:

      猜你喜欢
      • 2021-11-07
      • 2018-12-15
      • 2022-09-25
      • 2022-12-26
      • 1970-01-01
      • 2021-03-11
      • 2020-10-02
      • 2017-08-14
      • 2021-04-13
      相关资源
      最近更新 更多