Как применить разные функции стоимости к разным выходным каналам сверточной сети?

У меня есть сверточная нейронная сеть, выход которой представляет собой 4-канальное 2D-изображение. Я хочу применить сигмовидную функцию активации к первым двум каналам, а затем использовать BCECriterion для вычисления потери полученных изображений с исходными изображениями. Я хочу применить функцию квадратичных потерь к последним двум каналам и, наконец, вычислить градиенты и выполнить обратное распространение. Я также хотел бы умножить стоимость квадрата потерь для каждого из двух последних каналов на желаемый скаляр.

Таким образом, стоимость имеет следующий вид:

cost = crossEntropyCh[{1, 2}] + l1 * squaredLossCh_3 + l2 * squaredLossCh_4

Я думаю об этом следующим образом:

criterion1 = nn.BCECriterion()
criterion2 = nn.MSECriterion()

error = criterion1:forward(model.output[{{}, {1, 2}}], groundTruth1) + l1 * criterion2:forward(model.output[{{}, {3}}], groundTruth2) + l2 * criterion2:forward(model.output[{{}, {4}}], groundTruth3)

Однако я не думаю, что это правильный способ сделать это, поскольку мне придется выполнить 3 отдельных шага обратного распространения, по одному для каждого условия стоимости. Поэтому мне интересно, может ли кто-нибудь дать мне лучшее решение для этого в Torch?


person Amir    schedule 25.05.2016    source источник


Ответы (1)


SplitTable и ParallelCriterion может помочь в решении вашей проблемы.

За вашим текущим выходным слоем следует nn.SplitTable, который разделяет ваши выходные каналы и преобразует ваш выходной тензор в таблицу. Вы также можете комбинировать различные функции, используя ParallelCriterion, чтобы каждый критерий применялся к соответствующей записи выходной таблицы.

Для получения подробной информации я предлагаю вам прочитать документацию Torch о таблицах.

После комментариев я добавил следующий сегмент кода, решающий исходный вопрос.

M = 100
C = 4
H = 64
W = 64
dataIn = torch.rand(M, C, H, W)

layerOfTables = nn.Sequential()
-- Because SplitTable discards the dimension it is applied on, we insert
-- an additional dimension.
layerOfTables:add(nn.Reshape(M,C,1,H,W))
-- We want to split over the second dimension (i.e. channels).
layerOfTables:add(nn.SplitTable(2, 5))

-- We use ConcatTable in order to create paths accessing to the data for 
-- numereous number of criterions. Each branch from the ConcatTable will 
-- have access to the data (i.e. the output table).
criterionPath = nn.ConcatTable()
-- Starting from offset 1, NarrowTable will select 2 elements. Since you 
-- want to use this portion as a 2 dimensional channel, we need to combine
-- then by using JoinTable. Without JoinTable, the output will be again a 
-- table with 2 elements. 
criterionPath:add(nn.Sequential():add(nn.NarrowTable(1, 2)):add(nn.JoinTable(2)))
-- SelectTable is simplified version of NarrowTable, and it fetches the desired element.
criterionPath:add(nn.SelectTable(3))
criterionPath:add(nn.SelectTable(4))

layerOfTables:add(criterionPath)

-- Here goes the criterion container. You can use this as if it is a regular
-- criterion function (Please see the examples on documentation page).
criterionContainer = nn.ParallelCriterion()
criterionContainer:add(nn.BCECriterion())
criterionContainer:add(nn.MSECriterion())
criterionContainer:add(nn.MSECriterion())

Поскольку я использовал почти все возможные табличные операции, это выглядит немного противно. Однако это единственный способ решить эту проблему. Я надеюсь, что это поможет вам и другим людям, страдающим от той же проблемы. Вот как выглядит результат:

dataOut = layerOfTables:forward(dataIn)
print(dataOut)
{
  1 : DoubleTensor - size: 100x2x64x64
  2 : DoubleTensor - size: 100x1x64x64
  3 : DoubleTensor - size: 100x1x64x64
}
person eaksan    schedule 26.05.2016
comment
Я не думаю, что это способ сделать это. Когда я добавляю nn.SplitTable(2) в свой вывод, он дает мне таблицу с 4 элементами. Каждый элемент содержит 2D-изображение. Однако я хочу применить функцию стоимости к первым двум элементам таблицы, другую функцию стоимости к 3-му каналу и другую функцию стоимости к последнему. Как бы вы это реализовали? - person Amir; 28.05.2016
comment
Давайте немного упростим задачу: предположим, у меня есть сеть сверточных декодеров, которая выдает тензор размером [M x C x H x W], где M — размер пакета, C — количество каналов (кратное 2). ) и H = W — целое число. Я хочу разделить вывод на таблицу с двумя элементами, каждый из которых имеет размер [M x C / 2 x H x W]. Я думаю, что это можно сделать с помощью nn.SplitTable(), но я не делал этого должным образом. После разделения тензоров я хотел бы применить к ним две функции стоимости (эта часть проста). Можете ли вы дать мне несколько советов? - person Amir; 29.05.2016