2017-02-02 7 views
1

최근에 신경망에 대해 배우기 시작했고 직접 만든 2 계층 ANN을 코딩하고 MNIST 데이터 세트를 사용하여 벤치마킹하기로 결정했습니다. 배치 크기가 사용자에 의해 제공되는 배치 SGD를 사용하여이를 프로그래밍하려고했습니다. 다음과 같이 내 코드는 다음과 같습니다 자기 코딩 2 레이어 인공 신경망 최적화

class NeuralNetwork: 
    def __init__(self, inodes, hnodes, outnodes, activation_func, learning_rate): 
     self.inodes = inodes 
     self.hnodes = hnodes 
     self.onodes = outnodes 
     self.activation_function = activation_func 
     self.lr = learning_rate 
     self.wih = np.random.randn(self.hnodes, self.inodes)/pow(self.inodes, 0.5) 
     self.who = np.random.randn(self.onodes, self.hnodes)/pow(self.hnodes, 0.5) 

    def train(self, training_data, target_labels, batch=1, l2_penalty=0, verbose=False): 
     batch_size = len(training_data)/batch 
     print "Starting to train........" 
     for i in range(batch): 
      train_data_batch = training_data[batch_size*i : batch_size*(i+1)] 
      label_batch = target_labels[batch_size*i : batch_size*(i+1)] 
      batch_error = self.train_batch(train_data_batch, label_batch, l2_penalty) 
      if verbose: 
       print "Batch : " + str(i+1) + " ; Error : " + str(batch_error) 
     print "..........Finished!" 

    def train_batch(self, training_data, target_labels, l2_penalty=0): 
     train = np.array(training_data, ndmin=2).T 
     label = np.array(target_labels, ndmin=2).T 

     inputs = train # IxN 
     hidden_input = np.dot(self.wih, inputs) # (HxI).(IxN) = HxN 
     hidden_ouputs = self.activation_function(hidden_input) # (HxN) -> (HxN) 

     final_input = np.dot(self.who, hidden_ouputs) # (OxH).(HxN) -> OxN 
     final_outputs = self.activation_function(final_input) # OxN -> OxN 

     final_outputs = np.exp(final_outputs) # OxN 
     for f in range(len(final_outputs)): 
      final_outputs[f] = final_outputs[f]/sum(final_outputs[f]) 

     final_error_wrt_out = label - final_outputs # OxN 
     hidden_error_wrt_out = np.dot(self.who.T, final_outputs) # HxN 

     final_in_wrt_out = self.activation_function(final_input, der=True) # OxN 
     hidden_in_wrt_out = self.activation_function(hidden_input, der=True) # HxN 

     grad_who = np.dot(final_error_wrt_out * final_in_wrt_out, hidden_ouputs.T) # (OxN).(NxH) -> OxH 
     grad_wih = np.dot(hidden_error_wrt_out * hidden_in_wrt_out, inputs.T) # (HxN).(NxI) -> HxI 

     self.who = self.who - self.lr * (grad_who + l2_penalty*(self.who)) 
     self.wih = self.wih - self.lr * (grad_wih + l2_penalty*(self.wih)) 

     return np.sum(final_error_wrt_out * final_error_wrt_out)/(2*len(training_data)) 

    def query(self, inputs): 
     if len(inputs) != self.inodes: 
      print "Invalid input size" 
      return 
     inputs = np.array(inputs) 
     hidden_input = np.dot(self.wih, inputs) 
     hidden_ouputs = self.activation_function(hidden_input) 

     final_input = np.dot(self.who, hidden_ouputs) 
     final_outputs = self.activation_function(final_input) 

     final_outputs = np.exp(final_outputs) 
     total = sum(final_outputs) 
     probs = final_outputs/total 

     return probs 

내가 약 95 %의 정확도를 제공 github에 타리크 라시드에 의해 유사한 코드를 발견했다. 반면에 내 코드는 10 % 만주고있다.

Backpropogation에 대한 다양한 자습서를 참조하면서 코드를 여러 번 디버깅하려고했지만 내 정확성을 향상시킬 수 없었습니다. 이 문제에 대한 통찰력에 감사드립니다.

편집 1 : 이것은 mattdeak의 답을 따릅니다.

이전에 softmax 레이어에 대해 음수 로그 가능성 오류 대신 내 MSE를 사용했습니다. 이는 내 부분의 오류입니다. 대답에 따라 나는 다음과 같이 열차 기능을 변경했다. 그러나 이것은 성능 향상을 가져 오지 못했다.

+0

내가 궁극적으로 np.exp를하고있는 중이 야 (final_outputs) /np.sum : 내가 잘못 본게 아니라면 , 나는이 softmax의 기울기가 단순히 같이 계산 될 수 있다고 생각 (np.exp (final_outputs)). 이 결과는 final_outputs = np.exp (final_outputs) 바로 다음에 'for'루프를 사용하여 'probs'변수에 저장됩니다. 프로그램을 더 잘 디버깅하는 데 도움이되므로 여러 줄에 걸쳐이 작업을 수행하는 것이 더 쉬웠다 고 생각했습니다. – Chaitanya

답변

1

나는 당신이 기차 단계에서 softmax 레이어를 통해 역 전파하지 않는다고 생각합니다.

grad_softmax = final_outputs - 1 
이 softmax를 회귀가 참으로 @mattdeak