Факел: обратное распространение от потерь, рассчитанных по подмножеству выходных данных

У меня есть простая сверточная нейронная сеть, чья продукция представляет собой карту каналов 4х4 с одним каналом. Во время обучения потери (регрессии) необходимо рассчитывать только по одному значению из 16 выходных данных. Расположение этого значения будет определено после прямого прохода. Как рассчитать потери только из одного этого выхода, убедившись, что все нерелевантные градиенты обнуляются во время обратного пропора?

Допустим, у меня есть следующая простая модель в факеле:

require 'nn'

-- the input
local batch_sz = 2
local x = torch.Tensor(batch_sz, 3, 100, 100):uniform(-1,1)

-- the model
local net = nn.Sequential()
net:add(nn.SpatialConvolution(3, 128, 9, 9, 9, 9, 1, 1))
net:add(nn.SpatialConvolution(128, 1, 3, 3, 3, 3, 1, 1))
net:add(nn.Squeeze(1, 3))

print(net)

-- the loss (don't know how to employ it yet)
local loss = nn.SmoothL1Criterion()

-- forward'ing x through the network would result in a 2x4x4 output
y = net:forward(x)

print(y)

Я посмотрел на nn.SelectTable, и кажется, что если я преобразовать вывод в табличную форму, я смог бы реализовать то, что я хочу?

1 ответ

Это мое текущее решение. Он работает, разбивая вывод в таблицу, а затем используя nn.SelectTable():backward(), чтобы получить полный градиент:

require 'nn'

-- the input
local batch_sz = 2
local x = torch.Tensor(batch_sz, 3, 100, 100):uniform(-1,1)

-- the model
local net = nn.Sequential()
net:add(nn.SpatialConvolution(3, 128, 9, 9, 9, 9, 1, 1))
net:add(nn.SpatialConvolution(128, 1, 3, 3, 3, 3, 1, 1))
net:add(nn.Squeeze(1, 3))

-- convert output into a table format
net:add(nn.View(1, -1))         -- vectorize
net:add(nn.SplitTable(1, 1))    -- split all outputs into table elements

print(net)

-- the loss
local loss = nn.SmoothL1Criterion()

-- forward'ing x through the network would result in a (2)x4x4 output
y = net:forward(x)

print(y)

-- returns the output table's index belonging to specific location
function get_sample_idx(feat_h, feat_w, smpl_idx, feat_r, feat_c)
    local idx = (smpl_idx - 1) * feat_h * feat_w
    return idx + feat_c + ((feat_r - 1) * feat_w)
end

-- I want to back-propagate the loss of this sample at this feature location
local smpl_idx = 2
local feat_r = 3
local feat_c = 4
-- get the actual index location in the output table (for a 4x4 output feature map)
local out_idx = get_sample_idx(4, 4, smpl_idx, feat_r, feat_c)

-- the (fake) ground-truth
local gt = torch.rand(1)

-- compute loss on the selected feature map location for the selected sample
local err = loss:forward(y[out_idx], gt)
-- compute loss gradient, as if there was only this one location
local dE_dy = loss:backward(y[out_idx], gt)
-- now convert into full loss gradient (zero'ing out irrelevant losses)
local full_dE_dy = nn.SelectTable(out_idx):backward(y, dE_dy)
-- do back-prop through who network
net:backward(x, full_dE_dy)

print("The full dE/dy")
print(table.unpack(full_dE_dy))

Я был бы очень признателен, если бы кто-нибудь указал на более простой ИЛИ более эффективный метод.

Другие вопросы по тегам