【问题标题】:Errors from building a one hidden neural network构建单隐神经网络的错误
【发布时间】:2018-07-22 16:57:43
【问题描述】:

我目前正在使用 numpy 从头开始​​构建我的 3-4-1 神经网络(我避免使用 keras 和 tensorflow 来学习和尝试展示我的知识,而不是使用预构建的库来完成所有工作),我在运行程序时发现的问题是: 1/在“更新的”权重中经过一定次数的迭代后获得“nan”值,降低学习率只会延迟问题,并不能解决问题。 2/ 第二个问题是预测准确率非常低。 我想知道是什么导致我的程序出现这些错误,并希望得到任何帮助。 这是代码:

# Import our dependencies
from numpy import exp, array, random, dot, ones_like, where

# Create our Artificial Neural Network class
class ArtificialNeuralNetwork():

    # initializing the class
    def __init__(self):

        # generating the same synaptic weights every time the program runs
        random.seed(1)

        # synaptic weights (3 × 4 Matrix) of the hidden layer 
        self.w_ij = 2 * random.rand(3, 4) - 1

        # synaptic weights (4 × 1 Matrix) of the output layer
        self.w_jk = 2 * random.rand(4, 1) - 1

    def LeakyReLU(self, x):

        # The Leaky ReLU (short for Rectified Linear Unit) activation function will be applied to the inputs of the hidden layer
        # The activation function will return the same value of x if x is positive
        # while it will multiply the negative values of x by the alpha parameter
        # we used in this example the Leaky ReLU instead of the standard ReLU activation function to avoid the dying ReLU problem

        return where(x > 0, x, x * 0.01)

    def LeakyReLUDerivative(self, x, α = 0.01):

        # The Leaky ReLU Derivative will return 1 for every positive value in the x array 
        # while returning the value of the parameter alpha for every negative value

        x[x > 0] = 1 # returns 1 for every positive value in the x array 

        x[x <= 0] = α # returns α for every negative value in the x array

        return x

    def Sigmoid(self, x):

        # The Sigmoid activation function will turn every input value into probabilities between 0 and 1
        # the probabilistic values help us assert which class x belongs to

        return 1 / (1 + exp(-x))

    def SigmoidDerivative(self, x):

        # The derivative of the Sigmoid activation function will be used to calculate the gradient during the backpropagation process
        # and help optimize the random starting synaptic weights

        return x * (1 - x)

    def train(self, x, y, learning_rate, iterations):

        # x: training set of data
        # y: the actual output of the training data

        for i in range(iterations):

            z_ij = dot(x, self.w_ij) # the dot product of the weights of the hidden layer and the inputs
            a_ij = self.LeakyReLU(z_ij) # using the Leaky ReLU activation function to introduce non-linearity to our Neural Network

            z_jk = dot(a_ij, self.w_jk) # the same precedent process will be applied to find the last input of the output layer
            a_jk = self.Sigmoid(z_jk) # this time the Sigmoid activation function will be used instead of Leaky ReLU 

            dl_jk = -y/a_jk + (1 - y)/(1 - a_jk) # calculating the derivative of the cross entropy loss wrt output
            da_jk = self.SigmoidDerivative(a_jk) # calculating the derivative of the Sigmoid activation function wrt the input (before activation) of the output layer
            dz_jk = a_ij # calculating the derivative of the inputs of the hidden layer (before activation) wrt weights of the output layer

            dl_ij = dot(da_jk * dl_jk, self.w_jk.T) # calculating the derivative of the cross entropy loss wrt activated input of the hidden layer
                                                # to do so we multiply the derivative of the cross entropy loss wrt output by the derivative of the Sigmoid activation function wrt the input (before activation) of the output layer by the derivative of the inputs of the hidden layer (before activation) wrt weights of the output layer 
            da_ij = self.LeakyReLUDerivative(z_ij) # calculating the derivative of the Leaky ReLU activation function wrt the inputs of the hidden layer (before activation)
            dz_ij = x # calculating the derivative of the inputs of the hidden layer (before activation) wrt weights of the hidden layer

            # calculating the gradient using the chain rule
            gradient_ij = dot(dz_ij.T , dl_ij * da_ij)
            gradient_jk = dot(dz_jk.T , dl_jk * da_jk)

            # calculating the new optimal weights
            self.w_ij = self.w_ij - learning_rate * gradient_ij 
            self.w_jk = self.w_jk - learning_rate * gradient_jk

    def predict(self, inputs):

        # predicting the class of the input data after weights optimization

        output_from_layer1 = self.LeakyReLU(dot(inputs, self.w_ij)) # the output of the hidden layer

        output_from_layer2 = self.Sigmoid(dot(output_from_layer1, self.w_jk)) # the output of the output layer

        return output_from_layer1, output_from_layer2

    # the function will print the initial starting weights before training
    def SynapticWeights(self):

        print("Layer 1 (4 neurons, each with 3 inputs): ")

        print("w_ij: ", self.w_ij)

        print("Layer 2 (1 neuron, with 4 inputs): ")

        print("w_jk: ", self.w_jk)


