刚用python写了我的第一堂神经网络课。据我所知,每件事都应该有效,但其中有一些我似乎找不到的错误(可能正盯着我的脸)。我首先在10,000个MNIST数据示例上试用了它,然后在尝试复制符号函数时,以及在试图复制XOR门时又试了一次。每一次,无论时代的#,它总是产生输出的所有输出神经元(不管可能有多少)都是大致相同的值,但成本函数似乎正在下降。我使用的是批处理梯度下降,所有这些都是使用向量完成的(每个训练示例都没有循环)。
#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
所以我的问题是,我的背传播有什么明显的问题吗?还是梯度检查?当人工神经网络显示这些症状时,有没有常见的问题(输出结果大致相同/成本正在下降)?
发布于 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函数和其他更复杂的任务。
这一过程似乎很费时,但最终几乎都会导致神经网络的工作。
https://stackoverflow.com/questions/27640496
复制相似问题