2016-07-16 6 views
0

저는 Keras (Theano 백엔드)를 사용하여 chacter 기반 rnn 모델을 구축하고 있습니다. 한 가지 유의할 것은 미리 작성된 손실 함수를 사용하고 싶지 않다는 것입니다. 대신 일부 데이터 포인트의 손실을 계산하려고합니다. 여기에 의미하는 바가 있습니다.Theano의 슬라이스 3-d 텐서

벡터화 된 학습 세트 및 그 레이블은 다음과 같습니다. X_train = np.array ([[0,1,2,3,4]] y_train = np.array ([[1,2,3, 4,5]])

하지만 y_train의 첫 번째 k 요소를 어떤 이유로 든 0으로 대체했습니다. 따라서, 예를 들어, 새로운 y_train는

y_train np.array = ([0,0,3,4,5])

I 0 처음 두 요소를 설정하는 이유는 I이다 돈 손실을 계산할 때 이들을 포함하고 싶지 않습니다. 즉, X_train [2 :]과 y_train [2 :] 사이의 손실을 계산하려고합니다.

여기 내 시도입니다. 라인 35에서 잘못된 paranthesis 마지막 줄에 잘못된 변수 이름과 같은 사소한 오류에서

import numpy as np 
np.random.seed(0) # for reproducibility 

from keras.preprocessing import sequence 
from keras.utils import np_utils 
from keras.models import Sequential 
from keras.layers import Dense, Dropout, Activation, Embedding 
from keras.layers import LSTM 
from keras.layers.wrappers import TimeDistributed 

X_train = np.array([[0,1,2,3,4]]) 
y_train = np.array([[0,0,3,4,5]]) 

y_3d = np.zeros((y_train.shape[0], y_train.shape[1], 6)) 
for i in range(y_train.shape[0]): 
    for j in range(y_train.shape[1]): 
     y_3d[i, j, y_train[i,j]] = 1 

model = Sequential() 
model.add(Embedding(6, 5, input_length=5, dropout=0.2)) 
model.add(LSTM(5, input_shape=(5, 12), return_sequences=True) ) 

model.add(TimeDistributed(Dense(6))) #output classes =6 
model.add(Activation('softmax')) 

from keras import backend as K 
import theano.tensor as T 
def custom_objective(y_true,y_pred): 
    # Find the last index of minimum value in y_true, axis=-1 
    # For example, y_train = np.array([[0,0,3,4,5]]) in my example, and 
    # I'd like to calculate the loss only between X_train[3:] and  y_train[3:] because the values 
    # in y_train[:3] (i.e.0) are dummies. The following is pseudo code if y_true is 1-d numpy array, which is not true. 
    def rindex(y_true): 
     for i in range(len(y_true), -1, -1): 
      if y_true(i) == 0: 
       return i 
    starting_point = rindex(y_true) 
    return K.categorical_crossentropy(y_pred[starting_point:], y_true[starting_point:]) 


model.compile(loss=custom_objective, 
       optimizer='adam', 
       metrics=['accuracy']) 

model.fit(X_train, y_t, batch_size=batch_size, nb_epoch=1) 
+0

그리고 문제의 원인을 설명해 주시겠습니까? – malioboro

+0

함수 "custom_objective"가 작동하지 않습니다. – user1610952

답변

0

아파트, 코드 두 가지 문제가있다.

먼저 정의한 모델은 각 타임 스텝에서 클래스에 대한 확률 분포 행렬을 반환합니다 (softmax 활성화로 인해). 그러나 custom_objective에서 출력을 벡터로 처리합니다. 이미 y_train을 위의 행렬로 올바르게 변환하고 있습니다.

그래서 먼저 실제 예측, 가장 간단한 경우는 확률이 가장 높은 클래스를 할당됩니다를 얻을 수있을 것입니다 즉 :

y_pred = y_pred.argmax(axis=2) 
y_true = y_true.argmax(axis=2) # this reconstructs y_train resp. a subset thereof 

두 번째 문제는 당신이 실제 변수처럼이 치료된다는 것입니다 (numpy 배열). 그러나 y_truey_pred은 상징적 인 텐서입니다. 당신이 명확하게 얻을 오류가 발생하는 문제 중 하나가 상태 :

TypeError: object of type 'TensorVariable' has no len() 

TensorVariable의 실제 값을 삽입하기 전에 간단하게 알려져 있지 않다으로, 더 길이가 없습니다! 이렇게하면 불가능한 방식으로 반복을 반복합니다. 그런데 , 당신이 진짜 벡터를 반복하는 경우에 당신이 이런 식으로 그것을 뒤로 반복 작업을 수행 할 수 있습니다 : 경계 밖으로 이동하지 range(len(y_true)-1, -1, -1), 또는 for val in y_true[::-1]

당신이 원하는 것을 달성하기 위해, 당신은 대응을 치료하는 데 필요 변수를 그대로 사용하고 텐서에 대해 제공된 메소드를 사용합니다.

이 계산의 중심은 최소값을 찾는 argmin 함수입니다. 기본적으로이 최소값의 첫 번째 항목을 반환합니다. 이 최소값의 마지막 발생을 찾으려면이를 역 테너에 적용하고 원본 벡터에 대한 인덱스로 다시 계산해야합니다.

starting_point = y_true.shape[0] - y_true[::-1].argmin() - 1 

아마도 마스킹과 같은 것을 구현하려고하는 것처럼 보이는 것처럼 문제가 훨씬 간단 할 수도 있습니다. 레이어 삽입에 mask_zero=True 플래그를 사용하는 것이 좋습니다. 하지만 이것은 입력측에서 작동 할 것입니다.

관련 문제