Scipy的最小函数可以优化类数据成员的值吗?

时间:2015-01-02 03:09:40

标签: python class optimization scipy neural-network

我正在研究ANN,并使用渐变下降来解决简单的AND / XOR问题,但我发现找到更复杂问题的最佳权重要困难得多。我的解决方案是使用Scipy的最小功能,但我遇到了一些麻烦。

我的ANN是一个类,当创建ANN对象时,在初始化时创建权重作为数据成员self .__权重,这很有用,因为我实际上不必将权重参数传递给任何一个在类上使用的方法,它在我早期的非Scipy使用实现中工作。

我使用self .__权重作为最小函数的初始猜测,并传入使函数工作所需的其他参数(输入数据,正确的输出值)。但似乎优化器在不需要时将权重传递给方法(Cost Function / FeedForward / Backprop)作为参数,因为它可以用self .__权重调用。例如,当调用我的FeedForward方法时,它会传递权重,并声明输入的大小不正确,这是因为权重是传入的。并且输入数据被传递到最小的可选' arg ='参数。

因此,所有解释都必须要优化的值实际上是用于优化它的方法的参数,而不仅仅是可以从类中的任何位置调用的类数据成员吗?我试图通过他们在那里传递的课程找到例子来衡量'或根据其使用而优化的其他值,而不是该类的数据成员。

编辑:

这是我的火车方法中的代码片段。它的参数是input_datatarget

opt_theta = minimize(self.CostFunction,x0=self.__weights,args = (input_data,target),method='Newton-CG',jac= self.Weight_Grad)       
    print(opt_theta)
    self.__weights = opt_theta.x 

self.CostFunctionself.Weight_Grad都采用相同的两个参数。后两个函数都使用前馈方法来获取网络的输出,并使用该信息执行相应的任务。每当我调用最小化函数时,它似乎将self.__weights传递给self.CostFunction作为input_data参数,然后将其作为输入传递给FeedForward方法,我得到一个错误。如果我打印"输入"传递给Feedforward,它是self.__weights的值。这就是我知道self.__weights作为参数传递的方式。

所以,我以为我会创建一个"虚拟"?用于将self.__weights值传递给所有方法的参数(' self.CostFunction ,'self.Weight_GradFeedforward)并且没有发生错误但是没有更改重量或输出。我需要做些什么才能让自我.__权重更新。

以下是有用的方法:

def Feedforward(self,input):

        #Code to take self.__weights and convert to list of matrices. 
        weight_matrix_list = []
        prev_val = 0


        for i in range(len(self.__weight_sizes)):
            curr_w_size = self.__weight_sizes[i]
            weight_count = curr_w_size[0]*curr_w_size[1]
            matrix_elements = self.__weights[prev_val:prev_val+weight_count]
            weight_matrix_list.append(matrix_elements.reshape(curr_w_size))


        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:

                print(self.__input_cases)
                print(input)
                X = np.concatenate((np.ones((self.__input_cases,1)),input),1)

                output = self.sigmoid(np.dot(X,weight_matrix_list[0].T))
                output_list.append(output)
            else:
                output = self.sigmoid(np.dot(np.concatenate((np.ones((self.__input_cases,1)),output),1),weight_matrix_list[i].T))                 
                output_list.append(output)


        return output_list

    def CostFunction(self,input_data,target,error_func=1):
        """Gives the cost of using a particular weight matrix 
        based off of the input and targeted output"""
        print("Cost")
        #Run the network to get output using current theta matrices.
        output = self.Feedforward(input_data)[-1]


        #Determines number of input/training examples
        m = np.shape(input_data)[0]

        #####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 = (1/(2*m)) * np.sum(np.sum(error))

        return total_error

    def Weight_Grad(self,input_data,target):
        print('Grad')
        weight_matrix_list = []
        prev_val = 0

        for i in range(len(self.__weight_sizes)):
            curr_w_size = self.__weight_sizes[i]
            weight_count = curr_w_size[0]*curr_w_size[1]
            matrix_elements = self.__weights[prev_val:prev_val+weight_count]
            weight_matrix_list.append(matrix_elements.reshape(curr_w_size))        

        output_list = self.Feedforward(theta,input_data)

        #Finds the 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],weight_matrix_list[-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(weight_matrix_list)):

            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)




        #
        #Converts Weight Delta List to a single vector
        #        
        Weight_Delta_Vector = np.array([])
        for i in range(len(Weight_Delta_List)):
            Weight_Delta_Vector = np.concatenate((Weight_Delta_Vector,Weight_Delta_List[i].flatten()))
        print("WDV Shape:",np.shape(Weight_Delta_Vector))
        return Weight_Delta_Vector

    def Train(self,input_data,target):           

        opt_theta = minimize(self.CostFunction,x0=self.__weights,args = (input_data,target),method='Newton-CG',jac= self.Weight_Grad)       
        print(opt_theta)
        self.__weights = opt_theta.x

        print("Done")

0 个答案:

没有答案