首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ANN BackProp/梯度检验问题

ANN BackProp/梯度检验问题
EN

Stack Overflow用户
提问于 2014-12-24 17:39:06
回答 1查看 650关注 0票数 0

刚用python写了我的第一堂神经网络课。据我所知,每件事都应该有效,但其中有一些我似乎找不到的错误(可能正盯着我的脸)。我首先在10,000个MNIST数据示例上试用了它,然后在尝试复制符号函数时,以及在试图复制XOR门时又试了一次。每一次,无论时代的#,它总是产生输出的所有输出神经元(不管可能有多少)都是大致相同的值,但成本函数似乎正在下降。我使用的是批处理梯度下降,所有这些都是使用向量完成的(每个训练示例都没有循环)。

代码语言:javascript
复制
#Neural Network Class

import numpy as np



class NeuralNetwork:

#methods
def __init__(self,layer_shape):
    #Useful Network Info
    self.__layer_shape = layer_shape
    self.__layers = len(layer_shape)

    #Initialize Random Weights
    self.__weights = [] 
    self.__weight_sizes = []
    for i in range(len(layer_shape)-1):
        current_weight_size = (layer_shape[i+1],layer_shape[i]+1)
        self.__weight_sizes.append(current_weight_size)
        self.__weights.append(np.random.normal(loc=0.1,scale=0.1,size=current_weight_size))

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

def sig_prime(self,z):
    return np.multiply(self.sigmoid(z),(1-self.sigmoid(z)))


def Feedforward(self,input,Train=False):
    self.__input_cases = np.shape(input)[0]

    #Empty list to hold the output of every layer.
    output_list = []
    #Appends the output of the the 1st input layer.
    output_list.append(input)

    for i in range(self.__layers-1):
        if i == 0:
            output = self.sigmoid(np.dot(np.concatenate((np.ones((self.__input_cases,1)),input),1),self.__weights[0].T))
            output_list.append(output)
        else:
            output = self.sigmoid(np.dot(np.concatenate((np.ones((self.__input_cases,1)),output),1),self.__weights[i].T))                 
            output_list.append(output)

    #Returns the final output if not training.         
    if Train == False:
        return output_list[-1]
    #Returns the entire output_list if need for training
    else:
        return output_list

def CostFunction(self,input,target,error_func=1):
    """Gives the cost of using a particular weight matrix 
    based off of the input and targeted output"""

    #Run the network to get output using current theta matrices.
    output = self.Feedforward(input)


    #####Allows user to choose Cost Functions.##### 

    #
    #Log Based Error Function
    #
    if error_func == 0:
        error = np.multiply(-target,np.log(output))-np.multiply((1-target),np.log(1-output))
        total_error = np.sum(np.sum(error))
    #    
    #Squared Error Cost Function
    #
    elif error_func == 1:
        error = (target - output)**2
        total_error = 0.5 * np.sum(np.sum(error))

    return total_error

def Weight_Grad(self,input,target,output_list):

            #Finds the Error Deltas for Each Layer
            # 
            deltas = []
            for i in range(self.__layers - 1):
                #Finds Error Delta for the last layer
                if i == 0:

                    error = (target-output_list[-1])

                    error_delta = -1*np.multiply(error,np.multiply(output_list[-1],(1-output_list[-1])))
                    deltas.append(error_delta)
                #Finds Error Delta for the hidden layers   
                else:
                    #Weight matrices have bias values removed
                    error_delta = np.multiply(np.dot(deltas[-1],self.__weights[-i][:,1:]),output_list[-i-1]*(1-output_list[-i-1]))
                    deltas.append(error_delta)

            #
            #Finds the Deltas for each Weight Matrix
            #
            Weight_Delta_List = []
            deltas.reverse()
            for i in range(len(self.__weights)):

                current_weight_delta = (1/self.__input_cases) * np.dot(deltas[i].T,np.concatenate((np.ones((self.__input_cases,1)),output_list[i]),1))
                Weight_Delta_List.append(current_weight_delta)
                #print("Weight",i,"Delta:","\n",current_weight_delta)
                #print()

            #
            #Combines all Weight Deltas into a single row vector
            #
            Weight_Delta_Vector = np.array([[]])
            for i in Weight_Delta_List:

                Weight_Delta_Vector = np.concatenate((Weight_Delta_Vector,np.reshape(i,(1,-1))),1)
            return Weight_Delta_List        