def main():

    ANN = ArtificialNeuralNetwork()

    ANN.SynapticWeights()

    # the training inputs 
    x = array([[0, 0, 1], [0, 1, 1], [1, 0, 1], [0, 1, 0], [1, 0, 0], [1, 1, 1], [0, 0, 0]])

    # the training outputs
    y = array([[0, 1, 1, 1, 1, 0, 0]]).T

    ANN.train(x, y, 1, 10000)

    # Printing the new synaptic weights after training
    print("New synaptic weights after training: ")
    print("w_ij: ", ANN.w_ij)
    print("w_jk: ", ANN.w_jk)

    # Our prediction after feeding the ANN with new set of data
    print("Considering new situation [1, 1, 0] -> ?: ")
    print(ANN.predict(array([[1, 1, 0]])))

if __name__=="__main__":
    main()

【问题讨论】:

  • 你能详细说明这个问题吗?我没有得到任何 Nan FYI
  • 嗨 Umang Gupta 感谢您的快速响应,如果迭代次数超过一定限制,程序会给出 nan 值作为其更新的权重,我现在编辑了代码,以下程序将失败。跨度>

标签: python tensorflow neural-network deep-learning


【解决方案1】:

所以,我改变了一些东西。 (免责声明:我没有检查代码的正确性)

  1. 权重初始化:初始化为更小的权重。

    # synaptic weights (3 × 4 Matrix) of the hidden layer
    self.w_ij = (2 * random.rand(3, 4) - 1)*0.1
    
    # synaptic weights (4 × 1 Matrix) of the output layer
    self.w_jk = (2 * random.rand(4, 1) - 1)*0.1  
    

权重初始化真的很重要。

  1. 我将学习率降低到 0.1。

    ANN.train(x, y, .1, 500000)
    
  2. 我看到神经网络完美拟合您的数据,即使经过 500,000 次迭代也没有给出 Nan。

    print(ANN.predict(array([[0, 0, 1],
                             [0, 1, 1],
                             [1, 0, 1],
                             [0, 1, 0],
                             [1, 0, 0],
                             [1, 1, 1],
                             [0, 0, 0]])))
    

【讨论】:

  • 感谢 Umang Gupta 的帮助 我非常感谢您为解决我的问题所付出的努力,在传递训练数据时(再次)我发现我的数据实际上与您提到的一样,除了最后一个[0, 0, 0] 数组,其中即使在更新权重之后,输入也会给出 0.5 的输出。这可能解释了我的神经网络在输入从未见过的输入时的中等准确性。
  • @BlgKhalil 可能是神经网络不能比这更好。你可以增加参数,看看是否合适。另外,如果您认为这足以解决您的问题,请接受和/或投票:)
  • 肯定会为你为我的编码问题而牺牲的时间做这件事:)
猜你喜欢
  • 1970-01-01
  • 2017-11-20
  • 2021-03-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-28
  • 2015-10-17
  • 1970-01-01
相关资源
最近更新 更多