损失函数增加而不是减少

时间:2020-03-04 21:38:24

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

我一直在尝试从头开始建立自己的神经网络。一段时间后,我做到了,但是遇到了我无法解决的问题。我一直在关注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,因此您可以检查整个代码并运行它而不会出现任何问题。

2 个答案:

答案 0 :(得分:1)

1。

第12行

self.surface.blit(world.subsurface((self.x, self.y, self.width, self.height)), (0,0))

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

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

2。

第75行

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

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

dfunction = self.dactivate(last_derivative)

3。

第77行

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

last_derivative应该是函数。我认为这只是一个错误。
更改为

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

4。

第85行

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

不知道该怎么做,但我认为初始化值太大。我们没有进行精确的超调,所以我把它做的很小。

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))

现在一切都好

此后,由于学习速度变慢,我将学习率更改为0.01,并且效果很好。
我认为您误解了反向传播。您可能应该仔细检查它的工作方式。我认为其他部分还可以。

答案 1 :(得分:0)

这可能是由您的训练数据引起的。标签太小或标签太多(我从您共享的链接中从代码中得到的信息)。

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

我认为这次重要的是您的训练数据。尽管学习率足够好(假设您对线性组合,反向传播等进行了正确的计算)。