损失函数增加而不是减少

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

# sigmoidself.activate = lambda x: np.divide(1, 1 + np.exp(-x))self.dactivate = lambda x: np.multiply(self.activate(x), (1 - self.activate(x)))# reluself.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,这样你就可以检查整个代码并无障碍地运行它。


回答:

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)) / 100self.biases = np.random.randn(1, self.neurons) * np.divide(6, np.sqrt(self.neurons * neurons)) / 100

现在一切正常

之后我将学习率改为0.01,因为它太慢了,然后它工作得很好。
我认为你对反向传播有误解。你应该仔细检查它是如何工作的。我认为其他部分是可以的。

Related Posts

使用LSTM在Python中预测未来值

这段代码可以预测指定股票的当前日期之前的值,但不能预测…

如何在gensim的word2vec模型中查找双词组的相似性

我有一个word2vec模型,假设我使用的是googl…

dask_xgboost.predict 可以工作但无法显示 – 数据必须是一维的

我试图使用 XGBoost 创建模型。 看起来我成功地…

ML Tuning – Cross Validation in Spark

我在https://spark.apache.org/…

如何在React JS中使用fetch从REST API获取预测

我正在开发一个应用程序,其中Flask REST AP…

如何分析ML.NET中多类分类预测得分数组?

我在ML.NET中创建了一个多类分类项目。该项目可以对…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注