我正在研究ANN,并使用渐变下降来解决简单的AND / XOR问题,但我发现找到更复杂问题的最佳权重要困难得多。我的解决方案是使用Scipy的最小功能,但我遇到了一些麻烦。
我的ANN是一个类,当创建ANN对象时,在初始化时创建权重作为数据成员self .__权重,这很有用,因为我实际上不必将权重参数传递给任何一个在类上使用的方法,它在我早期的非Scipy使用实现中工作。
我使用self .__权重作为最小函数的初始猜测,并传入使函数工作所需的其他参数(输入数据,正确的输出值)。但似乎优化器在不需要时将权重传递给方法(Cost Function / FeedForward / Backprop)作为参数,因为它可以用self .__权重调用。例如,当调用我的FeedForward方法时,它会传递权重,并声明输入的大小不正确,这是因为权重是传入的。并且输入数据被传递到最小的可选' arg ='参数。
因此,所有解释都必须要优化的值实际上是用于优化它的方法的参数,而不仅仅是可以从类中的任何位置调用的类数据成员吗?我试图通过他们在那里传递的课程找到例子来衡量'或根据其使用而优化的其他值,而不是该类的数据成员。
编辑:
这是我的火车方法中的代码片段。它的参数是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
self.CostFunction
和self.Weight_Grad
都采用相同的两个参数。后两个函数都使用前馈方法来获取网络的输出,并使用该信息执行相应的任务。每当我调用最小化函数时,它似乎将self.__weights
传递给self.CostFunction
作为input_data
参数,然后将其作为输入传递给FeedForward方法,我得到一个错误。如果我打印"输入"传递给Feedforward,它是self.__weights
的值。这就是我知道self.__weights
作为参数传递的方式。
所以,我以为我会创建一个"虚拟"?用于将self.__weights
值传递给所有方法的参数(' self.CostFunction ,'self.Weight_Grad
,Feedforward
)并且没有发生错误但是没有更改重量或输出。我需要做些什么才能让自我.__权重更新。
以下是有用的方法:
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")