in caffe/src/caffe/layers/octree_base_conv_layer.cpp [19:134]
void OctreeBaseConvLayer<Dtype>::LayerSetUp(const vector<Blob<Dtype>*>& bottom,
const vector<Blob<Dtype>*>& top) {
// kernel size
ConvolutionParameter conv_param = this->layer_param_.convolution_param();
size_t kss = conv_param.kernel_size_size();
CHECK(kss == 1 || kss == 3) << "Specify 1 or 3 kernel_size paramters";
kernel_size_.resize(3);
if (kss == 1) {
kernel_size_[0] = conv_param.kernel_size(0);
kernel_size_[1] = conv_param.kernel_size(0);
kernel_size_[2] = conv_param.kernel_size(0);
} else {
kernel_size_[0] = conv_param.kernel_size(0);
kernel_size_[1] = conv_param.kernel_size(1);
kernel_size_[2] = conv_param.kernel_size(2);
}
CHECK(kernel_size_[0] < 4 && kernel_size_[1] < 4 && kernel_size_[2] < 4)
<< "kernel_size should be less than 4";
kernel_sdim_ = kernel_size_[0] * kernel_size_[1] * kernel_size_[2];
// stride
CHECK_LE(conv_param.stride_size(), 1);
stride_ = conv_param.stride_size() == 0 ? 1 : conv_param.stride(0);
CHECK_LE(stride_, 2) << "stride should be less than 2";
// special case: im2col is the identity for 1x1 convolution with stride 1
is_1x1_ = kernel_size_[0] == 1 && kernel_size_[1] == 1 &&
kernel_size_[2] == 1 && stride_ == 1;
// current octree depth
CHECK(this->layer_param_.octree_param().has_curr_depth())
<< "Error in " << this->layer_param_.name() << ": "
<< "The octree depth of bottom blob should be set coreectly.";
curr_depth_ = this->layer_param_.octree_param().curr_depth();
//curr_depth_ = Octree::get_curr_depth();
//if (stride_ == 2) {
// if (is_deconvolution_layer()) Octree::set_curr_depth(curr_depth_ + 1);
// else Octree::set_curr_depth(curr_depth_ - 1);
//}
// channels & num_output_
channels_ = conv_in_channels_ = bottom[0]->shape(1);
num_output_ = conv_out_channels_ = conv_param.num_output();
if (is_deconvolution_layer()) {
std::swap(conv_out_channels_, conv_in_channels_);
}
// Handle the parameters: weights and biases.
// - blobs_[0] holds the filter weights
// - blobs_[1] holds the biases (optional)
vector<int> weight_shape{ conv_out_channels_, conv_in_channels_, kernel_sdim_, 1 };
vector<int> bias_shape;
bias_term_ = conv_param.bias_term();
if (bias_term_) bias_shape.push_back(num_output_);
if (this->blobs_.size() > 0) {
CHECK_EQ(1 + bias_term_, this->blobs_.size())
<< "Incorrect number of weight blobs.";
if (weight_shape != this->blobs_[0]->shape()) {
Blob<Dtype> weight_shaped_blob(weight_shape);
LOG(FATAL) << "Incorrect weight shape: expected shape "
<< weight_shaped_blob.shape_string()
<< "; instead, shape was "
<< this->blobs_[0]->shape_string();
}
if (bias_term_ && bias_shape != this->blobs_[1]->shape()) {
Blob<Dtype> bias_shaped_blob(bias_shape);
LOG(FATAL) << "Incorrect bias shape: expected shape "
<< bias_shaped_blob.shape_string()
<< "; instead, shape was "
<< this->blobs_[1]->shape_string();
}
LOG(INFO) << "Skipping parameter initialization";
} else {
if (bias_term_) this->blobs_.resize(2);
else this->blobs_.resize(1);
// Initialize and fill the weights:
this->blobs_[0].reset(new Blob<Dtype>(weight_shape));
shared_ptr<Filler<Dtype>> weight_filler(
GetFiller<Dtype>(conv_param.weight_filler()));
weight_filler->Fill(this->blobs_[0].get());
// If necessary, initialize and fill the biases.
if (bias_term_) {
this->blobs_[1].reset(new Blob<Dtype>(bias_shape));
shared_ptr<Filler<Dtype> > bias_filler(
GetFiller<Dtype>(conv_param.bias_filler()));
bias_filler->Fill(this->blobs_[1].get());
}
}
kernel_dim_ = this->blobs_[0]->count(1);
// Propagate gradients to the parameters (as directed by backward pass).
this->param_propagate_down_.resize(this->blobs_.size(), true);
// set the pointer of workspace
workspace_ = Octree::get_workspace(Dtype(0), 0);
result_buffer_ = Octree::get_workspace(Dtype(0), 1);
// for the deconv layer, the following code is wrong in the backward pass
//data_buffer_ = Octree::get_workspace(Dtype(0), 2);
data_buffer_.reset(new Blob<Dtype>());
#if defined(USE_CUDNN) && !defined(CPU_ONLY)
// cudnn
CUDNN_CHECK(cudnnCreate(&handle_));
cudnn::createFilterDesc<Dtype>(&filter_desc_, weight_shape[0],
weight_shape[1], weight_shape[2], weight_shape[3]);
cudnn::createTensor4dDesc<Dtype>(&bottom_desc_);
cudnn::createTensor4dDesc<Dtype>(&top_desc_);
cudnn::createConvolutionDesc<Dtype>(&conv_desc_);
filter_workspace_size_ = 8 * 1024 * 1024;
vector<int> filter_workspace_shape(1, filter_workspace_size_);
filter_workspace_.Reshape(filter_workspace_shape);
#endif //USE_CUDNN
}