2015-10-30 2 views
1

Я пытаюсь реализовать этот документ: Deep Learning for Answer Sentence Selection и более точно модель Биграммные с помощью функции сканирования Theano как это:Theano: использовать IfElse для подавления оценки сканирования

Tl = theano.shared(...) 
Tr = theano.shared(...) 
b = theano.shared(...) 

s = T.matrix('s') 

results, updates = theano.scan(
     lambda t_0, t_p1, prior_result, Tl, Tr, b: prior_result + T.tanh(T.dot(Tl, t_0) + T.dot(Tr, t_m1) + b), 
     sequences = dict(input = s, taps = [0, 1]), 
     outputs_info = T.zeros_like(b, dtype = 'float64') 
     non_sequences = [Tl, Tr, b], 
     strict = True 
     ) 
final_result = ifelse(T.eq(s.shape[0],1), s[0], result[-1]) 

Моя проблема заключается в том, что ответы на некоторые вопросы только один word long, поэтому s - это вектор, а не матрица. Это вызывает проблему с функцией сканирования, так как отсутствует кратковременное нажатие клавиши. Для этого я хочу использовать оператор ifelse.

Теперь мой первый вопрос:

даже возможно ли это? Или сканирование всегда будет оцениваться, и ifelse только решает, какое значение использовать?


второй вопрос:

как я могу сделать tensor.eq (а, б) возвращает скаляр? Потому что я получаю следующее сообщение об ошибке:

TypeError: Condition given to the op has to be a scalar with 0 standing for False, anything else for True


EDIT некоторый код, который вызывает ошибку индекса, поскольку IfElse не будет ленивой вычисляется, если Theano вычисляет градиенты

import numpy as np 

import theano 
import theano.tensor as T 

from theano.ifelse import ifelse 

def trainBigram(q, a, y, seed = 8024, lRate = 0.1, maxEpochs = 1, 
    modelSize = 3): 

    # q: list (all questions) of lists(words per question) of list (values of word embedding) 
    # a: list (all questions) of lists(1 possible answers) of lists(words per possible answer) of list (values of word embedding) 
    # y: list (all questions) of list (correctness of answer) 

    # trains on triplets of(q(i), a(i,j), y(i,j)) instead of softmaxing all 4 answer possibilities 
    # uses SGD 

    np.random.seed(seed) 

    # theano variables 
    q_t = T.matrix('q_t') 
    a_t = T.matrix('a_t') 
    y_t = T.scalar('y_t') 

    # initialize weights (distribution from paper) 
    M = theano.shared(np.random.normal(0,0.01,(modelSize,modelSize))) 
    bm = theano.shared(np.random.normal(0,0.01,1)) 

    Tl = theano.shared(np.random.normal(0,0.01,(modelSize,modelSize))) 
    Tr = theano.shared(np.random.normal(0,0.01,(modelSize,modelSize))) 
    bt = theano.shared(np.random.normal(0,0.01,modelSize)) 


    # define graph for Bigram Model 
    q_em_scan, scanUpdatesQ = theano.scan(
        lambda t_0, t_p1, prior_result, Tl, Tr, bt: prior_result + T.tanh(T.dot(Tl, t_0) + T.dot(Tr, t_p1) + bt), 
        sequences = dict(input = q_t, taps = [0, 1]), 
        outputs_info = T.zeros_like(bt, dtype = 'float64'), 
        non_sequences = [Tl, Tr, bt], 
        strict = True 
    ) 
    q_em = q_em_scan[-1] 

    a_em_scan, scanUpdatesA = theano.scan(
        lambda t_0, t_p1, prior_result, Tl, Tr, bt: prior_result + T.tanh(T.dot(Tl, t_0) + T.dot(Tr, t_p1) + bt), 
        sequences = dict(input = a_t, taps = [0, 1]), 
        outputs_info = T.zeros_like(bt, dtype = 'float64'), 
        non_sequences = [Tl, Tr, bt], 
        strict = True 
    ) 

    # printing calculated values to check for lazy evaluation of ifelse 
    MultipleWords= theano.printing.Print('multiple Words answer')(a_em_scan[-1]) 
    OneWord = theano.printing.Print('1 Word answer')(a_t[0]) 
    a_em = ifelse(T.eq(a_t.shape[0], 1), OneWord, MultipleWords) 

    # define graph for Question/Answer model 
    prob = 1/(1 + T.exp(- T.dot(T.dot(M, a_em), q_em) + bm)) 
    xent = - y_t * T.log(prob) - (1 - y_t) * T.log((1 - prob)) 
    loss = xent.sum() 

    g_M,g_bm, g_Tl, g_Tr, g_bt = T.grad(loss, [M, bm, Tl, Tr, bt]) 


    updates = (
      (M, M - lRate * g_M), 
      (bm, bm - lRate * g_bm), 
      (Tl, Tl - lRate * g_Tl), 
      (Tr, Tr - lRate * g_Tr), 
      (bt, bt - lRate * g_bt) 
    ) 

    # compile function 
    train = theano.function(
     inputs = [q_t, a_t, y_t], 
     outputs = prob, 
     updates = updates 
    ) 

    # training 
    for question, answers, labels in zip(q,a,y): 


     # for triplets instead of softmax 
     for answer, label in zip(answers, labels): 

      answer = np.asarray(answer) 

      if (answer.shape[0] == 1): 
       print "!!! One-Word-Answer !!!" 
       print "shape:", answer.shape 

      prob = train(question, answer, label) 
      print prob 




