Уровень InfogainLoss
Я хочу использовать в моей модели слой потерь InfogainLoss
. Но у меня возникают трудности с его определением.
-
Есть ли какой-нибудь учебник/пример использования слоя INFOGAIN_LOSS
?
-
Должен ли вход этого уровня, вероятности класса, быть выходным слоем SOFTMAX
, или достаточно ввести "верх" полностью связанного слоя?
INFOGAIN_LOSS
требуется три входа: вероятности класса, метки и матрица H
.
Матрица H
может быть предоставлена либо как параметры слоя infogain_loss_param { source: "fiename" }
.
Предположим, что у меня есть python script, который вычисляет H
как numpy.array
формы (L,L)
с dtype='f4'
(где L
- количество меток в моей модели).
-
Как преобразовать мой numpy.array
в файл binproto
, который может быть представлен как infogain_loss_param { source }
для модели?
-
Предположим, что я хочу, чтобы H
предоставлялся как третий вход (внизу) на уровень потерь (а не как параметр модели). Как я могу это сделать?
Определить ли я новый уровень данных, который "сверху" H
? Если это так, не будут ли увеличиваться данные этого уровня на каждой обучающей итерации, например, данные обучения будут увеличиваться?
Как я могу определить несколько несвязанных входных "данных" слоев, и как известно, что caffe читает из уровня подготовки/тестирования "данных" после партии, тогда как из уровня данных H
он знает, что читает только один раз для всех учебный процесс?
Ответы
Ответ 1
У меня до сих пор нет полного ответа на мой вопрос. Этот ответ охватывает только мою третью и четвертую части:
3. Как я могу преобразовать numpy.array в файл binproto:
В питоне
H = np.eye( L, dtype = 'f4' )
import caffe
blob = caffe.io.array_to_blobproto( H.reshape( (1,1,L,L) ) )
with open( 'infogainH.binaryproto', 'wb' ) as f :
f.write( blob.SerializeToString() )
Теперь вы можете добавить к прототипу INFOGAIN_LOSS
слой INFOGAIN_LOSS
с H
в качестве параметра:
layer {
bottom: "topOfPrevLayer"
bottom: "label"
top: "infoGainLoss"
name: "infoGainLoss"
type: "InfogainLoss"
infogain_loss_param {
source: "infogainH.binaryproto"
}
}
4. Как загрузить H
как часть слоя DATA
Цитирую сообщение Эвана Шелхамера:
В настоящее время нет способа заставить слои данных загружать ввод с различной скоростью. Каждый проход вперед все слои данных будут продвигаться. Тем не менее, постоянный ввод H может быть сделан путем создания входного файла lmdb/leveldb/hdf5, который является только H, так как слой данных будет зацикливаться и продолжать загружать тот же H. Это, очевидно, приводит к бесполезному использованию дискового ввода-вывода.
Что касается первых двух частей моего вопроса:
1. Есть ли урок/пример по использованию слоя InfogainLoss?:
Хороший пример можно найти здесь: использование InfogainLoss для устранения дисбаланса классов.
2. Должны ли входные данные этого слоя, вероятности класса, быть выходными данными слоя Softmax?
Исторически ответ был ДА в соответствии с ответом Яир. Старая реализация "InfogainLoss"
должна была быть выходом слоя "Softmax"
или любого другого слоя, который гарантирует, что входные значения находятся в диапазоне [0..1].
ОП заметила, что использование "InfogainLoss"
поверх слоя "Softmax"
может привести к численной нестабильности. Его запрос на извлечение, объединяющий эти два слоя в один (очень похожий на слой "SoftmaxWithLoss"
), был принят и объединен в официальные репозитории Caffe 14/04/2017. Математика этого комбинированного слоя дана здесь.
Модернизированный слой "внешний вид и стиль" точно такой же, как и старый, за исключением того факта, что больше не нужно явно передавать входные данные через слой "Softmax"
.
Ответ 2
Слой суммируется
-log(p_i)
и поэтому p_i должно быть в (0, 1), чтобы иметь смысл в качестве функции потерь (иначе более высокие оценки доверия приведут к более высоким потерям). См. кривую ниже для значений log (p).
![enter image description here]()
Я не думаю, что они должны суммировать до 1, но передача их через слой Softmax обеспечит оба свойства.
Ответ 3
Так как мне пришлось искать по многим веб-сайтам, чтобы разгадать весь код, я решил поделиться своей реализацией:
Уровень Python для вычисления H-матрицы с весами для каждого класса:
import numpy as np
import caffe
class ComputeH(caffe.Layer):
def __init__(self, p_object, *args, **kwargs):
super(ComputeH, self).__init__(p_object, *args, **kwargs)
self.n_classes = -1
def setup(self, bottom, top):
if len(bottom) != 1:
raise Exception("Need (only) one input to compute H matrix.")
params = eval(self.param_str)
if 'n_classes' in params:
self.n_classes = int(params['n_classes'])
else:
raise Exception('The number of classes (n_classes) must be specified.')
def reshape(self, bottom, top):
top[0].reshape(1, 1, self.n_classes, self.n_classes)
def forward(self, bottom, top):
classes, cls_num = np.unique(bottom[0].data, return_counts=True)
if np.size(classes) != self.n_classes or self.n_classes == -1:
raise Exception("Invalid number of classes")
cls_num = cls_num.astype(float)
cls_num = cls_num.max() / cls_num
weights = cls_num / np.sum(cls_num)
top[0].data[...] = np.diag(weights)
def backward(self, top, propagate_down, bottom):
pass
и соответствующая часть из train_val.prototxt:
layer {
name: "computeH"
bottom: "label"
top: "H"
type: "Python"
python_param {
module: "digits_python_layers"
layer: "ComputeH"
param_str: '{"n_classes": 7}'
}
exclude { stage: "deploy" }
}
layer {
name: "loss"
type: "InfogainLoss"
bottom: "score"
bottom: "label"
bottom: "H"
top: "loss"
infogain_loss_param {
axis: 1 # compute loss and probability along axis
}
loss_param {
normalization: 0
}
exclude {
stage: "deploy"
}
}