2
votes

Example

I'm trying to understand a specific code written in C++ version of Caffe to port it in Python version of Keras.

Obviously, layer in the Caffe can be defined as the example below:

template <typename Dtype>
void ROIPoolingLayer<Dtype>::LayerSetUp(const vector<Blob<Dtype>*>& bottom,
      const vector<Blob<Dtype>*>& top) {

where bottom is a one-dimensional array that takes inputs and top is a one-dimensional array that produces outputs.

Then soon after, few parameters are already set using bottom vector:

template <typename Dtype>
void ROIPoolingLayer<Dtype>::LayerSetUp(const vector<Blob<Dtype>*>& bottom,
      const vector<Blob<Dtype>*>& top) {
  ROIPoolingParameter roi_pool_param = this->layer_param_.roi_pooling_param();
  CHECK_GT(roi_pool_param.pooled_h(), 0)
      << "pooled_h must be > 0";
  CHECK_GT(roi_pool_param.pooled_w(), 0)
      << "pooled_w must be > 0";
  pooled_height_ = roi_pool_param.pooled_h();
  pooled_width_ = roi_pool_param.pooled_w();
  spatial_scale_ = roi_pool_param.spatial_scale();
  LOG(INFO) << "Spatial scale: " << spatial_scale_;
}

template <typename Dtype>
void ROIPoolingLayer<Dtype>::Reshape(const vector<Blob<Dtype>*>& bottom,
      const vector<Blob<Dtype>*>& top) {
  channels_ = bottom[0]->channels();
  height_ = bottom[0]->height();
  width_ = bottom[0]->width();
  top[0]->Reshape(bottom[1]->num(), channels_, pooled_height_,
      pooled_width_);
  max_idx_.Reshape(bottom[1]->num(), channels_, pooled_height_,
      pooled_width_);
}

And if we expand code furthermore they use cpu_data method:

template <typename Dtype>
void ROIPoolingLayer<Dtype>::Forward_cpu(const vector<Blob<Dtype>*>& bottom,
      const vector<Blob<Dtype>*>& top) {
  const Dtype* bottom_data = bottom[0]->cpu_data();
  const Dtype* bottom_rois = bottom[1]->cpu_data();

reference to full code.


Question

From Caffe documentation:

As we are often interested in the values as well as the gradients of the blob, a Blob stores two chunks of memories, data and diff. The former is the normal data that we pass along, and the latter is the gradient computed by the network.

Further, as the actual values could be stored either on the CPU and on the GPU, there are two different ways to access them: the const way, which does not change the values, and the mutable way, which changes the values:

const Dtype* cpu_data() const; Dtype* mutable_cpu_data();

So according to description above, is bottom_data[0].cpu_data() defined in the recent code block above simply an array stored in CPU registers containing input data and partial derivative with respect to error? If so, how could I replicate such code in Keras? Is it even significant in Keras (where the layer is either already evaluated or just an empty shape)?

Thank you!

1

1 Answers

1
votes

bottom_data[0].cpu_data() is the method that will return you a constant pointer to the memory of the first input blob. If necessary, the data will be first copied from GPU memory.

You do not need to operate on such a low-level concepts in Keras.

Look at this code from the Keras example:

def call(self, x):
    return K.dot(x, self.kernel)

Here you return the result of the dot product between the input tensor and the layer's kernel.

Unlike Caffe, in Keras you (mostly) define operations on tensors, not on memory arrays. Tensors will be filled with the actual data on execution time, when running a session. Keras backend will take care of all the memory operations needed to perform the K.dot operation (which also returns a tensor).

Also, you can choose which device will be used to place your tensor: FAQ. Again, Keras will perform all necessary operations under the hood.