def Train(self,input_data,target):
    #
    #Gradient Checking:
    #

    #First Get Gradients from first iteration of Back Propagation 
    output_list = self.Feedforward(input_data,Train=True)
    self.__input_cases = np.shape(input_data)[0]

    Weight_Delta_List = self.Weight_Grad(input_data,target,output_list)  

    #Creates List of Gradient Approx arrays set to zero.
    grad_approx_list = []
    for i in self.__weight_sizes:
        current_grad_approx = np.zeros(i)
        grad_approx_list.append(current_grad_approx)


    #Compute Approx. Gradient for every Weight Change
    for W in range(len(self.__weights)):
        for index,value in np.ndenumerate(self.__weights[W]):
            orig_value = self.__weights[W][index]      #Saves the Original Value
            print("Orig Value:", orig_value)

            #Sets weight to  weight +/- epsilon
            self.__weights[W][index] = orig_value+.00001
            cost_plusE = self.CostFunction(input_data, target)

            self.__weights[W][index] = orig_value-.00001
            cost_minusE = self.CostFunction(input_data, target)

            #Solves for grad approx:
            grad_approx = (cost_plusE-cost_minusE)/(2*.00001)
            grad_approx_list[W][index] = grad_approx

            #Sets Weight Value back to its original value
            self.__weights[W][index] = orig_value


    #
    #Print Gradients from Back Prop. and Grad Approx. side-by-side:
    #

    print("Back Prop. Grad","\t","Grad. Approx")
    print("-"*15,"\t","-"*15)
    for W in range(len(self.__weights)):
        for index, value in np.ndenumerate(self.__weights[W]):
            print(self.__weights[W][index],"\t"*3,grad_approx_list[W][index])

    print("\n"*3)
    input_ = input("Press Enter to continue:")


    #
    #Perform Weight Updates for X number of Iterations
    #
    for i in range(10000):
    #Run the network
        output_list = self.Feedforward(input_data,Train=True)
        self.__input_cases = np.shape(input_data)[0]

        Weight_Delta_List = self.Weight_Grad(input_data,target,output_list)


        for w in range(len(self.__weights)):
            #print(self.__weights[w])
            #print(Weight_Delta_List[w])
            self.__weights[w] = self.__weights[w] - (.01*Weight_Delta_List[w]) 


    print("Done")`

我甚至实现了梯度检查,并且值是不同的,我想我会尝试用Approx替换回传播更新。梯度检查值,但这给出了相同的结果,导致我怀疑甚至我的梯度检查代码。

以下是为XOR门进行培训时产生的一些值:

后背支柱。毕业生: 0.0756102610697 0.261814503398 0.0292734023876毕业生Approx: 0.05302210631166 0.0416095559674 0.0246847342122训练前: 0.508019225507训练后0.50007095103 ( 10000次后)输出4个不同的例子(训练后):0.49317733 0.50489004

所以我的问题是,我的背传播有什么明显的问题吗?还是梯度检查?当人工神经网络显示这些症状时,有没有常见的问题(输出结果大致相同/成本正在下降)?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-12-25 11:33:44

我不太擅长阅读python代码,但是XOR的梯度列表包含3个元素,对应于3个权重。我假设,这是对单个神经元的两个输入和一个偏倚。如果是这样的话,这种网络不能学习异或(最小神经网络,可以学习异或需要两个隐藏神经元和一个输出单元)。现在,看看前馈函数,如果np.dot计算它的名称(即两个向量的点乘积),并且sigmoid是标量,那么这总是对应于一个神经元的输出,我不知道如何用这个代码向层中添加更多的神经元。

以下建议可能有助于调试任何新实现的NN:

1)不要从MNIST甚至XOR开始。完美的实现可能无法学习XOR,因为它很容易陷入局部极小值,并且您可以花费大量时间寻找不存在的错误。一个很好的起点和功能,可以用单个神经元来学习。

( 2)在少数实例上,通过手工计算结果验证前向计算传递。这很容易用少量的重量来做。然后尝试用数值梯度来训练它。如果它失败了,那么您的数值梯度是错误的(手工检查)或训练程序是错误的。(如果设置太大的学习速率,它可能无法工作,但是由于错误面是凸的,否则训练必须收敛)。

3)一旦你可以用数值梯度来训练它,调试你的分析梯度(检查每个神经元的梯度,然后对单个权重进行梯度)。这同样可以手工计算,并与您所看到的进行比较。

4)步骤3完成后,如果一切正常,添加一个隐藏层,并使用和函数重复步骤2和步骤3。

5)在使用完和之后,您可以转移到XOR函数和其他更复杂的任务。

这一过程似乎很费时,但最终几乎都会导致神经网络的工作。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27640496

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档