def main(): 

    questionOne = [[1,2,3],[1,2,3]] 
    answerOne_One = [[1,2,3], [1,2,3]] 
    answerOne_Two = [[1,2,3], [1,2,3]] 
    answersOne = [answerOne_One, answerOne_Two] 
    correctnessOne = [0,1] 

    questionTwo = [[4,5,6],[4,5,6]] 
    answerTwo_One = [[4,5,6]] 
    answerTwo_Two = [[4,5,6]] 
    answersTwo = [answerTwo_One, answerTwo_Two] 
    correctnessTwo = [1,0] 

    q = [questionOne, questionTwo] 
    a = [answersOne, answersTwo] 
    y = [correctnessOne, correctnessTwo] 

    trainBigram(q,a,y) 

main() 

ответ

1

я сделал поверхностные изменения к вашему коду, чтобы сделать исполняемый файл, но он действительно работает, а ifelse- ленивый (то есть он только вычисляет сканирование при необходимости). Чтобы продемонстрировать, я добавил некоторые символические операторы печати, которые показывают, какое значение (ы) вычисляется.

Tl = theano.shared(numpy.random.randn(2, 3).astype(theano.config.floatX)) 
Tr = theano.shared(numpy.random.randn(2, 3).astype(theano.config.floatX)) 
b = theano.shared(numpy.zeros((2,), dtype=theano.config.floatX)) 

s = tt.matrix('s') 

results, updates = theano.scan(
    lambda t_0, t_p1, prior_result, Tl, Tr, b: prior_result + tt.tanh(tt.dot(Tl, t_0) + tt.dot(Tr, t_p1) + b), 
    sequences=dict(input=s, taps=[0, 1]), 
    outputs_info=tt.zeros_like(b, dtype='float64'), 
    non_sequences=[Tl, Tr, b], 
    strict=True 
) 

true_value = theano.printing.Print('true')(s[0]) 
false_value = theano.printing.Print('false')(results[-1]) 
final_result = theano.ifelse.ifelse(tt.eq(s.shape[0], 1), true_value, false_value) 
f = theano.function(inputs=[s], outputs=final_result) 
print 'a ', f([[1, 2, 3], [4, 5, 6]]) 
print 'b ', f([[1, 2, 3]]) 
+0

спасибо, мой пример игрушки работает и сейчас. Я понятия не имею, что я сделал, что вызвало TypeError. Но это не работает в моей реальной реализации, где сканирование кажется оцененным, даже если ввод имеет форму (1, modelSize), я попробую еще дольше, и если я не найду ошибку, отправьте этот код а также – user3688217

+0

странно, что когда я добавляю в свой код заявления печати, он выводит только ложные значения для длинных ответов (-> lazy), но когда я сталкиваюсь с первым входом с размерами (1, modelSize), он все еще дает мне ошибку: _IndexError: сканирование было запрошено для отрицательного числа шагов -1_ – user3688217

+0

Я добавил код, который запускает индекс Error. Ошибка не срабатывает, когда я только предсказываю ответ, поэтому проблема лежит где-то в градиентах или правилах обновления SGD – user3688217

Смежные вопросы