Подтвердить что ты не робот

Уровень InfogainLoss

Я хочу использовать в моей модели слой потерь InfogainLoss. Но у меня возникают трудности с его определением.

  • Есть ли какой-нибудь учебник/пример использования слоя INFOGAIN_LOSS?

  • Должен ли вход этого уровня, вероятности класса, быть выходным слоем SOFTMAX, или достаточно ввести "верх" полностью связанного слоя?

INFOGAIN_LOSS требуется три входа: вероятности класса, метки и матрица H. Матрица H может быть предоставлена ​​либо как параметры слоя infogain_loss_param { source: "fiename" }.
Предположим, что у меня есть python script, который вычисляет H как numpy.array формы (L,L) с dtype='f4' (где L - количество меток в моей модели).

  1. Как преобразовать мой numpy.array в файл binproto, который может быть представлен как infogain_loss_param { source } для модели?

  2. Предположим, что я хочу, чтобы H предоставлялся как третий вход (внизу) на уровень потерь (а не как параметр модели). Как я могу это сделать?
    Определить ли я новый уровень данных, который "сверху" H? Если это так, не будут ли увеличиваться данные этого уровня на каждой обучающей итерации, например, данные обучения будут увеличиваться? Как я могу определить несколько несвязанных входных "данных" слоев, и как известно, что caffe читает из уровня подготовки/тестирования "данных" после партии, тогда как из уровня данных H он знает, что читает только один раз для всех учебный процесс?

4b9b3361

Ответ 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"
  }
}