2014-12-18 5 views
5

나는 잠시 동안 내 머리를 두들겨 봤는데, 무엇을 잘못했는지 알아낼 수 없다. RNN. 여러분에게 앞으로의 단계를 보완하기 위해 두 구현이 동일한 출력을 계산하므로 앞으로 단계가 정확하다고 말할 수 있습니다. 문제는 뒤로 단계입니다.순수 python RNN 및 theano RNN 다른 그라디언트 컴퓨팅 - 코드 및 결과 제공

여기 내 파이썬 백 워드 코드입니다. . 아주 밀접하지만 정확히 karpathy의 neuraltalk의 스타일 다음 : 나는 그래서 내 순수 파이썬 RNN의 무작위 무게에 가중치를 초기화

def backward(self, cache, target,c=leastsquares_cost, dc=leastsquares_dcost): 
     ''' 
     cache is from forward pass 

     c is a cost function 
     dc is a function used as dc(output, target) which gives the gradient dc/doutput 
     ''' 
     XdotW = cache['XdotW'] #num_time_steps x hidden_size 
     Hin = cache['Hin'] # num_time_steps x hidden_size 
     T = Hin.shape[0] 
     Hout = cache['Hout'] 
     Xin = cache['Xin'] 
     Xout = cache['Xout'] 

     Oin = cache['Oin'] # num_time_steps x output_size 
     Oout=cache['Oout'] 

     dcdOin = dc(Oout, target) # this will be num_time_steps x num_outputs. these are dc/dO_j 


     dcdWho = np.dot(Hout.transpose(), dcdOin) # this is the sum of outer products for all time 

     # bias term is added at the end with coefficient 1 hence the dot product is just the sum 
     dcdbho = np.sum(dcdOin, axis=0, keepdims=True) #this sums all the time steps 

     dcdHout = np.dot(dcdOin, self.Who.transpose()) #reflects dcdHout_ij should be the dot product of dcdoin and the i'th row of Who; this is only for the outputs 
     # now go back in time 
     dcdHin = np.zeros(dcdHout.shape) 
     # for t=T we can ignore the other term (error from the next timestep). self.df is derivative of activation function (here, tanh): 
     dcdHin[T-1] = self.df(Hin[T-1]) * dcdHout[T-1] # because we don't need to worry about the next timestep, dcdHout is already corrent for t=T 

     for t in reversed(xrange(T-1)): 
      # we need to add to dcdHout[t] the error from the next timestep 
      dcdHout[t] += np.dot(dcdHin[t], self.Whh.transpose()) 
      # now we have the correct form for dcdHout[t] 
      dcdHin[t] = self.df(Hin[t]) * dcdHout[t] 
     # now we've gone through all t, and we can continue 
     dcdWhh = np.zeros(self.Whh.shape) 
     for t in range(T-1): #skip T bc dHdin[T+1] doesn't exist 
      dcdWhh += np.outer(Hout[t], dcdHin[t+1]) 
     # and we can do bias as well 
     dcdbhh = np.sum(dcdHin,axis=0, keepdims=True) 


     # now we need to go back to the embeddings 
     dcdWxh = np.dot(Xout.transpose(), dcdHin) 

     return {'dcdOout': dcdOout, 'dcdWxh': dcdWxh, 'dcdWhh': dcdWhh, 'dcdWho': dcdWho, 'dcdbhh': dcdbhh, 'dcdbho': dcdbho, 'cost':c(Oout, target)} 

을 그리고 여기에 주로 나는 온라인으로 볼 다른 구현에서 복사 theano 코드 (의 모든 같은 것입니다.) :

# input (where first dimension is time) 
u = TT.matrix() 
# target (where first dimension is time) 
t = TT.matrix() 
# initial hidden state of the RNN 
h0 = TT.vector() 
# learning rate 
lr = TT.scalar() 
# recurrent weights as a shared variable 
W = theano.shared(rnn.Whh) 
# input to hidden layer weights 
W_in = theano.shared(rnn.Wxh) 
# hidden to output layer weights 
W_out = theano.shared(rnn.Who) 

# bias 1 
b_h = theano.shared(rnn.bhh[0]) 
# bias 2 
b_o = theano.shared(rnn.bho[0]) 


# recurrent function (using tanh activation function) and linear output 
# activation function 
def step(u_t, h_tm1, W, W_in, W_out): 
    h_t = TT.tanh(TT.dot(u_t, W_in) + TT.dot(h_tm1, W) + b_h) 
    y_t = TT.dot(h_t, W_out) + b_o 
    return h_t, y_t 

