Изменить порог в ReLU в Caffe framework

Я новичок в Caffe, и теперь мне нужно изменить пороговые значения в слоях ReLU в сверточной нейронной сети. Способ, который я сейчас использую для изменения пороговых значений, заключается в редактировании исходного кода C++ в caffe/src/caffe/layers/relu_layer.cpp и его повторной компиляции. Однако это изменит пороговое значение на указанное значение каждый раз, когда вызывается ReLU. Есть ли способ использовать разные значения в качестве порога на каждом уровне ReLU в сети? Кстати, я использую интерфейс pycaffe и не могу найти такой способ сделать это.

Наконец, извините за мой плохой английский, если есть что-то непонятное, просто дайте мне знать, я постараюсь описать это подробно.


person zbqv    schedule 12.11.2016    source источник
comment
Ответ Дейла хорош, но ответ Шая следует выбрать как правильный. Вам следует избегать изменения Caffe, когда это не нужно.   -  person Jonathan    schedule 14.11.2016


Ответы (2)


Если я правильно понимаю, ваш «ReLU с порогом» в основном

f(x) = x-threshold if x>threshold, 0 otherwise

Вы можете легко реализовать это, добавив слой "Bias", который вычитает threshold из ввода непосредственно перед обычным слоем "ReLU".

person Shai    schedule 14.11.2016
comment
Это должно быть предпочтительным решением. Следует избегать изменения caffe без необходимости. - person Jonathan; 14.11.2016
comment
Спасибо, это решение легче реализовать. - person zbqv; 16.11.2016

Да, ты можешь. В src/caffe/proto добавьте строку:

message ReLUParameter {
  ...
  optional float threshold = 3 [default = 0]; #add this line
  ... 
}

и в src/caffe/layers/relu_layer.cpp внесите небольшие изменения:

template <typename Dtype>
void ReLULayer<Dtype>::Forward_cpu(const vector<Blob<Dtype>*>& bottom,
    const vector<Blob<Dtype>*>& top) {
  ...
  Dtype threshold = this->layer_param_.relu_param().threshold(); //add this line
  for (int i = 0; i < count; ++i) {
    top_data[i] = (bottom_data[i] > threshold) ? (bottom_data[i] - threshold) : 
                  (negative_slope * (bottom_data[i] - threshold));
  }
}

template <typename Dtype>
void ReLULayer<Dtype>::Backward_cpu(const vector<Blob<Dtype>*>& top,
    const vector<bool>& propagate_down,
    const vector<Blob<Dtype>*>& bottom) {
  if (propagate_down[0]) {
    ...
    Dtype threshold = this->layer_param_.relu_param().threshold(); //this line
    for (int i = 0; i < count; ++i) {
      bottom_diff[i] = top_diff[i] * ((bottom_data[i] > threshold)
          + negative_slope * (bottom_data[i] <= threshold));
    }
  }
}

и аналогично в src/caffe/layers/relu_layer.cu код должен выглядеть как этот.

И после компиляции ваших caffe и pycaffe в вашем net.prototxt вы можете написать слой relu, например:

layer {
  name: "threshold_relu"
  type: "ReLU"
  relu_param: {threshold: 1 #e.g. you want this relu layer to have a threshold 1}
  bottom: "input"
  top: "output"
}
person Dale    schedule 12.11.2016
comment
Что означает threshold = 3? Почему 3? - person zbqv; 12.11.2016
comment
Я понял, что означает threshold = 3. И мой net.prototxt работает, когда я добавляю relu_param { threshold: 1 } вместо threshold: 1. Если я использую threshold: 1, я получаю ошибку типа Message type "caffe.LayerParameter" has no field named "threshold". - person zbqv; 12.11.2016
comment
@zbqv Извините, моя невнимательность. И я исправил свой ответ. - person Dale; 13.11.2016
comment
в вашей прямой передаче второй аргумент для минимума. должно быть пороговым, а не нулевым. При чем тут порог? Я думаю, вам нужно изменить функцию... - person Shai; 14.11.2016
comment
@Shai Извините, моя ошибка и код был неправильным, я исправил его. Спасибо, что поправили меня. - person Dale; 14.11.2016
comment
у вас все еще есть разрыв в x=threshold. В чем смысл ReLU с порогом, отличным от нуля? это f(x) = x-threshold if x>threshold, 0 otherwise или f(x) = x if x>threshold, thershold otherwise? - person Shai; 14.11.2016
comment
@Шай Плохо. Как я прочитал из вопроса, это должен быть первый случай, о котором вы упомянули. Я исправил, еще раз спасибо! - person Dale; 14.11.2016