2015-11-05 3 views
0

У меня есть график следующим образом, где вход x имеет два пути для достижения y. Они объединены с gModule, который использует cMulTable. Теперь, если я делаю gModule: назад (x, y), я получаю таблицу из двух значений. Соответствуют ли они производной ошибки, полученной из двух путей? enter image description hereфакел назад через gModule

Но так как path2 содержит другие nn-слои, я полагаю, что мне нужно выводить производные по этому пути поэтапно. Но почему я получил таблицу из двух значений для dy/dx?

Для того, чтобы прояснить ситуацию, код, чтобы проверить это следующим образом:

input1 = nn.Identity()() 
input2 = nn.Identity()() 
score = nn.CAddTable()({nn.Linear(3, 5)(input1),nn.Linear(3, 5)(input2)}) 
g = nn.gModule({input1, input2}, {score}) #gModule 

mlp = nn.Linear(3,3) #path2 layer 

x = torch.rand(3,3) 
x_p = mlp:forward(x) 
result = g:forward({x,x_p}) 
error = torch.rand(result:size()) 
gradient1 = g:backward(x, error) #this is a table of 2 tensors 
gradient2 = g:backward(x_p, error) #this is also a table of 2 tensors 

Так что случилось с моими шагами?

P.S, возможно, я выяснил причину, потому что g: назад ({x, x_p}, ошибка) приводит к той же таблице. Поэтому я думаю, что эти два значения означают dy/dx и dy/dx_p соответственно.

ответ

1

Я думаю, вы просто сделали ошибку, построив свой gModule. gradInput каждого nn.Module должен иметь ту же структуру, что и ее input - так работает backprop.

Вот пример того, как создать модуль, как у вас с помощью nngraph:

require 'torch' 
require 'nn' 
require 'nngraph' 

function CreateModule(input_size) 
    local input = nn.Identity()() -- network input 

    local nn_module_1 = nn.Linear(input_size, 100)(input) 
    local nn_module_2 = nn.Linear(100, input_size)(nn_module_1) 

    local output = nn.CMulTable()({input, nn_module_2}) 

    -- pack a graph into a convenient module with standard API (:forward(), :backward()) 
    return nn.gModule({input}, {output}) 
end 


input = torch.rand(30) 

my_module = CreateModule(input:size(1)) 

output = my_module:forward(input) 
criterion_err = torch.rand(output:size()) 

gradInput = my_module:backward(input, criterion_err) 
print(gradInput) 

UPDATE

Как я уже говорил, gradInput каждого nn.Module должен иметь точно такую ​​же структуру, как и его input. Итак, если вы определяете свой модуль как nn.gModule({input1, input2}, {score}), то ваш gradOutput (результат обратного прохода) будет представлять собой таблицу градиентов w.r.t. input1 и input2 которые в вашем случае являются x и x_p.

Единственный вопрос остается: почему на Земле вы не получите сообщение об ошибке, когда вызов:

gradient1 = g:backward(x, error) 
gradient2 = g:backward(x_p, error) 

должно быть поднято исключение, потому что первый аргумент должен быть не тензором, а таблица двух тензоров. Наилучшим образом, большинство (возможно, все) модулей факела при вычислении :backward(input, gradOutput) не используют аргумент input (они обычно хранят копию input с последнего вызова :forward(input)). На самом деле, этот аргумент настолько бесполезен, что модули даже не утруждают себя проверкой.

+0

Привет, Алекс, спасибо за ваш ответ. Вместо того, чтобы использовать один вход x, я создал gModule с двумя входами a и b, а значение b зависит от a. Я сделал это таким образом, потому что слой nn более сложный, чем линейное преобразование. Он имеет структуру LSTM. –

+1

Я также включил мое моделирование кода, пожалуйста, проверьте его @ Александр Луценко –

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