# the hidden state `h` for the entire sequence, and the output for the 
# entrie sequence `y` (first dimension is always time) 
[h, y], _ = theano.scan(step, 
         sequences=u, 
         outputs_info=[h0, None], 
         non_sequences=[W, W_in, W_out]) 
# error between output and target 
error = (.5*(y - t) ** 2).sum() 
# gradients on the weights using BPTT 
gW, gW_in, gW_out, gb_h, gb_o = TT.grad(error, [W, W_in, W_out, b_h, b_o]) 
# training function, that computes the error and updates the weights using 
# SGD. 

여기에 미친 문제가 있습니다.

fn = theano.function([h0, u, t, lr], 
        [error, y, h, gW, gW_in, gW_out, gb_h, gb_o], 
        updates={W: W - lr * gW, 
          W_in: W_in - lr * gW_in, 
          W_out: W_out - lr * gW_out}) 

er, yout, hout, gWhh, gWhx, gWho, gbh, gbo =fn(numpy.zeros((n,)), numpy.eye(5), numpy.eye(5),.01) 
cache = rnn.forward(np.eye(5)) 
bc = rnn.backward(cache, np.eye(5)) 

print "sum difference between gWho (theano) and bc['dcdWho'] (pure python):" 
print np.sum(gWho - bc['dcdWho']) 
print "sum differnce between gWhh(theano) and bc['dcdWho'] (pure python):" 
print np.sum(gWhh - bc['dcdWhh']) 
print "sum difference between gWhx (theano) and bc['dcdWxh'] (pure pyython):" 
print np.sum(gWhx - bc['dcdWxh']) 

print "sum different between the last row of gWhx (theano) and the last row of bc['dcdWxh'] (pure python):" 
print np.sum(gWhx[-1] - bc['dcdWxh'][-1]) 

내가 얻을 다음과 같은 출력 :

sum difference between gWho (theano) and bc['dcdWho'] (pure python): 
-4.59268040265e-16 
sum differnce between gWhh(theano) and bc['dcdWhh'] (pure python): 
0.120527063611 
sum difference between gWhx (theano) and bc['dcdWxh'] (pure pyython): 
-0.332613468652 
sum different between the last row of gWhx (theano) and the last row of bc['dcdWxh'] (pure python): 
4.33680868994e-18 

그래서, 숨겨진 레이어 및 출력 권리 사이의 가중치 행렬의 파생 상품을 받고 있어요,하지만 파생 상품 난 다음 실행하는 경우 가중치 행렬 숨김 -> 숨김 또는 입력 -> 숨김. 하지만이 미친 짓은 항상 가중치 행렬 입력의 마지막 행을 가져와 올바른 숨김을 얻는다는 것입니다. 이것은 나에게 광기입니다. 나는 여기서 무슨 일이 일어나는지 전혀 모른다. 가중치 행렬 입력 -> 숨김의 마지막 행은 마지막 시간 단계 또는 기타 항목과 일치하지 않습니다 (예를 들어, 마지막 시간 단계에 대해 파생 상품을 올바르게 계산하지만 시간을 올바르게 되풀이하지 않음). dcdWxh는 dcdWxh의 모든 시간 단계에 걸친 합계입니다 - 어떻게하면이 행의 올바른 행 하나를 얻을 수 있습니까?

아무도 도와 줄 수 있습니까? 나는 여기서 아이디어를 모두 잃어 버렸다.

답변

0

두 개의 행렬의 차이점의 포인트 별 절대 값 의 합계를 계산해야합니다. 평범한 합계는 특정 학습 과제 (제로 함수를 에뮬레이트합니까?) 중 어느 것이 든간에 때문에 0에 가까울 수 있습니다.

마지막 열은 뉴런 상수, 즉 바이어스에서 가중치를 구현하는 것으로 추정되므로 항상 바이어스를 올바르게 가져옵니다 (그러나 절대 값의 합계를 확인하십시오).

는 또한 행 메이저 행렬의 열 주요 표기가 "X 숨겨진에"반대의 "X에 숨겨진"중량 같이 판독

gWhx - bc['dcdWxh'] 

에서처럼 혼란 같다.

나는 이것을 코멘트로 게시하고 싶지만 그렇게하는 데는 명성이 부족합니다. 죄송합니다!