如何修复“无效值”,“被零除”和其他计算错误

时间:2020-08-26 18:45:03

标签: python numpy neural-network runtime-error nan

我正在使用numpy来计算神经网络的权重和节点,但是几乎每次我遇到类似这样的错误时:

  • “ RuntimeWarning:除以日志中遇到的零”
  • “乘法时遇到无效的值”
  • “ RuntimeWarning:exp中遇到溢出”
  • ...

大多数情况下导致值变为“ nan”。

因为权重是随机启动的,所以我并不总是会遇到相同的错误。

当我构建小型神经网络(例如2个输入,4个隐藏节点和1个输出)时,我根本不会遇到这些错误,但是如果我增加隐藏节点的数量,它将破坏并导致'nan'为值一切。

我已经搜索了解决方案,但没有帮助。我检查了那些不是会导致'nan'的值,但我什么也没找到。

import numpy as np
import sys
import matplotlib.pyplot as plt

np.set_printoptions(threshold=sys.maxsize)


class NeuralNetwork:
    def __init__(self, inputs, outputs, epochs, lr):
        self.inputs = inputs
        self.outputs = outputs
        self.m = self.inputs.shape[0]
        self.n = self.inputs.shape[1]
        self.epochs = epochs
        self.lr = lr
        self.hidden1Size = 64
        self.hidden2Size = 64
        self.w1 = np.random.randn(self.n, self.hidden1Size)
        self.w2 = np.random.randn(self.hidden1Size, self.hidden2Size)
        self.w3 = np.random.randn(self.hidden2Size, self.outputs.shape[1])

    def sigmoid(self, n):
        return 1 / (1 - np.exp(-n))

    def sigmoidDerivative(self, n):
        return self.sigmoid(n) * (1 - self.sigmoid(n))

    def ReLU(self, n):
        return n * (n > 0)

    def ReLUDerivatie(self, n):
        return n > 0

    def crossEntropyLoss(self, y, h):
        return - (y * np.log(h) + (y - 1) * np.log(1 - h))

    def train(self):
        for i in range(self.epochs):
            X, a2, a3, h = self.feedForward()
            self.backProp(X, a2, a3, h)
            if i % 100 == 0:
                print('Cost at ', i, 'epochs: ', print(self.crossEntropyLoss(self.inputs, h)))

    def feedForward(self):
        X = self.inputs
        z2 = X.dot(self.w1)
        a2 = self.ReLU(z2)
        z3 = a2.dot(self.w2)
        a3 = self.ReLU(z3)
        z4 = a3.dot(self.w3)
        h = self.sigmoid(z4)

        return X, a2, a3, h

    def backProp(self, X, a2, a3, h):

        outputErrors = self.crossEntropyLoss(self.outputs, h)
        outputDeltas = outputErrors * self.sigmoidDerivative(h)

        hidden2Errors = outputDeltas.dot(self.w3.T)
        hidden2Deltas = hidden2Errors * self.ReLUDerivatie(a3)

        hidden1Errors = hidden2Deltas.dot(self.w2.T)
        hidden1Deltas = hidden1Errors * self.ReLUDerivatie(a2)

        self.w3 += self.lr * a3.T.dot(outputDeltas)
        self.w2 += self.lr * a2.T.dot(hidden2Deltas)
        self.w1 += self.lr * X.T.dot(hidden1Deltas)


NN = NeuralNetwork(np.array([[0, 0], [0, 1], [1, 0], [1, 1]]), np.array([[0], [0], [0], [1]]), 10000, 0.01)
NN.train()

这些值仅供测试。我打算提供图像数据以区分数字,但据我所知,不应该破坏这些数字。

1 个答案:

答案 0 :(得分:0)

因此,以下操作可能会导致nan /错误:

# if n == 0, you'll have division by 0
def sigmoid(self, n):
    return 1 / (1 - np.exp(-n))

在这里:

# log function is not defined for negatives, thus for h < 0 or 1 - h < 0
def crossEntropyLoss(self, y, h):
        return - (y * np.log(h) + (y - 1) * np.log(1 - h))

正在进行许多转换,很难跟踪值的来源,但这是我的第一个猜测。如果向量是平行的,dot将渲染0-也许对您也有帮助。

因此,如果出现上述情况,我建议在这两个函数中打印回溯:https://docs.python.org/3/library/traceback.html#traceback.print_tb

这样,您将能够找出导致这种无效情况的调用的迭代/函数。